bnx2x: 8073 PHY changes
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / net / bnx2x_link.c
blob693efce7cda5f0dbf5aed18983d63ec3f8b55a06
1 /* Copyright 2008 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>
24 #include <linux/version.h>
26 #include "bnx2x_reg.h"
27 #include "bnx2x_fw_defs.h"
28 #include "bnx2x_hsi.h"
29 #include "bnx2x_link.h"
30 #include "bnx2x.h"
32 /********************************************************/
33 #define SUPPORT_CL73 0 /* Currently no */
34 #define ETH_HLEN 14
35 #define ETH_OVREHEAD (ETH_HLEN + 8)/* 8 for CRC + VLAN*/
36 #define ETH_MIN_PACKET_SIZE 60
37 #define ETH_MAX_PACKET_SIZE 1500
38 #define ETH_MAX_JUMBO_PACKET_SIZE 9600
39 #define MDIO_ACCESS_TIMEOUT 1000
40 #define BMAC_CONTROL_RX_ENABLE 2
42 /***********************************************************/
43 /* Shortcut definitions */
44 /***********************************************************/
46 #define NIG_STATUS_XGXS0_LINK10G \
47 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G
48 #define NIG_STATUS_XGXS0_LINK_STATUS \
49 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS
50 #define NIG_STATUS_XGXS0_LINK_STATUS_SIZE \
51 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE
52 #define NIG_STATUS_SERDES0_LINK_STATUS \
53 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS
54 #define NIG_MASK_MI_INT \
55 NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT
56 #define NIG_MASK_XGXS0_LINK10G \
57 NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G
58 #define NIG_MASK_XGXS0_LINK_STATUS \
59 NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK_STATUS
60 #define NIG_MASK_SERDES0_LINK_STATUS \
61 NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS
63 #define MDIO_AN_CL73_OR_37_COMPLETE \
64 (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | \
65 MDIO_GP_STATUS_TOP_AN_STATUS1_CL37_AUTONEG_COMPLETE)
67 #define XGXS_RESET_BITS \
68 (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW | \
69 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_IDDQ | \
70 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN | \
71 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN_SD | \
72 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB)
74 #define SERDES_RESET_BITS \
75 (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_RSTB_HW | \
76 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ | \
77 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN | \
78 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN_SD)
80 #define AUTONEG_CL37 SHARED_HW_CFG_AN_ENABLE_CL37
81 #define AUTONEG_CL73 SHARED_HW_CFG_AN_ENABLE_CL73
82 #define AUTONEG_BAM SHARED_HW_CFG_AN_ENABLE_BAM
83 #define AUTONEG_PARALLEL \
84 SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
85 #define AUTONEG_SGMII_FIBER_AUTODET \
86 SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT
87 #define AUTONEG_REMOTE_PHY SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY
89 #define GP_STATUS_PAUSE_RSOLUTION_TXSIDE \
90 MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE
91 #define GP_STATUS_PAUSE_RSOLUTION_RXSIDE \
92 MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_RXSIDE
93 #define GP_STATUS_SPEED_MASK \
94 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_MASK
95 #define GP_STATUS_10M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10M
96 #define GP_STATUS_100M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_100M
97 #define GP_STATUS_1G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G
98 #define GP_STATUS_2_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_2_5G
99 #define GP_STATUS_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_5G
100 #define GP_STATUS_6G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_6G
101 #define GP_STATUS_10G_HIG \
102 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG
103 #define GP_STATUS_10G_CX4 \
104 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4
105 #define GP_STATUS_12G_HIG \
106 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12G_HIG
107 #define GP_STATUS_12_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12_5G
108 #define GP_STATUS_13G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_13G
109 #define GP_STATUS_15G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_15G
110 #define GP_STATUS_16G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G
111 #define GP_STATUS_1G_KX MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX
112 #define GP_STATUS_10G_KX4 \
113 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
115 #define LINK_10THD LINK_STATUS_SPEED_AND_DUPLEX_10THD
116 #define LINK_10TFD LINK_STATUS_SPEED_AND_DUPLEX_10TFD
117 #define LINK_100TXHD LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
118 #define LINK_100T4 LINK_STATUS_SPEED_AND_DUPLEX_100T4
119 #define LINK_100TXFD LINK_STATUS_SPEED_AND_DUPLEX_100TXFD
120 #define LINK_1000THD LINK_STATUS_SPEED_AND_DUPLEX_1000THD
121 #define LINK_1000TFD LINK_STATUS_SPEED_AND_DUPLEX_1000TFD
122 #define LINK_1000XFD LINK_STATUS_SPEED_AND_DUPLEX_1000XFD
123 #define LINK_2500THD LINK_STATUS_SPEED_AND_DUPLEX_2500THD
124 #define LINK_2500TFD LINK_STATUS_SPEED_AND_DUPLEX_2500TFD
125 #define LINK_2500XFD LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
126 #define LINK_10GTFD LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
127 #define LINK_10GXFD LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
128 #define LINK_12GTFD LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
129 #define LINK_12GXFD LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
130 #define LINK_12_5GTFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD
131 #define LINK_12_5GXFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD
132 #define LINK_13GTFD LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
133 #define LINK_13GXFD LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
134 #define LINK_15GTFD LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
135 #define LINK_15GXFD LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
136 #define LINK_16GTFD LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
137 #define LINK_16GXFD LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
139 #define PHY_XGXS_FLAG 0x1
140 #define PHY_SGMII_FLAG 0x2
141 #define PHY_SERDES_FLAG 0x4
143 /**********************************************************/
144 /* INTERFACE */
145 /**********************************************************/
146 #define CL45_WR_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
147 bnx2x_cl45_write(_bp, _port, 0, _phy_addr, \
148 DEFAULT_PHY_DEV_ADDR, \
149 (_bank + (_addr & 0xf)), \
150 _val)
152 #define CL45_RD_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
153 bnx2x_cl45_read(_bp, _port, 0, _phy_addr, \
154 DEFAULT_PHY_DEV_ADDR, \
155 (_bank + (_addr & 0xf)), \
156 _val)
158 static void bnx2x_set_phy_mdio(struct link_params *params)
160 struct bnx2x *bp = params->bp;
161 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
162 params->port*0x18, 0);
163 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
164 DEFAULT_PHY_DEV_ADDR);
167 static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
169 u32 val = REG_RD(bp, reg);
171 val |= bits;
172 REG_WR(bp, reg, val);
173 return val;
176 static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits)
178 u32 val = REG_RD(bp, reg);
180 val &= ~bits;
181 REG_WR(bp, reg, val);
182 return val;
185 static void bnx2x_emac_init(struct link_params *params,
186 struct link_vars *vars)
188 /* reset and unreset the emac core */
189 struct bnx2x *bp = params->bp;
190 u8 port = params->port;
191 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
192 u32 val;
193 u16 timeout;
195 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
196 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
197 udelay(5);
198 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
199 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
201 /* init emac - use read-modify-write */
202 /* self clear reset */
203 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
204 EMAC_WR(EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET));
206 timeout = 200;
209 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
210 DP(NETIF_MSG_LINK, "EMAC reset reg is %u\n", val);
211 if (!timeout) {
212 DP(NETIF_MSG_LINK, "EMAC timeout!\n");
213 return;
215 timeout--;
216 }while (val & EMAC_MODE_RESET);
218 /* Set mac address */
219 val = ((params->mac_addr[0] << 8) |
220 params->mac_addr[1]);
221 EMAC_WR(EMAC_REG_EMAC_MAC_MATCH, val);
223 val = ((params->mac_addr[2] << 24) |
224 (params->mac_addr[3] << 16) |
225 (params->mac_addr[4] << 8) |
226 params->mac_addr[5]);
227 EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + 4, val);
230 static u8 bnx2x_emac_enable(struct link_params *params,
231 struct link_vars *vars, u8 lb)
233 struct bnx2x *bp = params->bp;
234 u8 port = params->port;
235 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
236 u32 val;
238 DP(NETIF_MSG_LINK, "enabling EMAC\n");
240 /* enable emac and not bmac */
241 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
243 /* for paladium */
244 if (CHIP_REV_IS_EMUL(bp)) {
245 /* Use lane 1 (of lanes 0-3) */
246 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
247 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
248 port*4, 1);
250 /* for fpga */
251 else
253 if (CHIP_REV_IS_FPGA(bp)) {
254 /* Use lane 1 (of lanes 0-3) */
255 DP(NETIF_MSG_LINK, "bnx2x_emac_enable: Setting FPGA\n");
257 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
258 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4,
260 } else
261 /* ASIC */
262 if (vars->phy_flags & PHY_XGXS_FLAG) {
263 u32 ser_lane = ((params->lane_config &
264 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
265 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
267 DP(NETIF_MSG_LINK, "XGXS\n");
268 /* select the master lanes (out of 0-3) */
269 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 +
270 port*4, ser_lane);
271 /* select XGXS */
272 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
273 port*4, 1);
275 } else { /* SerDes */
276 DP(NETIF_MSG_LINK, "SerDes\n");
277 /* select SerDes */
278 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
279 port*4, 0);
282 /* enable emac */
283 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1);
285 if (CHIP_REV_IS_SLOW(bp)) {
286 /* config GMII mode */
287 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
288 EMAC_WR(EMAC_REG_EMAC_MODE,
289 (val | EMAC_MODE_PORT_GMII));
290 } else { /* ASIC */
291 /* pause enable/disable */
292 bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
293 EMAC_RX_MODE_FLOW_EN);
294 if (vars->flow_ctrl & FLOW_CTRL_RX)
295 bnx2x_bits_en(bp, emac_base +
296 EMAC_REG_EMAC_RX_MODE,
297 EMAC_RX_MODE_FLOW_EN);
299 bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
300 (EMAC_TX_MODE_EXT_PAUSE_EN |
301 EMAC_TX_MODE_FLOW_EN));
302 if (vars->flow_ctrl & FLOW_CTRL_TX)
303 bnx2x_bits_en(bp, emac_base +
304 EMAC_REG_EMAC_TX_MODE,
305 (EMAC_TX_MODE_EXT_PAUSE_EN |
306 EMAC_TX_MODE_FLOW_EN));
309 /* KEEP_VLAN_TAG, promiscuous */
310 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
311 val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
312 EMAC_WR(EMAC_REG_EMAC_RX_MODE, val);
314 /* Set Loopback */
315 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
316 if (lb)
317 val |= 0x810;
318 else
319 val &= ~0x810;
320 EMAC_WR(EMAC_REG_EMAC_MODE, val);
322 /* enable emac for jumbo packets */
323 EMAC_WR(EMAC_REG_EMAC_RX_MTU_SIZE,
324 (EMAC_RX_MTU_SIZE_JUMBO_ENA |
325 (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD)));
327 /* strip CRC */
328 REG_WR(bp, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1);
330 /* disable the NIG in/out to the bmac */
331 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x0);
332 REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, 0x0);
333 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x0);
335 /* enable the NIG in/out to the emac */
336 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x1);
337 val = 0;
338 if (vars->flow_ctrl & FLOW_CTRL_TX)
339 val = 1;
341 REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
342 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x1);
344 if (CHIP_REV_IS_EMUL(bp)) {
345 /* take the BigMac out of reset */
346 REG_WR(bp,
347 GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
348 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
350 /* enable access for bmac registers */
351 REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
354 vars->mac_type = MAC_TYPE_EMAC;
355 return 0;
360 static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
361 u8 is_lb)
363 struct bnx2x *bp = params->bp;
364 u8 port = params->port;
365 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
366 NIG_REG_INGRESS_BMAC0_MEM;
367 u32 wb_data[2];
368 u32 val;
370 DP(NETIF_MSG_LINK, "Enabling BigMAC\n");
371 /* reset and unreset the BigMac */
372 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
373 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
374 msleep(1);
376 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
377 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
379 /* enable access for bmac registers */
380 REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
382 /* XGXS control */
383 wb_data[0] = 0x3c;
384 wb_data[1] = 0;
385 REG_WR_DMAE(bp, bmac_addr +
386 BIGMAC_REGISTER_BMAC_XGXS_CONTROL,
387 wb_data, 2);
389 /* tx MAC SA */
390 wb_data[0] = ((params->mac_addr[2] << 24) |
391 (params->mac_addr[3] << 16) |
392 (params->mac_addr[4] << 8) |
393 params->mac_addr[5]);
394 wb_data[1] = ((params->mac_addr[0] << 8) |
395 params->mac_addr[1]);
396 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR,
397 wb_data, 2);
399 /* tx control */
400 val = 0xc0;
401 if (vars->flow_ctrl & FLOW_CTRL_TX)
402 val |= 0x800000;
403 wb_data[0] = val;
404 wb_data[1] = 0;
405 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_CONTROL,
406 wb_data, 2);
408 /* mac control */
409 val = 0x3;
410 if (is_lb) {
411 val |= 0x4;
412 DP(NETIF_MSG_LINK, "enable bmac loopback\n");
414 wb_data[0] = val;
415 wb_data[1] = 0;
416 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
417 wb_data, 2);
420 /* set rx mtu */
421 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
422 wb_data[1] = 0;
423 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE,
424 wb_data, 2);
426 /* rx control set to don't strip crc */
427 val = 0x14;
428 if (vars->flow_ctrl & FLOW_CTRL_RX)
429 val |= 0x20;
430 wb_data[0] = val;
431 wb_data[1] = 0;
432 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_CONTROL,
433 wb_data, 2);
435 /* set tx mtu */
436 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
437 wb_data[1] = 0;
438 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE,
439 wb_data, 2);
441 /* set cnt max size */
442 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
443 wb_data[1] = 0;
444 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE,
445 wb_data, 2);
447 /* configure safc */
448 wb_data[0] = 0x1000200;
449 wb_data[1] = 0;
450 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
451 wb_data, 2);
452 /* fix for emulation */
453 if (CHIP_REV_IS_EMUL(bp)) {
454 wb_data[0] = 0xf000;
455 wb_data[1] = 0;
456 REG_WR_DMAE(bp,
457 bmac_addr + BIGMAC_REGISTER_TX_PAUSE_THRESHOLD,
458 wb_data, 2);
461 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
462 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
463 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
464 val = 0;
465 if (vars->flow_ctrl & FLOW_CTRL_TX)
466 val = 1;
467 REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
468 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
469 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x0);
470 REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, 0x0);
471 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x1);
472 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);
474 vars->mac_type = MAC_TYPE_BMAC;
475 return 0;
478 static void bnx2x_phy_deassert(struct link_params *params, u8 phy_flags)
480 struct bnx2x *bp = params->bp;
481 u32 val;
483 if (phy_flags & PHY_XGXS_FLAG) {
484 DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:XGXS\n");
485 val = XGXS_RESET_BITS;
487 } else { /* SerDes */
488 DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:SerDes\n");
489 val = SERDES_RESET_BITS;
492 val = val << (params->port*16);
494 /* reset and unreset the SerDes/XGXS */
495 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
496 val);
497 udelay(500);
498 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET,
499 val);
500 bnx2x_set_phy_mdio(params);
503 void bnx2x_link_status_update(struct link_params *params,
504 struct link_vars *vars)
506 struct bnx2x *bp = params->bp;
507 u8 link_10g;
508 u8 port = params->port;
510 if (params->switch_cfg == SWITCH_CFG_1G)
511 vars->phy_flags = PHY_SERDES_FLAG;
512 else
513 vars->phy_flags = PHY_XGXS_FLAG;
514 vars->link_status = REG_RD(bp, params->shmem_base +
515 offsetof(struct shmem_region,
516 port_mb[port].link_status));
518 vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
520 if (vars->link_up) {
521 DP(NETIF_MSG_LINK, "phy link up\n");
523 vars->phy_link_up = 1;
524 vars->duplex = DUPLEX_FULL;
525 switch (vars->link_status &
526 LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
527 case LINK_10THD:
528 vars->duplex = DUPLEX_HALF;
529 /* fall thru */
530 case LINK_10TFD:
531 vars->line_speed = SPEED_10;
532 break;
534 case LINK_100TXHD:
535 vars->duplex = DUPLEX_HALF;
536 /* fall thru */
537 case LINK_100T4:
538 case LINK_100TXFD:
539 vars->line_speed = SPEED_100;
540 break;
542 case LINK_1000THD:
543 vars->duplex = DUPLEX_HALF;
544 /* fall thru */
545 case LINK_1000TFD:
546 vars->line_speed = SPEED_1000;
547 break;
549 case LINK_2500THD:
550 vars->duplex = DUPLEX_HALF;
551 /* fall thru */
552 case LINK_2500TFD:
553 vars->line_speed = SPEED_2500;
554 break;
556 case LINK_10GTFD:
557 vars->line_speed = SPEED_10000;
558 break;
560 case LINK_12GTFD:
561 vars->line_speed = SPEED_12000;
562 break;
564 case LINK_12_5GTFD:
565 vars->line_speed = SPEED_12500;
566 break;
568 case LINK_13GTFD:
569 vars->line_speed = SPEED_13000;
570 break;
572 case LINK_15GTFD:
573 vars->line_speed = SPEED_15000;
574 break;
576 case LINK_16GTFD:
577 vars->line_speed = SPEED_16000;
578 break;
580 default:
581 break;
584 if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
585 vars->flow_ctrl |= FLOW_CTRL_TX;
586 else
587 vars->flow_ctrl &= ~FLOW_CTRL_TX;
589 if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
590 vars->flow_ctrl |= FLOW_CTRL_RX;
591 else
592 vars->flow_ctrl &= ~FLOW_CTRL_RX;
594 if (vars->phy_flags & PHY_XGXS_FLAG) {
595 if (vars->line_speed &&
596 ((vars->line_speed == SPEED_10) ||
597 (vars->line_speed == SPEED_100))) {
598 vars->phy_flags |= PHY_SGMII_FLAG;
599 } else {
600 vars->phy_flags &= ~PHY_SGMII_FLAG;
604 /* anything 10 and over uses the bmac */
605 link_10g = ((vars->line_speed == SPEED_10000) ||
606 (vars->line_speed == SPEED_12000) ||
607 (vars->line_speed == SPEED_12500) ||
608 (vars->line_speed == SPEED_13000) ||
609 (vars->line_speed == SPEED_15000) ||
610 (vars->line_speed == SPEED_16000));
611 if (link_10g)
612 vars->mac_type = MAC_TYPE_BMAC;
613 else
614 vars->mac_type = MAC_TYPE_EMAC;
616 } else { /* link down */
617 DP(NETIF_MSG_LINK, "phy link down\n");
619 vars->phy_link_up = 0;
621 vars->line_speed = 0;
622 vars->duplex = DUPLEX_FULL;
623 vars->flow_ctrl = FLOW_CTRL_NONE;
625 /* indicate no mac active */
626 vars->mac_type = MAC_TYPE_NONE;
629 DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x\n",
630 vars->link_status, vars->phy_link_up);
631 DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n",
632 vars->line_speed, vars->duplex, vars->flow_ctrl);
635 static void bnx2x_update_mng(struct link_params *params, u32 link_status)
637 struct bnx2x *bp = params->bp;
638 REG_WR(bp, params->shmem_base +
639 offsetof(struct shmem_region,
640 port_mb[params->port].link_status),
641 link_status);
644 static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
646 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
647 NIG_REG_INGRESS_BMAC0_MEM;
648 u32 wb_data[2];
649 u32 nig_bmac_enable = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4);
651 /* Only if the bmac is out of reset */
652 if (REG_RD(bp, MISC_REG_RESET_REG_2) &
653 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) &&
654 nig_bmac_enable) {
656 /* Clear Rx Enable bit in BMAC_CONTROL register */
657 REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
658 wb_data, 2);
659 wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
660 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
661 wb_data, 2);
663 msleep(1);
667 static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
668 u32 line_speed)
670 struct bnx2x *bp = params->bp;
671 u8 port = params->port;
672 u32 init_crd, crd;
673 u32 count = 1000;
675 /* disable port */
676 REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1);
678 /* wait for init credit */
679 init_crd = REG_RD(bp, PBF_REG_P0_INIT_CRD + port*4);
680 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
681 DP(NETIF_MSG_LINK, "init_crd 0x%x crd 0x%x\n", init_crd, crd);
683 while ((init_crd != crd) && count) {
684 msleep(5);
686 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
687 count--;
689 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
690 if (init_crd != crd) {
691 DP(NETIF_MSG_LINK, "BUG! init_crd 0x%x != crd 0x%x\n",
692 init_crd, crd);
693 return -EINVAL;
696 if (flow_ctrl & FLOW_CTRL_RX ||
697 line_speed == SPEED_10 ||
698 line_speed == SPEED_100 ||
699 line_speed == SPEED_1000 ||
700 line_speed == SPEED_2500) {
701 REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 1);
702 /* update threshold */
703 REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, 0);
704 /* update init credit */
705 init_crd = 778; /* (800-18-4) */
707 } else {
708 u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
709 ETH_OVREHEAD)/16;
710 REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
711 /* update threshold */
712 REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh);
713 /* update init credit */
714 switch (line_speed) {
715 case SPEED_10000:
716 init_crd = thresh + 553 - 22;
717 break;
719 case SPEED_12000:
720 init_crd = thresh + 664 - 22;
721 break;
723 case SPEED_13000:
724 init_crd = thresh + 742 - 22;
725 break;
727 case SPEED_16000:
728 init_crd = thresh + 778 - 22;
729 break;
730 default:
731 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
732 line_speed);
733 return -EINVAL;
734 break;
737 REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, init_crd);
738 DP(NETIF_MSG_LINK, "PBF updated to speed %d credit %d\n",
739 line_speed, init_crd);
741 /* probe the credit changes */
742 REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x1);
743 msleep(5);
744 REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x0);
746 /* enable port */
747 REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x0);
748 return 0;
751 static u32 bnx2x_get_emac_base(u32 ext_phy_type, u8 port)
753 u32 emac_base;
754 switch (ext_phy_type) {
755 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
756 emac_base = GRCBASE_EMAC0;
757 break;
758 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
759 emac_base = (port) ? GRCBASE_EMAC0: GRCBASE_EMAC1;
760 break;
761 default:
762 emac_base = (port) ? GRCBASE_EMAC1: GRCBASE_EMAC0;
763 break;
765 return emac_base;
769 u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type,
770 u8 phy_addr, u8 devad, u16 reg, u16 val)
772 u32 tmp, saved_mode;
773 u8 i, rc = 0;
774 u32 mdio_ctrl = bnx2x_get_emac_base(ext_phy_type, port);
776 /* set clause 45 mode, slow down the MDIO clock to 2.5MHz
777 * (a value of 49==0x31) and make sure that the AUTO poll is off
779 saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
780 tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
781 EMAC_MDIO_MODE_CLOCK_CNT);
782 tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
783 (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
784 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
785 REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
786 udelay(40);
788 /* address */
790 tmp = ((phy_addr << 21) | (devad << 16) | reg |
791 EMAC_MDIO_COMM_COMMAND_ADDRESS |
792 EMAC_MDIO_COMM_START_BUSY);
793 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
795 for (i = 0; i < 50; i++) {
796 udelay(10);
798 tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
799 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
800 udelay(5);
801 break;
804 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
805 DP(NETIF_MSG_LINK, "write phy register failed\n");
806 rc = -EFAULT;
807 } else {
808 /* data */
809 tmp = ((phy_addr << 21) | (devad << 16) | val |
810 EMAC_MDIO_COMM_COMMAND_WRITE_45 |
811 EMAC_MDIO_COMM_START_BUSY);
812 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
814 for (i = 0; i < 50; i++) {
815 udelay(10);
817 tmp = REG_RD(bp, mdio_ctrl +
818 EMAC_REG_EMAC_MDIO_COMM);
819 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
820 udelay(5);
821 break;
824 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
825 DP(NETIF_MSG_LINK, "write phy register failed\n");
826 rc = -EFAULT;
830 /* Restore the saved mode */
831 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
833 return rc;
836 u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type,
837 u8 phy_addr, u8 devad, u16 reg, u16 *ret_val)
839 u32 val, saved_mode;
840 u16 i;
841 u8 rc = 0;
843 u32 mdio_ctrl = bnx2x_get_emac_base(ext_phy_type, port);
844 /* set clause 45 mode, slow down the MDIO clock to 2.5MHz
845 * (a value of 49==0x31) and make sure that the AUTO poll is off
847 saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
848 val = saved_mode & ((EMAC_MDIO_MODE_AUTO_POLL |
849 EMAC_MDIO_MODE_CLOCK_CNT));
850 val |= (EMAC_MDIO_MODE_CLAUSE_45 |
851 (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
852 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
853 REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
854 udelay(40);
856 /* address */
857 val = ((phy_addr << 21) | (devad << 16) | reg |
858 EMAC_MDIO_COMM_COMMAND_ADDRESS |
859 EMAC_MDIO_COMM_START_BUSY);
860 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
862 for (i = 0; i < 50; i++) {
863 udelay(10);
865 val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
866 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
867 udelay(5);
868 break;
871 if (val & EMAC_MDIO_COMM_START_BUSY) {
872 DP(NETIF_MSG_LINK, "read phy register failed\n");
874 *ret_val = 0;
875 rc = -EFAULT;
877 } else {
878 /* data */
879 val = ((phy_addr << 21) | (devad << 16) |
880 EMAC_MDIO_COMM_COMMAND_READ_45 |
881 EMAC_MDIO_COMM_START_BUSY);
882 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
884 for (i = 0; i < 50; i++) {
885 udelay(10);
887 val = REG_RD(bp, mdio_ctrl +
888 EMAC_REG_EMAC_MDIO_COMM);
889 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
890 *ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
891 break;
894 if (val & EMAC_MDIO_COMM_START_BUSY) {
895 DP(NETIF_MSG_LINK, "read phy register failed\n");
897 *ret_val = 0;
898 rc = -EFAULT;
902 /* Restore the saved mode */
903 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
905 return rc;
908 static void bnx2x_set_aer_mmd(struct link_params *params,
909 struct link_vars *vars)
911 struct bnx2x *bp = params->bp;
912 u32 ser_lane;
913 u16 offset;
915 ser_lane = ((params->lane_config &
916 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
917 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
919 offset = (vars->phy_flags & PHY_XGXS_FLAG) ?
920 (params->phy_addr + ser_lane) : 0;
922 CL45_WR_OVER_CL22(bp, params->port,
923 params->phy_addr,
924 MDIO_REG_BANK_AER_BLOCK,
925 MDIO_AER_BLOCK_AER_REG, 0x3800 + offset);
928 static void bnx2x_set_master_ln(struct link_params *params)
930 struct bnx2x *bp = params->bp;
931 u16 new_master_ln, ser_lane;
932 ser_lane = ((params->lane_config &
933 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
934 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
936 /* set the master_ln for AN */
937 CL45_RD_OVER_CL22(bp, params->port,
938 params->phy_addr,
939 MDIO_REG_BANK_XGXS_BLOCK2,
940 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
941 &new_master_ln);
943 CL45_WR_OVER_CL22(bp, params->port,
944 params->phy_addr,
945 MDIO_REG_BANK_XGXS_BLOCK2 ,
946 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
947 (new_master_ln | ser_lane));
950 static u8 bnx2x_reset_unicore(struct link_params *params)
952 struct bnx2x *bp = params->bp;
953 u16 mii_control;
954 u16 i;
956 CL45_RD_OVER_CL22(bp, params->port,
957 params->phy_addr,
958 MDIO_REG_BANK_COMBO_IEEE0,
959 MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
961 /* reset the unicore */
962 CL45_WR_OVER_CL22(bp, params->port,
963 params->phy_addr,
964 MDIO_REG_BANK_COMBO_IEEE0,
965 MDIO_COMBO_IEEE0_MII_CONTROL,
966 (mii_control |
967 MDIO_COMBO_IEEO_MII_CONTROL_RESET));
969 /* wait for the reset to self clear */
970 for (i = 0; i < MDIO_ACCESS_TIMEOUT; i++) {
971 udelay(5);
973 /* the reset erased the previous bank value */
974 CL45_RD_OVER_CL22(bp, params->port,
975 params->phy_addr,
976 MDIO_REG_BANK_COMBO_IEEE0,
977 MDIO_COMBO_IEEE0_MII_CONTROL,
978 &mii_control);
980 if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) {
981 udelay(5);
982 return 0;
986 DP(NETIF_MSG_LINK, "BUG! XGXS is still in reset!\n");
987 return -EINVAL;
991 static void bnx2x_set_swap_lanes(struct link_params *params)
993 struct bnx2x *bp = params->bp;
994 /* Each two bits represents a lane number:
995 No swap is 0123 => 0x1b no need to enable the swap */
996 u16 ser_lane, rx_lane_swap, tx_lane_swap;
998 ser_lane = ((params->lane_config &
999 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
1000 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
1001 rx_lane_swap = ((params->lane_config &
1002 PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
1003 PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
1004 tx_lane_swap = ((params->lane_config &
1005 PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
1006 PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
1008 if (rx_lane_swap != 0x1b) {
1009 CL45_WR_OVER_CL22(bp, params->port,
1010 params->phy_addr,
1011 MDIO_REG_BANK_XGXS_BLOCK2,
1012 MDIO_XGXS_BLOCK2_RX_LN_SWAP,
1013 (rx_lane_swap |
1014 MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
1015 MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
1016 } else {
1017 CL45_WR_OVER_CL22(bp, params->port,
1018 params->phy_addr,
1019 MDIO_REG_BANK_XGXS_BLOCK2,
1020 MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
1023 if (tx_lane_swap != 0x1b) {
1024 CL45_WR_OVER_CL22(bp, params->port,
1025 params->phy_addr,
1026 MDIO_REG_BANK_XGXS_BLOCK2,
1027 MDIO_XGXS_BLOCK2_TX_LN_SWAP,
1028 (tx_lane_swap |
1029 MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
1030 } else {
1031 CL45_WR_OVER_CL22(bp, params->port,
1032 params->phy_addr,
1033 MDIO_REG_BANK_XGXS_BLOCK2,
1034 MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
1038 static void bnx2x_set_parallel_detection(struct link_params *params,
1039 u8 phy_flags)
1041 struct bnx2x *bp = params->bp;
1042 u16 control2;
1044 CL45_RD_OVER_CL22(bp, params->port,
1045 params->phy_addr,
1046 MDIO_REG_BANK_SERDES_DIGITAL,
1047 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1048 &control2);
1051 control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
1054 CL45_WR_OVER_CL22(bp, params->port,
1055 params->phy_addr,
1056 MDIO_REG_BANK_SERDES_DIGITAL,
1057 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1058 control2);
1060 if (phy_flags & PHY_XGXS_FLAG) {
1061 DP(NETIF_MSG_LINK, "XGXS\n");
1063 CL45_WR_OVER_CL22(bp, params->port,
1064 params->phy_addr,
1065 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1066 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
1067 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
1069 CL45_RD_OVER_CL22(bp, params->port,
1070 params->phy_addr,
1071 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1072 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
1073 &control2);
1076 control2 |=
1077 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
1079 CL45_WR_OVER_CL22(bp, params->port,
1080 params->phy_addr,
1081 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1082 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
1083 control2);
1085 /* Disable parallel detection of HiG */
1086 CL45_WR_OVER_CL22(bp, params->port,
1087 params->phy_addr,
1088 MDIO_REG_BANK_XGXS_BLOCK2,
1089 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
1090 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
1091 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
1095 static void bnx2x_set_autoneg(struct link_params *params,
1096 struct link_vars *vars)
1098 struct bnx2x *bp = params->bp;
1099 u16 reg_val;
1101 /* CL37 Autoneg */
1103 CL45_RD_OVER_CL22(bp, params->port,
1104 params->phy_addr,
1105 MDIO_REG_BANK_COMBO_IEEE0,
1106 MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1108 /* CL37 Autoneg Enabled */
1109 if (vars->line_speed == SPEED_AUTO_NEG)
1110 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN;
1111 else /* CL37 Autoneg Disabled */
1112 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1113 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);
1115 CL45_WR_OVER_CL22(bp, params->port,
1116 params->phy_addr,
1117 MDIO_REG_BANK_COMBO_IEEE0,
1118 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1120 /* Enable/Disable Autodetection */
1122 CL45_RD_OVER_CL22(bp, params->port,
1123 params->phy_addr,
1124 MDIO_REG_BANK_SERDES_DIGITAL,
1125 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
1126 reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN;
1127 if (vars->line_speed == SPEED_AUTO_NEG)
1128 reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1129 else
1130 reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1132 CL45_WR_OVER_CL22(bp, params->port,
1133 params->phy_addr,
1134 MDIO_REG_BANK_SERDES_DIGITAL,
1135 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
1137 /* Enable TetonII and BAM autoneg */
1138 CL45_RD_OVER_CL22(bp, params->port,
1139 params->phy_addr,
1140 MDIO_REG_BANK_BAM_NEXT_PAGE,
1141 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1142 &reg_val);
1143 if (vars->line_speed == SPEED_AUTO_NEG) {
1144 /* Enable BAM aneg Mode and TetonII aneg Mode */
1145 reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1146 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1147 } else {
1148 /* TetonII and BAM Autoneg Disabled */
1149 reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1150 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1152 CL45_WR_OVER_CL22(bp, params->port,
1153 params->phy_addr,
1154 MDIO_REG_BANK_BAM_NEXT_PAGE,
1155 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1156 reg_val);
1158 /* Enable Clause 73 Aneg */
1159 if ((vars->line_speed == SPEED_AUTO_NEG) &&
1160 (SUPPORT_CL73)) {
1161 /* Enable BAM Station Manager */
1163 CL45_WR_OVER_CL22(bp, params->port,
1164 params->phy_addr,
1165 MDIO_REG_BANK_CL73_USERB0,
1166 MDIO_CL73_USERB0_CL73_BAM_CTRL1,
1167 (MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
1168 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN |
1169 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN));
1171 /* Merge CL73 and CL37 aneg resolution */
1172 CL45_RD_OVER_CL22(bp, params->port,
1173 params->phy_addr,
1174 MDIO_REG_BANK_CL73_USERB0,
1175 MDIO_CL73_USERB0_CL73_BAM_CTRL3,
1176 &reg_val);
1178 CL45_WR_OVER_CL22(bp, params->port,
1179 params->phy_addr,
1180 MDIO_REG_BANK_CL73_USERB0,
1181 MDIO_CL73_USERB0_CL73_BAM_CTRL3,
1182 (reg_val |
1183 MDIO_CL73_USERB0_CL73_BAM_CTRL3_USE_CL73_HCD_MR));
1185 /* Set the CL73 AN speed */
1187 CL45_RD_OVER_CL22(bp, params->port,
1188 params->phy_addr,
1189 MDIO_REG_BANK_CL73_IEEEB1,
1190 MDIO_CL73_IEEEB1_AN_ADV2, &reg_val);
1191 /* In the SerDes we support only the 1G.
1192 In the XGXS we support the 10G KX4
1193 but we currently do not support the KR */
1194 if (vars->phy_flags & PHY_XGXS_FLAG) {
1195 DP(NETIF_MSG_LINK, "XGXS\n");
1196 /* 10G KX4 */
1197 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
1198 } else {
1199 DP(NETIF_MSG_LINK, "SerDes\n");
1200 /* 1000M KX */
1201 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
1203 CL45_WR_OVER_CL22(bp, params->port,
1204 params->phy_addr,
1205 MDIO_REG_BANK_CL73_IEEEB1,
1206 MDIO_CL73_IEEEB1_AN_ADV2, reg_val);
1208 /* CL73 Autoneg Enabled */
1209 reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;
1210 } else {
1211 /* CL73 Autoneg Disabled */
1212 reg_val = 0;
1214 CL45_WR_OVER_CL22(bp, params->port,
1215 params->phy_addr,
1216 MDIO_REG_BANK_CL73_IEEEB0,
1217 MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
1220 /* program SerDes, forced speed */
1221 static void bnx2x_program_serdes(struct link_params *params,
1222 struct link_vars *vars)
1224 struct bnx2x *bp = params->bp;
1225 u16 reg_val;
1227 /* program duplex, disable autoneg */
1229 CL45_RD_OVER_CL22(bp, params->port,
1230 params->phy_addr,
1231 MDIO_REG_BANK_COMBO_IEEE0,
1232 MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1233 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
1234 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN);
1235 if (params->req_duplex == DUPLEX_FULL)
1236 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
1237 CL45_WR_OVER_CL22(bp, params->port,
1238 params->phy_addr,
1239 MDIO_REG_BANK_COMBO_IEEE0,
1240 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1242 /* program speed
1243 - needed only if the speed is greater than 1G (2.5G or 10G) */
1244 CL45_RD_OVER_CL22(bp, params->port,
1245 params->phy_addr,
1246 MDIO_REG_BANK_SERDES_DIGITAL,
1247 MDIO_SERDES_DIGITAL_MISC1, &reg_val);
1248 /* clearing the speed value before setting the right speed */
1249 DP(NETIF_MSG_LINK, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x\n", reg_val);
1251 reg_val &= ~(MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK |
1252 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
1254 if (!((vars->line_speed == SPEED_1000) ||
1255 (vars->line_speed == SPEED_100) ||
1256 (vars->line_speed == SPEED_10))) {
1258 reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M |
1259 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
1260 if (vars->line_speed == SPEED_10000)
1261 reg_val |=
1262 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
1263 if (vars->line_speed == SPEED_13000)
1264 reg_val |=
1265 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
1268 CL45_WR_OVER_CL22(bp, params->port,
1269 params->phy_addr,
1270 MDIO_REG_BANK_SERDES_DIGITAL,
1271 MDIO_SERDES_DIGITAL_MISC1, reg_val);
1275 static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params)
1277 struct bnx2x *bp = params->bp;
1278 u16 val = 0;
1280 /* configure the 48 bits for BAM AN */
1282 /* set extended capabilities */
1283 if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
1284 val |= MDIO_OVER_1G_UP1_2_5G;
1285 if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
1286 val |= MDIO_OVER_1G_UP1_10G;
1287 CL45_WR_OVER_CL22(bp, params->port,
1288 params->phy_addr,
1289 MDIO_REG_BANK_OVER_1G,
1290 MDIO_OVER_1G_UP1, val);
1292 CL45_WR_OVER_CL22(bp, params->port,
1293 params->phy_addr,
1294 MDIO_REG_BANK_OVER_1G,
1295 MDIO_OVER_1G_UP3, 0);
1298 static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u32 *ieee_fc)
1300 *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
1301 /* resolve pause mode and advertisement
1302 * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
1304 switch (params->req_flow_ctrl) {
1305 case FLOW_CTRL_AUTO:
1306 if (params->req_fc_auto_adv == FLOW_CTRL_BOTH) {
1307 *ieee_fc |=
1308 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
1309 } else {
1310 *ieee_fc |=
1311 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1313 break;
1314 case FLOW_CTRL_TX:
1315 *ieee_fc |=
1316 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1317 break;
1319 case FLOW_CTRL_RX:
1320 case FLOW_CTRL_BOTH:
1321 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
1322 break;
1324 case FLOW_CTRL_NONE:
1325 default:
1326 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
1327 break;
1331 static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params,
1332 u32 ieee_fc)
1334 struct bnx2x *bp = params->bp;
1335 /* for AN, we are always publishing full duplex */
1337 CL45_WR_OVER_CL22(bp, params->port,
1338 params->phy_addr,
1339 MDIO_REG_BANK_COMBO_IEEE0,
1340 MDIO_COMBO_IEEE0_AUTO_NEG_ADV, (u16)ieee_fc);
1343 static void bnx2x_restart_autoneg(struct link_params *params)
1345 struct bnx2x *bp = params->bp;
1346 DP(NETIF_MSG_LINK, "bnx2x_restart_autoneg\n");
1347 if (SUPPORT_CL73) {
1348 /* enable and restart clause 73 aneg */
1349 u16 an_ctrl;
1351 CL45_RD_OVER_CL22(bp, params->port,
1352 params->phy_addr,
1353 MDIO_REG_BANK_CL73_IEEEB0,
1354 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1355 &an_ctrl);
1356 CL45_WR_OVER_CL22(bp, params->port,
1357 params->phy_addr,
1358 MDIO_REG_BANK_CL73_IEEEB0,
1359 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1360 (an_ctrl |
1361 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
1362 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
1364 } else {
1365 /* Enable and restart BAM/CL37 aneg */
1366 u16 mii_control;
1368 CL45_RD_OVER_CL22(bp, params->port,
1369 params->phy_addr,
1370 MDIO_REG_BANK_COMBO_IEEE0,
1371 MDIO_COMBO_IEEE0_MII_CONTROL,
1372 &mii_control);
1373 DP(NETIF_MSG_LINK,
1374 "bnx2x_restart_autoneg mii_control before = 0x%x\n",
1375 mii_control);
1376 CL45_WR_OVER_CL22(bp, params->port,
1377 params->phy_addr,
1378 MDIO_REG_BANK_COMBO_IEEE0,
1379 MDIO_COMBO_IEEE0_MII_CONTROL,
1380 (mii_control |
1381 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1382 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
1386 static void bnx2x_initialize_sgmii_process(struct link_params *params,
1387 struct link_vars *vars)
1389 struct bnx2x *bp = params->bp;
1390 u16 control1;
1392 /* in SGMII mode, the unicore is always slave */
1394 CL45_RD_OVER_CL22(bp, params->port,
1395 params->phy_addr,
1396 MDIO_REG_BANK_SERDES_DIGITAL,
1397 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1398 &control1);
1399 control1 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT;
1400 /* set sgmii mode (and not fiber) */
1401 control1 &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE |
1402 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET |
1403 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE);
1404 CL45_WR_OVER_CL22(bp, params->port,
1405 params->phy_addr,
1406 MDIO_REG_BANK_SERDES_DIGITAL,
1407 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1408 control1);
1410 /* if forced speed */
1411 if (!(vars->line_speed == SPEED_AUTO_NEG)) {
1412 /* set speed, disable autoneg */
1413 u16 mii_control;
1415 CL45_RD_OVER_CL22(bp, params->port,
1416 params->phy_addr,
1417 MDIO_REG_BANK_COMBO_IEEE0,
1418 MDIO_COMBO_IEEE0_MII_CONTROL,
1419 &mii_control);
1420 mii_control &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1421 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK|
1422 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX);
1424 switch (vars->line_speed) {
1425 case SPEED_100:
1426 mii_control |=
1427 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100;
1428 break;
1429 case SPEED_1000:
1430 mii_control |=
1431 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_1000;
1432 break;
1433 case SPEED_10:
1434 /* there is nothing to set for 10M */
1435 break;
1436 default:
1437 /* invalid speed for SGMII */
1438 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
1439 vars->line_speed);
1440 break;
1443 /* setting the full duplex */
1444 if (params->req_duplex == DUPLEX_FULL)
1445 mii_control |=
1446 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
1447 CL45_WR_OVER_CL22(bp, params->port,
1448 params->phy_addr,
1449 MDIO_REG_BANK_COMBO_IEEE0,
1450 MDIO_COMBO_IEEE0_MII_CONTROL,
1451 mii_control);
1453 } else { /* AN mode */
1454 /* enable and restart AN */
1455 bnx2x_restart_autoneg(params);
1461 * link management
1464 static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
1465 { /* LD LP */
1466 switch (pause_result) { /* ASYM P ASYM P */
1467 case 0xb: /* 1 0 1 1 */
1468 vars->flow_ctrl = FLOW_CTRL_TX;
1469 break;
1471 case 0xe: /* 1 1 1 0 */
1472 vars->flow_ctrl = FLOW_CTRL_RX;
1473 break;
1475 case 0x5: /* 0 1 0 1 */
1476 case 0x7: /* 0 1 1 1 */
1477 case 0xd: /* 1 1 0 1 */
1478 case 0xf: /* 1 1 1 1 */
1479 vars->flow_ctrl = FLOW_CTRL_BOTH;
1480 break;
1482 default:
1483 break;
1487 static u8 bnx2x_ext_phy_resove_fc(struct link_params *params,
1488 struct link_vars *vars)
1490 struct bnx2x *bp = params->bp;
1491 u8 ext_phy_addr;
1492 u16 ld_pause; /* local */
1493 u16 lp_pause; /* link partner */
1494 u16 an_complete; /* AN complete */
1495 u16 pause_result;
1496 u8 ret = 0;
1497 u32 ext_phy_type;
1498 u8 port = params->port;
1499 ext_phy_addr = ((params->ext_phy_config &
1500 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1501 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1503 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1504 /* read twice */
1506 bnx2x_cl45_read(bp, port,
1507 ext_phy_type,
1508 ext_phy_addr,
1509 MDIO_AN_DEVAD,
1510 MDIO_AN_REG_STATUS, &an_complete);
1511 bnx2x_cl45_read(bp, port,
1512 ext_phy_type,
1513 ext_phy_addr,
1514 MDIO_AN_DEVAD,
1515 MDIO_AN_REG_STATUS, &an_complete);
1517 if (an_complete & MDIO_AN_REG_STATUS_AN_COMPLETE) {
1518 ret = 1;
1519 bnx2x_cl45_read(bp, port,
1520 ext_phy_type,
1521 ext_phy_addr,
1522 MDIO_AN_DEVAD,
1523 MDIO_AN_REG_ADV_PAUSE, &ld_pause);
1524 bnx2x_cl45_read(bp, port,
1525 ext_phy_type,
1526 ext_phy_addr,
1527 MDIO_AN_DEVAD,
1528 MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
1529 pause_result = (ld_pause &
1530 MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
1531 pause_result |= (lp_pause &
1532 MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
1533 DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x \n",
1534 pause_result);
1535 bnx2x_pause_resolve(vars, pause_result);
1536 if (vars->flow_ctrl == FLOW_CTRL_NONE &&
1537 ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
1538 bnx2x_cl45_read(bp, port,
1539 ext_phy_type,
1540 ext_phy_addr,
1541 MDIO_AN_DEVAD,
1542 MDIO_AN_REG_CL37_FC_LD, &ld_pause);
1544 bnx2x_cl45_read(bp, port,
1545 ext_phy_type,
1546 ext_phy_addr,
1547 MDIO_AN_DEVAD,
1548 MDIO_AN_REG_CL37_FC_LP, &lp_pause);
1549 pause_result = (ld_pause &
1550 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
1551 pause_result |= (lp_pause &
1552 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
1554 bnx2x_pause_resolve(vars, pause_result);
1555 DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x \n",
1556 pause_result);
1559 return ret;
1563 static void bnx2x_flow_ctrl_resolve(struct link_params *params,
1564 struct link_vars *vars,
1565 u32 gp_status)
1567 struct bnx2x *bp = params->bp;
1568 u16 ld_pause; /* local driver */
1569 u16 lp_pause; /* link partner */
1570 u16 pause_result;
1572 vars->flow_ctrl = FLOW_CTRL_NONE;
1574 /* resolve from gp_status in case of AN complete and not sgmii */
1575 if ((params->req_flow_ctrl == FLOW_CTRL_AUTO) &&
1576 (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
1577 (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
1578 (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1579 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) {
1580 CL45_RD_OVER_CL22(bp, params->port,
1581 params->phy_addr,
1582 MDIO_REG_BANK_COMBO_IEEE0,
1583 MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
1584 &ld_pause);
1585 CL45_RD_OVER_CL22(bp, params->port,
1586 params->phy_addr,
1587 MDIO_REG_BANK_COMBO_IEEE0,
1588 MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
1589 &lp_pause);
1590 pause_result = (ld_pause &
1591 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
1592 pause_result |= (lp_pause &
1593 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
1594 DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result);
1595 bnx2x_pause_resolve(vars, pause_result);
1596 } else if ((params->req_flow_ctrl == FLOW_CTRL_AUTO) &&
1597 (bnx2x_ext_phy_resove_fc(params, vars))) {
1598 return;
1599 } else {
1600 if (params->req_flow_ctrl == FLOW_CTRL_AUTO)
1601 vars->flow_ctrl = params->req_fc_auto_adv;
1602 else
1603 vars->flow_ctrl = params->req_flow_ctrl;
1605 DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
1609 static u8 bnx2x_link_settings_status(struct link_params *params,
1610 struct link_vars *vars,
1611 u32 gp_status)
1613 struct bnx2x *bp = params->bp;
1614 u8 rc = 0;
1615 vars->link_status = 0;
1617 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
1618 DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
1619 gp_status);
1621 vars->phy_link_up = 1;
1622 vars->link_status |= LINK_STATUS_LINK_UP;
1624 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
1625 vars->duplex = DUPLEX_FULL;
1626 else
1627 vars->duplex = DUPLEX_HALF;
1629 bnx2x_flow_ctrl_resolve(params, vars, gp_status);
1631 switch (gp_status & GP_STATUS_SPEED_MASK) {
1632 case GP_STATUS_10M:
1633 vars->line_speed = SPEED_10;
1634 if (vars->duplex == DUPLEX_FULL)
1635 vars->link_status |= LINK_10TFD;
1636 else
1637 vars->link_status |= LINK_10THD;
1638 break;
1640 case GP_STATUS_100M:
1641 vars->line_speed = SPEED_100;
1642 if (vars->duplex == DUPLEX_FULL)
1643 vars->link_status |= LINK_100TXFD;
1644 else
1645 vars->link_status |= LINK_100TXHD;
1646 break;
1648 case GP_STATUS_1G:
1649 case GP_STATUS_1G_KX:
1650 vars->line_speed = SPEED_1000;
1651 if (vars->duplex == DUPLEX_FULL)
1652 vars->link_status |= LINK_1000TFD;
1653 else
1654 vars->link_status |= LINK_1000THD;
1655 break;
1657 case GP_STATUS_2_5G:
1658 vars->line_speed = SPEED_2500;
1659 if (vars->duplex == DUPLEX_FULL)
1660 vars->link_status |= LINK_2500TFD;
1661 else
1662 vars->link_status |= LINK_2500THD;
1663 break;
1665 case GP_STATUS_5G:
1666 case GP_STATUS_6G:
1667 DP(NETIF_MSG_LINK,
1668 "link speed unsupported gp_status 0x%x\n",
1669 gp_status);
1670 return -EINVAL;
1671 break;
1672 case GP_STATUS_10G_KX4:
1673 case GP_STATUS_10G_HIG:
1674 case GP_STATUS_10G_CX4:
1675 vars->line_speed = SPEED_10000;
1676 vars->link_status |= LINK_10GTFD;
1677 break;
1679 case GP_STATUS_12G_HIG:
1680 vars->line_speed = SPEED_12000;
1681 vars->link_status |= LINK_12GTFD;
1682 break;
1684 case GP_STATUS_12_5G:
1685 vars->line_speed = SPEED_12500;
1686 vars->link_status |= LINK_12_5GTFD;
1687 break;
1689 case GP_STATUS_13G:
1690 vars->line_speed = SPEED_13000;
1691 vars->link_status |= LINK_13GTFD;
1692 break;
1694 case GP_STATUS_15G:
1695 vars->line_speed = SPEED_15000;
1696 vars->link_status |= LINK_15GTFD;
1697 break;
1699 case GP_STATUS_16G:
1700 vars->line_speed = SPEED_16000;
1701 vars->link_status |= LINK_16GTFD;
1702 break;
1704 default:
1705 DP(NETIF_MSG_LINK,
1706 "link speed unsupported gp_status 0x%x\n",
1707 gp_status);
1708 return -EINVAL;
1709 break;
1712 vars->link_status |= LINK_STATUS_SERDES_LINK;
1714 if ((params->req_line_speed == SPEED_AUTO_NEG) &&
1715 ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1716 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
1717 (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1718 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705))) {
1719 vars->autoneg = AUTO_NEG_ENABLED;
1721 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
1722 vars->autoneg |= AUTO_NEG_COMPLETE;
1723 vars->link_status |=
1724 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
1727 vars->autoneg |= AUTO_NEG_PARALLEL_DETECTION_USED;
1728 vars->link_status |=
1729 LINK_STATUS_PARALLEL_DETECTION_USED;
1732 if (vars->flow_ctrl & FLOW_CTRL_TX)
1733 vars->link_status |=
1734 LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
1736 if (vars->flow_ctrl & FLOW_CTRL_RX)
1737 vars->link_status |=
1738 LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
1740 } else { /* link_down */
1741 DP(NETIF_MSG_LINK, "phy link down\n");
1743 vars->phy_link_up = 0;
1745 vars->duplex = DUPLEX_FULL;
1746 vars->flow_ctrl = FLOW_CTRL_NONE;
1747 vars->autoneg = AUTO_NEG_DISABLED;
1748 vars->mac_type = MAC_TYPE_NONE;
1751 DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x \n",
1752 gp_status, vars->phy_link_up, vars->line_speed);
1753 DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x"
1754 " autoneg 0x%x\n",
1755 vars->duplex,
1756 vars->flow_ctrl, vars->autoneg);
1757 DP(NETIF_MSG_LINK, "link_status 0x%x\n", vars->link_status);
1759 return rc;
1762 static void bnx2x_set_sgmii_tx_driver(struct link_params *params)
1764 struct bnx2x *bp = params->bp;
1765 u16 lp_up2;
1766 u16 tx_driver;
1768 /* read precomp */
1770 CL45_RD_OVER_CL22(bp, params->port,
1771 params->phy_addr,
1772 MDIO_REG_BANK_OVER_1G,
1773 MDIO_OVER_1G_LP_UP2, &lp_up2);
1775 CL45_RD_OVER_CL22(bp, params->port,
1776 params->phy_addr,
1777 MDIO_REG_BANK_TX0,
1778 MDIO_TX0_TX_DRIVER, &tx_driver);
1780 /* bits [10:7] at lp_up2, positioned at [15:12] */
1781 lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >>
1782 MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT) <<
1783 MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT);
1785 if ((lp_up2 != 0) &&
1786 (lp_up2 != (tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK))) {
1787 /* replace tx_driver bits [15:12] */
1788 tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
1789 tx_driver |= lp_up2;
1790 CL45_WR_OVER_CL22(bp, params->port,
1791 params->phy_addr,
1792 MDIO_REG_BANK_TX0,
1793 MDIO_TX0_TX_DRIVER, tx_driver);
1797 static u8 bnx2x_emac_program(struct link_params *params,
1798 u32 line_speed, u32 duplex)
1800 struct bnx2x *bp = params->bp;
1801 u8 port = params->port;
1802 u16 mode = 0;
1804 DP(NETIF_MSG_LINK, "setting link speed & duplex\n");
1805 bnx2x_bits_dis(bp, GRCBASE_EMAC0 + port*0x400 +
1806 EMAC_REG_EMAC_MODE,
1807 (EMAC_MODE_25G_MODE |
1808 EMAC_MODE_PORT_MII_10M |
1809 EMAC_MODE_HALF_DUPLEX));
1810 switch (line_speed) {
1811 case SPEED_10:
1812 mode |= EMAC_MODE_PORT_MII_10M;
1813 break;
1815 case SPEED_100:
1816 mode |= EMAC_MODE_PORT_MII;
1817 break;
1819 case SPEED_1000:
1820 mode |= EMAC_MODE_PORT_GMII;
1821 break;
1823 case SPEED_2500:
1824 mode |= (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_GMII);
1825 break;
1827 default:
1828 /* 10G not valid for EMAC */
1829 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n", line_speed);
1830 return -EINVAL;
1833 if (duplex == DUPLEX_HALF)
1834 mode |= EMAC_MODE_HALF_DUPLEX;
1835 bnx2x_bits_en(bp,
1836 GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
1837 mode);
1839 bnx2x_set_led(bp, params->port, LED_MODE_OPER,
1840 line_speed, params->hw_led_mode, params->chip_id);
1841 return 0;
1844 /*****************************************************************************/
1845 /* External Phy section */
1846 /*****************************************************************************/
1847 static void bnx2x_hw_reset(struct bnx2x *bp, u8 port)
1849 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1850 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
1851 msleep(1);
1852 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1853 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
1856 static void bnx2x_ext_phy_reset(struct link_params *params,
1857 struct link_vars *vars)
1859 struct bnx2x *bp = params->bp;
1860 u32 ext_phy_type;
1861 u8 ext_phy_addr = ((params->ext_phy_config &
1862 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1863 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1864 DP(NETIF_MSG_LINK, "Port %x: bnx2x_ext_phy_reset\n", params->port);
1865 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1866 /* The PHY reset is controled by GPIO 1
1867 * Give it 1ms of reset pulse
1869 if (vars->phy_flags & PHY_XGXS_FLAG) {
1871 switch (ext_phy_type) {
1872 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
1873 DP(NETIF_MSG_LINK, "XGXS Direct\n");
1874 break;
1876 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
1877 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
1878 DP(NETIF_MSG_LINK, "XGXS 8705/8706\n");
1880 /* Restore normal power mode*/
1881 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1882 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1883 params->port);
1885 /* HW reset */
1886 bnx2x_hw_reset(bp, params->port);
1888 bnx2x_cl45_write(bp, params->port,
1889 ext_phy_type,
1890 ext_phy_addr,
1891 MDIO_PMA_DEVAD,
1892 MDIO_PMA_REG_CTRL, 0xa040);
1893 break;
1894 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
1895 /* Unset Low Power Mode and SW reset */
1896 /* Restore normal power mode*/
1897 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1898 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1899 params->port);
1901 DP(NETIF_MSG_LINK, "XGXS 8072\n");
1902 bnx2x_cl45_write(bp, params->port,
1903 ext_phy_type,
1904 ext_phy_addr,
1905 MDIO_PMA_DEVAD,
1906 MDIO_PMA_REG_CTRL,
1907 1<<15);
1908 break;
1909 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
1911 u16 emac_base;
1912 emac_base = (params->port) ? GRCBASE_EMAC0 :
1913 GRCBASE_EMAC1;
1915 /* Restore normal power mode*/
1916 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1917 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1918 params->port);
1920 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1921 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1922 params->port);
1924 DP(NETIF_MSG_LINK, "XGXS 8073\n");
1926 break;
1928 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
1929 DP(NETIF_MSG_LINK, "XGXS SFX7101\n");
1931 /* Restore normal power mode*/
1932 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1933 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1934 params->port);
1936 /* HW reset */
1937 bnx2x_hw_reset(bp, params->port);
1939 break;
1941 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
1942 DP(NETIF_MSG_LINK, "XGXS PHY Failure detected\n");
1943 break;
1945 default:
1946 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
1947 params->ext_phy_config);
1948 break;
1951 } else { /* SerDes */
1952 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
1953 switch (ext_phy_type) {
1954 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
1955 DP(NETIF_MSG_LINK, "SerDes Direct\n");
1956 break;
1958 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
1959 DP(NETIF_MSG_LINK, "SerDes 5482\n");
1960 bnx2x_hw_reset(bp, params->port);
1961 break;
1963 default:
1964 DP(NETIF_MSG_LINK,
1965 "BAD SerDes ext_phy_config 0x%x\n",
1966 params->ext_phy_config);
1967 break;
1972 static void bnx2x_bcm8072_external_rom_boot(struct link_params *params)
1974 struct bnx2x *bp = params->bp;
1975 u8 port = params->port;
1976 u8 ext_phy_addr = ((params->ext_phy_config &
1977 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1978 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1979 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1980 u16 fw_ver1, fw_ver2;
1982 /* Need to wait 200ms after reset */
1983 msleep(200);
1984 /* Boot port from external ROM
1985 * Set ser_boot_ctl bit in the MISC_CTRL1 register
1987 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1988 MDIO_PMA_DEVAD,
1989 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
1991 /* Reset internal microprocessor */
1992 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1993 MDIO_PMA_DEVAD,
1994 MDIO_PMA_REG_GEN_CTRL,
1995 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
1996 /* set micro reset = 0 */
1997 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1998 MDIO_PMA_DEVAD,
1999 MDIO_PMA_REG_GEN_CTRL,
2000 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
2001 /* Reset internal microprocessor */
2002 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2003 MDIO_PMA_DEVAD,
2004 MDIO_PMA_REG_GEN_CTRL,
2005 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2006 /* wait for 100ms for code download via SPI port */
2007 msleep(100);
2009 /* Clear ser_boot_ctl bit */
2010 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2011 MDIO_PMA_DEVAD,
2012 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2013 /* Wait 100ms */
2014 msleep(100);
2016 /* Print the PHY FW version */
2017 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2018 MDIO_PMA_DEVAD,
2019 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
2020 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2021 MDIO_PMA_DEVAD,
2022 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
2023 DP(NETIF_MSG_LINK, "8072 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
2026 static u8 bnx2x_8073_is_snr_needed(struct link_params *params)
2028 /* This is only required for 8073A1, version 102 only */
2030 struct bnx2x *bp = params->bp;
2031 u8 ext_phy_addr = ((params->ext_phy_config &
2032 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2033 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2034 u16 val;
2036 /* Read 8073 HW revision*/
2037 bnx2x_cl45_read(bp, params->port,
2038 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2039 ext_phy_addr,
2040 MDIO_PMA_DEVAD,
2041 0xc801, &val);
2043 if (val != 1) {
2044 /* No need to workaround in 8073 A1 */
2045 return 0;
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 MDIO_PMA_REG_ROM_VER2, &val);
2054 /* SNR should be applied only for version 0x102 */
2055 if (val != 0x102)
2056 return 0;
2058 return 1;
2061 static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
2063 struct bnx2x *bp = params->bp;
2064 u8 ext_phy_addr = ((params->ext_phy_config &
2065 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2066 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2067 u16 val, cnt, cnt1 ;
2069 bnx2x_cl45_read(bp, params->port,
2070 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2071 ext_phy_addr,
2072 MDIO_PMA_DEVAD,
2073 0xc801, &val);
2075 if (val > 0) {
2076 /* No need to workaround in 8073 A1 */
2077 return 0;
2079 /* XAUI workaround in 8073 A0: */
2081 /* After loading the boot ROM and restarting Autoneg,
2082 poll Dev1, Reg $C820: */
2084 for (cnt = 0; cnt < 1000; cnt++) {
2085 bnx2x_cl45_read(bp, params->port,
2086 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2087 ext_phy_addr,
2088 MDIO_PMA_DEVAD,
2089 0xc820, &val);
2090 /* If bit [14] = 0 or bit [13] = 0, continue on with
2091 system initialization (XAUI work-around not required,
2092 as these bits indicate 2.5G or 1G link up). */
2093 if (!(val & (1<<14)) || !(val & (1<<13))) {
2094 DP(NETIF_MSG_LINK, "XAUI work-around not required\n");
2095 return 0;
2096 } else if (!(val & (1<<15))) {
2097 DP(NETIF_MSG_LINK, "clc bit 15 went off\n");
2098 /* If bit 15 is 0, then poll Dev1, Reg $C841 until
2099 it's MSB (bit 15) goes to 1 (indicating that the
2100 XAUI workaround has completed),
2101 then continue on with system initialization.*/
2102 for (cnt1 = 0; cnt1 < 1000; cnt1++) {
2103 bnx2x_cl45_read(bp, params->port,
2104 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2105 ext_phy_addr,
2106 MDIO_PMA_DEVAD,
2107 0xc841, &val);
2108 if (val & (1<<15)) {
2109 DP(NETIF_MSG_LINK,
2110 "XAUI workaround has completed\n");
2111 return 0;
2113 msleep(3);
2115 break;
2117 msleep(3);
2119 DP(NETIF_MSG_LINK, "Warning: XAUI work-around timeout !!!\n");
2120 return -EINVAL;
2124 static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
2125 u8 ext_phy_addr)
2127 u16 fw_ver1, fw_ver2;
2128 /* Boot port from external ROM */
2129 /* EDC grst */
2130 bnx2x_cl45_write(bp, port,
2131 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2132 ext_phy_addr,
2133 MDIO_PMA_DEVAD,
2134 MDIO_PMA_REG_GEN_CTRL,
2135 0x0001);
2137 /* ucode reboot and rst */
2138 bnx2x_cl45_write(bp, port,
2139 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2140 ext_phy_addr,
2141 MDIO_PMA_DEVAD,
2142 MDIO_PMA_REG_GEN_CTRL,
2143 0x008c);
2145 bnx2x_cl45_write(bp, port,
2146 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2147 ext_phy_addr,
2148 MDIO_PMA_DEVAD,
2149 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
2151 /* Reset internal microprocessor */
2152 bnx2x_cl45_write(bp, port,
2153 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2154 ext_phy_addr,
2155 MDIO_PMA_DEVAD,
2156 MDIO_PMA_REG_GEN_CTRL,
2157 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
2159 /* Release srst bit */
2160 bnx2x_cl45_write(bp, port,
2161 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2162 ext_phy_addr,
2163 MDIO_PMA_DEVAD,
2164 MDIO_PMA_REG_GEN_CTRL,
2165 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2167 /* wait for 100ms for code download via SPI port */
2168 msleep(100);
2170 /* Clear ser_boot_ctl 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_MISC_CTRL1, 0x0000);
2177 bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2178 ext_phy_addr,
2179 MDIO_PMA_DEVAD,
2180 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
2181 bnx2x_cl45_read(bp, port,
2182 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2183 ext_phy_addr,
2184 MDIO_PMA_DEVAD,
2185 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
2186 DP(NETIF_MSG_LINK, "8073 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
2190 static void bnx2x_bcm807x_force_10G(struct link_params *params)
2192 struct bnx2x *bp = params->bp;
2193 u8 port = params->port;
2194 u8 ext_phy_addr = ((params->ext_phy_config &
2195 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2196 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2197 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2199 /* Force KR or KX */
2200 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2201 MDIO_PMA_DEVAD,
2202 MDIO_PMA_REG_CTRL,
2203 0x2040);
2204 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2205 MDIO_PMA_DEVAD,
2206 MDIO_PMA_REG_10G_CTRL2,
2207 0x000b);
2208 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2209 MDIO_PMA_DEVAD,
2210 MDIO_PMA_REG_BCM_CTRL,
2211 0x0000);
2212 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2213 MDIO_AN_DEVAD,
2214 MDIO_AN_REG_CTRL,
2215 0x0000);
2217 static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
2219 struct bnx2x *bp = params->bp;
2220 u8 port = params->port;
2221 u16 val;
2222 u8 ext_phy_addr = ((params->ext_phy_config &
2223 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2224 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2225 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2227 bnx2x_cl45_read(bp, params->port,
2228 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2229 ext_phy_addr,
2230 MDIO_PMA_DEVAD,
2231 0xc801, &val);
2233 if (val == 0) {
2234 /* Mustn't set low power mode in 8073 A0 */
2235 return;
2238 /* Disable PLL sequencer (use read-modify-write to clear bit 13) */
2239 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2240 MDIO_XS_DEVAD,
2241 MDIO_XS_PLL_SEQUENCER, &val);
2242 val &= ~(1<<13);
2243 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2244 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
2246 /* PLL controls */
2247 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2248 MDIO_XS_DEVAD, 0x805E, 0x1077);
2249 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2250 MDIO_XS_DEVAD, 0x805D, 0x0000);
2251 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2252 MDIO_XS_DEVAD, 0x805C, 0x030B);
2253 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2254 MDIO_XS_DEVAD, 0x805B, 0x1240);
2255 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2256 MDIO_XS_DEVAD, 0x805A, 0x2490);
2258 /* Tx Controls */
2259 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2260 MDIO_XS_DEVAD, 0x80A7, 0x0C74);
2261 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2262 MDIO_XS_DEVAD, 0x80A6, 0x9041);
2263 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2264 MDIO_XS_DEVAD, 0x80A5, 0x4640);
2266 /* Rx Controls */
2267 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2268 MDIO_XS_DEVAD, 0x80FE, 0x01C4);
2269 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2270 MDIO_XS_DEVAD, 0x80FD, 0x9249);
2271 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2272 MDIO_XS_DEVAD, 0x80FC, 0x2015);
2274 /* Enable PLL sequencer (use read-modify-write to set bit 13) */
2275 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2276 MDIO_XS_DEVAD,
2277 MDIO_XS_PLL_SEQUENCER, &val);
2278 val |= (1<<13);
2279 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2280 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
2283 static void bnx2x_8073_set_pause_cl37(struct link_params *params,
2284 struct link_vars *vars)
2287 struct bnx2x *bp = params->bp;
2288 u16 cl37_val;
2289 u8 ext_phy_addr = ((params->ext_phy_config &
2290 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2291 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2292 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2294 bnx2x_cl45_read(bp, params->port,
2295 ext_phy_type,
2296 ext_phy_addr,
2297 MDIO_AN_DEVAD,
2298 MDIO_AN_REG_CL37_FC_LD, &cl37_val);
2300 cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
2301 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
2303 if ((vars->ieee_fc &
2304 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
2305 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
2306 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
2308 if ((vars->ieee_fc &
2309 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
2310 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
2311 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
2313 if ((vars->ieee_fc &
2314 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
2315 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
2316 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
2318 DP(NETIF_MSG_LINK,
2319 "Ext phy AN advertize cl37 0x%x\n", cl37_val);
2321 bnx2x_cl45_write(bp, params->port,
2322 ext_phy_type,
2323 ext_phy_addr,
2324 MDIO_AN_DEVAD,
2325 MDIO_AN_REG_CL37_FC_LD, cl37_val);
2326 msleep(500);
2329 static void bnx2x_ext_phy_set_pause(struct link_params *params,
2330 struct link_vars *vars)
2332 struct bnx2x *bp = params->bp;
2333 u16 val;
2334 u8 ext_phy_addr = ((params->ext_phy_config &
2335 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2336 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2337 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2339 /* read modify write pause advertizing */
2340 bnx2x_cl45_read(bp, params->port,
2341 ext_phy_type,
2342 ext_phy_addr,
2343 MDIO_AN_DEVAD,
2344 MDIO_AN_REG_ADV_PAUSE, &val);
2346 val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
2348 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
2350 if ((vars->ieee_fc &
2351 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
2352 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
2353 val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
2355 if ((vars->ieee_fc &
2356 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
2357 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
2358 val |=
2359 MDIO_AN_REG_ADV_PAUSE_PAUSE;
2361 DP(NETIF_MSG_LINK,
2362 "Ext phy AN advertize 0x%x\n", val);
2363 bnx2x_cl45_write(bp, params->port,
2364 ext_phy_type,
2365 ext_phy_addr,
2366 MDIO_AN_DEVAD,
2367 MDIO_AN_REG_ADV_PAUSE, val);
2371 static void bnx2x_init_internal_phy(struct link_params *params,
2372 struct link_vars *vars)
2374 struct bnx2x *bp = params->bp;
2375 u8 port = params->port;
2376 if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
2377 u16 bank, rx_eq;
2379 rx_eq = ((params->serdes_config &
2380 PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK) >>
2381 PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT);
2383 DP(NETIF_MSG_LINK, "setting rx eq to 0x%x\n", rx_eq);
2384 for (bank = MDIO_REG_BANK_RX0; bank <= MDIO_REG_BANK_RX_ALL;
2385 bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0)) {
2386 CL45_WR_OVER_CL22(bp, port,
2387 params->phy_addr,
2388 bank ,
2389 MDIO_RX0_RX_EQ_BOOST,
2390 ((rx_eq &
2391 MDIO_RX0_RX_EQ_BOOST_EQUALIZER_CTRL_MASK) |
2392 MDIO_RX0_RX_EQ_BOOST_OFFSET_CTRL));
2395 /* forced speed requested? */
2396 if (vars->line_speed != SPEED_AUTO_NEG) {
2397 DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
2399 /* disable autoneg */
2400 bnx2x_set_autoneg(params, vars);
2402 /* program speed and duplex */
2403 bnx2x_program_serdes(params, vars);
2405 } else { /* AN_mode */
2406 DP(NETIF_MSG_LINK, "not SGMII, AN\n");
2408 /* AN enabled */
2409 bnx2x_set_brcm_cl37_advertisment(params);
2411 /* program duplex & pause advertisement (for aneg) */
2412 bnx2x_set_ieee_aneg_advertisment(params,
2413 vars->ieee_fc);
2415 /* enable autoneg */
2416 bnx2x_set_autoneg(params, vars);
2418 /* enable and restart AN */
2419 bnx2x_restart_autoneg(params);
2422 } else { /* SGMII mode */
2423 DP(NETIF_MSG_LINK, "SGMII\n");
2425 bnx2x_initialize_sgmii_process(params, vars);
2429 static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
2431 struct bnx2x *bp = params->bp;
2432 u32 ext_phy_type;
2433 u8 ext_phy_addr;
2434 u16 cnt;
2435 u16 ctrl = 0;
2436 u16 val = 0;
2437 u8 rc = 0;
2438 if (vars->phy_flags & PHY_XGXS_FLAG) {
2439 ext_phy_addr = ((params->ext_phy_config &
2440 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2441 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2443 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2444 /* Make sure that the soft reset is off (expect for the 8072:
2445 * due to the lock, it will be done inside the specific
2446 * handling)
2448 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
2449 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
2450 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) &&
2451 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
2452 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
2453 /* Wait for soft reset to get cleared upto 1 sec */
2454 for (cnt = 0; cnt < 1000; cnt++) {
2455 bnx2x_cl45_read(bp, params->port,
2456 ext_phy_type,
2457 ext_phy_addr,
2458 MDIO_PMA_DEVAD,
2459 MDIO_PMA_REG_CTRL, &ctrl);
2460 if (!(ctrl & (1<<15)))
2461 break;
2462 msleep(1);
2464 DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n",
2465 ctrl, cnt);
2468 switch (ext_phy_type) {
2469 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
2470 break;
2472 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2473 DP(NETIF_MSG_LINK, "XGXS 8705\n");
2475 bnx2x_cl45_write(bp, params->port,
2476 ext_phy_type,
2477 ext_phy_addr,
2478 MDIO_PMA_DEVAD,
2479 MDIO_PMA_REG_MISC_CTRL,
2480 0x8288);
2481 bnx2x_cl45_write(bp, params->port,
2482 ext_phy_type,
2483 ext_phy_addr,
2484 MDIO_PMA_DEVAD,
2485 MDIO_PMA_REG_PHY_IDENTIFIER,
2486 0x7fbf);
2487 bnx2x_cl45_write(bp, params->port,
2488 ext_phy_type,
2489 ext_phy_addr,
2490 MDIO_PMA_DEVAD,
2491 MDIO_PMA_REG_CMU_PLL_BYPASS,
2492 0x0100);
2493 bnx2x_cl45_write(bp, params->port,
2494 ext_phy_type,
2495 ext_phy_addr,
2496 MDIO_WIS_DEVAD,
2497 MDIO_WIS_REG_LASI_CNTL, 0x1);
2498 break;
2500 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2501 DP(NETIF_MSG_LINK, "XGXS 8706\n");
2503 msleep(10);
2504 /* Force speed */
2505 /* First enable LASI */
2506 bnx2x_cl45_write(bp, params->port,
2507 ext_phy_type,
2508 ext_phy_addr,
2509 MDIO_PMA_DEVAD,
2510 MDIO_PMA_REG_RX_ALARM_CTRL,
2511 0x0400);
2512 bnx2x_cl45_write(bp, params->port,
2513 ext_phy_type,
2514 ext_phy_addr,
2515 MDIO_PMA_DEVAD,
2516 MDIO_PMA_REG_LASI_CTRL, 0x0004);
2518 if (params->req_line_speed == SPEED_10000) {
2519 DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n");
2521 bnx2x_cl45_write(bp, params->port,
2522 ext_phy_type,
2523 ext_phy_addr,
2524 MDIO_PMA_DEVAD,
2525 MDIO_PMA_REG_DIGITAL_CTRL,
2526 0x400);
2527 } else {
2528 /* Force 1Gbps using autoneg with 1G
2529 advertisment */
2531 /* Allow CL37 through CL73 */
2532 DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
2533 bnx2x_cl45_write(bp, params->port,
2534 ext_phy_type,
2535 ext_phy_addr,
2536 MDIO_AN_DEVAD,
2537 MDIO_AN_REG_CL37_CL73,
2538 0x040c);
2540 /* Enable Full-Duplex advertisment on CL37 */
2541 bnx2x_cl45_write(bp, params->port,
2542 ext_phy_type,
2543 ext_phy_addr,
2544 MDIO_AN_DEVAD,
2545 MDIO_AN_REG_CL37_FC_LP,
2546 0x0020);
2547 /* Enable CL37 AN */
2548 bnx2x_cl45_write(bp, params->port,
2549 ext_phy_type,
2550 ext_phy_addr,
2551 MDIO_AN_DEVAD,
2552 MDIO_AN_REG_CL37_AN,
2553 0x1000);
2554 /* 1G support */
2555 bnx2x_cl45_write(bp, params->port,
2556 ext_phy_type,
2557 ext_phy_addr,
2558 MDIO_AN_DEVAD,
2559 MDIO_AN_REG_ADV, (1<<5));
2561 /* Enable clause 73 AN */
2562 bnx2x_cl45_write(bp, params->port,
2563 ext_phy_type,
2564 ext_phy_addr,
2565 MDIO_AN_DEVAD,
2566 MDIO_AN_REG_CTRL,
2567 0x1200);
2571 break;
2573 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2574 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2576 u16 tmp1;
2577 u16 rx_alarm_ctrl_val;
2578 u16 lasi_ctrl_val;
2579 if (ext_phy_type ==
2580 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
2581 rx_alarm_ctrl_val = 0x400;
2582 lasi_ctrl_val = 0x0004;
2583 } else {
2584 rx_alarm_ctrl_val = (1<<2);
2585 lasi_ctrl_val = 0x0004;
2588 /* enable LASI */
2589 bnx2x_cl45_write(bp, params->port,
2590 ext_phy_type,
2591 ext_phy_addr,
2592 MDIO_PMA_DEVAD,
2593 MDIO_PMA_REG_RX_ALARM_CTRL,
2594 rx_alarm_ctrl_val);
2596 bnx2x_cl45_write(bp, params->port,
2597 ext_phy_type,
2598 ext_phy_addr,
2599 MDIO_PMA_DEVAD,
2600 MDIO_PMA_REG_LASI_CTRL,
2601 lasi_ctrl_val);
2603 bnx2x_8073_set_pause_cl37(params, vars);
2605 if (ext_phy_type ==
2606 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072){
2607 bnx2x_bcm8072_external_rom_boot(params);
2608 } else {
2610 /* In case of 8073 with long xaui lines,
2611 don't set the 8073 xaui low power*/
2612 bnx2x_bcm8073_set_xaui_low_power_mode(params);
2615 bnx2x_cl45_read(bp, params->port,
2616 ext_phy_type,
2617 ext_phy_addr,
2618 MDIO_PMA_DEVAD,
2619 0xca13,
2620 &tmp1);
2622 bnx2x_cl45_read(bp, params->port,
2623 ext_phy_type,
2624 ext_phy_addr,
2625 MDIO_PMA_DEVAD,
2626 MDIO_PMA_REG_RX_ALARM, &tmp1);
2628 DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1):"
2629 "0x%x\n", tmp1);
2631 /* If this is forced speed, set to KR or KX
2632 * (all other are not supported)
2634 if (params->loopback_mode == LOOPBACK_EXT) {
2635 bnx2x_bcm807x_force_10G(params);
2636 DP(NETIF_MSG_LINK,
2637 "Forced speed 10G on 807X\n");
2638 break;
2639 } else {
2640 bnx2x_cl45_write(bp, params->port,
2641 ext_phy_type, ext_phy_addr,
2642 MDIO_PMA_DEVAD,
2643 MDIO_PMA_REG_BCM_CTRL,
2644 0x0002);
2646 if (params->req_line_speed != SPEED_AUTO_NEG) {
2647 if (params->req_line_speed == SPEED_10000) {
2648 val = (1<<7);
2649 } else if (params->req_line_speed ==
2650 SPEED_2500) {
2651 val = (1<<5);
2652 /* Note that 2.5G works only
2653 when used with 1G advertisment */
2654 } else
2655 val = (1<<5);
2656 } else {
2658 val = 0;
2659 if (params->speed_cap_mask &
2660 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
2661 val |= (1<<7);
2663 /* Note that 2.5G works only when
2664 used with 1G advertisment */
2665 if (params->speed_cap_mask &
2666 (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
2667 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
2668 val |= (1<<5);
2669 DP(NETIF_MSG_LINK,
2670 "807x autoneg val = 0x%x\n", val);
2673 bnx2x_cl45_write(bp, params->port,
2674 ext_phy_type,
2675 ext_phy_addr,
2676 MDIO_AN_DEVAD,
2677 MDIO_AN_REG_ADV, val);
2679 if (ext_phy_type ==
2680 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
2682 bnx2x_cl45_read(bp, params->port,
2683 ext_phy_type,
2684 ext_phy_addr,
2685 MDIO_AN_DEVAD,
2686 0x8329, &tmp1);
2688 if (((params->speed_cap_mask &
2689 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
2690 (params->req_line_speed ==
2691 SPEED_AUTO_NEG)) ||
2692 (params->req_line_speed ==
2693 SPEED_2500)) {
2694 u16 phy_ver;
2695 /* Allow 2.5G for A1 and above */
2696 bnx2x_cl45_read(bp, params->port,
2697 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2698 ext_phy_addr,
2699 MDIO_PMA_DEVAD,
2700 0xc801, &phy_ver);
2701 DP(NETIF_MSG_LINK, "Add 2.5G\n");
2702 if (phy_ver > 0)
2703 tmp1 |= 1;
2704 else
2705 tmp1 &= 0xfffe;
2706 } else {
2707 DP(NETIF_MSG_LINK, "Disable 2.5G\n");
2708 tmp1 &= 0xfffe;
2711 bnx2x_cl45_write(bp, params->port,
2712 ext_phy_type,
2713 ext_phy_addr,
2714 MDIO_AN_DEVAD,
2715 0x8329, tmp1);
2718 /* Add support for CL37 (passive mode) II */
2720 bnx2x_cl45_read(bp, params->port,
2721 ext_phy_type,
2722 ext_phy_addr,
2723 MDIO_AN_DEVAD,
2724 MDIO_AN_REG_CL37_FC_LD,
2725 &tmp1);
2727 bnx2x_cl45_write(bp, params->port,
2728 ext_phy_type,
2729 ext_phy_addr,
2730 MDIO_AN_DEVAD,
2731 MDIO_AN_REG_CL37_FC_LD, (tmp1 |
2732 ((params->req_duplex == DUPLEX_FULL) ?
2733 0x20 : 0x40)));
2735 /* Add support for CL37 (passive mode) III */
2736 bnx2x_cl45_write(bp, params->port,
2737 ext_phy_type,
2738 ext_phy_addr,
2739 MDIO_AN_DEVAD,
2740 MDIO_AN_REG_CL37_AN, 0x1000);
2742 if (ext_phy_type ==
2743 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
2744 /* The SNR will improve about 2db by changing
2745 BW and FEE main tap. Rest commands are executed
2746 after link is up*/
2747 /*Change FFE main cursor to 5 in EDC register*/
2748 if (bnx2x_8073_is_snr_needed(params))
2749 bnx2x_cl45_write(bp, params->port,
2750 ext_phy_type,
2751 ext_phy_addr,
2752 MDIO_PMA_DEVAD,
2753 MDIO_PMA_REG_EDC_FFE_MAIN,
2754 0xFB0C);
2756 /* Enable FEC (Forware Error Correction)
2757 Request in the AN */
2758 bnx2x_cl45_read(bp, params->port,
2759 ext_phy_type,
2760 ext_phy_addr,
2761 MDIO_AN_DEVAD,
2762 MDIO_AN_REG_ADV2, &tmp1);
2764 tmp1 |= (1<<15);
2766 bnx2x_cl45_write(bp, params->port,
2767 ext_phy_type,
2768 ext_phy_addr,
2769 MDIO_AN_DEVAD,
2770 MDIO_AN_REG_ADV2, tmp1);
2774 bnx2x_ext_phy_set_pause(params, vars);
2776 /* Restart autoneg */
2777 msleep(500);
2778 bnx2x_cl45_write(bp, params->port,
2779 ext_phy_type,
2780 ext_phy_addr,
2781 MDIO_AN_DEVAD,
2782 MDIO_AN_REG_CTRL, 0x1200);
2783 DP(NETIF_MSG_LINK, "807x Autoneg Restart: "
2784 "Advertise 1G=%x, 10G=%x\n",
2785 ((val & (1<<5)) > 0),
2786 ((val & (1<<7)) > 0));
2787 break;
2789 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
2790 DP(NETIF_MSG_LINK,
2791 "Setting the SFX7101 LASI indication\n");
2793 bnx2x_cl45_write(bp, params->port,
2794 ext_phy_type,
2795 ext_phy_addr,
2796 MDIO_PMA_DEVAD,
2797 MDIO_PMA_REG_LASI_CTRL, 0x1);
2798 DP(NETIF_MSG_LINK,
2799 "Setting the SFX7101 LED to blink on traffic\n");
2800 bnx2x_cl45_write(bp, params->port,
2801 ext_phy_type,
2802 ext_phy_addr,
2803 MDIO_PMA_DEVAD,
2804 MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
2806 bnx2x_ext_phy_set_pause(params, vars);
2807 /* Restart autoneg */
2808 bnx2x_cl45_read(bp, params->port,
2809 ext_phy_type,
2810 ext_phy_addr,
2811 MDIO_AN_DEVAD,
2812 MDIO_AN_REG_CTRL, &val);
2813 val |= 0x200;
2814 bnx2x_cl45_write(bp, params->port,
2815 ext_phy_type,
2816 ext_phy_addr,
2817 MDIO_AN_DEVAD,
2818 MDIO_AN_REG_CTRL, val);
2819 break;
2820 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
2821 DP(NETIF_MSG_LINK,
2822 "XGXS PHY Failure detected 0x%x\n",
2823 params->ext_phy_config);
2824 rc = -EINVAL;
2825 break;
2826 default:
2827 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
2828 params->ext_phy_config);
2829 rc = -EINVAL;
2830 break;
2833 } else { /* SerDes */
2835 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
2836 switch (ext_phy_type) {
2837 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
2838 DP(NETIF_MSG_LINK, "SerDes Direct\n");
2839 break;
2841 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
2842 DP(NETIF_MSG_LINK, "SerDes 5482\n");
2843 break;
2845 default:
2846 DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
2847 params->ext_phy_config);
2848 break;
2851 return rc;
2855 static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
2856 struct link_vars *vars)
2858 struct bnx2x *bp = params->bp;
2859 u32 ext_phy_type;
2860 u8 ext_phy_addr;
2861 u16 val1 = 0, val2;
2862 u16 rx_sd, pcs_status;
2863 u8 ext_phy_link_up = 0;
2864 u8 port = params->port;
2865 if (vars->phy_flags & PHY_XGXS_FLAG) {
2866 ext_phy_addr = ((params->ext_phy_config &
2867 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2868 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2870 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2871 switch (ext_phy_type) {
2872 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
2873 DP(NETIF_MSG_LINK, "XGXS Direct\n");
2874 ext_phy_link_up = 1;
2875 break;
2877 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2878 DP(NETIF_MSG_LINK, "XGXS 8705\n");
2879 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2880 ext_phy_addr,
2881 MDIO_WIS_DEVAD,
2882 MDIO_WIS_REG_LASI_STATUS, &val1);
2883 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
2885 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2886 ext_phy_addr,
2887 MDIO_WIS_DEVAD,
2888 MDIO_WIS_REG_LASI_STATUS, &val1);
2889 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
2891 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2892 ext_phy_addr,
2893 MDIO_PMA_DEVAD,
2894 MDIO_PMA_REG_RX_SD, &rx_sd);
2895 DP(NETIF_MSG_LINK, "8705 rx_sd 0x%x\n", rx_sd);
2896 ext_phy_link_up = (rx_sd & 0x1);
2897 if (ext_phy_link_up)
2898 vars->line_speed = SPEED_10000;
2899 break;
2901 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2902 DP(NETIF_MSG_LINK, "XGXS 8706\n");
2903 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2904 ext_phy_addr,
2905 MDIO_PMA_DEVAD,
2906 MDIO_PMA_REG_LASI_STATUS, &val1);
2907 DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
2909 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2910 ext_phy_addr,
2911 MDIO_PMA_DEVAD,
2912 MDIO_PMA_REG_LASI_STATUS, &val1);
2913 DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
2915 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2916 ext_phy_addr,
2917 MDIO_PMA_DEVAD,
2918 MDIO_PMA_REG_RX_SD, &rx_sd);
2919 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2920 ext_phy_addr,
2921 MDIO_PCS_DEVAD,
2922 MDIO_PCS_REG_STATUS, &pcs_status);
2924 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2925 ext_phy_addr,
2926 MDIO_AN_DEVAD,
2927 MDIO_AN_REG_LINK_STATUS, &val2);
2928 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2929 ext_phy_addr,
2930 MDIO_AN_DEVAD,
2931 MDIO_AN_REG_LINK_STATUS, &val2);
2933 DP(NETIF_MSG_LINK, "8706 rx_sd 0x%x"
2934 " pcs_status 0x%x 1Gbps link_status 0x%x\n",
2935 rx_sd, pcs_status, val2);
2936 /* link is up if both bit 0 of pmd_rx_sd and
2937 * bit 0 of pcs_status are set, or if the autoneg bit
2938 1 is set
2940 ext_phy_link_up = ((rx_sd & pcs_status & 0x1) ||
2941 (val2 & (1<<1)));
2942 if (ext_phy_link_up) {
2943 if (val2 & (1<<1))
2944 vars->line_speed = SPEED_1000;
2945 else
2946 vars->line_speed = SPEED_10000;
2949 /* clear LASI indication*/
2950 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2951 ext_phy_addr,
2952 MDIO_PMA_DEVAD,
2953 MDIO_PMA_REG_RX_ALARM, &val2);
2954 break;
2956 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2957 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2959 u16 link_status = 0;
2960 u16 an1000_status = 0;
2961 if (ext_phy_type ==
2962 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
2963 bnx2x_cl45_read(bp, params->port,
2964 ext_phy_type,
2965 ext_phy_addr,
2966 MDIO_PCS_DEVAD,
2967 MDIO_PCS_REG_LASI_STATUS, &val1);
2968 bnx2x_cl45_read(bp, params->port,
2969 ext_phy_type,
2970 ext_phy_addr,
2971 MDIO_PCS_DEVAD,
2972 MDIO_PCS_REG_LASI_STATUS, &val2);
2973 DP(NETIF_MSG_LINK,
2974 "870x LASI status 0x%x->0x%x\n",
2975 val1, val2);
2977 } else {
2978 /* In 8073, port1 is directed through emac0 and
2979 * port0 is directed through emac1
2981 bnx2x_cl45_read(bp, params->port,
2982 ext_phy_type,
2983 ext_phy_addr,
2984 MDIO_PMA_DEVAD,
2985 MDIO_PMA_REG_LASI_STATUS, &val1);
2987 DP(NETIF_MSG_LINK,
2988 "8703 LASI status 0x%x\n",
2989 val1);
2992 /* clear the interrupt LASI status register */
2993 bnx2x_cl45_read(bp, params->port,
2994 ext_phy_type,
2995 ext_phy_addr,
2996 MDIO_PCS_DEVAD,
2997 MDIO_PCS_REG_STATUS, &val2);
2998 bnx2x_cl45_read(bp, params->port,
2999 ext_phy_type,
3000 ext_phy_addr,
3001 MDIO_PCS_DEVAD,
3002 MDIO_PCS_REG_STATUS, &val1);
3003 DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n",
3004 val2, val1);
3005 /* Clear MSG-OUT */
3006 bnx2x_cl45_read(bp, params->port,
3007 ext_phy_type,
3008 ext_phy_addr,
3009 MDIO_PMA_DEVAD,
3010 0xca13,
3011 &val1);
3013 /* Check the LASI */
3014 bnx2x_cl45_read(bp, params->port,
3015 ext_phy_type,
3016 ext_phy_addr,
3017 MDIO_PMA_DEVAD,
3018 MDIO_PMA_REG_RX_ALARM, &val2);
3020 DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
3022 /* Check the link status */
3023 bnx2x_cl45_read(bp, params->port,
3024 ext_phy_type,
3025 ext_phy_addr,
3026 MDIO_PCS_DEVAD,
3027 MDIO_PCS_REG_STATUS, &val2);
3028 DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
3030 bnx2x_cl45_read(bp, params->port,
3031 ext_phy_type,
3032 ext_phy_addr,
3033 MDIO_PMA_DEVAD,
3034 MDIO_PMA_REG_STATUS, &val2);
3035 bnx2x_cl45_read(bp, params->port,
3036 ext_phy_type,
3037 ext_phy_addr,
3038 MDIO_PMA_DEVAD,
3039 MDIO_PMA_REG_STATUS, &val1);
3040 ext_phy_link_up = ((val1 & 4) == 4);
3041 DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
3042 if (ext_phy_type ==
3043 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
3045 if (ext_phy_link_up &&
3046 ((params->req_line_speed !=
3047 SPEED_10000))) {
3048 if (bnx2x_bcm8073_xaui_wa(params)
3049 != 0) {
3050 ext_phy_link_up = 0;
3051 break;
3054 bnx2x_cl45_read(bp, params->port,
3055 ext_phy_type,
3056 ext_phy_addr,
3057 MDIO_AN_DEVAD,
3058 0x8304,
3059 &an1000_status);
3060 bnx2x_cl45_read(bp, params->port,
3061 ext_phy_type,
3062 ext_phy_addr,
3063 MDIO_AN_DEVAD,
3064 0x8304,
3065 &an1000_status);
3067 /* Check the link status on 1.1.2 */
3068 bnx2x_cl45_read(bp, params->port,
3069 ext_phy_type,
3070 ext_phy_addr,
3071 MDIO_PMA_DEVAD,
3072 MDIO_PMA_REG_STATUS, &val2);
3073 bnx2x_cl45_read(bp, params->port,
3074 ext_phy_type,
3075 ext_phy_addr,
3076 MDIO_PMA_DEVAD,
3077 MDIO_PMA_REG_STATUS, &val1);
3078 DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x,"
3079 "an_link_status=0x%x\n",
3080 val2, val1, an1000_status);
3082 ext_phy_link_up = (((val1 & 4) == 4) ||
3083 (an1000_status & (1<<1)));
3084 if (ext_phy_link_up &&
3085 bnx2x_8073_is_snr_needed(params)) {
3086 /* The SNR will improve about 2dbby
3087 changing the BW and FEE main tap.*/
3089 /* The 1st write to change FFE main
3090 tap is set before restart AN */
3091 /* Change PLL Bandwidth in EDC
3092 register */
3093 bnx2x_cl45_write(bp, port, ext_phy_type,
3094 ext_phy_addr,
3095 MDIO_PMA_DEVAD,
3096 MDIO_PMA_REG_PLL_BANDWIDTH,
3097 0x26BC);
3099 /* Change CDR Bandwidth in EDC
3100 register */
3101 bnx2x_cl45_write(bp, port, ext_phy_type,
3102 ext_phy_addr,
3103 MDIO_PMA_DEVAD,
3104 MDIO_PMA_REG_CDR_BANDWIDTH,
3105 0x0333);
3109 bnx2x_cl45_read(bp, params->port,
3110 ext_phy_type,
3111 ext_phy_addr,
3112 MDIO_PMA_DEVAD,
3113 0xc820,
3114 &link_status);
3116 /* Bits 0..2 --> speed detected,
3117 bits 13..15--> link is down */
3118 if ((link_status & (1<<2)) &&
3119 (!(link_status & (1<<15)))) {
3120 ext_phy_link_up = 1;
3121 vars->line_speed = SPEED_10000;
3122 DP(NETIF_MSG_LINK,
3123 "port %x: External link"
3124 " up in 10G\n", params->port);
3125 } else if ((link_status & (1<<1)) &&
3126 (!(link_status & (1<<14)))) {
3127 ext_phy_link_up = 1;
3128 vars->line_speed = SPEED_2500;
3129 DP(NETIF_MSG_LINK,
3130 "port %x: External link"
3131 " up in 2.5G\n", params->port);
3132 } else if ((link_status & (1<<0)) &&
3133 (!(link_status & (1<<13)))) {
3134 ext_phy_link_up = 1;
3135 vars->line_speed = SPEED_1000;
3136 DP(NETIF_MSG_LINK,
3137 "port %x: External link"
3138 " up in 1G\n", params->port);
3139 } else {
3140 ext_phy_link_up = 0;
3141 DP(NETIF_MSG_LINK,
3142 "port %x: External link"
3143 " is down\n", params->port);
3145 } else {
3146 /* See if 1G link is up for the 8072 */
3147 bnx2x_cl45_read(bp, params->port,
3148 ext_phy_type,
3149 ext_phy_addr,
3150 MDIO_AN_DEVAD,
3151 0x8304,
3152 &an1000_status);
3153 bnx2x_cl45_read(bp, params->port,
3154 ext_phy_type,
3155 ext_phy_addr,
3156 MDIO_AN_DEVAD,
3157 0x8304,
3158 &an1000_status);
3159 if (an1000_status & (1<<1)) {
3160 ext_phy_link_up = 1;
3161 vars->line_speed = SPEED_1000;
3162 DP(NETIF_MSG_LINK,
3163 "port %x: External link"
3164 " up in 1G\n", params->port);
3165 } else if (ext_phy_link_up) {
3166 ext_phy_link_up = 1;
3167 vars->line_speed = SPEED_10000;
3168 DP(NETIF_MSG_LINK,
3169 "port %x: External link"
3170 " up in 10G\n", params->port);
3175 break;
3177 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3178 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3179 ext_phy_addr,
3180 MDIO_PMA_DEVAD,
3181 MDIO_PMA_REG_LASI_STATUS, &val2);
3182 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3183 ext_phy_addr,
3184 MDIO_PMA_DEVAD,
3185 MDIO_PMA_REG_LASI_STATUS, &val1);
3186 DP(NETIF_MSG_LINK,
3187 "10G-base-T LASI status 0x%x->0x%x\n",
3188 val2, val1);
3189 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3190 ext_phy_addr,
3191 MDIO_PMA_DEVAD,
3192 MDIO_PMA_REG_STATUS, &val2);
3193 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3194 ext_phy_addr,
3195 MDIO_PMA_DEVAD,
3196 MDIO_PMA_REG_STATUS, &val1);
3197 DP(NETIF_MSG_LINK,
3198 "10G-base-T PMA status 0x%x->0x%x\n",
3199 val2, val1);
3200 ext_phy_link_up = ((val1 & 4) == 4);
3201 /* if link is up
3202 * print the AN outcome of the SFX7101 PHY
3204 if (ext_phy_link_up) {
3205 bnx2x_cl45_read(bp, params->port,
3206 ext_phy_type,
3207 ext_phy_addr,
3208 MDIO_AN_DEVAD,
3209 MDIO_AN_REG_MASTER_STATUS,
3210 &val2);
3211 vars->line_speed = SPEED_10000;
3212 DP(NETIF_MSG_LINK,
3213 "SFX7101 AN status 0x%x->Master=%x\n",
3214 val2,
3215 (val2 & (1<<14)));
3217 break;
3219 default:
3220 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
3221 params->ext_phy_config);
3222 ext_phy_link_up = 0;
3223 break;
3226 } else { /* SerDes */
3227 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3228 switch (ext_phy_type) {
3229 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
3230 DP(NETIF_MSG_LINK, "SerDes Direct\n");
3231 ext_phy_link_up = 1;
3232 break;
3234 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
3235 DP(NETIF_MSG_LINK, "SerDes 5482\n");
3236 ext_phy_link_up = 1;
3237 break;
3239 default:
3240 DP(NETIF_MSG_LINK,
3241 "BAD SerDes ext_phy_config 0x%x\n",
3242 params->ext_phy_config);
3243 ext_phy_link_up = 0;
3244 break;
3248 return ext_phy_link_up;
3251 static void bnx2x_link_int_enable(struct link_params *params)
3253 u8 port = params->port;
3254 u32 ext_phy_type;
3255 u32 mask;
3256 struct bnx2x *bp = params->bp;
3257 /* setting the status to report on link up
3258 for either XGXS or SerDes */
3260 if (params->switch_cfg == SWITCH_CFG_10G) {
3261 mask = (NIG_MASK_XGXS0_LINK10G |
3262 NIG_MASK_XGXS0_LINK_STATUS);
3263 DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
3264 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3265 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
3266 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
3267 (ext_phy_type !=
3268 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) {
3269 mask |= NIG_MASK_MI_INT;
3270 DP(NETIF_MSG_LINK, "enabled external phy int\n");
3273 } else { /* SerDes */
3274 mask = NIG_MASK_SERDES0_LINK_STATUS;
3275 DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n");
3276 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3277 if ((ext_phy_type !=
3278 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
3279 (ext_phy_type !=
3280 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN)) {
3281 mask |= NIG_MASK_MI_INT;
3282 DP(NETIF_MSG_LINK, "enabled external phy int\n");
3285 bnx2x_bits_en(bp,
3286 NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
3287 mask);
3288 DP(NETIF_MSG_LINK, "port %x, is_xgxs=%x, int_status 0x%x\n", port,
3289 (params->switch_cfg == SWITCH_CFG_10G),
3290 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
3292 DP(NETIF_MSG_LINK, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n",
3293 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
3294 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
3295 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS+port*0x3c));
3296 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
3297 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
3298 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
3303 * link management
3305 static void bnx2x_link_int_ack(struct link_params *params,
3306 struct link_vars *vars, u16 is_10g)
3308 struct bnx2x *bp = params->bp;
3309 u8 port = params->port;
3311 /* first reset all status
3312 * we assume only one line will be change at a time */
3313 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3314 (NIG_STATUS_XGXS0_LINK10G |
3315 NIG_STATUS_XGXS0_LINK_STATUS |
3316 NIG_STATUS_SERDES0_LINK_STATUS));
3317 if (vars->phy_link_up) {
3318 if (is_10g) {
3319 /* Disable the 10G link interrupt
3320 * by writing 1 to the status register
3322 DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
3323 bnx2x_bits_en(bp,
3324 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3325 NIG_STATUS_XGXS0_LINK10G);
3327 } else if (params->switch_cfg == SWITCH_CFG_10G) {
3328 /* Disable the link interrupt
3329 * by writing 1 to the relevant lane
3330 * in the status register
3332 u32 ser_lane = ((params->lane_config &
3333 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
3334 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
3336 DP(NETIF_MSG_LINK, "1G XGXS phy link up\n");
3337 bnx2x_bits_en(bp,
3338 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3339 ((1 << ser_lane) <<
3340 NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
3342 } else { /* SerDes */
3343 DP(NETIF_MSG_LINK, "SerDes phy link up\n");
3344 /* Disable the link interrupt
3345 * by writing 1 to the status register
3347 bnx2x_bits_en(bp,
3348 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3349 NIG_STATUS_SERDES0_LINK_STATUS);
3352 } else { /* link_down */
3356 static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len)
3358 u8 *str_ptr = str;
3359 u32 mask = 0xf0000000;
3360 u8 shift = 8*4;
3361 u8 digit;
3362 if (len < 10) {
3363 /* Need more then 10chars for this format */
3364 *str_ptr = '\0';
3365 return -EINVAL;
3367 while (shift > 0) {
3369 shift -= 4;
3370 digit = ((num & mask) >> shift);
3371 if (digit < 0xa)
3372 *str_ptr = digit + '0';
3373 else
3374 *str_ptr = digit - 0xa + 'a';
3375 str_ptr++;
3376 mask = mask >> 4;
3377 if (shift == 4*4) {
3378 *str_ptr = ':';
3379 str_ptr++;
3382 *str_ptr = '\0';
3383 return 0;
3387 static void bnx2x_turn_on_ef(struct bnx2x *bp, u8 port, u8 ext_phy_addr,
3388 u32 ext_phy_type)
3390 u32 cnt = 0;
3391 u16 ctrl = 0;
3392 /* Enable EMAC0 in to enable MDIO */
3393 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
3394 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
3395 msleep(5);
3397 /* take ext phy out of reset */
3398 bnx2x_set_gpio(bp,
3399 MISC_REGISTERS_GPIO_2,
3400 MISC_REGISTERS_GPIO_HIGH,
3401 port);
3403 bnx2x_set_gpio(bp,
3404 MISC_REGISTERS_GPIO_1,
3405 MISC_REGISTERS_GPIO_HIGH,
3406 port);
3408 /* wait for 5ms */
3409 msleep(5);
3411 for (cnt = 0; cnt < 1000; cnt++) {
3412 msleep(1);
3413 bnx2x_cl45_read(bp, port,
3414 ext_phy_type,
3415 ext_phy_addr,
3416 MDIO_PMA_DEVAD,
3417 MDIO_PMA_REG_CTRL,
3418 &ctrl);
3419 if (!(ctrl & (1<<15))) {
3420 DP(NETIF_MSG_LINK, "Reset completed\n\n");
3421 break;
3426 static void bnx2x_turn_off_sf(struct bnx2x *bp, u8 port)
3428 /* put sf to reset */
3429 bnx2x_set_gpio(bp,
3430 MISC_REGISTERS_GPIO_1,
3431 MISC_REGISTERS_GPIO_LOW,
3432 port);
3433 bnx2x_set_gpio(bp,
3434 MISC_REGISTERS_GPIO_2,
3435 MISC_REGISTERS_GPIO_LOW,
3436 port);
3439 u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
3440 u8 *version, u16 len)
3442 struct bnx2x *bp = params->bp;
3443 u32 ext_phy_type = 0;
3444 u16 val = 0;
3445 u8 ext_phy_addr = 0 ;
3446 u8 status = 0 ;
3447 u32 ver_num;
3449 if (version == NULL || params == NULL)
3450 return -EINVAL;
3452 /* reset the returned value to zero */
3453 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3454 ext_phy_addr = ((params->ext_phy_config &
3455 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
3456 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
3458 switch (ext_phy_type) {
3459 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3461 if (len < 5)
3462 return -EINVAL;
3464 /* Take ext phy out of reset */
3465 if (!driver_loaded)
3466 bnx2x_turn_on_ef(bp, params->port, ext_phy_addr,
3467 ext_phy_type);
3469 /* wait for 1ms */
3470 msleep(1);
3472 bnx2x_cl45_read(bp, params->port,
3473 ext_phy_type,
3474 ext_phy_addr,
3475 MDIO_PMA_DEVAD,
3476 MDIO_PMA_REG_7101_VER1, &val);
3477 version[2] = (val & 0xFF);
3478 version[3] = ((val & 0xFF00)>>8);
3480 bnx2x_cl45_read(bp, params->port,
3481 ext_phy_type,
3482 ext_phy_addr,
3483 MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2,
3484 &val);
3485 version[0] = (val & 0xFF);
3486 version[1] = ((val & 0xFF00)>>8);
3487 version[4] = '\0';
3489 if (!driver_loaded)
3490 bnx2x_turn_off_sf(bp, params->port);
3491 break;
3492 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
3493 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
3495 /* Take ext phy out of reset */
3496 if (!driver_loaded)
3497 bnx2x_turn_on_ef(bp, params->port, ext_phy_addr,
3498 ext_phy_type);
3500 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3501 ext_phy_addr,
3502 MDIO_PMA_DEVAD,
3503 MDIO_PMA_REG_ROM_VER1, &val);
3504 ver_num = val<<16;
3505 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3506 ext_phy_addr,
3507 MDIO_PMA_DEVAD,
3508 MDIO_PMA_REG_ROM_VER2, &val);
3509 ver_num |= val;
3510 status = bnx2x_format_ver(ver_num, version, len);
3511 break;
3513 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
3514 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
3516 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3517 ext_phy_addr,
3518 MDIO_PMA_DEVAD,
3519 MDIO_PMA_REG_ROM_VER1, &val);
3520 ver_num = val<<16;
3521 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3522 ext_phy_addr,
3523 MDIO_PMA_DEVAD,
3524 MDIO_PMA_REG_ROM_VER2, &val);
3525 ver_num |= val;
3526 status = bnx2x_format_ver(ver_num, version, len);
3527 break;
3529 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3530 break;
3532 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
3533 DP(NETIF_MSG_LINK, "bnx2x_get_ext_phy_fw_version:"
3534 " type is FAILURE!\n");
3535 status = -EINVAL;
3536 break;
3538 default:
3539 break;
3541 return status;
3544 static void bnx2x_set_xgxs_loopback(struct link_params *params,
3545 struct link_vars *vars,
3546 u8 is_10g)
3548 u8 port = params->port;
3549 struct bnx2x *bp = params->bp;
3551 if (is_10g) {
3552 u32 md_devad;
3554 DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
3556 /* change the uni_phy_addr in the nig */
3557 md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
3558 port*0x18));
3560 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
3562 bnx2x_cl45_write(bp, port, 0,
3563 params->phy_addr,
3565 (MDIO_REG_BANK_AER_BLOCK +
3566 (MDIO_AER_BLOCK_AER_REG & 0xf)),
3567 0x2800);
3569 bnx2x_cl45_write(bp, port, 0,
3570 params->phy_addr,
3572 (MDIO_REG_BANK_CL73_IEEEB0 +
3573 (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
3574 0x6041);
3576 /* set aer mmd back */
3577 bnx2x_set_aer_mmd(params, vars);
3579 /* and md_devad */
3580 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
3581 md_devad);
3583 } else {
3584 u16 mii_control;
3586 DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
3588 CL45_RD_OVER_CL22(bp, port,
3589 params->phy_addr,
3590 MDIO_REG_BANK_COMBO_IEEE0,
3591 MDIO_COMBO_IEEE0_MII_CONTROL,
3592 &mii_control);
3594 CL45_WR_OVER_CL22(bp, port,
3595 params->phy_addr,
3596 MDIO_REG_BANK_COMBO_IEEE0,
3597 MDIO_COMBO_IEEE0_MII_CONTROL,
3598 (mii_control |
3599 MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK));
3604 static void bnx2x_ext_phy_loopback(struct link_params *params)
3606 struct bnx2x *bp = params->bp;
3607 u8 ext_phy_addr;
3608 u32 ext_phy_type;
3610 if (params->switch_cfg == SWITCH_CFG_10G) {
3611 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3612 /* CL37 Autoneg Enabled */
3613 ext_phy_addr = ((params->ext_phy_config &
3614 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
3615 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
3616 switch (ext_phy_type) {
3617 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3618 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
3619 DP(NETIF_MSG_LINK,
3620 "ext_phy_loopback: We should not get here\n");
3621 break;
3622 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
3623 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8705\n");
3624 break;
3625 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
3626 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8706\n");
3627 break;
3628 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3629 /* SFX7101_XGXS_TEST1 */
3630 bnx2x_cl45_write(bp, params->port, ext_phy_type,
3631 ext_phy_addr,
3632 MDIO_XS_DEVAD,
3633 MDIO_XS_SFX7101_XGXS_TEST1,
3634 0x100);
3635 DP(NETIF_MSG_LINK,
3636 "ext_phy_loopback: set ext phy loopback\n");
3637 break;
3638 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
3640 break;
3641 } /* switch external PHY type */
3642 } else {
3643 /* serdes */
3644 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3645 ext_phy_addr = (params->ext_phy_config &
3646 PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK)
3647 >> PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT;
3653 *------------------------------------------------------------------------
3654 * bnx2x_override_led_value -
3656 * Override the led value of the requsted led
3658 *------------------------------------------------------------------------
3660 u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port,
3661 u32 led_idx, u32 value)
3663 u32 reg_val;
3665 /* If port 0 then use EMAC0, else use EMAC1*/
3666 u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
3668 DP(NETIF_MSG_LINK,
3669 "bnx2x_override_led_value() port %x led_idx %d value %d\n",
3670 port, led_idx, value);
3672 switch (led_idx) {
3673 case 0: /* 10MB led */
3674 /* Read the current value of the LED register in
3675 the EMAC block */
3676 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3677 /* Set the OVERRIDE bit to 1 */
3678 reg_val |= EMAC_LED_OVERRIDE;
3679 /* If value is 1, set the 10M_OVERRIDE bit,
3680 otherwise reset it.*/
3681 reg_val = (value == 1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) :
3682 (reg_val & ~EMAC_LED_10MB_OVERRIDE);
3683 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3684 break;
3685 case 1: /*100MB led */
3686 /*Read the current value of the LED register in
3687 the EMAC block */
3688 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3689 /* Set the OVERRIDE bit to 1 */
3690 reg_val |= EMAC_LED_OVERRIDE;
3691 /* If value is 1, set the 100M_OVERRIDE bit,
3692 otherwise reset it.*/
3693 reg_val = (value == 1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) :
3694 (reg_val & ~EMAC_LED_100MB_OVERRIDE);
3695 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3696 break;
3697 case 2: /* 1000MB led */
3698 /* Read the current value of the LED register in the
3699 EMAC block */
3700 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3701 /* Set the OVERRIDE bit to 1 */
3702 reg_val |= EMAC_LED_OVERRIDE;
3703 /* If value is 1, set the 1000M_OVERRIDE bit, otherwise
3704 reset it. */
3705 reg_val = (value == 1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) :
3706 (reg_val & ~EMAC_LED_1000MB_OVERRIDE);
3707 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3708 break;
3709 case 3: /* 2500MB led */
3710 /* Read the current value of the LED register in the
3711 EMAC block*/
3712 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3713 /* Set the OVERRIDE bit to 1 */
3714 reg_val |= EMAC_LED_OVERRIDE;
3715 /* If value is 1, set the 2500M_OVERRIDE bit, otherwise
3716 reset it.*/
3717 reg_val = (value == 1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) :
3718 (reg_val & ~EMAC_LED_2500MB_OVERRIDE);
3719 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3720 break;
3721 case 4: /*10G led */
3722 if (port == 0) {
3723 REG_WR(bp, NIG_REG_LED_10G_P0,
3724 value);
3725 } else {
3726 REG_WR(bp, NIG_REG_LED_10G_P1,
3727 value);
3729 break;
3730 case 5: /* TRAFFIC led */
3731 /* Find if the traffic control is via BMAC or EMAC */
3732 if (port == 0)
3733 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC0_EN);
3734 else
3735 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC1_EN);
3737 /* Override the traffic led in the EMAC:*/
3738 if (reg_val == 1) {
3739 /* Read the current value of the LED register in
3740 the EMAC block */
3741 reg_val = REG_RD(bp, emac_base +
3742 EMAC_REG_EMAC_LED);
3743 /* Set the TRAFFIC_OVERRIDE bit to 1 */
3744 reg_val |= EMAC_LED_OVERRIDE;
3745 /* If value is 1, set the TRAFFIC bit, otherwise
3746 reset it.*/
3747 reg_val = (value == 1) ? (reg_val | EMAC_LED_TRAFFIC) :
3748 (reg_val & ~EMAC_LED_TRAFFIC);
3749 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3750 } else { /* Override the traffic led in the BMAC: */
3751 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
3752 + port*4, 1);
3753 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port*4,
3754 value);
3756 break;
3757 default:
3758 DP(NETIF_MSG_LINK,
3759 "bnx2x_override_led_value() unknown led index %d "
3760 "(should be 0-5)\n", led_idx);
3761 return -EINVAL;
3764 return 0;
3768 u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
3769 u16 hw_led_mode, u32 chip_id)
3771 u8 rc = 0;
3772 DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
3773 DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
3774 speed, hw_led_mode);
3775 switch (mode) {
3776 case LED_MODE_OFF:
3777 REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0);
3778 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
3779 SHARED_HW_CFG_LED_MAC1);
3780 break;
3782 case LED_MODE_OPER:
3783 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode);
3784 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
3785 port*4, 0);
3786 /* Set blinking rate to ~15.9Hz */
3787 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
3788 LED_BLINK_RATE_VAL);
3789 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
3790 port*4, 1);
3791 if (!CHIP_IS_E1H(bp) &&
3792 ((speed == SPEED_2500) ||
3793 (speed == SPEED_1000) ||
3794 (speed == SPEED_100) ||
3795 (speed == SPEED_10))) {
3796 /* On Everest 1 Ax chip versions for speeds less than
3797 10G LED scheme is different */
3798 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
3799 + port*4, 1);
3800 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
3801 port*4, 0);
3802 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
3803 port*4, 1);
3805 break;
3807 default:
3808 rc = -EINVAL;
3809 DP(NETIF_MSG_LINK, "bnx2x_set_led: Invalid led mode %d\n",
3810 mode);
3811 break;
3813 return rc;
3817 u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars)
3819 struct bnx2x *bp = params->bp;
3820 u16 gp_status = 0;
3822 CL45_RD_OVER_CL22(bp, params->port,
3823 params->phy_addr,
3824 MDIO_REG_BANK_GP_STATUS,
3825 MDIO_GP_STATUS_TOP_AN_STATUS1,
3826 &gp_status);
3827 /* link is up only if both local phy and external phy are up */
3828 if ((gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) &&
3829 bnx2x_ext_phy_is_link_up(params, vars))
3830 return 0;
3832 return -ESRCH;
3835 static u8 bnx2x_link_initialize(struct link_params *params,
3836 struct link_vars *vars)
3838 struct bnx2x *bp = params->bp;
3839 u8 port = params->port;
3840 u8 rc = 0;
3841 u8 non_ext_phy;
3842 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3843 /* Activate the external PHY */
3844 bnx2x_ext_phy_reset(params, vars);
3846 bnx2x_set_aer_mmd(params, vars);
3848 if (vars->phy_flags & PHY_XGXS_FLAG)
3849 bnx2x_set_master_ln(params);
3851 rc = bnx2x_reset_unicore(params);
3852 /* reset the SerDes and wait for reset bit return low */
3853 if (rc != 0)
3854 return rc;
3856 bnx2x_set_aer_mmd(params, vars);
3858 /* setting the masterLn_def again after the reset */
3859 if (vars->phy_flags & PHY_XGXS_FLAG) {
3860 bnx2x_set_master_ln(params);
3861 bnx2x_set_swap_lanes(params);
3864 if (vars->phy_flags & PHY_XGXS_FLAG) {
3865 if (params->req_line_speed &&
3866 ((params->req_line_speed == SPEED_100) ||
3867 (params->req_line_speed == SPEED_10))) {
3868 vars->phy_flags |= PHY_SGMII_FLAG;
3869 } else {
3870 vars->phy_flags &= ~PHY_SGMII_FLAG;
3873 /* In case of external phy existance, the line speed would be the
3874 line speed linked up by the external phy. In case it is direct only,
3875 then the line_speed during initialization will be equal to the
3876 req_line_speed*/
3877 vars->line_speed = params->req_line_speed;
3879 bnx2x_calc_ieee_aneg_adv(params, &vars->ieee_fc);
3881 /* init ext phy and enable link state int */
3882 non_ext_phy = ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
3883 (params->loopback_mode == LOOPBACK_XGXS_10) ||
3884 (params->loopback_mode == LOOPBACK_EXT_PHY));
3886 if (non_ext_phy ||
3887 (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705)) {
3888 if (params->req_line_speed == SPEED_AUTO_NEG)
3889 bnx2x_set_parallel_detection(params, vars->phy_flags);
3890 bnx2x_init_internal_phy(params, vars);
3893 if (!non_ext_phy)
3894 rc |= bnx2x_ext_phy_init(params, vars);
3896 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3897 (NIG_STATUS_XGXS0_LINK10G |
3898 NIG_STATUS_XGXS0_LINK_STATUS |
3899 NIG_STATUS_SERDES0_LINK_STATUS));
3901 return rc;
3906 u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
3908 struct bnx2x *bp = params->bp;
3910 u32 val;
3911 DP(NETIF_MSG_LINK, "Phy Initialization started\n");
3912 DP(NETIF_MSG_LINK, "req_speed = %d, req_flowctrl=%d\n",
3913 params->req_line_speed, params->req_flow_ctrl);
3914 vars->link_status = 0;
3915 vars->phy_link_up = 0;
3916 vars->link_up = 0;
3917 vars->line_speed = 0;
3918 vars->duplex = DUPLEX_FULL;
3919 vars->flow_ctrl = FLOW_CTRL_NONE;
3920 vars->mac_type = MAC_TYPE_NONE;
3922 if (params->switch_cfg == SWITCH_CFG_1G)
3923 vars->phy_flags = PHY_SERDES_FLAG;
3924 else
3925 vars->phy_flags = PHY_XGXS_FLAG;
3927 /* disable attentions */
3928 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
3929 (NIG_MASK_XGXS0_LINK_STATUS |
3930 NIG_MASK_XGXS0_LINK10G |
3931 NIG_MASK_SERDES0_LINK_STATUS |
3932 NIG_MASK_MI_INT));
3934 bnx2x_emac_init(params, vars);
3936 if (CHIP_REV_IS_FPGA(bp)) {
3937 vars->link_up = 1;
3938 vars->line_speed = SPEED_10000;
3939 vars->duplex = DUPLEX_FULL;
3940 vars->flow_ctrl = FLOW_CTRL_NONE;
3941 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
3942 /* enable on E1.5 FPGA */
3943 if (CHIP_IS_E1H(bp)) {
3944 vars->flow_ctrl |=
3945 (FLOW_CTRL_TX | FLOW_CTRL_RX);
3946 vars->link_status |=
3947 (LINK_STATUS_TX_FLOW_CONTROL_ENABLED |
3948 LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
3951 bnx2x_emac_enable(params, vars, 0);
3952 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
3953 /* disable drain */
3954 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
3955 + params->port*4, 0);
3957 /* update shared memory */
3958 bnx2x_update_mng(params, vars->link_status);
3960 return 0;
3962 } else
3963 if (CHIP_REV_IS_EMUL(bp)) {
3965 vars->link_up = 1;
3966 vars->line_speed = SPEED_10000;
3967 vars->duplex = DUPLEX_FULL;
3968 vars->flow_ctrl = FLOW_CTRL_NONE;
3969 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
3971 bnx2x_bmac_enable(params, vars, 0);
3973 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
3974 /* Disable drain */
3975 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
3976 + params->port*4, 0);
3978 /* update shared memory */
3979 bnx2x_update_mng(params, vars->link_status);
3981 return 0;
3983 } else
3984 if (params->loopback_mode == LOOPBACK_BMAC) {
3985 vars->link_up = 1;
3986 vars->line_speed = SPEED_10000;
3987 vars->duplex = DUPLEX_FULL;
3988 vars->flow_ctrl = FLOW_CTRL_NONE;
3989 vars->mac_type = MAC_TYPE_BMAC;
3991 vars->phy_flags = PHY_XGXS_FLAG;
3993 bnx2x_phy_deassert(params, vars->phy_flags);
3994 /* set bmac loopback */
3995 bnx2x_bmac_enable(params, vars, 1);
3997 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
3998 params->port*4, 0);
3999 } else if (params->loopback_mode == LOOPBACK_EMAC) {
4000 vars->link_up = 1;
4001 vars->line_speed = SPEED_1000;
4002 vars->duplex = DUPLEX_FULL;
4003 vars->flow_ctrl = FLOW_CTRL_NONE;
4004 vars->mac_type = MAC_TYPE_EMAC;
4006 vars->phy_flags = PHY_XGXS_FLAG;
4008 bnx2x_phy_deassert(params, vars->phy_flags);
4009 /* set bmac loopback */
4010 bnx2x_emac_enable(params, vars, 1);
4011 bnx2x_emac_program(params, vars->line_speed,
4012 vars->duplex);
4013 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
4014 params->port*4, 0);
4015 } else if ((params->loopback_mode == LOOPBACK_XGXS_10) ||
4016 (params->loopback_mode == LOOPBACK_EXT_PHY)) {
4017 vars->link_up = 1;
4018 vars->line_speed = SPEED_10000;
4019 vars->duplex = DUPLEX_FULL;
4020 vars->flow_ctrl = FLOW_CTRL_NONE;
4022 vars->phy_flags = PHY_XGXS_FLAG;
4024 val = REG_RD(bp,
4025 NIG_REG_XGXS0_CTRL_PHY_ADDR+
4026 params->port*0x18);
4027 params->phy_addr = (u8)val;
4029 bnx2x_phy_deassert(params, vars->phy_flags);
4030 bnx2x_link_initialize(params, vars);
4032 vars->mac_type = MAC_TYPE_BMAC;
4034 bnx2x_bmac_enable(params, vars, 0);
4036 if (params->loopback_mode == LOOPBACK_XGXS_10) {
4037 /* set 10G XGXS loopback */
4038 bnx2x_set_xgxs_loopback(params, vars, 1);
4039 } else {
4040 /* set external phy loopback */
4041 bnx2x_ext_phy_loopback(params);
4043 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
4044 params->port*4, 0);
4045 } else
4046 /* No loopback */
4049 bnx2x_phy_deassert(params, vars->phy_flags);
4050 switch (params->switch_cfg) {
4051 case SWITCH_CFG_1G:
4052 vars->phy_flags |= PHY_SERDES_FLAG;
4053 if ((params->ext_phy_config &
4054 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK) ==
4055 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482) {
4056 vars->phy_flags |=
4057 PHY_SGMII_FLAG;
4060 val = REG_RD(bp,
4061 NIG_REG_SERDES0_CTRL_PHY_ADDR+
4062 params->port*0x10);
4064 params->phy_addr = (u8)val;
4066 break;
4067 case SWITCH_CFG_10G:
4068 vars->phy_flags |= PHY_XGXS_FLAG;
4069 val = REG_RD(bp,
4070 NIG_REG_XGXS0_CTRL_PHY_ADDR+
4071 params->port*0x18);
4072 params->phy_addr = (u8)val;
4074 break;
4075 default:
4076 DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
4077 return -EINVAL;
4078 break;
4081 bnx2x_link_initialize(params, vars);
4082 msleep(30);
4083 bnx2x_link_int_enable(params);
4085 return 0;
4088 u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars)
4091 struct bnx2x *bp = params->bp;
4092 u32 ext_phy_config = params->ext_phy_config;
4093 u16 hw_led_mode = params->hw_led_mode;
4094 u32 chip_id = params->chip_id;
4095 u8 port = params->port;
4096 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
4097 /* disable attentions */
4099 vars->link_status = 0;
4100 bnx2x_update_mng(params, vars->link_status);
4101 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
4102 (NIG_MASK_XGXS0_LINK_STATUS |
4103 NIG_MASK_XGXS0_LINK10G |
4104 NIG_MASK_SERDES0_LINK_STATUS |
4105 NIG_MASK_MI_INT));
4107 /* activate nig drain */
4108 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
4110 /* disable nig egress interface */
4111 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
4112 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
4114 /* Stop BigMac rx */
4115 bnx2x_bmac_rx_disable(bp, port);
4117 /* disable emac */
4118 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
4120 msleep(10);
4121 /* The PHY reset is controled by GPIO 1
4122 * Hold it as vars low
4124 /* clear link led */
4125 bnx2x_set_led(bp, port, LED_MODE_OFF, 0, hw_led_mode, chip_id);
4126 if (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
4127 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
4128 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
4129 /* HW reset */
4131 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
4132 MISC_REGISTERS_GPIO_OUTPUT_LOW,
4133 port);
4135 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4136 MISC_REGISTERS_GPIO_OUTPUT_LOW,
4137 port);
4139 DP(NETIF_MSG_LINK, "reset external PHY\n");
4140 } else if (ext_phy_type ==
4141 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
4142 DP(NETIF_MSG_LINK, "Setting 8073 port %d into "
4143 "low power mode\n",
4144 port);
4145 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4146 MISC_REGISTERS_GPIO_OUTPUT_LOW,
4147 port);
4150 /* reset the SerDes/XGXS */
4151 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
4152 (0x1ff << (port*16)));
4154 /* reset BigMac */
4155 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
4156 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
4158 /* disable nig ingress interface */
4159 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
4160 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
4161 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
4162 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
4163 vars->link_up = 0;
4164 return 0;
4167 static u8 bnx2x_update_link_down(struct link_params *params,
4168 struct link_vars *vars)
4170 struct bnx2x *bp = params->bp;
4171 u8 port = params->port;
4172 DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
4173 bnx2x_set_led(bp, port, LED_MODE_OFF,
4174 0, params->hw_led_mode,
4175 params->chip_id);
4177 /* indicate no mac active */
4178 vars->mac_type = MAC_TYPE_NONE;
4180 /* update shared memory */
4181 vars->link_status = 0;
4182 vars->line_speed = 0;
4183 bnx2x_update_mng(params, vars->link_status);
4185 /* activate nig drain */
4186 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
4188 /* reset BigMac */
4189 bnx2x_bmac_rx_disable(bp, params->port);
4190 REG_WR(bp, GRCBASE_MISC +
4191 MISC_REGISTERS_RESET_REG_2_CLEAR,
4192 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
4193 return 0;
4196 static u8 bnx2x_update_link_up(struct link_params *params,
4197 struct link_vars *vars,
4198 u8 link_10g, u32 gp_status)
4200 struct bnx2x *bp = params->bp;
4201 u8 port = params->port;
4202 u8 rc = 0;
4203 vars->link_status |= LINK_STATUS_LINK_UP;
4204 if (link_10g) {
4205 bnx2x_bmac_enable(params, vars, 0);
4206 bnx2x_set_led(bp, port, LED_MODE_OPER,
4207 SPEED_10000, params->hw_led_mode,
4208 params->chip_id);
4210 } else {
4211 bnx2x_emac_enable(params, vars, 0);
4212 rc = bnx2x_emac_program(params, vars->line_speed,
4213 vars->duplex);
4215 /* AN complete? */
4216 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
4217 if (!(vars->phy_flags &
4218 PHY_SGMII_FLAG))
4219 bnx2x_set_sgmii_tx_driver(params);
4223 /* PBF - link up */
4224 rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
4225 vars->line_speed);
4227 /* disable drain */
4228 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
4230 /* update shared memory */
4231 bnx2x_update_mng(params, vars->link_status);
4232 return rc;
4234 /* This function should called upon link interrupt */
4235 /* In case vars->link_up, driver needs to
4236 1. Update the pbf
4237 2. Disable drain
4238 3. Update the shared memory
4239 4. Indicate link up
4240 5. Set LEDs
4241 Otherwise,
4242 1. Update shared memory
4243 2. Reset BigMac
4244 3. Report link down
4245 4. Unset LEDs
4247 u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
4249 struct bnx2x *bp = params->bp;
4250 u8 port = params->port;
4251 u16 gp_status;
4252 u8 link_10g;
4253 u8 ext_phy_link_up, rc = 0;
4254 u32 ext_phy_type;
4256 DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
4257 port,
4258 (vars->phy_flags & PHY_XGXS_FLAG),
4259 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
4261 DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
4262 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
4263 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
4264 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
4266 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
4267 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
4268 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
4270 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
4272 /* Check external link change only for non-direct */
4273 ext_phy_link_up = bnx2x_ext_phy_is_link_up(params, vars);
4275 /* Read gp_status */
4276 CL45_RD_OVER_CL22(bp, port, params->phy_addr,
4277 MDIO_REG_BANK_GP_STATUS,
4278 MDIO_GP_STATUS_TOP_AN_STATUS1,
4279 &gp_status);
4281 rc = bnx2x_link_settings_status(params, vars, gp_status);
4282 if (rc != 0)
4283 return rc;
4285 /* anything 10 and over uses the bmac */
4286 link_10g = ((vars->line_speed == SPEED_10000) ||
4287 (vars->line_speed == SPEED_12000) ||
4288 (vars->line_speed == SPEED_12500) ||
4289 (vars->line_speed == SPEED_13000) ||
4290 (vars->line_speed == SPEED_15000) ||
4291 (vars->line_speed == SPEED_16000));
4293 bnx2x_link_int_ack(params, vars, link_10g);
4295 /* In case external phy link is up, and internal link is down
4296 ( not initialized yet probably after link initialization, it needs
4297 to be initialized.
4298 Note that after link down-up as result of cable plug,
4299 the xgxs link would probably become up again without the need to
4300 initialize it*/
4302 if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
4303 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) &&
4304 (ext_phy_link_up && !vars->phy_link_up))
4305 bnx2x_init_internal_phy(params, vars);
4307 /* link is up only if both local phy and external phy are up */
4308 vars->link_up = (ext_phy_link_up && vars->phy_link_up);
4310 if (vars->link_up)
4311 rc = bnx2x_update_link_up(params, vars, link_10g, gp_status);
4312 else
4313 rc = bnx2x_update_link_down(params, vars);
4315 return rc;
4318 static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
4320 u8 ext_phy_addr[PORT_MAX];
4321 u16 val;
4322 s8 port;
4324 /* PART1 - Reset both phys */
4325 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4326 /* Extract the ext phy address for the port */
4327 u32 ext_phy_config = REG_RD(bp, shmem_base +
4328 offsetof(struct shmem_region,
4329 dev_info.port_hw_config[port].external_phy_config));
4331 /* disable attentions */
4332 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
4333 (NIG_MASK_XGXS0_LINK_STATUS |
4334 NIG_MASK_XGXS0_LINK10G |
4335 NIG_MASK_SERDES0_LINK_STATUS |
4336 NIG_MASK_MI_INT));
4338 ext_phy_addr[port] =
4339 ((ext_phy_config &
4340 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
4341 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
4343 /* Need to take the phy out of low power mode in order
4344 to write to access its registers */
4345 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4346 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
4348 /* Reset the phy */
4349 bnx2x_cl45_write(bp, port,
4350 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4351 ext_phy_addr[port],
4352 MDIO_PMA_DEVAD,
4353 MDIO_PMA_REG_CTRL,
4354 1<<15);
4357 /* Add delay of 150ms after reset */
4358 msleep(150);
4360 /* PART2 - Download firmware to both phys */
4361 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4362 u16 fw_ver1;
4364 bnx2x_bcm8073_external_rom_boot(bp, port,
4365 ext_phy_addr[port]);
4367 bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4368 ext_phy_addr[port],
4369 MDIO_PMA_DEVAD,
4370 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
4371 if (fw_ver1 == 0) {
4372 DP(NETIF_MSG_LINK,
4373 "bnx2x_8073_common_init_phy port %x "
4374 "fw Download failed\n", port);
4375 return -EINVAL;
4378 /* Only set bit 10 = 1 (Tx power down) */
4379 bnx2x_cl45_read(bp, port,
4380 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4381 ext_phy_addr[port],
4382 MDIO_PMA_DEVAD,
4383 MDIO_PMA_REG_TX_POWER_DOWN, &val);
4385 /* Phase1 of TX_POWER_DOWN reset */
4386 bnx2x_cl45_write(bp, port,
4387 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4388 ext_phy_addr[port],
4389 MDIO_PMA_DEVAD,
4390 MDIO_PMA_REG_TX_POWER_DOWN,
4391 (val | 1<<10));
4394 /* Toggle Transmitter: Power down and then up with 600ms
4395 delay between */
4396 msleep(600);
4398 /* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low */
4399 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4400 /* Phase2 of POWER_DOWN_RESET*/
4401 /* Release bit 10 (Release Tx power down) */
4402 bnx2x_cl45_read(bp, port,
4403 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4404 ext_phy_addr[port],
4405 MDIO_PMA_DEVAD,
4406 MDIO_PMA_REG_TX_POWER_DOWN, &val);
4408 bnx2x_cl45_write(bp, port,
4409 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4410 ext_phy_addr[port],
4411 MDIO_PMA_DEVAD,
4412 MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
4413 msleep(15);
4415 /* Read modify write the SPI-ROM version select register */
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_EDC_FFE_MAIN, &val);
4421 bnx2x_cl45_write(bp, port,
4422 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4423 ext_phy_addr[port],
4424 MDIO_PMA_DEVAD,
4425 MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
4427 /* set GPIO2 back to LOW */
4428 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4429 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
4431 return 0;
4435 u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base)
4437 u8 rc = 0;
4438 u32 ext_phy_type;
4440 DP(NETIF_MSG_LINK, "bnx2x_common_init_phy\n");
4442 /* Read the ext_phy_type for arbitrary port(0) */
4443 ext_phy_type = XGXS_EXT_PHY_TYPE(
4444 REG_RD(bp, shmem_base +
4445 offsetof(struct shmem_region,
4446 dev_info.port_hw_config[0].external_phy_config)));
4448 switch (ext_phy_type) {
4449 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
4451 rc = bnx2x_8073_common_init_phy(bp, shmem_base);
4452 break;
4454 default:
4455 DP(NETIF_MSG_LINK,
4456 "bnx2x_common_init_phy: ext_phy 0x%x not required\n",
4457 ext_phy_type);
4458 break;
4461 return rc;
4466 static void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
4468 u16 val, cnt;
4470 bnx2x_cl45_read(bp, port,
4471 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4472 phy_addr,
4473 MDIO_PMA_DEVAD,
4474 MDIO_PMA_REG_7101_RESET, &val);
4476 for (cnt = 0; cnt < 10; cnt++) {
4477 msleep(50);
4478 /* Writes a self-clearing reset */
4479 bnx2x_cl45_write(bp, port,
4480 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4481 phy_addr,
4482 MDIO_PMA_DEVAD,
4483 MDIO_PMA_REG_7101_RESET,
4484 (val | (1<<15)));
4485 /* Wait for clear */
4486 bnx2x_cl45_read(bp, port,
4487 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4488 phy_addr,
4489 MDIO_PMA_DEVAD,
4490 MDIO_PMA_REG_7101_RESET, &val);
4492 if ((val & (1<<15)) == 0)
4493 break;
4496 #define RESERVED_SIZE 256
4497 /* max application is 160K bytes - data at end of RAM */
4498 #define MAX_APP_SIZE 160*1024 - RESERVED_SIZE
4500 /* Header is 14 bytes */
4501 #define HEADER_SIZE 14
4502 #define DATA_OFFSET HEADER_SIZE
4504 #define SPI_START_TRANSFER(bp, port, ext_phy_addr) \
4505 bnx2x_cl45_write(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101, \
4506 ext_phy_addr, \
4507 MDIO_PCS_DEVAD, \
4508 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 1)
4510 /* Programs an image to DSP's flash via the SPI port*/
4511 static u8 bnx2x_sfx7101_flash_download(struct bnx2x *bp, u8 port,
4512 u8 ext_phy_addr,
4513 char data[], u32 size)
4515 const u16 num_trans = size/4; /* 4 bytes can be sent at a time */
4516 /* Doesn't include last trans!*/
4517 const u16 last_trans_size = size%4; /* Num bytes on last trans */
4518 u16 trans_cnt, byte_cnt;
4519 u32 data_index;
4520 u16 tmp;
4521 u16 code_started = 0;
4522 u16 image_revision1, image_revision2;
4523 u16 cnt;
4525 DP(NETIF_MSG_LINK, "bnx2x_sfx7101_flash_download file_size=%d\n", size);
4526 /* Going to flash*/
4527 if ((size-HEADER_SIZE) > MAX_APP_SIZE) {
4528 /* This very often will be the case, because the image is built
4529 with 160Kbytes size whereas the total image size must actually
4530 be 160Kbytes-RESERVED_SIZE */
4531 DP(NETIF_MSG_LINK, "Warning, file size was %d bytes "
4532 "truncated to %d bytes\n", size, MAX_APP_SIZE);
4533 size = MAX_APP_SIZE+HEADER_SIZE;
4535 DP(NETIF_MSG_LINK, "File version is %c%c\n", data[0x14e], data[0x14f]);
4536 DP(NETIF_MSG_LINK, " %c%c\n", data[0x150], data[0x151]);
4537 /* Put the DSP in download mode by setting FLASH_CFG[2] to 1
4538 and issuing a reset.*/
4540 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
4541 MISC_REGISTERS_GPIO_HIGH, port);
4543 bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
4545 /* wait 0.5 sec */
4546 for (cnt = 0; cnt < 100; cnt++)
4547 msleep(5);
4549 /* Make sure we can access the DSP
4550 And it's in the correct mode (waiting for download) */
4552 bnx2x_cl45_read(bp, port,
4553 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4554 ext_phy_addr,
4555 MDIO_PCS_DEVAD,
4556 MDIO_PCS_REG_7101_DSP_ACCESS, &tmp);
4558 if (tmp != 0x000A) {
4559 DP(NETIF_MSG_LINK, "DSP is not in waiting on download mode. "
4560 "Expected 0x000A, read 0x%04X\n", tmp);
4561 DP(NETIF_MSG_LINK, "Download failed\n");
4562 return -EINVAL;
4565 /* Mux the SPI interface away from the internal processor */
4566 bnx2x_cl45_write(bp, port,
4567 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4568 ext_phy_addr,
4569 MDIO_PCS_DEVAD,
4570 MDIO_PCS_REG_7101_SPI_MUX, 1);
4572 /* Reset the SPI port */
4573 bnx2x_cl45_write(bp, port,
4574 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4575 ext_phy_addr,
4576 MDIO_PCS_DEVAD,
4577 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
4578 bnx2x_cl45_write(bp, port,
4579 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4580 ext_phy_addr,
4581 MDIO_PCS_DEVAD,
4582 MDIO_PCS_REG_7101_SPI_CTRL_ADDR,
4583 (1<<MDIO_PCS_REG_7101_SPI_RESET_BIT));
4584 bnx2x_cl45_write(bp, port,
4585 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4586 ext_phy_addr,
4587 MDIO_PCS_DEVAD,
4588 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
4590 /* Erase the flash */
4591 bnx2x_cl45_write(bp, port,
4592 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4593 ext_phy_addr,
4594 MDIO_PCS_DEVAD,
4595 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4596 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4598 bnx2x_cl45_write(bp, port,
4599 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4600 ext_phy_addr,
4601 MDIO_PCS_DEVAD,
4602 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4605 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4606 bnx2x_cl45_write(bp, port,
4607 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4608 ext_phy_addr,
4609 MDIO_PCS_DEVAD,
4610 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4611 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_BULK_ERASE_CMD);
4613 bnx2x_cl45_write(bp, port,
4614 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4615 ext_phy_addr,
4616 MDIO_PCS_DEVAD,
4617 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4619 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4621 /* Wait 10 seconds, the maximum time for the erase to complete */
4622 DP(NETIF_MSG_LINK, "Erasing flash, this takes 10 seconds...\n");
4623 for (cnt = 0; cnt < 1000; cnt++)
4624 msleep(10);
4626 DP(NETIF_MSG_LINK, "Downloading flash, please wait...\n");
4627 data_index = 0;
4628 for (trans_cnt = 0; trans_cnt < num_trans; trans_cnt++) {
4629 bnx2x_cl45_write(bp, port,
4630 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4631 ext_phy_addr,
4632 MDIO_PCS_DEVAD,
4633 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4634 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4636 bnx2x_cl45_write(bp, port,
4637 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4638 ext_phy_addr,
4639 MDIO_PCS_DEVAD,
4640 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4642 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4644 bnx2x_cl45_write(bp, port,
4645 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4646 ext_phy_addr,
4647 MDIO_PCS_DEVAD,
4648 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4649 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
4651 /* Bits 23-16 of address */
4652 bnx2x_cl45_write(bp, port,
4653 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4654 ext_phy_addr,
4655 MDIO_PCS_DEVAD,
4656 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4657 (data_index>>16));
4658 /* Bits 15-8 of address */
4659 bnx2x_cl45_write(bp, port,
4660 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4661 ext_phy_addr,
4662 MDIO_PCS_DEVAD,
4663 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4664 (data_index>>8));
4666 /* Bits 7-0 of address */
4667 bnx2x_cl45_write(bp, port,
4668 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4669 ext_phy_addr,
4670 MDIO_PCS_DEVAD,
4671 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4672 ((u16)data_index));
4674 byte_cnt = 0;
4675 while (byte_cnt < 4 && data_index < size) {
4676 bnx2x_cl45_write(bp, port,
4677 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4678 ext_phy_addr,
4679 MDIO_PCS_DEVAD,
4680 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4681 data[data_index++]);
4682 byte_cnt++;
4685 bnx2x_cl45_write(bp, port,
4686 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4687 ext_phy_addr,
4688 MDIO_PCS_DEVAD,
4689 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4690 byte_cnt+4);
4692 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4693 msleep(5); /* Wait 5 ms minimum between transs */
4695 /* Let the user know something's going on.*/
4696 /* a pacifier ever 4K */
4697 if ((data_index % 1023) == 0)
4698 DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
4701 DP(NETIF_MSG_LINK, "\n");
4702 /* Transfer the last block if there is data remaining */
4703 if (last_trans_size) {
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 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4711 bnx2x_cl45_write(bp, port,
4712 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4713 ext_phy_addr,
4714 MDIO_PCS_DEVAD,
4715 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4718 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4720 bnx2x_cl45_write(bp, port,
4721 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4722 ext_phy_addr,
4723 MDIO_PCS_DEVAD,
4724 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4725 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
4727 /* Bits 23-16 of address */
4728 bnx2x_cl45_write(bp, port,
4729 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4730 ext_phy_addr,
4731 MDIO_PCS_DEVAD,
4732 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4733 (data_index>>16));
4734 /* Bits 15-8 of address */
4735 bnx2x_cl45_write(bp, port,
4736 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4737 ext_phy_addr,
4738 MDIO_PCS_DEVAD,
4739 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4740 (data_index>>8));
4742 /* Bits 7-0 of address */
4743 bnx2x_cl45_write(bp, port,
4744 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4745 ext_phy_addr,
4746 MDIO_PCS_DEVAD,
4747 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4748 ((u16)data_index));
4750 byte_cnt = 0;
4751 while (byte_cnt < last_trans_size && data_index < size) {
4752 /* Bits 7-0 of address */
4753 bnx2x_cl45_write(bp, port,
4754 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4755 ext_phy_addr,
4756 MDIO_PCS_DEVAD,
4757 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4758 data[data_index++]);
4759 byte_cnt++;
4762 bnx2x_cl45_write(bp, port,
4763 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4764 ext_phy_addr,
4765 MDIO_PCS_DEVAD,
4766 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4767 byte_cnt+4);
4769 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4772 /* DSP Remove Download Mode */
4773 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
4774 MISC_REGISTERS_GPIO_LOW, port);
4776 bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
4778 /* wait 0.5 sec to allow it to run */
4779 for (cnt = 0; cnt < 100; cnt++)
4780 msleep(5);
4782 bnx2x_hw_reset(bp, port);
4784 for (cnt = 0; cnt < 100; cnt++)
4785 msleep(5);
4787 /* Check that the code is started. In case the download
4788 checksum failed, the code won't be started. */
4789 bnx2x_cl45_read(bp, port,
4790 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4791 ext_phy_addr,
4792 MDIO_PCS_DEVAD,
4793 MDIO_PCS_REG_7101_DSP_ACCESS,
4794 &tmp);
4796 code_started = (tmp & (1<<4));
4797 if (!code_started) {
4798 DP(NETIF_MSG_LINK, "Download failed. Please check file.\n");
4799 return -EINVAL;
4802 /* Verify that the file revision is now equal to the image
4803 revision within the DSP */
4804 bnx2x_cl45_read(bp, port,
4805 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4806 ext_phy_addr,
4807 MDIO_PMA_DEVAD,
4808 MDIO_PMA_REG_7101_VER1,
4809 &image_revision1);
4811 bnx2x_cl45_read(bp, port,
4812 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4813 ext_phy_addr,
4814 MDIO_PMA_DEVAD,
4815 MDIO_PMA_REG_7101_VER2,
4816 &image_revision2);
4818 if (data[0x14e] != (image_revision2&0xFF) ||
4819 data[0x14f] != ((image_revision2&0xFF00)>>8) ||
4820 data[0x150] != (image_revision1&0xFF) ||
4821 data[0x151] != ((image_revision1&0xFF00)>>8)) {
4822 DP(NETIF_MSG_LINK, "Download failed.\n");
4823 return -EINVAL;
4825 DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
4826 return 0;
4829 u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config,
4830 u8 driver_loaded, char data[], u32 size)
4832 u8 rc = 0;
4833 u32 ext_phy_type;
4834 u8 ext_phy_addr;
4835 ext_phy_addr = ((ext_phy_config &
4836 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
4837 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
4839 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
4841 switch (ext_phy_type) {
4842 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
4843 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
4844 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
4845 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
4846 DP(NETIF_MSG_LINK,
4847 "Flash download not supported for this ext phy\n");
4848 rc = -EINVAL;
4849 break;
4850 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
4851 /* Take ext phy out of reset */
4852 if (!driver_loaded)
4853 bnx2x_turn_on_ef(bp, port, ext_phy_addr, ext_phy_type);
4854 rc = bnx2x_sfx7101_flash_download(bp, port, ext_phy_addr,
4855 data, size);
4856 if (!driver_loaded)
4857 bnx2x_turn_off_sf(bp, port);
4858 break;
4859 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
4860 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
4861 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
4862 default:
4863 DP(NETIF_MSG_LINK, "Invalid ext phy type\n");
4864 rc = -EINVAL;
4865 break;
4867 return rc;