devpts: Must release s_umount on error
[linux/fpc-iii.git] / drivers / net / bnx2x_link.c
blobaea26b4dc45327bd7bcdd3bb0e347fc34e688cfd
1 /* Copyright 2008-2009 Broadcom Corporation
3 * Unless you and Broadcom execute a separate written software license
4 * agreement governing use of this software, this software is licensed to you
5 * under the terms of the GNU General Public License version 2, available
6 * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
8 * Notwithstanding the above, under no circumstances may you combine this
9 * software in any way with any other Broadcom software provided under a
10 * license other than the GPL, without Broadcom's express prior written
11 * consent.
13 * Written by Yaniv Rosner
17 #include <linux/kernel.h>
18 #include <linux/errno.h>
19 #include <linux/pci.h>
20 #include <linux/netdevice.h>
21 #include <linux/delay.h>
22 #include <linux/ethtool.h>
23 #include <linux/mutex.h>
25 #include "bnx2x_reg.h"
26 #include "bnx2x_fw_defs.h"
27 #include "bnx2x_hsi.h"
28 #include "bnx2x_link.h"
29 #include "bnx2x.h"
31 /********************************************************/
32 #define SUPPORT_CL73 0 /* Currently no */
33 #define ETH_HLEN 14
34 #define ETH_OVREHEAD (ETH_HLEN + 8)/* 8 for CRC + VLAN*/
35 #define ETH_MIN_PACKET_SIZE 60
36 #define ETH_MAX_PACKET_SIZE 1500
37 #define ETH_MAX_JUMBO_PACKET_SIZE 9600
38 #define MDIO_ACCESS_TIMEOUT 1000
39 #define BMAC_CONTROL_RX_ENABLE 2
41 /***********************************************************/
42 /* Shortcut definitions */
43 /***********************************************************/
45 #define NIG_STATUS_XGXS0_LINK10G \
46 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G
47 #define NIG_STATUS_XGXS0_LINK_STATUS \
48 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS
49 #define NIG_STATUS_XGXS0_LINK_STATUS_SIZE \
50 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE
51 #define NIG_STATUS_SERDES0_LINK_STATUS \
52 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS
53 #define NIG_MASK_MI_INT \
54 NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT
55 #define NIG_MASK_XGXS0_LINK10G \
56 NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G
57 #define NIG_MASK_XGXS0_LINK_STATUS \
58 NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK_STATUS
59 #define NIG_MASK_SERDES0_LINK_STATUS \
60 NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS
62 #define MDIO_AN_CL73_OR_37_COMPLETE \
63 (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | \
64 MDIO_GP_STATUS_TOP_AN_STATUS1_CL37_AUTONEG_COMPLETE)
66 #define XGXS_RESET_BITS \
67 (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW | \
68 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_IDDQ | \
69 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN | \
70 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN_SD | \
71 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB)
73 #define SERDES_RESET_BITS \
74 (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_RSTB_HW | \
75 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ | \
76 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN | \
77 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN_SD)
79 #define AUTONEG_CL37 SHARED_HW_CFG_AN_ENABLE_CL37
80 #define AUTONEG_CL73 SHARED_HW_CFG_AN_ENABLE_CL73
81 #define AUTONEG_BAM SHARED_HW_CFG_AN_ENABLE_BAM
82 #define AUTONEG_PARALLEL \
83 SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
84 #define AUTONEG_SGMII_FIBER_AUTODET \
85 SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT
86 #define AUTONEG_REMOTE_PHY SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY
88 #define GP_STATUS_PAUSE_RSOLUTION_TXSIDE \
89 MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE
90 #define GP_STATUS_PAUSE_RSOLUTION_RXSIDE \
91 MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_RXSIDE
92 #define GP_STATUS_SPEED_MASK \
93 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_MASK
94 #define GP_STATUS_10M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10M
95 #define GP_STATUS_100M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_100M
96 #define GP_STATUS_1G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G
97 #define GP_STATUS_2_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_2_5G
98 #define GP_STATUS_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_5G
99 #define GP_STATUS_6G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_6G
100 #define GP_STATUS_10G_HIG \
101 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG
102 #define GP_STATUS_10G_CX4 \
103 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4
104 #define GP_STATUS_12G_HIG \
105 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12G_HIG
106 #define GP_STATUS_12_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12_5G
107 #define GP_STATUS_13G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_13G
108 #define GP_STATUS_15G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_15G
109 #define GP_STATUS_16G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G
110 #define GP_STATUS_1G_KX MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX
111 #define GP_STATUS_10G_KX4 \
112 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
114 #define LINK_10THD LINK_STATUS_SPEED_AND_DUPLEX_10THD
115 #define LINK_10TFD LINK_STATUS_SPEED_AND_DUPLEX_10TFD
116 #define LINK_100TXHD LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
117 #define LINK_100T4 LINK_STATUS_SPEED_AND_DUPLEX_100T4
118 #define LINK_100TXFD LINK_STATUS_SPEED_AND_DUPLEX_100TXFD
119 #define LINK_1000THD LINK_STATUS_SPEED_AND_DUPLEX_1000THD
120 #define LINK_1000TFD LINK_STATUS_SPEED_AND_DUPLEX_1000TFD
121 #define LINK_1000XFD LINK_STATUS_SPEED_AND_DUPLEX_1000XFD
122 #define LINK_2500THD LINK_STATUS_SPEED_AND_DUPLEX_2500THD
123 #define LINK_2500TFD LINK_STATUS_SPEED_AND_DUPLEX_2500TFD
124 #define LINK_2500XFD LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
125 #define LINK_10GTFD LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
126 #define LINK_10GXFD LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
127 #define LINK_12GTFD LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
128 #define LINK_12GXFD LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
129 #define LINK_12_5GTFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD
130 #define LINK_12_5GXFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD
131 #define LINK_13GTFD LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
132 #define LINK_13GXFD LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
133 #define LINK_15GTFD LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
134 #define LINK_15GXFD LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
135 #define LINK_16GTFD LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
136 #define LINK_16GXFD LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
138 #define PHY_XGXS_FLAG 0x1
139 #define PHY_SGMII_FLAG 0x2
140 #define PHY_SERDES_FLAG 0x4
142 /**********************************************************/
143 /* INTERFACE */
144 /**********************************************************/
145 #define CL45_WR_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
146 bnx2x_cl45_write(_bp, _port, 0, _phy_addr, \
147 DEFAULT_PHY_DEV_ADDR, \
148 (_bank + (_addr & 0xf)), \
149 _val)
151 #define CL45_RD_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
152 bnx2x_cl45_read(_bp, _port, 0, _phy_addr, \
153 DEFAULT_PHY_DEV_ADDR, \
154 (_bank + (_addr & 0xf)), \
155 _val)
157 static void bnx2x_set_phy_mdio(struct link_params *params)
159 struct bnx2x *bp = params->bp;
160 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
161 params->port*0x18, 0);
162 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
163 DEFAULT_PHY_DEV_ADDR);
166 static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
168 u32 val = REG_RD(bp, reg);
170 val |= bits;
171 REG_WR(bp, reg, val);
172 return val;
175 static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits)
177 u32 val = REG_RD(bp, reg);
179 val &= ~bits;
180 REG_WR(bp, reg, val);
181 return val;
184 static void bnx2x_emac_init(struct link_params *params,
185 struct link_vars *vars)
187 /* reset and unreset the emac core */
188 struct bnx2x *bp = params->bp;
189 u8 port = params->port;
190 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
191 u32 val;
192 u16 timeout;
194 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
195 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
196 udelay(5);
197 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
198 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
200 /* init emac - use read-modify-write */
201 /* self clear reset */
202 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
203 EMAC_WR(bp, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET));
205 timeout = 200;
206 do {
207 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
208 DP(NETIF_MSG_LINK, "EMAC reset reg is %u\n", val);
209 if (!timeout) {
210 DP(NETIF_MSG_LINK, "EMAC timeout!\n");
211 return;
213 timeout--;
214 } while (val & EMAC_MODE_RESET);
216 /* Set mac address */
217 val = ((params->mac_addr[0] << 8) |
218 params->mac_addr[1]);
219 EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH, val);
221 val = ((params->mac_addr[2] << 24) |
222 (params->mac_addr[3] << 16) |
223 (params->mac_addr[4] << 8) |
224 params->mac_addr[5]);
225 EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + 4, val);
228 static u8 bnx2x_emac_enable(struct link_params *params,
229 struct link_vars *vars, u8 lb)
231 struct bnx2x *bp = params->bp;
232 u8 port = params->port;
233 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
234 u32 val;
236 DP(NETIF_MSG_LINK, "enabling EMAC\n");
238 /* enable emac and not bmac */
239 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
241 /* for paladium */
242 if (CHIP_REV_IS_EMUL(bp)) {
243 /* Use lane 1 (of lanes 0-3) */
244 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
245 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
246 port*4, 1);
248 /* for fpga */
249 else
251 if (CHIP_REV_IS_FPGA(bp)) {
252 /* Use lane 1 (of lanes 0-3) */
253 DP(NETIF_MSG_LINK, "bnx2x_emac_enable: Setting FPGA\n");
255 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
256 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4,
258 } else
259 /* ASIC */
260 if (vars->phy_flags & PHY_XGXS_FLAG) {
261 u32 ser_lane = ((params->lane_config &
262 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
263 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
265 DP(NETIF_MSG_LINK, "XGXS\n");
266 /* select the master lanes (out of 0-3) */
267 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 +
268 port*4, ser_lane);
269 /* select XGXS */
270 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
271 port*4, 1);
273 } else { /* SerDes */
274 DP(NETIF_MSG_LINK, "SerDes\n");
275 /* select SerDes */
276 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
277 port*4, 0);
280 /* enable emac */
281 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1);
283 if (CHIP_REV_IS_SLOW(bp)) {
284 /* config GMII mode */
285 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
286 EMAC_WR(bp, EMAC_REG_EMAC_MODE,
287 (val | EMAC_MODE_PORT_GMII));
288 } else { /* ASIC */
289 /* pause enable/disable */
290 bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
291 EMAC_RX_MODE_FLOW_EN);
292 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
293 bnx2x_bits_en(bp, emac_base +
294 EMAC_REG_EMAC_RX_MODE,
295 EMAC_RX_MODE_FLOW_EN);
297 bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
298 (EMAC_TX_MODE_EXT_PAUSE_EN |
299 EMAC_TX_MODE_FLOW_EN));
300 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
301 bnx2x_bits_en(bp, emac_base +
302 EMAC_REG_EMAC_TX_MODE,
303 (EMAC_TX_MODE_EXT_PAUSE_EN |
304 EMAC_TX_MODE_FLOW_EN));
307 /* KEEP_VLAN_TAG, promiscuous */
308 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
309 val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
310 EMAC_WR(bp, EMAC_REG_EMAC_RX_MODE, val);
312 /* Set Loopback */
313 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
314 if (lb)
315 val |= 0x810;
316 else
317 val &= ~0x810;
318 EMAC_WR(bp, EMAC_REG_EMAC_MODE, val);
320 /* enable emac */
321 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1);
323 /* enable emac for jumbo packets */
324 EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE,
325 (EMAC_RX_MTU_SIZE_JUMBO_ENA |
326 (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD)));
328 /* strip CRC */
329 REG_WR(bp, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1);
331 /* disable the NIG in/out to the bmac */
332 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x0);
333 REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, 0x0);
334 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x0);
336 /* enable the NIG in/out to the emac */
337 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x1);
338 val = 0;
339 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
340 val = 1;
342 REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
343 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x1);
345 if (CHIP_REV_IS_EMUL(bp)) {
346 /* take the BigMac out of reset */
347 REG_WR(bp,
348 GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
349 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
351 /* enable access for bmac registers */
352 REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
355 vars->mac_type = MAC_TYPE_EMAC;
356 return 0;
361 static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
362 u8 is_lb)
364 struct bnx2x *bp = params->bp;
365 u8 port = params->port;
366 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
367 NIG_REG_INGRESS_BMAC0_MEM;
368 u32 wb_data[2];
369 u32 val;
371 DP(NETIF_MSG_LINK, "Enabling BigMAC\n");
372 /* reset and unreset the BigMac */
373 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
374 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
375 msleep(1);
377 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
378 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
380 /* enable access for bmac registers */
381 REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
383 /* XGXS control */
384 wb_data[0] = 0x3c;
385 wb_data[1] = 0;
386 REG_WR_DMAE(bp, bmac_addr +
387 BIGMAC_REGISTER_BMAC_XGXS_CONTROL,
388 wb_data, 2);
390 /* tx MAC SA */
391 wb_data[0] = ((params->mac_addr[2] << 24) |
392 (params->mac_addr[3] << 16) |
393 (params->mac_addr[4] << 8) |
394 params->mac_addr[5]);
395 wb_data[1] = ((params->mac_addr[0] << 8) |
396 params->mac_addr[1]);
397 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR,
398 wb_data, 2);
400 /* tx control */
401 val = 0xc0;
402 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
403 val |= 0x800000;
404 wb_data[0] = val;
405 wb_data[1] = 0;
406 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_CONTROL,
407 wb_data, 2);
409 /* mac control */
410 val = 0x3;
411 if (is_lb) {
412 val |= 0x4;
413 DP(NETIF_MSG_LINK, "enable bmac loopback\n");
415 wb_data[0] = val;
416 wb_data[1] = 0;
417 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
418 wb_data, 2);
421 /* set rx mtu */
422 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
423 wb_data[1] = 0;
424 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE,
425 wb_data, 2);
427 /* rx control set to don't strip crc */
428 val = 0x14;
429 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
430 val |= 0x20;
431 wb_data[0] = val;
432 wb_data[1] = 0;
433 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_CONTROL,
434 wb_data, 2);
436 /* set tx mtu */
437 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
438 wb_data[1] = 0;
439 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE,
440 wb_data, 2);
442 /* set cnt max size */
443 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
444 wb_data[1] = 0;
445 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE,
446 wb_data, 2);
448 /* configure safc */
449 wb_data[0] = 0x1000200;
450 wb_data[1] = 0;
451 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
452 wb_data, 2);
453 /* fix for emulation */
454 if (CHIP_REV_IS_EMUL(bp)) {
455 wb_data[0] = 0xf000;
456 wb_data[1] = 0;
457 REG_WR_DMAE(bp,
458 bmac_addr + BIGMAC_REGISTER_TX_PAUSE_THRESHOLD,
459 wb_data, 2);
462 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
463 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
464 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
465 val = 0;
466 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
467 val = 1;
468 REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
469 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
470 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x0);
471 REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, 0x0);
472 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x1);
473 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);
475 vars->mac_type = MAC_TYPE_BMAC;
476 return 0;
479 static void bnx2x_phy_deassert(struct link_params *params, u8 phy_flags)
481 struct bnx2x *bp = params->bp;
482 u32 val;
484 if (phy_flags & PHY_XGXS_FLAG) {
485 DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:XGXS\n");
486 val = XGXS_RESET_BITS;
488 } else { /* SerDes */
489 DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:SerDes\n");
490 val = SERDES_RESET_BITS;
493 val = val << (params->port*16);
495 /* reset and unreset the SerDes/XGXS */
496 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
497 val);
498 udelay(500);
499 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET,
500 val);
501 bnx2x_set_phy_mdio(params);
504 void bnx2x_link_status_update(struct link_params *params,
505 struct link_vars *vars)
507 struct bnx2x *bp = params->bp;
508 u8 link_10g;
509 u8 port = params->port;
511 if (params->switch_cfg == SWITCH_CFG_1G)
512 vars->phy_flags = PHY_SERDES_FLAG;
513 else
514 vars->phy_flags = PHY_XGXS_FLAG;
515 vars->link_status = REG_RD(bp, params->shmem_base +
516 offsetof(struct shmem_region,
517 port_mb[port].link_status));
519 vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
521 if (vars->link_up) {
522 DP(NETIF_MSG_LINK, "phy link up\n");
524 vars->phy_link_up = 1;
525 vars->duplex = DUPLEX_FULL;
526 switch (vars->link_status &
527 LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
528 case LINK_10THD:
529 vars->duplex = DUPLEX_HALF;
530 /* fall thru */
531 case LINK_10TFD:
532 vars->line_speed = SPEED_10;
533 break;
535 case LINK_100TXHD:
536 vars->duplex = DUPLEX_HALF;
537 /* fall thru */
538 case LINK_100T4:
539 case LINK_100TXFD:
540 vars->line_speed = SPEED_100;
541 break;
543 case LINK_1000THD:
544 vars->duplex = DUPLEX_HALF;
545 /* fall thru */
546 case LINK_1000TFD:
547 vars->line_speed = SPEED_1000;
548 break;
550 case LINK_2500THD:
551 vars->duplex = DUPLEX_HALF;
552 /* fall thru */
553 case LINK_2500TFD:
554 vars->line_speed = SPEED_2500;
555 break;
557 case LINK_10GTFD:
558 vars->line_speed = SPEED_10000;
559 break;
561 case LINK_12GTFD:
562 vars->line_speed = SPEED_12000;
563 break;
565 case LINK_12_5GTFD:
566 vars->line_speed = SPEED_12500;
567 break;
569 case LINK_13GTFD:
570 vars->line_speed = SPEED_13000;
571 break;
573 case LINK_15GTFD:
574 vars->line_speed = SPEED_15000;
575 break;
577 case LINK_16GTFD:
578 vars->line_speed = SPEED_16000;
579 break;
581 default:
582 break;
585 if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
586 vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
587 else
588 vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_TX;
590 if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
591 vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
592 else
593 vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_RX;
595 if (vars->phy_flags & PHY_XGXS_FLAG) {
596 if (vars->line_speed &&
597 ((vars->line_speed == SPEED_10) ||
598 (vars->line_speed == SPEED_100))) {
599 vars->phy_flags |= PHY_SGMII_FLAG;
600 } else {
601 vars->phy_flags &= ~PHY_SGMII_FLAG;
605 /* anything 10 and over uses the bmac */
606 link_10g = ((vars->line_speed == SPEED_10000) ||
607 (vars->line_speed == SPEED_12000) ||
608 (vars->line_speed == SPEED_12500) ||
609 (vars->line_speed == SPEED_13000) ||
610 (vars->line_speed == SPEED_15000) ||
611 (vars->line_speed == SPEED_16000));
612 if (link_10g)
613 vars->mac_type = MAC_TYPE_BMAC;
614 else
615 vars->mac_type = MAC_TYPE_EMAC;
617 } else { /* link down */
618 DP(NETIF_MSG_LINK, "phy link down\n");
620 vars->phy_link_up = 0;
622 vars->line_speed = 0;
623 vars->duplex = DUPLEX_FULL;
624 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
626 /* indicate no mac active */
627 vars->mac_type = MAC_TYPE_NONE;
630 DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x\n",
631 vars->link_status, vars->phy_link_up);
632 DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n",
633 vars->line_speed, vars->duplex, vars->flow_ctrl);
636 static void bnx2x_update_mng(struct link_params *params, u32 link_status)
638 struct bnx2x *bp = params->bp;
639 REG_WR(bp, params->shmem_base +
640 offsetof(struct shmem_region,
641 port_mb[params->port].link_status),
642 link_status);
645 static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
647 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
648 NIG_REG_INGRESS_BMAC0_MEM;
649 u32 wb_data[2];
650 u32 nig_bmac_enable = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4);
652 /* Only if the bmac is out of reset */
653 if (REG_RD(bp, MISC_REG_RESET_REG_2) &
654 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) &&
655 nig_bmac_enable) {
657 /* Clear Rx Enable bit in BMAC_CONTROL register */
658 REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
659 wb_data, 2);
660 wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
661 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
662 wb_data, 2);
664 msleep(1);
668 static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
669 u32 line_speed)
671 struct bnx2x *bp = params->bp;
672 u8 port = params->port;
673 u32 init_crd, crd;
674 u32 count = 1000;
676 /* disable port */
677 REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1);
679 /* wait for init credit */
680 init_crd = REG_RD(bp, PBF_REG_P0_INIT_CRD + port*4);
681 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
682 DP(NETIF_MSG_LINK, "init_crd 0x%x crd 0x%x\n", init_crd, crd);
684 while ((init_crd != crd) && count) {
685 msleep(5);
687 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
688 count--;
690 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
691 if (init_crd != crd) {
692 DP(NETIF_MSG_LINK, "BUG! init_crd 0x%x != crd 0x%x\n",
693 init_crd, crd);
694 return -EINVAL;
697 if (flow_ctrl & BNX2X_FLOW_CTRL_RX ||
698 line_speed == SPEED_10 ||
699 line_speed == SPEED_100 ||
700 line_speed == SPEED_1000 ||
701 line_speed == SPEED_2500) {
702 REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 1);
703 /* update threshold */
704 REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, 0);
705 /* update init credit */
706 init_crd = 778; /* (800-18-4) */
708 } else {
709 u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
710 ETH_OVREHEAD)/16;
711 REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
712 /* update threshold */
713 REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh);
714 /* update init credit */
715 switch (line_speed) {
716 case SPEED_10000:
717 init_crd = thresh + 553 - 22;
718 break;
720 case SPEED_12000:
721 init_crd = thresh + 664 - 22;
722 break;
724 case SPEED_13000:
725 init_crd = thresh + 742 - 22;
726 break;
728 case SPEED_16000:
729 init_crd = thresh + 778 - 22;
730 break;
731 default:
732 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
733 line_speed);
734 return -EINVAL;
735 break;
738 REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, init_crd);
739 DP(NETIF_MSG_LINK, "PBF updated to speed %d credit %d\n",
740 line_speed, init_crd);
742 /* probe the credit changes */
743 REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x1);
744 msleep(5);
745 REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x0);
747 /* enable port */
748 REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x0);
749 return 0;
752 static u32 bnx2x_get_emac_base(u32 ext_phy_type, u8 port)
754 u32 emac_base;
755 switch (ext_phy_type) {
756 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
757 emac_base = GRCBASE_EMAC0;
758 break;
759 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
760 emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
761 break;
762 default:
763 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
764 break;
766 return emac_base;
770 u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type,
771 u8 phy_addr, u8 devad, u16 reg, u16 val)
773 u32 tmp, saved_mode;
774 u8 i, rc = 0;
775 u32 mdio_ctrl = bnx2x_get_emac_base(ext_phy_type, port);
777 /* set clause 45 mode, slow down the MDIO clock to 2.5MHz
778 * (a value of 49==0x31) and make sure that the AUTO poll is off
780 saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
781 tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
782 EMAC_MDIO_MODE_CLOCK_CNT);
783 tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
784 (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
785 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
786 REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
787 udelay(40);
789 /* address */
791 tmp = ((phy_addr << 21) | (devad << 16) | reg |
792 EMAC_MDIO_COMM_COMMAND_ADDRESS |
793 EMAC_MDIO_COMM_START_BUSY);
794 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
796 for (i = 0; i < 50; i++) {
797 udelay(10);
799 tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
800 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
801 udelay(5);
802 break;
805 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
806 DP(NETIF_MSG_LINK, "write phy register failed\n");
807 rc = -EFAULT;
808 } else {
809 /* data */
810 tmp = ((phy_addr << 21) | (devad << 16) | val |
811 EMAC_MDIO_COMM_COMMAND_WRITE_45 |
812 EMAC_MDIO_COMM_START_BUSY);
813 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
815 for (i = 0; i < 50; i++) {
816 udelay(10);
818 tmp = REG_RD(bp, mdio_ctrl +
819 EMAC_REG_EMAC_MDIO_COMM);
820 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
821 udelay(5);
822 break;
825 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
826 DP(NETIF_MSG_LINK, "write phy register failed\n");
827 rc = -EFAULT;
831 /* Restore the saved mode */
832 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
834 return rc;
837 u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type,
838 u8 phy_addr, u8 devad, u16 reg, u16 *ret_val)
840 u32 val, saved_mode;
841 u16 i;
842 u8 rc = 0;
844 u32 mdio_ctrl = bnx2x_get_emac_base(ext_phy_type, port);
845 /* set clause 45 mode, slow down the MDIO clock to 2.5MHz
846 * (a value of 49==0x31) and make sure that the AUTO poll is off
848 saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
849 val = saved_mode & ((EMAC_MDIO_MODE_AUTO_POLL |
850 EMAC_MDIO_MODE_CLOCK_CNT));
851 val |= (EMAC_MDIO_MODE_CLAUSE_45 |
852 (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
853 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
854 REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
855 udelay(40);
857 /* address */
858 val = ((phy_addr << 21) | (devad << 16) | reg |
859 EMAC_MDIO_COMM_COMMAND_ADDRESS |
860 EMAC_MDIO_COMM_START_BUSY);
861 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
863 for (i = 0; i < 50; i++) {
864 udelay(10);
866 val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
867 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
868 udelay(5);
869 break;
872 if (val & EMAC_MDIO_COMM_START_BUSY) {
873 DP(NETIF_MSG_LINK, "read phy register failed\n");
875 *ret_val = 0;
876 rc = -EFAULT;
878 } else {
879 /* data */
880 val = ((phy_addr << 21) | (devad << 16) |
881 EMAC_MDIO_COMM_COMMAND_READ_45 |
882 EMAC_MDIO_COMM_START_BUSY);
883 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
885 for (i = 0; i < 50; i++) {
886 udelay(10);
888 val = REG_RD(bp, mdio_ctrl +
889 EMAC_REG_EMAC_MDIO_COMM);
890 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
891 *ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
892 break;
895 if (val & EMAC_MDIO_COMM_START_BUSY) {
896 DP(NETIF_MSG_LINK, "read phy register failed\n");
898 *ret_val = 0;
899 rc = -EFAULT;
903 /* Restore the saved mode */
904 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
906 return rc;
909 static void bnx2x_set_aer_mmd(struct link_params *params,
910 struct link_vars *vars)
912 struct bnx2x *bp = params->bp;
913 u32 ser_lane;
914 u16 offset;
916 ser_lane = ((params->lane_config &
917 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
918 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
920 offset = (vars->phy_flags & PHY_XGXS_FLAG) ?
921 (params->phy_addr + ser_lane) : 0;
923 CL45_WR_OVER_CL22(bp, params->port,
924 params->phy_addr,
925 MDIO_REG_BANK_AER_BLOCK,
926 MDIO_AER_BLOCK_AER_REG, 0x3800 + offset);
929 static void bnx2x_set_master_ln(struct link_params *params)
931 struct bnx2x *bp = params->bp;
932 u16 new_master_ln, ser_lane;
933 ser_lane = ((params->lane_config &
934 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
935 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
937 /* set the master_ln for AN */
938 CL45_RD_OVER_CL22(bp, params->port,
939 params->phy_addr,
940 MDIO_REG_BANK_XGXS_BLOCK2,
941 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
942 &new_master_ln);
944 CL45_WR_OVER_CL22(bp, params->port,
945 params->phy_addr,
946 MDIO_REG_BANK_XGXS_BLOCK2 ,
947 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
948 (new_master_ln | ser_lane));
951 static u8 bnx2x_reset_unicore(struct link_params *params)
953 struct bnx2x *bp = params->bp;
954 u16 mii_control;
955 u16 i;
957 CL45_RD_OVER_CL22(bp, params->port,
958 params->phy_addr,
959 MDIO_REG_BANK_COMBO_IEEE0,
960 MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
962 /* reset the unicore */
963 CL45_WR_OVER_CL22(bp, params->port,
964 params->phy_addr,
965 MDIO_REG_BANK_COMBO_IEEE0,
966 MDIO_COMBO_IEEE0_MII_CONTROL,
967 (mii_control |
968 MDIO_COMBO_IEEO_MII_CONTROL_RESET));
970 /* wait for the reset to self clear */
971 for (i = 0; i < MDIO_ACCESS_TIMEOUT; i++) {
972 udelay(5);
974 /* the reset erased the previous bank value */
975 CL45_RD_OVER_CL22(bp, params->port,
976 params->phy_addr,
977 MDIO_REG_BANK_COMBO_IEEE0,
978 MDIO_COMBO_IEEE0_MII_CONTROL,
979 &mii_control);
981 if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) {
982 udelay(5);
983 return 0;
987 DP(NETIF_MSG_LINK, "BUG! XGXS is still in reset!\n");
988 return -EINVAL;
992 static void bnx2x_set_swap_lanes(struct link_params *params)
994 struct bnx2x *bp = params->bp;
995 /* Each two bits represents a lane number:
996 No swap is 0123 => 0x1b no need to enable the swap */
997 u16 ser_lane, rx_lane_swap, tx_lane_swap;
999 ser_lane = ((params->lane_config &
1000 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
1001 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
1002 rx_lane_swap = ((params->lane_config &
1003 PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
1004 PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
1005 tx_lane_swap = ((params->lane_config &
1006 PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
1007 PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
1009 if (rx_lane_swap != 0x1b) {
1010 CL45_WR_OVER_CL22(bp, params->port,
1011 params->phy_addr,
1012 MDIO_REG_BANK_XGXS_BLOCK2,
1013 MDIO_XGXS_BLOCK2_RX_LN_SWAP,
1014 (rx_lane_swap |
1015 MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
1016 MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
1017 } else {
1018 CL45_WR_OVER_CL22(bp, params->port,
1019 params->phy_addr,
1020 MDIO_REG_BANK_XGXS_BLOCK2,
1021 MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
1024 if (tx_lane_swap != 0x1b) {
1025 CL45_WR_OVER_CL22(bp, params->port,
1026 params->phy_addr,
1027 MDIO_REG_BANK_XGXS_BLOCK2,
1028 MDIO_XGXS_BLOCK2_TX_LN_SWAP,
1029 (tx_lane_swap |
1030 MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
1031 } else {
1032 CL45_WR_OVER_CL22(bp, params->port,
1033 params->phy_addr,
1034 MDIO_REG_BANK_XGXS_BLOCK2,
1035 MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
1039 static void bnx2x_set_parallel_detection(struct link_params *params,
1040 u8 phy_flags)
1042 struct bnx2x *bp = params->bp;
1043 u16 control2;
1045 CL45_RD_OVER_CL22(bp, params->port,
1046 params->phy_addr,
1047 MDIO_REG_BANK_SERDES_DIGITAL,
1048 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1049 &control2);
1052 control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
1055 CL45_WR_OVER_CL22(bp, params->port,
1056 params->phy_addr,
1057 MDIO_REG_BANK_SERDES_DIGITAL,
1058 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1059 control2);
1061 if (phy_flags & PHY_XGXS_FLAG) {
1062 DP(NETIF_MSG_LINK, "XGXS\n");
1064 CL45_WR_OVER_CL22(bp, params->port,
1065 params->phy_addr,
1066 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1067 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
1068 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
1070 CL45_RD_OVER_CL22(bp, params->port,
1071 params->phy_addr,
1072 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1073 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
1074 &control2);
1077 control2 |=
1078 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
1080 CL45_WR_OVER_CL22(bp, params->port,
1081 params->phy_addr,
1082 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1083 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
1084 control2);
1086 /* Disable parallel detection of HiG */
1087 CL45_WR_OVER_CL22(bp, params->port,
1088 params->phy_addr,
1089 MDIO_REG_BANK_XGXS_BLOCK2,
1090 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
1091 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
1092 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
1096 static void bnx2x_set_autoneg(struct link_params *params,
1097 struct link_vars *vars)
1099 struct bnx2x *bp = params->bp;
1100 u16 reg_val;
1102 /* CL37 Autoneg */
1104 CL45_RD_OVER_CL22(bp, params->port,
1105 params->phy_addr,
1106 MDIO_REG_BANK_COMBO_IEEE0,
1107 MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1109 /* CL37 Autoneg Enabled */
1110 if (vars->line_speed == SPEED_AUTO_NEG)
1111 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN;
1112 else /* CL37 Autoneg Disabled */
1113 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1114 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);
1116 CL45_WR_OVER_CL22(bp, params->port,
1117 params->phy_addr,
1118 MDIO_REG_BANK_COMBO_IEEE0,
1119 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1121 /* Enable/Disable Autodetection */
1123 CL45_RD_OVER_CL22(bp, params->port,
1124 params->phy_addr,
1125 MDIO_REG_BANK_SERDES_DIGITAL,
1126 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
1127 reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN;
1128 if (vars->line_speed == SPEED_AUTO_NEG)
1129 reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1130 else
1131 reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1133 CL45_WR_OVER_CL22(bp, params->port,
1134 params->phy_addr,
1135 MDIO_REG_BANK_SERDES_DIGITAL,
1136 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
1138 /* Enable TetonII and BAM autoneg */
1139 CL45_RD_OVER_CL22(bp, params->port,
1140 params->phy_addr,
1141 MDIO_REG_BANK_BAM_NEXT_PAGE,
1142 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1143 &reg_val);
1144 if (vars->line_speed == SPEED_AUTO_NEG) {
1145 /* Enable BAM aneg Mode and TetonII aneg Mode */
1146 reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1147 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1148 } else {
1149 /* TetonII and BAM Autoneg Disabled */
1150 reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1151 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1153 CL45_WR_OVER_CL22(bp, params->port,
1154 params->phy_addr,
1155 MDIO_REG_BANK_BAM_NEXT_PAGE,
1156 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1157 reg_val);
1159 /* Enable Clause 73 Aneg */
1160 if ((vars->line_speed == SPEED_AUTO_NEG) &&
1161 (SUPPORT_CL73)) {
1162 /* Enable BAM Station Manager */
1164 CL45_WR_OVER_CL22(bp, params->port,
1165 params->phy_addr,
1166 MDIO_REG_BANK_CL73_USERB0,
1167 MDIO_CL73_USERB0_CL73_BAM_CTRL1,
1168 (MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
1169 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN |
1170 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN));
1172 /* Merge CL73 and CL37 aneg resolution */
1173 CL45_RD_OVER_CL22(bp, params->port,
1174 params->phy_addr,
1175 MDIO_REG_BANK_CL73_USERB0,
1176 MDIO_CL73_USERB0_CL73_BAM_CTRL3,
1177 &reg_val);
1179 CL45_WR_OVER_CL22(bp, params->port,
1180 params->phy_addr,
1181 MDIO_REG_BANK_CL73_USERB0,
1182 MDIO_CL73_USERB0_CL73_BAM_CTRL3,
1183 (reg_val |
1184 MDIO_CL73_USERB0_CL73_BAM_CTRL3_USE_CL73_HCD_MR));
1186 /* Set the CL73 AN speed */
1188 CL45_RD_OVER_CL22(bp, params->port,
1189 params->phy_addr,
1190 MDIO_REG_BANK_CL73_IEEEB1,
1191 MDIO_CL73_IEEEB1_AN_ADV2, &reg_val);
1192 /* In the SerDes we support only the 1G.
1193 In the XGXS we support the 10G KX4
1194 but we currently do not support the KR */
1195 if (vars->phy_flags & PHY_XGXS_FLAG) {
1196 DP(NETIF_MSG_LINK, "XGXS\n");
1197 /* 10G KX4 */
1198 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
1199 } else {
1200 DP(NETIF_MSG_LINK, "SerDes\n");
1201 /* 1000M KX */
1202 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
1204 CL45_WR_OVER_CL22(bp, params->port,
1205 params->phy_addr,
1206 MDIO_REG_BANK_CL73_IEEEB1,
1207 MDIO_CL73_IEEEB1_AN_ADV2, reg_val);
1209 /* CL73 Autoneg Enabled */
1210 reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;
1211 } else {
1212 /* CL73 Autoneg Disabled */
1213 reg_val = 0;
1215 CL45_WR_OVER_CL22(bp, params->port,
1216 params->phy_addr,
1217 MDIO_REG_BANK_CL73_IEEEB0,
1218 MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
1221 /* program SerDes, forced speed */
1222 static void bnx2x_program_serdes(struct link_params *params,
1223 struct link_vars *vars)
1225 struct bnx2x *bp = params->bp;
1226 u16 reg_val;
1228 /* program duplex, disable autoneg */
1230 CL45_RD_OVER_CL22(bp, params->port,
1231 params->phy_addr,
1232 MDIO_REG_BANK_COMBO_IEEE0,
1233 MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1234 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
1235 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN);
1236 if (params->req_duplex == DUPLEX_FULL)
1237 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
1238 CL45_WR_OVER_CL22(bp, params->port,
1239 params->phy_addr,
1240 MDIO_REG_BANK_COMBO_IEEE0,
1241 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1243 /* program speed
1244 - needed only if the speed is greater than 1G (2.5G or 10G) */
1245 CL45_RD_OVER_CL22(bp, params->port,
1246 params->phy_addr,
1247 MDIO_REG_BANK_SERDES_DIGITAL,
1248 MDIO_SERDES_DIGITAL_MISC1, &reg_val);
1249 /* clearing the speed value before setting the right speed */
1250 DP(NETIF_MSG_LINK, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x\n", reg_val);
1252 reg_val &= ~(MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK |
1253 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
1255 if (!((vars->line_speed == SPEED_1000) ||
1256 (vars->line_speed == SPEED_100) ||
1257 (vars->line_speed == SPEED_10))) {
1259 reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M |
1260 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
1261 if (vars->line_speed == SPEED_10000)
1262 reg_val |=
1263 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
1264 if (vars->line_speed == SPEED_13000)
1265 reg_val |=
1266 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
1269 CL45_WR_OVER_CL22(bp, params->port,
1270 params->phy_addr,
1271 MDIO_REG_BANK_SERDES_DIGITAL,
1272 MDIO_SERDES_DIGITAL_MISC1, reg_val);
1276 static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params)
1278 struct bnx2x *bp = params->bp;
1279 u16 val = 0;
1281 /* configure the 48 bits for BAM AN */
1283 /* set extended capabilities */
1284 if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
1285 val |= MDIO_OVER_1G_UP1_2_5G;
1286 if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
1287 val |= MDIO_OVER_1G_UP1_10G;
1288 CL45_WR_OVER_CL22(bp, params->port,
1289 params->phy_addr,
1290 MDIO_REG_BANK_OVER_1G,
1291 MDIO_OVER_1G_UP1, val);
1293 CL45_WR_OVER_CL22(bp, params->port,
1294 params->phy_addr,
1295 MDIO_REG_BANK_OVER_1G,
1296 MDIO_OVER_1G_UP3, 0);
1299 static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u32 *ieee_fc)
1301 *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
1302 /* resolve pause mode and advertisement
1303 * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
1305 switch (params->req_flow_ctrl) {
1306 case BNX2X_FLOW_CTRL_AUTO:
1307 if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) {
1308 *ieee_fc |=
1309 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
1310 } else {
1311 *ieee_fc |=
1312 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1314 break;
1315 case BNX2X_FLOW_CTRL_TX:
1316 *ieee_fc |=
1317 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1318 break;
1320 case BNX2X_FLOW_CTRL_RX:
1321 case BNX2X_FLOW_CTRL_BOTH:
1322 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
1323 break;
1325 case BNX2X_FLOW_CTRL_NONE:
1326 default:
1327 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
1328 break;
1332 static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params,
1333 u32 ieee_fc)
1335 struct bnx2x *bp = params->bp;
1336 /* for AN, we are always publishing full duplex */
1338 CL45_WR_OVER_CL22(bp, params->port,
1339 params->phy_addr,
1340 MDIO_REG_BANK_COMBO_IEEE0,
1341 MDIO_COMBO_IEEE0_AUTO_NEG_ADV, (u16)ieee_fc);
1344 static void bnx2x_restart_autoneg(struct link_params *params)
1346 struct bnx2x *bp = params->bp;
1347 DP(NETIF_MSG_LINK, "bnx2x_restart_autoneg\n");
1348 if (SUPPORT_CL73) {
1349 /* enable and restart clause 73 aneg */
1350 u16 an_ctrl;
1352 CL45_RD_OVER_CL22(bp, params->port,
1353 params->phy_addr,
1354 MDIO_REG_BANK_CL73_IEEEB0,
1355 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1356 &an_ctrl);
1357 CL45_WR_OVER_CL22(bp, params->port,
1358 params->phy_addr,
1359 MDIO_REG_BANK_CL73_IEEEB0,
1360 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1361 (an_ctrl |
1362 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
1363 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
1365 } else {
1366 /* Enable and restart BAM/CL37 aneg */
1367 u16 mii_control;
1369 CL45_RD_OVER_CL22(bp, params->port,
1370 params->phy_addr,
1371 MDIO_REG_BANK_COMBO_IEEE0,
1372 MDIO_COMBO_IEEE0_MII_CONTROL,
1373 &mii_control);
1374 DP(NETIF_MSG_LINK,
1375 "bnx2x_restart_autoneg mii_control before = 0x%x\n",
1376 mii_control);
1377 CL45_WR_OVER_CL22(bp, params->port,
1378 params->phy_addr,
1379 MDIO_REG_BANK_COMBO_IEEE0,
1380 MDIO_COMBO_IEEE0_MII_CONTROL,
1381 (mii_control |
1382 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1383 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
1387 static void bnx2x_initialize_sgmii_process(struct link_params *params,
1388 struct link_vars *vars)
1390 struct bnx2x *bp = params->bp;
1391 u16 control1;
1393 /* in SGMII mode, the unicore is always slave */
1395 CL45_RD_OVER_CL22(bp, params->port,
1396 params->phy_addr,
1397 MDIO_REG_BANK_SERDES_DIGITAL,
1398 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1399 &control1);
1400 control1 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT;
1401 /* set sgmii mode (and not fiber) */
1402 control1 &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE |
1403 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET |
1404 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE);
1405 CL45_WR_OVER_CL22(bp, params->port,
1406 params->phy_addr,
1407 MDIO_REG_BANK_SERDES_DIGITAL,
1408 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1409 control1);
1411 /* if forced speed */
1412 if (!(vars->line_speed == SPEED_AUTO_NEG)) {
1413 /* set speed, disable autoneg */
1414 u16 mii_control;
1416 CL45_RD_OVER_CL22(bp, params->port,
1417 params->phy_addr,
1418 MDIO_REG_BANK_COMBO_IEEE0,
1419 MDIO_COMBO_IEEE0_MII_CONTROL,
1420 &mii_control);
1421 mii_control &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1422 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK|
1423 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX);
1425 switch (vars->line_speed) {
1426 case SPEED_100:
1427 mii_control |=
1428 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100;
1429 break;
1430 case SPEED_1000:
1431 mii_control |=
1432 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_1000;
1433 break;
1434 case SPEED_10:
1435 /* there is nothing to set for 10M */
1436 break;
1437 default:
1438 /* invalid speed for SGMII */
1439 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
1440 vars->line_speed);
1441 break;
1444 /* setting the full duplex */
1445 if (params->req_duplex == DUPLEX_FULL)
1446 mii_control |=
1447 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
1448 CL45_WR_OVER_CL22(bp, params->port,
1449 params->phy_addr,
1450 MDIO_REG_BANK_COMBO_IEEE0,
1451 MDIO_COMBO_IEEE0_MII_CONTROL,
1452 mii_control);
1454 } else { /* AN mode */
1455 /* enable and restart AN */
1456 bnx2x_restart_autoneg(params);
1462 * link management
1465 static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
1466 { /* LD LP */
1467 switch (pause_result) { /* ASYM P ASYM P */
1468 case 0xb: /* 1 0 1 1 */
1469 vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
1470 break;
1472 case 0xe: /* 1 1 1 0 */
1473 vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
1474 break;
1476 case 0x5: /* 0 1 0 1 */
1477 case 0x7: /* 0 1 1 1 */
1478 case 0xd: /* 1 1 0 1 */
1479 case 0xf: /* 1 1 1 1 */
1480 vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
1481 break;
1483 default:
1484 break;
1488 static u8 bnx2x_ext_phy_resove_fc(struct link_params *params,
1489 struct link_vars *vars)
1491 struct bnx2x *bp = params->bp;
1492 u8 ext_phy_addr;
1493 u16 ld_pause; /* local */
1494 u16 lp_pause; /* link partner */
1495 u16 an_complete; /* AN complete */
1496 u16 pause_result;
1497 u8 ret = 0;
1498 u32 ext_phy_type;
1499 u8 port = params->port;
1500 ext_phy_addr = ((params->ext_phy_config &
1501 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1502 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1504 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1505 /* read twice */
1507 bnx2x_cl45_read(bp, port,
1508 ext_phy_type,
1509 ext_phy_addr,
1510 MDIO_AN_DEVAD,
1511 MDIO_AN_REG_STATUS, &an_complete);
1512 bnx2x_cl45_read(bp, port,
1513 ext_phy_type,
1514 ext_phy_addr,
1515 MDIO_AN_DEVAD,
1516 MDIO_AN_REG_STATUS, &an_complete);
1518 if (an_complete & MDIO_AN_REG_STATUS_AN_COMPLETE) {
1519 ret = 1;
1520 bnx2x_cl45_read(bp, port,
1521 ext_phy_type,
1522 ext_phy_addr,
1523 MDIO_AN_DEVAD,
1524 MDIO_AN_REG_ADV_PAUSE, &ld_pause);
1525 bnx2x_cl45_read(bp, port,
1526 ext_phy_type,
1527 ext_phy_addr,
1528 MDIO_AN_DEVAD,
1529 MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
1530 pause_result = (ld_pause &
1531 MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
1532 pause_result |= (lp_pause &
1533 MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
1534 DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x \n",
1535 pause_result);
1536 bnx2x_pause_resolve(vars, pause_result);
1537 if (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE &&
1538 ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
1539 bnx2x_cl45_read(bp, port,
1540 ext_phy_type,
1541 ext_phy_addr,
1542 MDIO_AN_DEVAD,
1543 MDIO_AN_REG_CL37_FC_LD, &ld_pause);
1545 bnx2x_cl45_read(bp, port,
1546 ext_phy_type,
1547 ext_phy_addr,
1548 MDIO_AN_DEVAD,
1549 MDIO_AN_REG_CL37_FC_LP, &lp_pause);
1550 pause_result = (ld_pause &
1551 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
1552 pause_result |= (lp_pause &
1553 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
1555 bnx2x_pause_resolve(vars, pause_result);
1556 DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x \n",
1557 pause_result);
1560 return ret;
1564 static void bnx2x_flow_ctrl_resolve(struct link_params *params,
1565 struct link_vars *vars,
1566 u32 gp_status)
1568 struct bnx2x *bp = params->bp;
1569 u16 ld_pause; /* local driver */
1570 u16 lp_pause; /* link partner */
1571 u16 pause_result;
1573 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
1575 /* resolve from gp_status in case of AN complete and not sgmii */
1576 if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
1577 (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
1578 (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
1579 (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1580 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) {
1581 CL45_RD_OVER_CL22(bp, params->port,
1582 params->phy_addr,
1583 MDIO_REG_BANK_COMBO_IEEE0,
1584 MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
1585 &ld_pause);
1586 CL45_RD_OVER_CL22(bp, params->port,
1587 params->phy_addr,
1588 MDIO_REG_BANK_COMBO_IEEE0,
1589 MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
1590 &lp_pause);
1591 pause_result = (ld_pause &
1592 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
1593 pause_result |= (lp_pause &
1594 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
1595 DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result);
1596 bnx2x_pause_resolve(vars, pause_result);
1597 } else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
1598 (bnx2x_ext_phy_resove_fc(params, vars))) {
1599 return;
1600 } else {
1601 if (params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
1602 vars->flow_ctrl = params->req_fc_auto_adv;
1603 else
1604 vars->flow_ctrl = params->req_flow_ctrl;
1606 DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
1610 static u8 bnx2x_link_settings_status(struct link_params *params,
1611 struct link_vars *vars,
1612 u32 gp_status)
1614 struct bnx2x *bp = params->bp;
1615 u16 new_line_speed;
1616 u8 rc = 0;
1617 vars->link_status = 0;
1619 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
1620 DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
1621 gp_status);
1623 vars->phy_link_up = 1;
1624 vars->link_status |= LINK_STATUS_LINK_UP;
1626 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
1627 vars->duplex = DUPLEX_FULL;
1628 else
1629 vars->duplex = DUPLEX_HALF;
1631 bnx2x_flow_ctrl_resolve(params, vars, gp_status);
1633 switch (gp_status & GP_STATUS_SPEED_MASK) {
1634 case GP_STATUS_10M:
1635 new_line_speed = SPEED_10;
1636 if (vars->duplex == DUPLEX_FULL)
1637 vars->link_status |= LINK_10TFD;
1638 else
1639 vars->link_status |= LINK_10THD;
1640 break;
1642 case GP_STATUS_100M:
1643 new_line_speed = SPEED_100;
1644 if (vars->duplex == DUPLEX_FULL)
1645 vars->link_status |= LINK_100TXFD;
1646 else
1647 vars->link_status |= LINK_100TXHD;
1648 break;
1650 case GP_STATUS_1G:
1651 case GP_STATUS_1G_KX:
1652 new_line_speed = SPEED_1000;
1653 if (vars->duplex == DUPLEX_FULL)
1654 vars->link_status |= LINK_1000TFD;
1655 else
1656 vars->link_status |= LINK_1000THD;
1657 break;
1659 case GP_STATUS_2_5G:
1660 new_line_speed = SPEED_2500;
1661 if (vars->duplex == DUPLEX_FULL)
1662 vars->link_status |= LINK_2500TFD;
1663 else
1664 vars->link_status |= LINK_2500THD;
1665 break;
1667 case GP_STATUS_5G:
1668 case GP_STATUS_6G:
1669 DP(NETIF_MSG_LINK,
1670 "link speed unsupported gp_status 0x%x\n",
1671 gp_status);
1672 return -EINVAL;
1673 break;
1674 case GP_STATUS_10G_KX4:
1675 case GP_STATUS_10G_HIG:
1676 case GP_STATUS_10G_CX4:
1677 new_line_speed = SPEED_10000;
1678 vars->link_status |= LINK_10GTFD;
1679 break;
1681 case GP_STATUS_12G_HIG:
1682 new_line_speed = SPEED_12000;
1683 vars->link_status |= LINK_12GTFD;
1684 break;
1686 case GP_STATUS_12_5G:
1687 new_line_speed = SPEED_12500;
1688 vars->link_status |= LINK_12_5GTFD;
1689 break;
1691 case GP_STATUS_13G:
1692 new_line_speed = SPEED_13000;
1693 vars->link_status |= LINK_13GTFD;
1694 break;
1696 case GP_STATUS_15G:
1697 new_line_speed = SPEED_15000;
1698 vars->link_status |= LINK_15GTFD;
1699 break;
1701 case GP_STATUS_16G:
1702 new_line_speed = SPEED_16000;
1703 vars->link_status |= LINK_16GTFD;
1704 break;
1706 default:
1707 DP(NETIF_MSG_LINK,
1708 "link speed unsupported gp_status 0x%x\n",
1709 gp_status);
1710 return -EINVAL;
1711 break;
1714 /* Upon link speed change set the NIG into drain mode.
1715 Comes to deals with possible FIFO glitch due to clk change
1716 when speed is decreased without link down indicator */
1717 if (new_line_speed != vars->line_speed) {
1718 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
1719 + params->port*4, 0);
1720 msleep(1);
1722 vars->line_speed = new_line_speed;
1723 vars->link_status |= LINK_STATUS_SERDES_LINK;
1725 if ((params->req_line_speed == SPEED_AUTO_NEG) &&
1726 ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1727 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
1728 (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1729 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705))) {
1730 vars->autoneg = AUTO_NEG_ENABLED;
1732 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
1733 vars->autoneg |= AUTO_NEG_COMPLETE;
1734 vars->link_status |=
1735 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
1738 vars->autoneg |= AUTO_NEG_PARALLEL_DETECTION_USED;
1739 vars->link_status |=
1740 LINK_STATUS_PARALLEL_DETECTION_USED;
1743 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
1744 vars->link_status |=
1745 LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
1747 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
1748 vars->link_status |=
1749 LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
1751 } else { /* link_down */
1752 DP(NETIF_MSG_LINK, "phy link down\n");
1754 vars->phy_link_up = 0;
1756 vars->duplex = DUPLEX_FULL;
1757 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
1758 vars->autoneg = AUTO_NEG_DISABLED;
1759 vars->mac_type = MAC_TYPE_NONE;
1762 DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x \n",
1763 gp_status, vars->phy_link_up, vars->line_speed);
1764 DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x"
1765 " autoneg 0x%x\n",
1766 vars->duplex,
1767 vars->flow_ctrl, vars->autoneg);
1768 DP(NETIF_MSG_LINK, "link_status 0x%x\n", vars->link_status);
1770 return rc;
1773 static void bnx2x_set_sgmii_tx_driver(struct link_params *params)
1775 struct bnx2x *bp = params->bp;
1776 u16 lp_up2;
1777 u16 tx_driver;
1779 /* read precomp */
1781 CL45_RD_OVER_CL22(bp, params->port,
1782 params->phy_addr,
1783 MDIO_REG_BANK_OVER_1G,
1784 MDIO_OVER_1G_LP_UP2, &lp_up2);
1786 CL45_RD_OVER_CL22(bp, params->port,
1787 params->phy_addr,
1788 MDIO_REG_BANK_TX0,
1789 MDIO_TX0_TX_DRIVER, &tx_driver);
1791 /* bits [10:7] at lp_up2, positioned at [15:12] */
1792 lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >>
1793 MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT) <<
1794 MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT);
1796 if ((lp_up2 != 0) &&
1797 (lp_up2 != (tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK))) {
1798 /* replace tx_driver bits [15:12] */
1799 tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
1800 tx_driver |= lp_up2;
1801 CL45_WR_OVER_CL22(bp, params->port,
1802 params->phy_addr,
1803 MDIO_REG_BANK_TX0,
1804 MDIO_TX0_TX_DRIVER, tx_driver);
1808 static u8 bnx2x_emac_program(struct link_params *params,
1809 u32 line_speed, u32 duplex)
1811 struct bnx2x *bp = params->bp;
1812 u8 port = params->port;
1813 u16 mode = 0;
1815 DP(NETIF_MSG_LINK, "setting link speed & duplex\n");
1816 bnx2x_bits_dis(bp, GRCBASE_EMAC0 + port*0x400 +
1817 EMAC_REG_EMAC_MODE,
1818 (EMAC_MODE_25G_MODE |
1819 EMAC_MODE_PORT_MII_10M |
1820 EMAC_MODE_HALF_DUPLEX));
1821 switch (line_speed) {
1822 case SPEED_10:
1823 mode |= EMAC_MODE_PORT_MII_10M;
1824 break;
1826 case SPEED_100:
1827 mode |= EMAC_MODE_PORT_MII;
1828 break;
1830 case SPEED_1000:
1831 mode |= EMAC_MODE_PORT_GMII;
1832 break;
1834 case SPEED_2500:
1835 mode |= (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_GMII);
1836 break;
1838 default:
1839 /* 10G not valid for EMAC */
1840 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n", line_speed);
1841 return -EINVAL;
1844 if (duplex == DUPLEX_HALF)
1845 mode |= EMAC_MODE_HALF_DUPLEX;
1846 bnx2x_bits_en(bp,
1847 GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
1848 mode);
1850 bnx2x_set_led(bp, params->port, LED_MODE_OPER,
1851 line_speed, params->hw_led_mode, params->chip_id);
1852 return 0;
1855 /*****************************************************************************/
1856 /* External Phy section */
1857 /*****************************************************************************/
1858 static void bnx2x_hw_reset(struct bnx2x *bp, u8 port)
1860 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1861 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
1862 msleep(1);
1863 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1864 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
1867 static void bnx2x_ext_phy_reset(struct link_params *params,
1868 struct link_vars *vars)
1870 struct bnx2x *bp = params->bp;
1871 u32 ext_phy_type;
1872 u8 ext_phy_addr = ((params->ext_phy_config &
1873 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1874 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1875 DP(NETIF_MSG_LINK, "Port %x: bnx2x_ext_phy_reset\n", params->port);
1876 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1877 /* The PHY reset is controled by GPIO 1
1878 * Give it 1ms of reset pulse
1880 if (vars->phy_flags & PHY_XGXS_FLAG) {
1882 switch (ext_phy_type) {
1883 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
1884 DP(NETIF_MSG_LINK, "XGXS Direct\n");
1885 break;
1887 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
1888 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
1889 DP(NETIF_MSG_LINK, "XGXS 8705/8706\n");
1891 /* Restore normal power mode*/
1892 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1893 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1894 params->port);
1896 /* HW reset */
1897 bnx2x_hw_reset(bp, params->port);
1899 bnx2x_cl45_write(bp, params->port,
1900 ext_phy_type,
1901 ext_phy_addr,
1902 MDIO_PMA_DEVAD,
1903 MDIO_PMA_REG_CTRL, 0xa040);
1904 break;
1905 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
1906 /* Unset Low Power Mode and SW reset */
1907 /* Restore normal power mode*/
1908 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1909 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1910 params->port);
1912 DP(NETIF_MSG_LINK, "XGXS 8072\n");
1913 bnx2x_cl45_write(bp, params->port,
1914 ext_phy_type,
1915 ext_phy_addr,
1916 MDIO_PMA_DEVAD,
1917 MDIO_PMA_REG_CTRL,
1918 1<<15);
1919 break;
1920 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
1922 u16 emac_base;
1923 emac_base = (params->port) ? GRCBASE_EMAC0 :
1924 GRCBASE_EMAC1;
1926 /* Restore normal power mode*/
1927 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1928 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1929 params->port);
1931 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1932 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1933 params->port);
1935 DP(NETIF_MSG_LINK, "XGXS 8073\n");
1937 break;
1939 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
1940 DP(NETIF_MSG_LINK, "XGXS SFX7101\n");
1942 /* Restore normal power mode*/
1943 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1944 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1945 params->port);
1947 /* HW reset */
1948 bnx2x_hw_reset(bp, params->port);
1950 break;
1952 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
1953 DP(NETIF_MSG_LINK, "XGXS PHY Failure detected\n");
1954 break;
1956 default:
1957 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
1958 params->ext_phy_config);
1959 break;
1962 } else { /* SerDes */
1963 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
1964 switch (ext_phy_type) {
1965 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
1966 DP(NETIF_MSG_LINK, "SerDes Direct\n");
1967 break;
1969 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
1970 DP(NETIF_MSG_LINK, "SerDes 5482\n");
1971 bnx2x_hw_reset(bp, params->port);
1972 break;
1974 default:
1975 DP(NETIF_MSG_LINK,
1976 "BAD SerDes ext_phy_config 0x%x\n",
1977 params->ext_phy_config);
1978 break;
1983 static void bnx2x_bcm8072_external_rom_boot(struct link_params *params)
1985 struct bnx2x *bp = params->bp;
1986 u8 port = params->port;
1987 u8 ext_phy_addr = ((params->ext_phy_config &
1988 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1989 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1990 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1991 u16 fw_ver1, fw_ver2;
1993 /* Need to wait 200ms after reset */
1994 msleep(200);
1995 /* Boot port from external ROM
1996 * Set ser_boot_ctl bit in the MISC_CTRL1 register
1998 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1999 MDIO_PMA_DEVAD,
2000 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
2002 /* Reset internal microprocessor */
2003 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2004 MDIO_PMA_DEVAD,
2005 MDIO_PMA_REG_GEN_CTRL,
2006 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2007 /* set micro reset = 0 */
2008 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2009 MDIO_PMA_DEVAD,
2010 MDIO_PMA_REG_GEN_CTRL,
2011 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
2012 /* Reset internal microprocessor */
2013 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2014 MDIO_PMA_DEVAD,
2015 MDIO_PMA_REG_GEN_CTRL,
2016 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2017 /* wait for 100ms for code download via SPI port */
2018 msleep(100);
2020 /* Clear ser_boot_ctl bit */
2021 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2022 MDIO_PMA_DEVAD,
2023 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2024 /* Wait 100ms */
2025 msleep(100);
2027 /* Print the PHY FW version */
2028 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2029 MDIO_PMA_DEVAD,
2030 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
2031 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2032 MDIO_PMA_DEVAD,
2033 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
2034 DP(NETIF_MSG_LINK, "8072 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
2037 static u8 bnx2x_8073_is_snr_needed(struct link_params *params)
2039 /* This is only required for 8073A1, version 102 only */
2041 struct bnx2x *bp = params->bp;
2042 u8 ext_phy_addr = ((params->ext_phy_config &
2043 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2044 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2045 u16 val;
2047 /* Read 8073 HW revision*/
2048 bnx2x_cl45_read(bp, params->port,
2049 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2050 ext_phy_addr,
2051 MDIO_PMA_DEVAD,
2052 0xc801, &val);
2054 if (val != 1) {
2055 /* No need to workaround in 8073 A1 */
2056 return 0;
2059 bnx2x_cl45_read(bp, params->port,
2060 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2061 ext_phy_addr,
2062 MDIO_PMA_DEVAD,
2063 MDIO_PMA_REG_ROM_VER2, &val);
2065 /* SNR should be applied only for version 0x102 */
2066 if (val != 0x102)
2067 return 0;
2069 return 1;
2072 static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
2074 struct bnx2x *bp = params->bp;
2075 u8 ext_phy_addr = ((params->ext_phy_config &
2076 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2077 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2078 u16 val, cnt, cnt1 ;
2080 bnx2x_cl45_read(bp, params->port,
2081 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2082 ext_phy_addr,
2083 MDIO_PMA_DEVAD,
2084 0xc801, &val);
2086 if (val > 0) {
2087 /* No need to workaround in 8073 A1 */
2088 return 0;
2090 /* XAUI workaround in 8073 A0: */
2092 /* After loading the boot ROM and restarting Autoneg,
2093 poll Dev1, Reg $C820: */
2095 for (cnt = 0; cnt < 1000; cnt++) {
2096 bnx2x_cl45_read(bp, params->port,
2097 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2098 ext_phy_addr,
2099 MDIO_PMA_DEVAD,
2100 0xc820, &val);
2101 /* If bit [14] = 0 or bit [13] = 0, continue on with
2102 system initialization (XAUI work-around not required,
2103 as these bits indicate 2.5G or 1G link up). */
2104 if (!(val & (1<<14)) || !(val & (1<<13))) {
2105 DP(NETIF_MSG_LINK, "XAUI work-around not required\n");
2106 return 0;
2107 } else if (!(val & (1<<15))) {
2108 DP(NETIF_MSG_LINK, "clc bit 15 went off\n");
2109 /* If bit 15 is 0, then poll Dev1, Reg $C841 until
2110 it's MSB (bit 15) goes to 1 (indicating that the
2111 XAUI workaround has completed),
2112 then continue on with system initialization.*/
2113 for (cnt1 = 0; cnt1 < 1000; cnt1++) {
2114 bnx2x_cl45_read(bp, params->port,
2115 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2116 ext_phy_addr,
2117 MDIO_PMA_DEVAD,
2118 0xc841, &val);
2119 if (val & (1<<15)) {
2120 DP(NETIF_MSG_LINK,
2121 "XAUI workaround has completed\n");
2122 return 0;
2124 msleep(3);
2126 break;
2128 msleep(3);
2130 DP(NETIF_MSG_LINK, "Warning: XAUI work-around timeout !!!\n");
2131 return -EINVAL;
2135 static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
2136 u8 ext_phy_addr)
2138 u16 fw_ver1, fw_ver2;
2139 /* Boot port from external ROM */
2140 /* EDC grst */
2141 bnx2x_cl45_write(bp, port,
2142 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2143 ext_phy_addr,
2144 MDIO_PMA_DEVAD,
2145 MDIO_PMA_REG_GEN_CTRL,
2146 0x0001);
2148 /* ucode reboot and rst */
2149 bnx2x_cl45_write(bp, port,
2150 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2151 ext_phy_addr,
2152 MDIO_PMA_DEVAD,
2153 MDIO_PMA_REG_GEN_CTRL,
2154 0x008c);
2156 bnx2x_cl45_write(bp, port,
2157 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2158 ext_phy_addr,
2159 MDIO_PMA_DEVAD,
2160 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
2162 /* Reset internal microprocessor */
2163 bnx2x_cl45_write(bp, port,
2164 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2165 ext_phy_addr,
2166 MDIO_PMA_DEVAD,
2167 MDIO_PMA_REG_GEN_CTRL,
2168 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
2170 /* Release srst bit */
2171 bnx2x_cl45_write(bp, port,
2172 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2173 ext_phy_addr,
2174 MDIO_PMA_DEVAD,
2175 MDIO_PMA_REG_GEN_CTRL,
2176 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2178 /* wait for 100ms for code download via SPI port */
2179 msleep(100);
2181 /* Clear ser_boot_ctl bit */
2182 bnx2x_cl45_write(bp, port,
2183 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2184 ext_phy_addr,
2185 MDIO_PMA_DEVAD,
2186 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2188 bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2189 ext_phy_addr,
2190 MDIO_PMA_DEVAD,
2191 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
2192 bnx2x_cl45_read(bp, port,
2193 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2194 ext_phy_addr,
2195 MDIO_PMA_DEVAD,
2196 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
2197 DP(NETIF_MSG_LINK, "8073 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
2201 static void bnx2x_bcm807x_force_10G(struct link_params *params)
2203 struct bnx2x *bp = params->bp;
2204 u8 port = params->port;
2205 u8 ext_phy_addr = ((params->ext_phy_config &
2206 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2207 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2208 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2210 /* Force KR or KX */
2211 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2212 MDIO_PMA_DEVAD,
2213 MDIO_PMA_REG_CTRL,
2214 0x2040);
2215 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2216 MDIO_PMA_DEVAD,
2217 MDIO_PMA_REG_10G_CTRL2,
2218 0x000b);
2219 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2220 MDIO_PMA_DEVAD,
2221 MDIO_PMA_REG_BCM_CTRL,
2222 0x0000);
2223 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2224 MDIO_AN_DEVAD,
2225 MDIO_AN_REG_CTRL,
2226 0x0000);
2228 static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
2230 struct bnx2x *bp = params->bp;
2231 u8 port = params->port;
2232 u16 val;
2233 u8 ext_phy_addr = ((params->ext_phy_config &
2234 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2235 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2236 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2238 bnx2x_cl45_read(bp, params->port,
2239 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2240 ext_phy_addr,
2241 MDIO_PMA_DEVAD,
2242 0xc801, &val);
2244 if (val == 0) {
2245 /* Mustn't set low power mode in 8073 A0 */
2246 return;
2249 /* Disable PLL sequencer (use read-modify-write to clear bit 13) */
2250 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2251 MDIO_XS_DEVAD,
2252 MDIO_XS_PLL_SEQUENCER, &val);
2253 val &= ~(1<<13);
2254 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2255 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
2257 /* PLL controls */
2258 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2259 MDIO_XS_DEVAD, 0x805E, 0x1077);
2260 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2261 MDIO_XS_DEVAD, 0x805D, 0x0000);
2262 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2263 MDIO_XS_DEVAD, 0x805C, 0x030B);
2264 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2265 MDIO_XS_DEVAD, 0x805B, 0x1240);
2266 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2267 MDIO_XS_DEVAD, 0x805A, 0x2490);
2269 /* Tx Controls */
2270 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2271 MDIO_XS_DEVAD, 0x80A7, 0x0C74);
2272 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2273 MDIO_XS_DEVAD, 0x80A6, 0x9041);
2274 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2275 MDIO_XS_DEVAD, 0x80A5, 0x4640);
2277 /* Rx Controls */
2278 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2279 MDIO_XS_DEVAD, 0x80FE, 0x01C4);
2280 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2281 MDIO_XS_DEVAD, 0x80FD, 0x9249);
2282 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2283 MDIO_XS_DEVAD, 0x80FC, 0x2015);
2285 /* Enable PLL sequencer (use read-modify-write to set bit 13) */
2286 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2287 MDIO_XS_DEVAD,
2288 MDIO_XS_PLL_SEQUENCER, &val);
2289 val |= (1<<13);
2290 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2291 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
2294 static void bnx2x_8073_set_pause_cl37(struct link_params *params,
2295 struct link_vars *vars)
2298 struct bnx2x *bp = params->bp;
2299 u16 cl37_val;
2300 u8 ext_phy_addr = ((params->ext_phy_config &
2301 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2302 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2303 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2305 bnx2x_cl45_read(bp, params->port,
2306 ext_phy_type,
2307 ext_phy_addr,
2308 MDIO_AN_DEVAD,
2309 MDIO_AN_REG_CL37_FC_LD, &cl37_val);
2311 cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
2312 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
2314 if ((vars->ieee_fc &
2315 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
2316 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
2317 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
2319 if ((vars->ieee_fc &
2320 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
2321 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
2322 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
2324 if ((vars->ieee_fc &
2325 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
2326 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
2327 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
2329 DP(NETIF_MSG_LINK,
2330 "Ext phy AN advertize cl37 0x%x\n", cl37_val);
2332 bnx2x_cl45_write(bp, params->port,
2333 ext_phy_type,
2334 ext_phy_addr,
2335 MDIO_AN_DEVAD,
2336 MDIO_AN_REG_CL37_FC_LD, cl37_val);
2337 msleep(500);
2340 static void bnx2x_ext_phy_set_pause(struct link_params *params,
2341 struct link_vars *vars)
2343 struct bnx2x *bp = params->bp;
2344 u16 val;
2345 u8 ext_phy_addr = ((params->ext_phy_config &
2346 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2347 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2348 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2350 /* read modify write pause advertizing */
2351 bnx2x_cl45_read(bp, params->port,
2352 ext_phy_type,
2353 ext_phy_addr,
2354 MDIO_AN_DEVAD,
2355 MDIO_AN_REG_ADV_PAUSE, &val);
2357 val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
2359 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
2361 if ((vars->ieee_fc &
2362 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
2363 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
2364 val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
2366 if ((vars->ieee_fc &
2367 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
2368 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
2369 val |=
2370 MDIO_AN_REG_ADV_PAUSE_PAUSE;
2372 DP(NETIF_MSG_LINK,
2373 "Ext phy AN advertize 0x%x\n", val);
2374 bnx2x_cl45_write(bp, params->port,
2375 ext_phy_type,
2376 ext_phy_addr,
2377 MDIO_AN_DEVAD,
2378 MDIO_AN_REG_ADV_PAUSE, val);
2382 static void bnx2x_init_internal_phy(struct link_params *params,
2383 struct link_vars *vars)
2385 struct bnx2x *bp = params->bp;
2386 u8 port = params->port;
2387 if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
2388 u16 bank, rx_eq;
2390 rx_eq = ((params->serdes_config &
2391 PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK) >>
2392 PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT);
2394 DP(NETIF_MSG_LINK, "setting rx eq to 0x%x\n", rx_eq);
2395 for (bank = MDIO_REG_BANK_RX0; bank <= MDIO_REG_BANK_RX_ALL;
2396 bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0)) {
2397 CL45_WR_OVER_CL22(bp, port,
2398 params->phy_addr,
2399 bank ,
2400 MDIO_RX0_RX_EQ_BOOST,
2401 ((rx_eq &
2402 MDIO_RX0_RX_EQ_BOOST_EQUALIZER_CTRL_MASK) |
2403 MDIO_RX0_RX_EQ_BOOST_OFFSET_CTRL));
2406 /* forced speed requested? */
2407 if (vars->line_speed != SPEED_AUTO_NEG) {
2408 DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
2410 /* disable autoneg */
2411 bnx2x_set_autoneg(params, vars);
2413 /* program speed and duplex */
2414 bnx2x_program_serdes(params, vars);
2416 } else { /* AN_mode */
2417 DP(NETIF_MSG_LINK, "not SGMII, AN\n");
2419 /* AN enabled */
2420 bnx2x_set_brcm_cl37_advertisment(params);
2422 /* program duplex & pause advertisement (for aneg) */
2423 bnx2x_set_ieee_aneg_advertisment(params,
2424 vars->ieee_fc);
2426 /* enable autoneg */
2427 bnx2x_set_autoneg(params, vars);
2429 /* enable and restart AN */
2430 bnx2x_restart_autoneg(params);
2433 } else { /* SGMII mode */
2434 DP(NETIF_MSG_LINK, "SGMII\n");
2436 bnx2x_initialize_sgmii_process(params, vars);
2440 static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
2442 struct bnx2x *bp = params->bp;
2443 u32 ext_phy_type;
2444 u8 ext_phy_addr;
2445 u16 cnt;
2446 u16 ctrl = 0;
2447 u16 val = 0;
2448 u8 rc = 0;
2449 if (vars->phy_flags & PHY_XGXS_FLAG) {
2450 ext_phy_addr = ((params->ext_phy_config &
2451 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2452 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2454 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2455 /* Make sure that the soft reset is off (expect for the 8072:
2456 * due to the lock, it will be done inside the specific
2457 * handling)
2459 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
2460 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
2461 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) &&
2462 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
2463 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
2464 /* Wait for soft reset to get cleared upto 1 sec */
2465 for (cnt = 0; cnt < 1000; cnt++) {
2466 bnx2x_cl45_read(bp, params->port,
2467 ext_phy_type,
2468 ext_phy_addr,
2469 MDIO_PMA_DEVAD,
2470 MDIO_PMA_REG_CTRL, &ctrl);
2471 if (!(ctrl & (1<<15)))
2472 break;
2473 msleep(1);
2475 DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n",
2476 ctrl, cnt);
2479 switch (ext_phy_type) {
2480 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
2481 break;
2483 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2484 DP(NETIF_MSG_LINK, "XGXS 8705\n");
2486 bnx2x_cl45_write(bp, params->port,
2487 ext_phy_type,
2488 ext_phy_addr,
2489 MDIO_PMA_DEVAD,
2490 MDIO_PMA_REG_MISC_CTRL,
2491 0x8288);
2492 bnx2x_cl45_write(bp, params->port,
2493 ext_phy_type,
2494 ext_phy_addr,
2495 MDIO_PMA_DEVAD,
2496 MDIO_PMA_REG_PHY_IDENTIFIER,
2497 0x7fbf);
2498 bnx2x_cl45_write(bp, params->port,
2499 ext_phy_type,
2500 ext_phy_addr,
2501 MDIO_PMA_DEVAD,
2502 MDIO_PMA_REG_CMU_PLL_BYPASS,
2503 0x0100);
2504 bnx2x_cl45_write(bp, params->port,
2505 ext_phy_type,
2506 ext_phy_addr,
2507 MDIO_WIS_DEVAD,
2508 MDIO_WIS_REG_LASI_CNTL, 0x1);
2509 break;
2511 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2512 DP(NETIF_MSG_LINK, "XGXS 8706\n");
2514 msleep(10);
2515 /* Force speed */
2516 /* First enable LASI */
2517 bnx2x_cl45_write(bp, params->port,
2518 ext_phy_type,
2519 ext_phy_addr,
2520 MDIO_PMA_DEVAD,
2521 MDIO_PMA_REG_RX_ALARM_CTRL,
2522 0x0400);
2523 bnx2x_cl45_write(bp, params->port,
2524 ext_phy_type,
2525 ext_phy_addr,
2526 MDIO_PMA_DEVAD,
2527 MDIO_PMA_REG_LASI_CTRL, 0x0004);
2529 if (params->req_line_speed == SPEED_10000) {
2530 DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n");
2532 bnx2x_cl45_write(bp, params->port,
2533 ext_phy_type,
2534 ext_phy_addr,
2535 MDIO_PMA_DEVAD,
2536 MDIO_PMA_REG_DIGITAL_CTRL,
2537 0x400);
2538 } else {
2539 /* Force 1Gbps using autoneg with 1G
2540 advertisment */
2542 /* Allow CL37 through CL73 */
2543 DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
2544 bnx2x_cl45_write(bp, params->port,
2545 ext_phy_type,
2546 ext_phy_addr,
2547 MDIO_AN_DEVAD,
2548 MDIO_AN_REG_CL37_CL73,
2549 0x040c);
2551 /* Enable Full-Duplex advertisment on CL37 */
2552 bnx2x_cl45_write(bp, params->port,
2553 ext_phy_type,
2554 ext_phy_addr,
2555 MDIO_AN_DEVAD,
2556 MDIO_AN_REG_CL37_FC_LP,
2557 0x0020);
2558 /* Enable CL37 AN */
2559 bnx2x_cl45_write(bp, params->port,
2560 ext_phy_type,
2561 ext_phy_addr,
2562 MDIO_AN_DEVAD,
2563 MDIO_AN_REG_CL37_AN,
2564 0x1000);
2565 /* 1G support */
2566 bnx2x_cl45_write(bp, params->port,
2567 ext_phy_type,
2568 ext_phy_addr,
2569 MDIO_AN_DEVAD,
2570 MDIO_AN_REG_ADV, (1<<5));
2572 /* Enable clause 73 AN */
2573 bnx2x_cl45_write(bp, params->port,
2574 ext_phy_type,
2575 ext_phy_addr,
2576 MDIO_AN_DEVAD,
2577 MDIO_AN_REG_CTRL,
2578 0x1200);
2582 break;
2584 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2585 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2587 u16 tmp1;
2588 u16 rx_alarm_ctrl_val;
2589 u16 lasi_ctrl_val;
2590 if (ext_phy_type ==
2591 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
2592 rx_alarm_ctrl_val = 0x400;
2593 lasi_ctrl_val = 0x0004;
2594 } else {
2595 rx_alarm_ctrl_val = (1<<2);
2596 lasi_ctrl_val = 0x0004;
2599 /* enable LASI */
2600 bnx2x_cl45_write(bp, params->port,
2601 ext_phy_type,
2602 ext_phy_addr,
2603 MDIO_PMA_DEVAD,
2604 MDIO_PMA_REG_RX_ALARM_CTRL,
2605 rx_alarm_ctrl_val);
2607 bnx2x_cl45_write(bp, params->port,
2608 ext_phy_type,
2609 ext_phy_addr,
2610 MDIO_PMA_DEVAD,
2611 MDIO_PMA_REG_LASI_CTRL,
2612 lasi_ctrl_val);
2614 bnx2x_8073_set_pause_cl37(params, vars);
2616 if (ext_phy_type ==
2617 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072){
2618 bnx2x_bcm8072_external_rom_boot(params);
2619 } else {
2621 /* In case of 8073 with long xaui lines,
2622 don't set the 8073 xaui low power*/
2623 bnx2x_bcm8073_set_xaui_low_power_mode(params);
2626 bnx2x_cl45_read(bp, params->port,
2627 ext_phy_type,
2628 ext_phy_addr,
2629 MDIO_PMA_DEVAD,
2630 0xca13,
2631 &tmp1);
2633 bnx2x_cl45_read(bp, params->port,
2634 ext_phy_type,
2635 ext_phy_addr,
2636 MDIO_PMA_DEVAD,
2637 MDIO_PMA_REG_RX_ALARM, &tmp1);
2639 DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1):"
2640 "0x%x\n", tmp1);
2642 /* If this is forced speed, set to KR or KX
2643 * (all other are not supported)
2645 if (params->loopback_mode == LOOPBACK_EXT) {
2646 bnx2x_bcm807x_force_10G(params);
2647 DP(NETIF_MSG_LINK,
2648 "Forced speed 10G on 807X\n");
2649 break;
2650 } else {
2651 bnx2x_cl45_write(bp, params->port,
2652 ext_phy_type, ext_phy_addr,
2653 MDIO_PMA_DEVAD,
2654 MDIO_PMA_REG_BCM_CTRL,
2655 0x0002);
2657 if (params->req_line_speed != SPEED_AUTO_NEG) {
2658 if (params->req_line_speed == SPEED_10000) {
2659 val = (1<<7);
2660 } else if (params->req_line_speed ==
2661 SPEED_2500) {
2662 val = (1<<5);
2663 /* Note that 2.5G works only
2664 when used with 1G advertisment */
2665 } else
2666 val = (1<<5);
2667 } else {
2669 val = 0;
2670 if (params->speed_cap_mask &
2671 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
2672 val |= (1<<7);
2674 /* Note that 2.5G works only when
2675 used with 1G advertisment */
2676 if (params->speed_cap_mask &
2677 (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
2678 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
2679 val |= (1<<5);
2680 DP(NETIF_MSG_LINK,
2681 "807x autoneg val = 0x%x\n", val);
2684 bnx2x_cl45_write(bp, params->port,
2685 ext_phy_type,
2686 ext_phy_addr,
2687 MDIO_AN_DEVAD,
2688 MDIO_AN_REG_ADV, val);
2690 if (ext_phy_type ==
2691 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
2693 bnx2x_cl45_read(bp, params->port,
2694 ext_phy_type,
2695 ext_phy_addr,
2696 MDIO_AN_DEVAD,
2697 0x8329, &tmp1);
2699 if (((params->speed_cap_mask &
2700 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
2701 (params->req_line_speed ==
2702 SPEED_AUTO_NEG)) ||
2703 (params->req_line_speed ==
2704 SPEED_2500)) {
2705 u16 phy_ver;
2706 /* Allow 2.5G for A1 and above */
2707 bnx2x_cl45_read(bp, params->port,
2708 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2709 ext_phy_addr,
2710 MDIO_PMA_DEVAD,
2711 0xc801, &phy_ver);
2712 DP(NETIF_MSG_LINK, "Add 2.5G\n");
2713 if (phy_ver > 0)
2714 tmp1 |= 1;
2715 else
2716 tmp1 &= 0xfffe;
2717 } else {
2718 DP(NETIF_MSG_LINK, "Disable 2.5G\n");
2719 tmp1 &= 0xfffe;
2722 bnx2x_cl45_write(bp, params->port,
2723 ext_phy_type,
2724 ext_phy_addr,
2725 MDIO_AN_DEVAD,
2726 0x8329, tmp1);
2729 /* Add support for CL37 (passive mode) II */
2731 bnx2x_cl45_read(bp, params->port,
2732 ext_phy_type,
2733 ext_phy_addr,
2734 MDIO_AN_DEVAD,
2735 MDIO_AN_REG_CL37_FC_LD,
2736 &tmp1);
2738 bnx2x_cl45_write(bp, params->port,
2739 ext_phy_type,
2740 ext_phy_addr,
2741 MDIO_AN_DEVAD,
2742 MDIO_AN_REG_CL37_FC_LD, (tmp1 |
2743 ((params->req_duplex == DUPLEX_FULL) ?
2744 0x20 : 0x40)));
2746 /* Add support for CL37 (passive mode) III */
2747 bnx2x_cl45_write(bp, params->port,
2748 ext_phy_type,
2749 ext_phy_addr,
2750 MDIO_AN_DEVAD,
2751 MDIO_AN_REG_CL37_AN, 0x1000);
2753 if (ext_phy_type ==
2754 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
2755 /* The SNR will improve about 2db by changing
2756 BW and FEE main tap. Rest commands are executed
2757 after link is up*/
2758 /*Change FFE main cursor to 5 in EDC register*/
2759 if (bnx2x_8073_is_snr_needed(params))
2760 bnx2x_cl45_write(bp, params->port,
2761 ext_phy_type,
2762 ext_phy_addr,
2763 MDIO_PMA_DEVAD,
2764 MDIO_PMA_REG_EDC_FFE_MAIN,
2765 0xFB0C);
2767 /* Enable FEC (Forware Error Correction)
2768 Request in the AN */
2769 bnx2x_cl45_read(bp, params->port,
2770 ext_phy_type,
2771 ext_phy_addr,
2772 MDIO_AN_DEVAD,
2773 MDIO_AN_REG_ADV2, &tmp1);
2775 tmp1 |= (1<<15);
2777 bnx2x_cl45_write(bp, params->port,
2778 ext_phy_type,
2779 ext_phy_addr,
2780 MDIO_AN_DEVAD,
2781 MDIO_AN_REG_ADV2, tmp1);
2785 bnx2x_ext_phy_set_pause(params, vars);
2787 /* Restart autoneg */
2788 msleep(500);
2789 bnx2x_cl45_write(bp, params->port,
2790 ext_phy_type,
2791 ext_phy_addr,
2792 MDIO_AN_DEVAD,
2793 MDIO_AN_REG_CTRL, 0x1200);
2794 DP(NETIF_MSG_LINK, "807x Autoneg Restart: "
2795 "Advertise 1G=%x, 10G=%x\n",
2796 ((val & (1<<5)) > 0),
2797 ((val & (1<<7)) > 0));
2798 break;
2800 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
2801 DP(NETIF_MSG_LINK,
2802 "Setting the SFX7101 LASI indication\n");
2804 bnx2x_cl45_write(bp, params->port,
2805 ext_phy_type,
2806 ext_phy_addr,
2807 MDIO_PMA_DEVAD,
2808 MDIO_PMA_REG_LASI_CTRL, 0x1);
2809 DP(NETIF_MSG_LINK,
2810 "Setting the SFX7101 LED to blink on traffic\n");
2811 bnx2x_cl45_write(bp, params->port,
2812 ext_phy_type,
2813 ext_phy_addr,
2814 MDIO_PMA_DEVAD,
2815 MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
2817 bnx2x_ext_phy_set_pause(params, vars);
2818 /* Restart autoneg */
2819 bnx2x_cl45_read(bp, params->port,
2820 ext_phy_type,
2821 ext_phy_addr,
2822 MDIO_AN_DEVAD,
2823 MDIO_AN_REG_CTRL, &val);
2824 val |= 0x200;
2825 bnx2x_cl45_write(bp, params->port,
2826 ext_phy_type,
2827 ext_phy_addr,
2828 MDIO_AN_DEVAD,
2829 MDIO_AN_REG_CTRL, val);
2830 break;
2831 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
2832 DP(NETIF_MSG_LINK,
2833 "XGXS PHY Failure detected 0x%x\n",
2834 params->ext_phy_config);
2835 rc = -EINVAL;
2836 break;
2837 default:
2838 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
2839 params->ext_phy_config);
2840 rc = -EINVAL;
2841 break;
2844 } else { /* SerDes */
2846 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
2847 switch (ext_phy_type) {
2848 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
2849 DP(NETIF_MSG_LINK, "SerDes Direct\n");
2850 break;
2852 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
2853 DP(NETIF_MSG_LINK, "SerDes 5482\n");
2854 break;
2856 default:
2857 DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
2858 params->ext_phy_config);
2859 break;
2862 return rc;
2866 static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
2867 struct link_vars *vars)
2869 struct bnx2x *bp = params->bp;
2870 u32 ext_phy_type;
2871 u8 ext_phy_addr;
2872 u16 val1 = 0, val2;
2873 u16 rx_sd, pcs_status;
2874 u8 ext_phy_link_up = 0;
2875 u8 port = params->port;
2876 if (vars->phy_flags & PHY_XGXS_FLAG) {
2877 ext_phy_addr = ((params->ext_phy_config &
2878 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2879 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2881 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2882 switch (ext_phy_type) {
2883 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
2884 DP(NETIF_MSG_LINK, "XGXS Direct\n");
2885 ext_phy_link_up = 1;
2886 break;
2888 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2889 DP(NETIF_MSG_LINK, "XGXS 8705\n");
2890 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2891 ext_phy_addr,
2892 MDIO_WIS_DEVAD,
2893 MDIO_WIS_REG_LASI_STATUS, &val1);
2894 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
2896 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2897 ext_phy_addr,
2898 MDIO_WIS_DEVAD,
2899 MDIO_WIS_REG_LASI_STATUS, &val1);
2900 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
2902 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2903 ext_phy_addr,
2904 MDIO_PMA_DEVAD,
2905 MDIO_PMA_REG_RX_SD, &rx_sd);
2906 DP(NETIF_MSG_LINK, "8705 rx_sd 0x%x\n", rx_sd);
2907 ext_phy_link_up = (rx_sd & 0x1);
2908 if (ext_phy_link_up)
2909 vars->line_speed = SPEED_10000;
2910 break;
2912 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2913 DP(NETIF_MSG_LINK, "XGXS 8706\n");
2914 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2915 ext_phy_addr,
2916 MDIO_PMA_DEVAD,
2917 MDIO_PMA_REG_LASI_STATUS, &val1);
2918 DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
2920 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2921 ext_phy_addr,
2922 MDIO_PMA_DEVAD,
2923 MDIO_PMA_REG_LASI_STATUS, &val1);
2924 DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
2926 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2927 ext_phy_addr,
2928 MDIO_PMA_DEVAD,
2929 MDIO_PMA_REG_RX_SD, &rx_sd);
2930 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2931 ext_phy_addr,
2932 MDIO_PCS_DEVAD,
2933 MDIO_PCS_REG_STATUS, &pcs_status);
2935 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2936 ext_phy_addr,
2937 MDIO_AN_DEVAD,
2938 MDIO_AN_REG_LINK_STATUS, &val2);
2939 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2940 ext_phy_addr,
2941 MDIO_AN_DEVAD,
2942 MDIO_AN_REG_LINK_STATUS, &val2);
2944 DP(NETIF_MSG_LINK, "8706 rx_sd 0x%x"
2945 " pcs_status 0x%x 1Gbps link_status 0x%x\n",
2946 rx_sd, pcs_status, val2);
2947 /* link is up if both bit 0 of pmd_rx_sd and
2948 * bit 0 of pcs_status are set, or if the autoneg bit
2949 1 is set
2951 ext_phy_link_up = ((rx_sd & pcs_status & 0x1) ||
2952 (val2 & (1<<1)));
2953 if (ext_phy_link_up) {
2954 if (val2 & (1<<1))
2955 vars->line_speed = SPEED_1000;
2956 else
2957 vars->line_speed = SPEED_10000;
2960 /* clear LASI indication*/
2961 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2962 ext_phy_addr,
2963 MDIO_PMA_DEVAD,
2964 MDIO_PMA_REG_RX_ALARM, &val2);
2965 break;
2967 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2968 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2970 u16 link_status = 0;
2971 u16 an1000_status = 0;
2972 if (ext_phy_type ==
2973 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
2974 bnx2x_cl45_read(bp, params->port,
2975 ext_phy_type,
2976 ext_phy_addr,
2977 MDIO_PCS_DEVAD,
2978 MDIO_PCS_REG_LASI_STATUS, &val1);
2979 bnx2x_cl45_read(bp, params->port,
2980 ext_phy_type,
2981 ext_phy_addr,
2982 MDIO_PCS_DEVAD,
2983 MDIO_PCS_REG_LASI_STATUS, &val2);
2984 DP(NETIF_MSG_LINK,
2985 "870x LASI status 0x%x->0x%x\n",
2986 val1, val2);
2988 } else {
2989 /* In 8073, port1 is directed through emac0 and
2990 * port0 is directed through emac1
2992 bnx2x_cl45_read(bp, params->port,
2993 ext_phy_type,
2994 ext_phy_addr,
2995 MDIO_PMA_DEVAD,
2996 MDIO_PMA_REG_LASI_STATUS, &val1);
2998 DP(NETIF_MSG_LINK,
2999 "8703 LASI status 0x%x\n",
3000 val1);
3003 /* clear the interrupt LASI status register */
3004 bnx2x_cl45_read(bp, params->port,
3005 ext_phy_type,
3006 ext_phy_addr,
3007 MDIO_PCS_DEVAD,
3008 MDIO_PCS_REG_STATUS, &val2);
3009 bnx2x_cl45_read(bp, params->port,
3010 ext_phy_type,
3011 ext_phy_addr,
3012 MDIO_PCS_DEVAD,
3013 MDIO_PCS_REG_STATUS, &val1);
3014 DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n",
3015 val2, val1);
3016 /* Clear MSG-OUT */
3017 bnx2x_cl45_read(bp, params->port,
3018 ext_phy_type,
3019 ext_phy_addr,
3020 MDIO_PMA_DEVAD,
3021 0xca13,
3022 &val1);
3024 /* Check the LASI */
3025 bnx2x_cl45_read(bp, params->port,
3026 ext_phy_type,
3027 ext_phy_addr,
3028 MDIO_PMA_DEVAD,
3029 MDIO_PMA_REG_RX_ALARM, &val2);
3031 DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
3033 /* Check the link status */
3034 bnx2x_cl45_read(bp, params->port,
3035 ext_phy_type,
3036 ext_phy_addr,
3037 MDIO_PCS_DEVAD,
3038 MDIO_PCS_REG_STATUS, &val2);
3039 DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
3041 bnx2x_cl45_read(bp, params->port,
3042 ext_phy_type,
3043 ext_phy_addr,
3044 MDIO_PMA_DEVAD,
3045 MDIO_PMA_REG_STATUS, &val2);
3046 bnx2x_cl45_read(bp, params->port,
3047 ext_phy_type,
3048 ext_phy_addr,
3049 MDIO_PMA_DEVAD,
3050 MDIO_PMA_REG_STATUS, &val1);
3051 ext_phy_link_up = ((val1 & 4) == 4);
3052 DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
3053 if (ext_phy_type ==
3054 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
3056 if (ext_phy_link_up &&
3057 ((params->req_line_speed !=
3058 SPEED_10000))) {
3059 if (bnx2x_bcm8073_xaui_wa(params)
3060 != 0) {
3061 ext_phy_link_up = 0;
3062 break;
3065 bnx2x_cl45_read(bp, params->port,
3066 ext_phy_type,
3067 ext_phy_addr,
3068 MDIO_AN_DEVAD,
3069 0x8304,
3070 &an1000_status);
3071 bnx2x_cl45_read(bp, params->port,
3072 ext_phy_type,
3073 ext_phy_addr,
3074 MDIO_AN_DEVAD,
3075 0x8304,
3076 &an1000_status);
3078 /* Check the link status on 1.1.2 */
3079 bnx2x_cl45_read(bp, params->port,
3080 ext_phy_type,
3081 ext_phy_addr,
3082 MDIO_PMA_DEVAD,
3083 MDIO_PMA_REG_STATUS, &val2);
3084 bnx2x_cl45_read(bp, params->port,
3085 ext_phy_type,
3086 ext_phy_addr,
3087 MDIO_PMA_DEVAD,
3088 MDIO_PMA_REG_STATUS, &val1);
3089 DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x,"
3090 "an_link_status=0x%x\n",
3091 val2, val1, an1000_status);
3093 ext_phy_link_up = (((val1 & 4) == 4) ||
3094 (an1000_status & (1<<1)));
3095 if (ext_phy_link_up &&
3096 bnx2x_8073_is_snr_needed(params)) {
3097 /* The SNR will improve about 2dbby
3098 changing the BW and FEE main tap.*/
3100 /* The 1st write to change FFE main
3101 tap is set before restart AN */
3102 /* Change PLL Bandwidth in EDC
3103 register */
3104 bnx2x_cl45_write(bp, port, ext_phy_type,
3105 ext_phy_addr,
3106 MDIO_PMA_DEVAD,
3107 MDIO_PMA_REG_PLL_BANDWIDTH,
3108 0x26BC);
3110 /* Change CDR Bandwidth in EDC
3111 register */
3112 bnx2x_cl45_write(bp, port, ext_phy_type,
3113 ext_phy_addr,
3114 MDIO_PMA_DEVAD,
3115 MDIO_PMA_REG_CDR_BANDWIDTH,
3116 0x0333);
3120 bnx2x_cl45_read(bp, params->port,
3121 ext_phy_type,
3122 ext_phy_addr,
3123 MDIO_PMA_DEVAD,
3124 0xc820,
3125 &link_status);
3127 /* Bits 0..2 --> speed detected,
3128 bits 13..15--> link is down */
3129 if ((link_status & (1<<2)) &&
3130 (!(link_status & (1<<15)))) {
3131 ext_phy_link_up = 1;
3132 vars->line_speed = SPEED_10000;
3133 DP(NETIF_MSG_LINK,
3134 "port %x: External link"
3135 " up in 10G\n", params->port);
3136 } else if ((link_status & (1<<1)) &&
3137 (!(link_status & (1<<14)))) {
3138 ext_phy_link_up = 1;
3139 vars->line_speed = SPEED_2500;
3140 DP(NETIF_MSG_LINK,
3141 "port %x: External link"
3142 " up in 2.5G\n", params->port);
3143 } else if ((link_status & (1<<0)) &&
3144 (!(link_status & (1<<13)))) {
3145 ext_phy_link_up = 1;
3146 vars->line_speed = SPEED_1000;
3147 DP(NETIF_MSG_LINK,
3148 "port %x: External link"
3149 " up in 1G\n", params->port);
3150 } else {
3151 ext_phy_link_up = 0;
3152 DP(NETIF_MSG_LINK,
3153 "port %x: External link"
3154 " is down\n", params->port);
3156 } else {
3157 /* See if 1G link is up for the 8072 */
3158 bnx2x_cl45_read(bp, params->port,
3159 ext_phy_type,
3160 ext_phy_addr,
3161 MDIO_AN_DEVAD,
3162 0x8304,
3163 &an1000_status);
3164 bnx2x_cl45_read(bp, params->port,
3165 ext_phy_type,
3166 ext_phy_addr,
3167 MDIO_AN_DEVAD,
3168 0x8304,
3169 &an1000_status);
3170 if (an1000_status & (1<<1)) {
3171 ext_phy_link_up = 1;
3172 vars->line_speed = SPEED_1000;
3173 DP(NETIF_MSG_LINK,
3174 "port %x: External link"
3175 " up in 1G\n", params->port);
3176 } else if (ext_phy_link_up) {
3177 ext_phy_link_up = 1;
3178 vars->line_speed = SPEED_10000;
3179 DP(NETIF_MSG_LINK,
3180 "port %x: External link"
3181 " up in 10G\n", params->port);
3186 break;
3188 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3189 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3190 ext_phy_addr,
3191 MDIO_PMA_DEVAD,
3192 MDIO_PMA_REG_LASI_STATUS, &val2);
3193 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3194 ext_phy_addr,
3195 MDIO_PMA_DEVAD,
3196 MDIO_PMA_REG_LASI_STATUS, &val1);
3197 DP(NETIF_MSG_LINK,
3198 "10G-base-T LASI status 0x%x->0x%x\n",
3199 val2, val1);
3200 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3201 ext_phy_addr,
3202 MDIO_PMA_DEVAD,
3203 MDIO_PMA_REG_STATUS, &val2);
3204 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3205 ext_phy_addr,
3206 MDIO_PMA_DEVAD,
3207 MDIO_PMA_REG_STATUS, &val1);
3208 DP(NETIF_MSG_LINK,
3209 "10G-base-T PMA status 0x%x->0x%x\n",
3210 val2, val1);
3211 ext_phy_link_up = ((val1 & 4) == 4);
3212 /* if link is up
3213 * print the AN outcome of the SFX7101 PHY
3215 if (ext_phy_link_up) {
3216 bnx2x_cl45_read(bp, params->port,
3217 ext_phy_type,
3218 ext_phy_addr,
3219 MDIO_AN_DEVAD,
3220 MDIO_AN_REG_MASTER_STATUS,
3221 &val2);
3222 vars->line_speed = SPEED_10000;
3223 DP(NETIF_MSG_LINK,
3224 "SFX7101 AN status 0x%x->Master=%x\n",
3225 val2,
3226 (val2 & (1<<14)));
3228 break;
3230 default:
3231 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
3232 params->ext_phy_config);
3233 ext_phy_link_up = 0;
3234 break;
3237 } else { /* SerDes */
3238 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3239 switch (ext_phy_type) {
3240 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
3241 DP(NETIF_MSG_LINK, "SerDes Direct\n");
3242 ext_phy_link_up = 1;
3243 break;
3245 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
3246 DP(NETIF_MSG_LINK, "SerDes 5482\n");
3247 ext_phy_link_up = 1;
3248 break;
3250 default:
3251 DP(NETIF_MSG_LINK,
3252 "BAD SerDes ext_phy_config 0x%x\n",
3253 params->ext_phy_config);
3254 ext_phy_link_up = 0;
3255 break;
3259 return ext_phy_link_up;
3262 static void bnx2x_link_int_enable(struct link_params *params)
3264 u8 port = params->port;
3265 u32 ext_phy_type;
3266 u32 mask;
3267 struct bnx2x *bp = params->bp;
3268 /* setting the status to report on link up
3269 for either XGXS or SerDes */
3271 if (params->switch_cfg == SWITCH_CFG_10G) {
3272 mask = (NIG_MASK_XGXS0_LINK10G |
3273 NIG_MASK_XGXS0_LINK_STATUS);
3274 DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
3275 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3276 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
3277 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
3278 (ext_phy_type !=
3279 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) {
3280 mask |= NIG_MASK_MI_INT;
3281 DP(NETIF_MSG_LINK, "enabled external phy int\n");
3284 } else { /* SerDes */
3285 mask = NIG_MASK_SERDES0_LINK_STATUS;
3286 DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n");
3287 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3288 if ((ext_phy_type !=
3289 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
3290 (ext_phy_type !=
3291 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN)) {
3292 mask |= NIG_MASK_MI_INT;
3293 DP(NETIF_MSG_LINK, "enabled external phy int\n");
3296 bnx2x_bits_en(bp,
3297 NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
3298 mask);
3299 DP(NETIF_MSG_LINK, "port %x, is_xgxs=%x, int_status 0x%x\n", port,
3300 (params->switch_cfg == SWITCH_CFG_10G),
3301 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
3303 DP(NETIF_MSG_LINK, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n",
3304 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
3305 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
3306 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS+port*0x3c));
3307 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
3308 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
3309 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
3314 * link management
3316 static void bnx2x_link_int_ack(struct link_params *params,
3317 struct link_vars *vars, u8 is_10g)
3319 struct bnx2x *bp = params->bp;
3320 u8 port = params->port;
3322 /* first reset all status
3323 * we assume only one line will be change at a time */
3324 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3325 (NIG_STATUS_XGXS0_LINK10G |
3326 NIG_STATUS_XGXS0_LINK_STATUS |
3327 NIG_STATUS_SERDES0_LINK_STATUS));
3328 if (vars->phy_link_up) {
3329 if (is_10g) {
3330 /* Disable the 10G link interrupt
3331 * by writing 1 to the status register
3333 DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
3334 bnx2x_bits_en(bp,
3335 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3336 NIG_STATUS_XGXS0_LINK10G);
3338 } else if (params->switch_cfg == SWITCH_CFG_10G) {
3339 /* Disable the link interrupt
3340 * by writing 1 to the relevant lane
3341 * in the status register
3343 u32 ser_lane = ((params->lane_config &
3344 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
3345 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
3347 DP(NETIF_MSG_LINK, "1G XGXS phy link up\n");
3348 bnx2x_bits_en(bp,
3349 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3350 ((1 << ser_lane) <<
3351 NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
3353 } else { /* SerDes */
3354 DP(NETIF_MSG_LINK, "SerDes phy link up\n");
3355 /* Disable the link interrupt
3356 * by writing 1 to the status register
3358 bnx2x_bits_en(bp,
3359 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3360 NIG_STATUS_SERDES0_LINK_STATUS);
3363 } else { /* link_down */
3367 static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len)
3369 u8 *str_ptr = str;
3370 u32 mask = 0xf0000000;
3371 u8 shift = 8*4;
3372 u8 digit;
3373 if (len < 10) {
3374 /* Need more than 10chars for this format */
3375 *str_ptr = '\0';
3376 return -EINVAL;
3378 while (shift > 0) {
3380 shift -= 4;
3381 digit = ((num & mask) >> shift);
3382 if (digit < 0xa)
3383 *str_ptr = digit + '0';
3384 else
3385 *str_ptr = digit - 0xa + 'a';
3386 str_ptr++;
3387 mask = mask >> 4;
3388 if (shift == 4*4) {
3389 *str_ptr = ':';
3390 str_ptr++;
3393 *str_ptr = '\0';
3394 return 0;
3398 static void bnx2x_turn_on_ef(struct bnx2x *bp, u8 port, u8 ext_phy_addr,
3399 u32 ext_phy_type)
3401 u32 cnt = 0;
3402 u16 ctrl = 0;
3403 /* Enable EMAC0 in to enable MDIO */
3404 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
3405 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
3406 msleep(5);
3408 /* take ext phy out of reset */
3409 bnx2x_set_gpio(bp,
3410 MISC_REGISTERS_GPIO_2,
3411 MISC_REGISTERS_GPIO_HIGH,
3412 port);
3414 bnx2x_set_gpio(bp,
3415 MISC_REGISTERS_GPIO_1,
3416 MISC_REGISTERS_GPIO_HIGH,
3417 port);
3419 /* wait for 5ms */
3420 msleep(5);
3422 for (cnt = 0; cnt < 1000; cnt++) {
3423 msleep(1);
3424 bnx2x_cl45_read(bp, port,
3425 ext_phy_type,
3426 ext_phy_addr,
3427 MDIO_PMA_DEVAD,
3428 MDIO_PMA_REG_CTRL,
3429 &ctrl);
3430 if (!(ctrl & (1<<15))) {
3431 DP(NETIF_MSG_LINK, "Reset completed\n\n");
3432 break;
3437 static void bnx2x_turn_off_sf(struct bnx2x *bp, u8 port)
3439 /* put sf to reset */
3440 bnx2x_set_gpio(bp,
3441 MISC_REGISTERS_GPIO_1,
3442 MISC_REGISTERS_GPIO_LOW,
3443 port);
3444 bnx2x_set_gpio(bp,
3445 MISC_REGISTERS_GPIO_2,
3446 MISC_REGISTERS_GPIO_LOW,
3447 port);
3450 u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
3451 u8 *version, u16 len)
3453 struct bnx2x *bp = params->bp;
3454 u32 ext_phy_type = 0;
3455 u16 val = 0;
3456 u8 ext_phy_addr = 0 ;
3457 u8 status = 0 ;
3458 u32 ver_num;
3460 if (version == NULL || params == NULL)
3461 return -EINVAL;
3463 /* reset the returned value to zero */
3464 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3465 ext_phy_addr = ((params->ext_phy_config &
3466 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
3467 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
3469 switch (ext_phy_type) {
3470 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3472 if (len < 5)
3473 return -EINVAL;
3475 /* Take ext phy out of reset */
3476 if (!driver_loaded)
3477 bnx2x_turn_on_ef(bp, params->port, ext_phy_addr,
3478 ext_phy_type);
3480 /* wait for 1ms */
3481 msleep(1);
3483 bnx2x_cl45_read(bp, params->port,
3484 ext_phy_type,
3485 ext_phy_addr,
3486 MDIO_PMA_DEVAD,
3487 MDIO_PMA_REG_7101_VER1, &val);
3488 version[2] = (val & 0xFF);
3489 version[3] = ((val & 0xFF00)>>8);
3491 bnx2x_cl45_read(bp, params->port,
3492 ext_phy_type,
3493 ext_phy_addr,
3494 MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2,
3495 &val);
3496 version[0] = (val & 0xFF);
3497 version[1] = ((val & 0xFF00)>>8);
3498 version[4] = '\0';
3500 if (!driver_loaded)
3501 bnx2x_turn_off_sf(bp, params->port);
3502 break;
3503 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
3504 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
3506 /* Take ext phy out of reset */
3507 if (!driver_loaded)
3508 bnx2x_turn_on_ef(bp, params->port, ext_phy_addr,
3509 ext_phy_type);
3511 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3512 ext_phy_addr,
3513 MDIO_PMA_DEVAD,
3514 MDIO_PMA_REG_ROM_VER1, &val);
3515 ver_num = val<<16;
3516 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3517 ext_phy_addr,
3518 MDIO_PMA_DEVAD,
3519 MDIO_PMA_REG_ROM_VER2, &val);
3520 ver_num |= val;
3521 status = bnx2x_format_ver(ver_num, version, len);
3522 break;
3524 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
3525 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
3527 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3528 ext_phy_addr,
3529 MDIO_PMA_DEVAD,
3530 MDIO_PMA_REG_ROM_VER1, &val);
3531 ver_num = val<<16;
3532 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3533 ext_phy_addr,
3534 MDIO_PMA_DEVAD,
3535 MDIO_PMA_REG_ROM_VER2, &val);
3536 ver_num |= val;
3537 status = bnx2x_format_ver(ver_num, version, len);
3538 break;
3540 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3541 break;
3543 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
3544 DP(NETIF_MSG_LINK, "bnx2x_get_ext_phy_fw_version:"
3545 " type is FAILURE!\n");
3546 status = -EINVAL;
3547 break;
3549 default:
3550 break;
3552 return status;
3555 static void bnx2x_set_xgxs_loopback(struct link_params *params,
3556 struct link_vars *vars,
3557 u8 is_10g)
3559 u8 port = params->port;
3560 struct bnx2x *bp = params->bp;
3562 if (is_10g) {
3563 u32 md_devad;
3565 DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
3567 /* change the uni_phy_addr in the nig */
3568 md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
3569 port*0x18));
3571 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
3573 bnx2x_cl45_write(bp, port, 0,
3574 params->phy_addr,
3576 (MDIO_REG_BANK_AER_BLOCK +
3577 (MDIO_AER_BLOCK_AER_REG & 0xf)),
3578 0x2800);
3580 bnx2x_cl45_write(bp, port, 0,
3581 params->phy_addr,
3583 (MDIO_REG_BANK_CL73_IEEEB0 +
3584 (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
3585 0x6041);
3586 msleep(200);
3587 /* set aer mmd back */
3588 bnx2x_set_aer_mmd(params, vars);
3590 /* and md_devad */
3591 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
3592 md_devad);
3594 } else {
3595 u16 mii_control;
3597 DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
3599 CL45_RD_OVER_CL22(bp, port,
3600 params->phy_addr,
3601 MDIO_REG_BANK_COMBO_IEEE0,
3602 MDIO_COMBO_IEEE0_MII_CONTROL,
3603 &mii_control);
3605 CL45_WR_OVER_CL22(bp, port,
3606 params->phy_addr,
3607 MDIO_REG_BANK_COMBO_IEEE0,
3608 MDIO_COMBO_IEEE0_MII_CONTROL,
3609 (mii_control |
3610 MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK));
3615 static void bnx2x_ext_phy_loopback(struct link_params *params)
3617 struct bnx2x *bp = params->bp;
3618 u8 ext_phy_addr;
3619 u32 ext_phy_type;
3621 if (params->switch_cfg == SWITCH_CFG_10G) {
3622 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3623 /* CL37 Autoneg Enabled */
3624 ext_phy_addr = ((params->ext_phy_config &
3625 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
3626 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
3627 switch (ext_phy_type) {
3628 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3629 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
3630 DP(NETIF_MSG_LINK,
3631 "ext_phy_loopback: We should not get here\n");
3632 break;
3633 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
3634 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8705\n");
3635 break;
3636 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
3637 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8706\n");
3638 break;
3639 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3640 /* SFX7101_XGXS_TEST1 */
3641 bnx2x_cl45_write(bp, params->port, ext_phy_type,
3642 ext_phy_addr,
3643 MDIO_XS_DEVAD,
3644 MDIO_XS_SFX7101_XGXS_TEST1,
3645 0x100);
3646 DP(NETIF_MSG_LINK,
3647 "ext_phy_loopback: set ext phy loopback\n");
3648 break;
3649 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
3651 break;
3652 } /* switch external PHY type */
3653 } else {
3654 /* serdes */
3655 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3656 ext_phy_addr = (params->ext_phy_config &
3657 PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK)
3658 >> PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT;
3664 *------------------------------------------------------------------------
3665 * bnx2x_override_led_value -
3667 * Override the led value of the requsted led
3669 *------------------------------------------------------------------------
3671 u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port,
3672 u32 led_idx, u32 value)
3674 u32 reg_val;
3676 /* If port 0 then use EMAC0, else use EMAC1*/
3677 u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
3679 DP(NETIF_MSG_LINK,
3680 "bnx2x_override_led_value() port %x led_idx %d value %d\n",
3681 port, led_idx, value);
3683 switch (led_idx) {
3684 case 0: /* 10MB led */
3685 /* Read the current value of the LED register in
3686 the EMAC block */
3687 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3688 /* Set the OVERRIDE bit to 1 */
3689 reg_val |= EMAC_LED_OVERRIDE;
3690 /* If value is 1, set the 10M_OVERRIDE bit,
3691 otherwise reset it.*/
3692 reg_val = (value == 1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) :
3693 (reg_val & ~EMAC_LED_10MB_OVERRIDE);
3694 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3695 break;
3696 case 1: /*100MB led */
3697 /*Read the current value of the LED register in
3698 the EMAC block */
3699 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3700 /* Set the OVERRIDE bit to 1 */
3701 reg_val |= EMAC_LED_OVERRIDE;
3702 /* If value is 1, set the 100M_OVERRIDE bit,
3703 otherwise reset it.*/
3704 reg_val = (value == 1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) :
3705 (reg_val & ~EMAC_LED_100MB_OVERRIDE);
3706 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3707 break;
3708 case 2: /* 1000MB led */
3709 /* Read the current value of the LED register in the
3710 EMAC block */
3711 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3712 /* Set the OVERRIDE bit to 1 */
3713 reg_val |= EMAC_LED_OVERRIDE;
3714 /* If value is 1, set the 1000M_OVERRIDE bit, otherwise
3715 reset it. */
3716 reg_val = (value == 1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) :
3717 (reg_val & ~EMAC_LED_1000MB_OVERRIDE);
3718 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3719 break;
3720 case 3: /* 2500MB led */
3721 /* Read the current value of the LED register in the
3722 EMAC block*/
3723 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3724 /* Set the OVERRIDE bit to 1 */
3725 reg_val |= EMAC_LED_OVERRIDE;
3726 /* If value is 1, set the 2500M_OVERRIDE bit, otherwise
3727 reset it.*/
3728 reg_val = (value == 1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) :
3729 (reg_val & ~EMAC_LED_2500MB_OVERRIDE);
3730 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3731 break;
3732 case 4: /*10G led */
3733 if (port == 0) {
3734 REG_WR(bp, NIG_REG_LED_10G_P0,
3735 value);
3736 } else {
3737 REG_WR(bp, NIG_REG_LED_10G_P1,
3738 value);
3740 break;
3741 case 5: /* TRAFFIC led */
3742 /* Find if the traffic control is via BMAC or EMAC */
3743 if (port == 0)
3744 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC0_EN);
3745 else
3746 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC1_EN);
3748 /* Override the traffic led in the EMAC:*/
3749 if (reg_val == 1) {
3750 /* Read the current value of the LED register in
3751 the EMAC block */
3752 reg_val = REG_RD(bp, emac_base +
3753 EMAC_REG_EMAC_LED);
3754 /* Set the TRAFFIC_OVERRIDE bit to 1 */
3755 reg_val |= EMAC_LED_OVERRIDE;
3756 /* If value is 1, set the TRAFFIC bit, otherwise
3757 reset it.*/
3758 reg_val = (value == 1) ? (reg_val | EMAC_LED_TRAFFIC) :
3759 (reg_val & ~EMAC_LED_TRAFFIC);
3760 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3761 } else { /* Override the traffic led in the BMAC: */
3762 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
3763 + port*4, 1);
3764 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port*4,
3765 value);
3767 break;
3768 default:
3769 DP(NETIF_MSG_LINK,
3770 "bnx2x_override_led_value() unknown led index %d "
3771 "(should be 0-5)\n", led_idx);
3772 return -EINVAL;
3775 return 0;
3779 u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
3780 u16 hw_led_mode, u32 chip_id)
3782 u8 rc = 0;
3783 u32 tmp;
3784 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
3785 DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
3786 DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
3787 speed, hw_led_mode);
3788 switch (mode) {
3789 case LED_MODE_OFF:
3790 REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0);
3791 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
3792 SHARED_HW_CFG_LED_MAC1);
3794 tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
3795 EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE));
3796 break;
3798 case LED_MODE_OPER:
3799 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode);
3800 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
3801 port*4, 0);
3802 /* Set blinking rate to ~15.9Hz */
3803 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
3804 LED_BLINK_RATE_VAL);
3805 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
3806 port*4, 1);
3807 tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
3808 EMAC_WR(bp, EMAC_REG_EMAC_LED,
3809 (tmp & (~EMAC_LED_OVERRIDE)));
3811 if (!CHIP_IS_E1H(bp) &&
3812 ((speed == SPEED_2500) ||
3813 (speed == SPEED_1000) ||
3814 (speed == SPEED_100) ||
3815 (speed == SPEED_10))) {
3816 /* On Everest 1 Ax chip versions for speeds less than
3817 10G LED scheme is different */
3818 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
3819 + port*4, 1);
3820 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
3821 port*4, 0);
3822 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
3823 port*4, 1);
3825 break;
3827 default:
3828 rc = -EINVAL;
3829 DP(NETIF_MSG_LINK, "bnx2x_set_led: Invalid led mode %d\n",
3830 mode);
3831 break;
3833 return rc;
3837 u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars)
3839 struct bnx2x *bp = params->bp;
3840 u16 gp_status = 0;
3842 CL45_RD_OVER_CL22(bp, params->port,
3843 params->phy_addr,
3844 MDIO_REG_BANK_GP_STATUS,
3845 MDIO_GP_STATUS_TOP_AN_STATUS1,
3846 &gp_status);
3847 /* link is up only if both local phy and external phy are up */
3848 if ((gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) &&
3849 bnx2x_ext_phy_is_link_up(params, vars))
3850 return 0;
3852 return -ESRCH;
3855 static u8 bnx2x_link_initialize(struct link_params *params,
3856 struct link_vars *vars)
3858 struct bnx2x *bp = params->bp;
3859 u8 port = params->port;
3860 u8 rc = 0;
3861 u8 non_ext_phy;
3862 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3863 /* Activate the external PHY */
3864 bnx2x_ext_phy_reset(params, vars);
3866 bnx2x_set_aer_mmd(params, vars);
3868 if (vars->phy_flags & PHY_XGXS_FLAG)
3869 bnx2x_set_master_ln(params);
3871 rc = bnx2x_reset_unicore(params);
3872 /* reset the SerDes and wait for reset bit return low */
3873 if (rc != 0)
3874 return rc;
3876 bnx2x_set_aer_mmd(params, vars);
3878 /* setting the masterLn_def again after the reset */
3879 if (vars->phy_flags & PHY_XGXS_FLAG) {
3880 bnx2x_set_master_ln(params);
3881 bnx2x_set_swap_lanes(params);
3884 if (vars->phy_flags & PHY_XGXS_FLAG) {
3885 if ((params->req_line_speed &&
3886 ((params->req_line_speed == SPEED_100) ||
3887 (params->req_line_speed == SPEED_10))) ||
3888 (!params->req_line_speed &&
3889 (params->speed_cap_mask >=
3890 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
3891 (params->speed_cap_mask <
3892 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
3893 )) {
3894 vars->phy_flags |= PHY_SGMII_FLAG;
3895 } else {
3896 vars->phy_flags &= ~PHY_SGMII_FLAG;
3899 /* In case of external phy existance, the line speed would be the
3900 line speed linked up by the external phy. In case it is direct only,
3901 then the line_speed during initialization will be equal to the
3902 req_line_speed*/
3903 vars->line_speed = params->req_line_speed;
3905 bnx2x_calc_ieee_aneg_adv(params, &vars->ieee_fc);
3907 /* init ext phy and enable link state int */
3908 non_ext_phy = ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
3909 (params->loopback_mode == LOOPBACK_XGXS_10) ||
3910 (params->loopback_mode == LOOPBACK_EXT_PHY));
3912 if (non_ext_phy ||
3913 (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705)) {
3914 if (params->req_line_speed == SPEED_AUTO_NEG)
3915 bnx2x_set_parallel_detection(params, vars->phy_flags);
3916 bnx2x_init_internal_phy(params, vars);
3919 if (!non_ext_phy)
3920 rc |= bnx2x_ext_phy_init(params, vars);
3922 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3923 (NIG_STATUS_XGXS0_LINK10G |
3924 NIG_STATUS_XGXS0_LINK_STATUS |
3925 NIG_STATUS_SERDES0_LINK_STATUS));
3927 return rc;
3932 u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
3934 struct bnx2x *bp = params->bp;
3936 u32 val;
3937 DP(NETIF_MSG_LINK, "Phy Initialization started \n");
3938 DP(NETIF_MSG_LINK, "req_speed = %d, req_flowctrl=%d\n",
3939 params->req_line_speed, params->req_flow_ctrl);
3940 vars->link_status = 0;
3941 vars->phy_link_up = 0;
3942 vars->link_up = 0;
3943 vars->line_speed = 0;
3944 vars->duplex = DUPLEX_FULL;
3945 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
3946 vars->mac_type = MAC_TYPE_NONE;
3948 if (params->switch_cfg == SWITCH_CFG_1G)
3949 vars->phy_flags = PHY_SERDES_FLAG;
3950 else
3951 vars->phy_flags = PHY_XGXS_FLAG;
3954 /* disable attentions */
3955 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
3956 (NIG_MASK_XGXS0_LINK_STATUS |
3957 NIG_MASK_XGXS0_LINK10G |
3958 NIG_MASK_SERDES0_LINK_STATUS |
3959 NIG_MASK_MI_INT));
3961 bnx2x_emac_init(params, vars);
3963 if (CHIP_REV_IS_FPGA(bp)) {
3964 vars->link_up = 1;
3965 vars->line_speed = SPEED_10000;
3966 vars->duplex = DUPLEX_FULL;
3967 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
3968 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
3969 /* enable on E1.5 FPGA */
3970 if (CHIP_IS_E1H(bp)) {
3971 vars->flow_ctrl |=
3972 (BNX2X_FLOW_CTRL_TX | BNX2X_FLOW_CTRL_RX);
3973 vars->link_status |=
3974 (LINK_STATUS_TX_FLOW_CONTROL_ENABLED |
3975 LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
3978 bnx2x_emac_enable(params, vars, 0);
3979 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
3980 /* disable drain */
3981 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
3982 + params->port*4, 0);
3984 /* update shared memory */
3985 bnx2x_update_mng(params, vars->link_status);
3987 return 0;
3989 } else
3990 if (CHIP_REV_IS_EMUL(bp)) {
3992 vars->link_up = 1;
3993 vars->line_speed = SPEED_10000;
3994 vars->duplex = DUPLEX_FULL;
3995 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
3996 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
3998 bnx2x_bmac_enable(params, vars, 0);
4000 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
4001 /* Disable drain */
4002 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
4003 + params->port*4, 0);
4005 /* update shared memory */
4006 bnx2x_update_mng(params, vars->link_status);
4008 return 0;
4010 } else
4011 if (params->loopback_mode == LOOPBACK_BMAC) {
4012 vars->link_up = 1;
4013 vars->line_speed = SPEED_10000;
4014 vars->duplex = DUPLEX_FULL;
4015 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
4016 vars->mac_type = MAC_TYPE_BMAC;
4018 vars->phy_flags = PHY_XGXS_FLAG;
4020 bnx2x_phy_deassert(params, vars->phy_flags);
4021 /* set bmac loopback */
4022 bnx2x_bmac_enable(params, vars, 1);
4024 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
4025 params->port*4, 0);
4026 } else if (params->loopback_mode == LOOPBACK_EMAC) {
4027 vars->link_up = 1;
4028 vars->line_speed = SPEED_1000;
4029 vars->duplex = DUPLEX_FULL;
4030 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
4031 vars->mac_type = MAC_TYPE_EMAC;
4033 vars->phy_flags = PHY_XGXS_FLAG;
4035 bnx2x_phy_deassert(params, vars->phy_flags);
4036 /* set bmac loopback */
4037 bnx2x_emac_enable(params, vars, 1);
4038 bnx2x_emac_program(params, vars->line_speed,
4039 vars->duplex);
4040 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
4041 params->port*4, 0);
4042 } else if ((params->loopback_mode == LOOPBACK_XGXS_10) ||
4043 (params->loopback_mode == LOOPBACK_EXT_PHY)) {
4044 vars->link_up = 1;
4045 vars->line_speed = SPEED_10000;
4046 vars->duplex = DUPLEX_FULL;
4047 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
4049 vars->phy_flags = PHY_XGXS_FLAG;
4051 val = REG_RD(bp,
4052 NIG_REG_XGXS0_CTRL_PHY_ADDR+
4053 params->port*0x18);
4054 params->phy_addr = (u8)val;
4056 bnx2x_phy_deassert(params, vars->phy_flags);
4057 bnx2x_link_initialize(params, vars);
4059 vars->mac_type = MAC_TYPE_BMAC;
4061 bnx2x_bmac_enable(params, vars, 0);
4063 if (params->loopback_mode == LOOPBACK_XGXS_10) {
4064 /* set 10G XGXS loopback */
4065 bnx2x_set_xgxs_loopback(params, vars, 1);
4066 } else {
4067 /* set external phy loopback */
4068 bnx2x_ext_phy_loopback(params);
4070 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
4071 params->port*4, 0);
4072 } else
4073 /* No loopback */
4076 bnx2x_phy_deassert(params, vars->phy_flags);
4077 switch (params->switch_cfg) {
4078 case SWITCH_CFG_1G:
4079 vars->phy_flags |= PHY_SERDES_FLAG;
4080 if ((params->ext_phy_config &
4081 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK) ==
4082 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482) {
4083 vars->phy_flags |=
4084 PHY_SGMII_FLAG;
4087 val = REG_RD(bp,
4088 NIG_REG_SERDES0_CTRL_PHY_ADDR+
4089 params->port*0x10);
4091 params->phy_addr = (u8)val;
4093 break;
4094 case SWITCH_CFG_10G:
4095 vars->phy_flags |= PHY_XGXS_FLAG;
4096 val = REG_RD(bp,
4097 NIG_REG_XGXS0_CTRL_PHY_ADDR+
4098 params->port*0x18);
4099 params->phy_addr = (u8)val;
4101 break;
4102 default:
4103 DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
4104 return -EINVAL;
4105 break;
4108 bnx2x_link_initialize(params, vars);
4109 msleep(30);
4110 bnx2x_link_int_enable(params);
4112 return 0;
4115 u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars)
4118 struct bnx2x *bp = params->bp;
4119 u32 ext_phy_config = params->ext_phy_config;
4120 u16 hw_led_mode = params->hw_led_mode;
4121 u32 chip_id = params->chip_id;
4122 u8 port = params->port;
4123 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
4124 /* disable attentions */
4126 vars->link_status = 0;
4127 bnx2x_update_mng(params, vars->link_status);
4128 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
4129 (NIG_MASK_XGXS0_LINK_STATUS |
4130 NIG_MASK_XGXS0_LINK10G |
4131 NIG_MASK_SERDES0_LINK_STATUS |
4132 NIG_MASK_MI_INT));
4134 /* activate nig drain */
4135 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
4137 /* disable nig egress interface */
4138 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
4139 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
4141 /* Stop BigMac rx */
4142 bnx2x_bmac_rx_disable(bp, port);
4144 /* disable emac */
4145 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
4147 msleep(10);
4148 /* The PHY reset is controled by GPIO 1
4149 * Hold it as vars low
4151 /* clear link led */
4152 bnx2x_set_led(bp, port, LED_MODE_OFF, 0, hw_led_mode, chip_id);
4153 if (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
4154 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
4155 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
4156 /* HW reset */
4158 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
4159 MISC_REGISTERS_GPIO_OUTPUT_LOW,
4160 port);
4162 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4163 MISC_REGISTERS_GPIO_OUTPUT_LOW,
4164 port);
4166 DP(NETIF_MSG_LINK, "reset external PHY\n");
4167 } else if (ext_phy_type ==
4168 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
4169 DP(NETIF_MSG_LINK, "Setting 8073 port %d into "
4170 "low power mode\n",
4171 port);
4172 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4173 MISC_REGISTERS_GPIO_OUTPUT_LOW,
4174 port);
4177 /* reset the SerDes/XGXS */
4178 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
4179 (0x1ff << (port*16)));
4181 /* reset BigMac */
4182 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
4183 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
4185 /* disable nig ingress interface */
4186 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
4187 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
4188 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
4189 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
4190 vars->link_up = 0;
4191 return 0;
4194 static u8 bnx2x_update_link_down(struct link_params *params,
4195 struct link_vars *vars)
4197 struct bnx2x *bp = params->bp;
4198 u8 port = params->port;
4199 DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
4200 bnx2x_set_led(bp, port, LED_MODE_OFF,
4201 0, params->hw_led_mode,
4202 params->chip_id);
4204 /* indicate no mac active */
4205 vars->mac_type = MAC_TYPE_NONE;
4207 /* update shared memory */
4208 vars->link_status = 0;
4209 vars->line_speed = 0;
4210 bnx2x_update_mng(params, vars->link_status);
4212 /* activate nig drain */
4213 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
4215 /* disable emac */
4216 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
4218 msleep(10);
4220 /* reset BigMac */
4221 bnx2x_bmac_rx_disable(bp, params->port);
4222 REG_WR(bp, GRCBASE_MISC +
4223 MISC_REGISTERS_RESET_REG_2_CLEAR,
4224 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
4225 return 0;
4228 static u8 bnx2x_update_link_up(struct link_params *params,
4229 struct link_vars *vars,
4230 u8 link_10g, u32 gp_status)
4232 struct bnx2x *bp = params->bp;
4233 u8 port = params->port;
4234 u8 rc = 0;
4235 vars->link_status |= LINK_STATUS_LINK_UP;
4236 if (link_10g) {
4237 bnx2x_bmac_enable(params, vars, 0);
4238 bnx2x_set_led(bp, port, LED_MODE_OPER,
4239 SPEED_10000, params->hw_led_mode,
4240 params->chip_id);
4242 } else {
4243 bnx2x_emac_enable(params, vars, 0);
4244 rc = bnx2x_emac_program(params, vars->line_speed,
4245 vars->duplex);
4247 /* AN complete? */
4248 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
4249 if (!(vars->phy_flags &
4250 PHY_SGMII_FLAG))
4251 bnx2x_set_sgmii_tx_driver(params);
4255 /* PBF - link up */
4256 rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
4257 vars->line_speed);
4259 /* disable drain */
4260 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
4262 /* update shared memory */
4263 bnx2x_update_mng(params, vars->link_status);
4264 msleep(20);
4265 return rc;
4267 /* This function should called upon link interrupt */
4268 /* In case vars->link_up, driver needs to
4269 1. Update the pbf
4270 2. Disable drain
4271 3. Update the shared memory
4272 4. Indicate link up
4273 5. Set LEDs
4274 Otherwise,
4275 1. Update shared memory
4276 2. Reset BigMac
4277 3. Report link down
4278 4. Unset LEDs
4280 u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
4282 struct bnx2x *bp = params->bp;
4283 u8 port = params->port;
4284 u16 gp_status;
4285 u8 link_10g;
4286 u8 ext_phy_link_up, rc = 0;
4287 u32 ext_phy_type;
4289 DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
4290 port,
4291 (vars->phy_flags & PHY_XGXS_FLAG),
4292 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
4294 DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
4295 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
4296 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
4297 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
4299 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
4300 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
4301 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
4303 /* disable emac */
4304 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
4306 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
4308 /* Check external link change only for non-direct */
4309 ext_phy_link_up = bnx2x_ext_phy_is_link_up(params, vars);
4311 /* Read gp_status */
4312 CL45_RD_OVER_CL22(bp, port, params->phy_addr,
4313 MDIO_REG_BANK_GP_STATUS,
4314 MDIO_GP_STATUS_TOP_AN_STATUS1,
4315 &gp_status);
4317 rc = bnx2x_link_settings_status(params, vars, gp_status);
4318 if (rc != 0)
4319 return rc;
4321 /* anything 10 and over uses the bmac */
4322 link_10g = ((vars->line_speed == SPEED_10000) ||
4323 (vars->line_speed == SPEED_12000) ||
4324 (vars->line_speed == SPEED_12500) ||
4325 (vars->line_speed == SPEED_13000) ||
4326 (vars->line_speed == SPEED_15000) ||
4327 (vars->line_speed == SPEED_16000));
4329 bnx2x_link_int_ack(params, vars, link_10g);
4331 /* In case external phy link is up, and internal link is down
4332 ( not initialized yet probably after link initialization, it needs
4333 to be initialized.
4334 Note that after link down-up as result of cable plug,
4335 the xgxs link would probably become up again without the need to
4336 initialize it*/
4338 if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
4339 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) &&
4340 (ext_phy_link_up && !vars->phy_link_up))
4341 bnx2x_init_internal_phy(params, vars);
4343 /* link is up only if both local phy and external phy are up */
4344 vars->link_up = (ext_phy_link_up && vars->phy_link_up);
4346 if (vars->link_up)
4347 rc = bnx2x_update_link_up(params, vars, link_10g, gp_status);
4348 else
4349 rc = bnx2x_update_link_down(params, vars);
4351 return rc;
4354 static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
4356 u8 ext_phy_addr[PORT_MAX];
4357 u16 val;
4358 s8 port;
4360 /* PART1 - Reset both phys */
4361 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4362 /* Extract the ext phy address for the port */
4363 u32 ext_phy_config = REG_RD(bp, shmem_base +
4364 offsetof(struct shmem_region,
4365 dev_info.port_hw_config[port].external_phy_config));
4367 /* disable attentions */
4368 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
4369 (NIG_MASK_XGXS0_LINK_STATUS |
4370 NIG_MASK_XGXS0_LINK10G |
4371 NIG_MASK_SERDES0_LINK_STATUS |
4372 NIG_MASK_MI_INT));
4374 ext_phy_addr[port] =
4375 ((ext_phy_config &
4376 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
4377 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
4379 /* Need to take the phy out of low power mode in order
4380 to write to access its registers */
4381 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4382 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
4384 /* Reset the phy */
4385 bnx2x_cl45_write(bp, port,
4386 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4387 ext_phy_addr[port],
4388 MDIO_PMA_DEVAD,
4389 MDIO_PMA_REG_CTRL,
4390 1<<15);
4393 /* Add delay of 150ms after reset */
4394 msleep(150);
4396 /* PART2 - Download firmware to both phys */
4397 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4398 u16 fw_ver1;
4400 bnx2x_bcm8073_external_rom_boot(bp, port,
4401 ext_phy_addr[port]);
4403 bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4404 ext_phy_addr[port],
4405 MDIO_PMA_DEVAD,
4406 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
4407 if (fw_ver1 == 0 || fw_ver1 == 0x4321) {
4408 DP(NETIF_MSG_LINK,
4409 "bnx2x_8073_common_init_phy port %x:"
4410 "Download failed. fw version = 0x%x\n",
4411 port, fw_ver1);
4412 return -EINVAL;
4415 /* Only set bit 10 = 1 (Tx power down) */
4416 bnx2x_cl45_read(bp, port,
4417 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4418 ext_phy_addr[port],
4419 MDIO_PMA_DEVAD,
4420 MDIO_PMA_REG_TX_POWER_DOWN, &val);
4422 /* Phase1 of TX_POWER_DOWN reset */
4423 bnx2x_cl45_write(bp, port,
4424 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4425 ext_phy_addr[port],
4426 MDIO_PMA_DEVAD,
4427 MDIO_PMA_REG_TX_POWER_DOWN,
4428 (val | 1<<10));
4431 /* Toggle Transmitter: Power down and then up with 600ms
4432 delay between */
4433 msleep(600);
4435 /* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low */
4436 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4437 /* Phase2 of POWER_DOWN_RESET*/
4438 /* Release bit 10 (Release Tx power down) */
4439 bnx2x_cl45_read(bp, port,
4440 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4441 ext_phy_addr[port],
4442 MDIO_PMA_DEVAD,
4443 MDIO_PMA_REG_TX_POWER_DOWN, &val);
4445 bnx2x_cl45_write(bp, port,
4446 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4447 ext_phy_addr[port],
4448 MDIO_PMA_DEVAD,
4449 MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
4450 msleep(15);
4452 /* Read modify write the SPI-ROM version select register */
4453 bnx2x_cl45_read(bp, port,
4454 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4455 ext_phy_addr[port],
4456 MDIO_PMA_DEVAD,
4457 MDIO_PMA_REG_EDC_FFE_MAIN, &val);
4458 bnx2x_cl45_write(bp, port,
4459 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4460 ext_phy_addr[port],
4461 MDIO_PMA_DEVAD,
4462 MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
4464 /* set GPIO2 back to LOW */
4465 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4466 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
4468 return 0;
4472 u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base)
4474 u8 rc = 0;
4475 u32 ext_phy_type;
4477 DP(NETIF_MSG_LINK, "bnx2x_common_init_phy\n");
4479 /* Read the ext_phy_type for arbitrary port(0) */
4480 ext_phy_type = XGXS_EXT_PHY_TYPE(
4481 REG_RD(bp, shmem_base +
4482 offsetof(struct shmem_region,
4483 dev_info.port_hw_config[0].external_phy_config)));
4485 switch (ext_phy_type) {
4486 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
4488 rc = bnx2x_8073_common_init_phy(bp, shmem_base);
4489 break;
4491 default:
4492 DP(NETIF_MSG_LINK,
4493 "bnx2x_common_init_phy: ext_phy 0x%x not required\n",
4494 ext_phy_type);
4495 break;
4498 return rc;
4503 static void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
4505 u16 val, cnt;
4507 bnx2x_cl45_read(bp, port,
4508 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4509 phy_addr,
4510 MDIO_PMA_DEVAD,
4511 MDIO_PMA_REG_7101_RESET, &val);
4513 for (cnt = 0; cnt < 10; cnt++) {
4514 msleep(50);
4515 /* Writes a self-clearing reset */
4516 bnx2x_cl45_write(bp, port,
4517 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4518 phy_addr,
4519 MDIO_PMA_DEVAD,
4520 MDIO_PMA_REG_7101_RESET,
4521 (val | (1<<15)));
4522 /* Wait for clear */
4523 bnx2x_cl45_read(bp, port,
4524 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4525 phy_addr,
4526 MDIO_PMA_DEVAD,
4527 MDIO_PMA_REG_7101_RESET, &val);
4529 if ((val & (1<<15)) == 0)
4530 break;
4533 #define RESERVED_SIZE 256
4534 /* max application is 160K bytes - data at end of RAM */
4535 #define MAX_APP_SIZE (160*1024 - RESERVED_SIZE)
4537 /* Header is 14 bytes */
4538 #define HEADER_SIZE 14
4539 #define DATA_OFFSET HEADER_SIZE
4541 #define SPI_START_TRANSFER(bp, port, ext_phy_addr) \
4542 bnx2x_cl45_write(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101, \
4543 ext_phy_addr, \
4544 MDIO_PCS_DEVAD, \
4545 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 1)
4547 /* Programs an image to DSP's flash via the SPI port*/
4548 static u8 bnx2x_sfx7101_flash_download(struct bnx2x *bp, u8 port,
4549 u8 ext_phy_addr,
4550 char data[], u32 size)
4552 const u16 num_trans = size/4; /* 4 bytes can be sent at a time */
4553 /* Doesn't include last trans!*/
4554 const u16 last_trans_size = size%4; /* Num bytes on last trans */
4555 u16 trans_cnt, byte_cnt;
4556 u32 data_index;
4557 u16 tmp;
4558 u16 code_started = 0;
4559 u16 image_revision1, image_revision2;
4560 u16 cnt;
4562 DP(NETIF_MSG_LINK, "bnx2x_sfx7101_flash_download file_size=%d\n", size);
4563 /* Going to flash*/
4564 if ((size-HEADER_SIZE) > MAX_APP_SIZE) {
4565 /* This very often will be the case, because the image is built
4566 with 160Kbytes size whereas the total image size must actually
4567 be 160Kbytes-RESERVED_SIZE */
4568 DP(NETIF_MSG_LINK, "Warning, file size was %d bytes "
4569 "truncated to %d bytes\n", size, MAX_APP_SIZE);
4570 size = MAX_APP_SIZE+HEADER_SIZE;
4572 DP(NETIF_MSG_LINK, "File version is %c%c\n", data[0x14e], data[0x14f]);
4573 DP(NETIF_MSG_LINK, " %c%c\n", data[0x150], data[0x151]);
4574 /* Put the DSP in download mode by setting FLASH_CFG[2] to 1
4575 and issuing a reset.*/
4577 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
4578 MISC_REGISTERS_GPIO_HIGH, port);
4580 bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
4582 /* wait 0.5 sec */
4583 for (cnt = 0; cnt < 100; cnt++)
4584 msleep(5);
4586 /* Make sure we can access the DSP
4587 And it's in the correct mode (waiting for download) */
4589 bnx2x_cl45_read(bp, port,
4590 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4591 ext_phy_addr,
4592 MDIO_PCS_DEVAD,
4593 MDIO_PCS_REG_7101_DSP_ACCESS, &tmp);
4595 if (tmp != 0x000A) {
4596 DP(NETIF_MSG_LINK, "DSP is not in waiting on download mode. "
4597 "Expected 0x000A, read 0x%04X\n", tmp);
4598 DP(NETIF_MSG_LINK, "Download failed\n");
4599 return -EINVAL;
4602 /* Mux the SPI interface away from the internal processor */
4603 bnx2x_cl45_write(bp, port,
4604 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4605 ext_phy_addr,
4606 MDIO_PCS_DEVAD,
4607 MDIO_PCS_REG_7101_SPI_MUX, 1);
4609 /* Reset the SPI port */
4610 bnx2x_cl45_write(bp, port,
4611 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4612 ext_phy_addr,
4613 MDIO_PCS_DEVAD,
4614 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
4615 bnx2x_cl45_write(bp, port,
4616 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4617 ext_phy_addr,
4618 MDIO_PCS_DEVAD,
4619 MDIO_PCS_REG_7101_SPI_CTRL_ADDR,
4620 (1<<MDIO_PCS_REG_7101_SPI_RESET_BIT));
4621 bnx2x_cl45_write(bp, port,
4622 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4623 ext_phy_addr,
4624 MDIO_PCS_DEVAD,
4625 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
4627 /* Erase the flash */
4628 bnx2x_cl45_write(bp, port,
4629 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4630 ext_phy_addr,
4631 MDIO_PCS_DEVAD,
4632 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4633 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4635 bnx2x_cl45_write(bp, port,
4636 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4637 ext_phy_addr,
4638 MDIO_PCS_DEVAD,
4639 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4642 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4643 bnx2x_cl45_write(bp, port,
4644 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4645 ext_phy_addr,
4646 MDIO_PCS_DEVAD,
4647 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4648 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_BULK_ERASE_CMD);
4650 bnx2x_cl45_write(bp, port,
4651 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4652 ext_phy_addr,
4653 MDIO_PCS_DEVAD,
4654 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4656 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4658 /* Wait 10 seconds, the maximum time for the erase to complete */
4659 DP(NETIF_MSG_LINK, "Erasing flash, this takes 10 seconds...\n");
4660 for (cnt = 0; cnt < 1000; cnt++)
4661 msleep(10);
4663 DP(NETIF_MSG_LINK, "Downloading flash, please wait...\n");
4664 data_index = 0;
4665 for (trans_cnt = 0; trans_cnt < num_trans; trans_cnt++) {
4666 bnx2x_cl45_write(bp, port,
4667 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4668 ext_phy_addr,
4669 MDIO_PCS_DEVAD,
4670 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4671 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4673 bnx2x_cl45_write(bp, port,
4674 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4675 ext_phy_addr,
4676 MDIO_PCS_DEVAD,
4677 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4679 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4681 bnx2x_cl45_write(bp, port,
4682 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4683 ext_phy_addr,
4684 MDIO_PCS_DEVAD,
4685 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4686 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
4688 /* Bits 23-16 of address */
4689 bnx2x_cl45_write(bp, port,
4690 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4691 ext_phy_addr,
4692 MDIO_PCS_DEVAD,
4693 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4694 (data_index>>16));
4695 /* Bits 15-8 of address */
4696 bnx2x_cl45_write(bp, port,
4697 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4698 ext_phy_addr,
4699 MDIO_PCS_DEVAD,
4700 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4701 (data_index>>8));
4703 /* Bits 7-0 of address */
4704 bnx2x_cl45_write(bp, port,
4705 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4706 ext_phy_addr,
4707 MDIO_PCS_DEVAD,
4708 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4709 ((u16)data_index));
4711 byte_cnt = 0;
4712 while (byte_cnt < 4 && data_index < size) {
4713 bnx2x_cl45_write(bp, port,
4714 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4715 ext_phy_addr,
4716 MDIO_PCS_DEVAD,
4717 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4718 data[data_index++]);
4719 byte_cnt++;
4722 bnx2x_cl45_write(bp, port,
4723 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4724 ext_phy_addr,
4725 MDIO_PCS_DEVAD,
4726 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4727 byte_cnt+4);
4729 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4730 msleep(5); /* Wait 5 ms minimum between transs */
4732 /* Let the user know something's going on.*/
4733 /* a pacifier ever 4K */
4734 if ((data_index % 1023) == 0)
4735 DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
4738 DP(NETIF_MSG_LINK, "\n");
4739 /* Transfer the last block if there is data remaining */
4740 if (last_trans_size) {
4741 bnx2x_cl45_write(bp, port,
4742 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4743 ext_phy_addr,
4744 MDIO_PCS_DEVAD,
4745 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4746 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4748 bnx2x_cl45_write(bp, port,
4749 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4750 ext_phy_addr,
4751 MDIO_PCS_DEVAD,
4752 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4755 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4757 bnx2x_cl45_write(bp, port,
4758 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4759 ext_phy_addr,
4760 MDIO_PCS_DEVAD,
4761 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4762 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
4764 /* Bits 23-16 of address */
4765 bnx2x_cl45_write(bp, port,
4766 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4767 ext_phy_addr,
4768 MDIO_PCS_DEVAD,
4769 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4770 (data_index>>16));
4771 /* Bits 15-8 of address */
4772 bnx2x_cl45_write(bp, port,
4773 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4774 ext_phy_addr,
4775 MDIO_PCS_DEVAD,
4776 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4777 (data_index>>8));
4779 /* Bits 7-0 of address */
4780 bnx2x_cl45_write(bp, port,
4781 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4782 ext_phy_addr,
4783 MDIO_PCS_DEVAD,
4784 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4785 ((u16)data_index));
4787 byte_cnt = 0;
4788 while (byte_cnt < last_trans_size && data_index < size) {
4789 /* Bits 7-0 of address */
4790 bnx2x_cl45_write(bp, port,
4791 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4792 ext_phy_addr,
4793 MDIO_PCS_DEVAD,
4794 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4795 data[data_index++]);
4796 byte_cnt++;
4799 bnx2x_cl45_write(bp, port,
4800 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4801 ext_phy_addr,
4802 MDIO_PCS_DEVAD,
4803 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4804 byte_cnt+4);
4806 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4809 /* DSP Remove Download Mode */
4810 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
4811 MISC_REGISTERS_GPIO_LOW, port);
4813 bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
4815 /* wait 0.5 sec to allow it to run */
4816 for (cnt = 0; cnt < 100; cnt++)
4817 msleep(5);
4819 bnx2x_hw_reset(bp, port);
4821 for (cnt = 0; cnt < 100; cnt++)
4822 msleep(5);
4824 /* Check that the code is started. In case the download
4825 checksum failed, the code won't be started. */
4826 bnx2x_cl45_read(bp, port,
4827 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4828 ext_phy_addr,
4829 MDIO_PCS_DEVAD,
4830 MDIO_PCS_REG_7101_DSP_ACCESS,
4831 &tmp);
4833 code_started = (tmp & (1<<4));
4834 if (!code_started) {
4835 DP(NETIF_MSG_LINK, "Download failed. Please check file.\n");
4836 return -EINVAL;
4839 /* Verify that the file revision is now equal to the image
4840 revision within the DSP */
4841 bnx2x_cl45_read(bp, port,
4842 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4843 ext_phy_addr,
4844 MDIO_PMA_DEVAD,
4845 MDIO_PMA_REG_7101_VER1,
4846 &image_revision1);
4848 bnx2x_cl45_read(bp, port,
4849 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4850 ext_phy_addr,
4851 MDIO_PMA_DEVAD,
4852 MDIO_PMA_REG_7101_VER2,
4853 &image_revision2);
4855 if (data[0x14e] != (image_revision2&0xFF) ||
4856 data[0x14f] != ((image_revision2&0xFF00)>>8) ||
4857 data[0x150] != (image_revision1&0xFF) ||
4858 data[0x151] != ((image_revision1&0xFF00)>>8)) {
4859 DP(NETIF_MSG_LINK, "Download failed.\n");
4860 return -EINVAL;
4862 DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
4863 return 0;
4866 u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config,
4867 u8 driver_loaded, char data[], u32 size)
4869 u8 rc = 0;
4870 u32 ext_phy_type;
4871 u8 ext_phy_addr;
4872 ext_phy_addr = ((ext_phy_config &
4873 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
4874 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
4876 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
4878 switch (ext_phy_type) {
4879 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
4880 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
4881 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
4882 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
4883 DP(NETIF_MSG_LINK,
4884 "Flash download not supported for this ext phy\n");
4885 rc = -EINVAL;
4886 break;
4887 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
4888 /* Take ext phy out of reset */
4889 if (!driver_loaded)
4890 bnx2x_turn_on_ef(bp, port, ext_phy_addr, ext_phy_type);
4891 rc = bnx2x_sfx7101_flash_download(bp, port, ext_phy_addr,
4892 data, size);
4893 if (!driver_loaded)
4894 bnx2x_turn_off_sf(bp, port);
4895 break;
4896 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
4897 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
4898 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
4899 default:
4900 DP(NETIF_MSG_LINK, "Invalid ext phy type\n");
4901 rc = -EINVAL;
4902 break;
4904 return rc;