V4L/DVB (8495): usb/anysee.c: make struct anysee_usb_mutex static
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / net / bnx2x_link.c
blobff2743db10d9ef69081a0d96762fcefe96d2de51
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
41 #define MAX_MTU_SIZE 5000
43 /***********************************************************/
44 /* Shortcut definitions */
45 /***********************************************************/
47 #define NIG_STATUS_XGXS0_LINK10G \
48 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G
49 #define NIG_STATUS_XGXS0_LINK_STATUS \
50 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS
51 #define NIG_STATUS_XGXS0_LINK_STATUS_SIZE \
52 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE
53 #define NIG_STATUS_SERDES0_LINK_STATUS \
54 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS
55 #define NIG_MASK_MI_INT \
56 NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT
57 #define NIG_MASK_XGXS0_LINK10G \
58 NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G
59 #define NIG_MASK_XGXS0_LINK_STATUS \
60 NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK_STATUS
61 #define NIG_MASK_SERDES0_LINK_STATUS \
62 NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS
64 #define MDIO_AN_CL73_OR_37_COMPLETE \
65 (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | \
66 MDIO_GP_STATUS_TOP_AN_STATUS1_CL37_AUTONEG_COMPLETE)
68 #define XGXS_RESET_BITS \
69 (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW | \
70 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_IDDQ | \
71 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN | \
72 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN_SD | \
73 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB)
75 #define SERDES_RESET_BITS \
76 (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_RSTB_HW | \
77 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ | \
78 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN | \
79 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN_SD)
81 #define AUTONEG_CL37 SHARED_HW_CFG_AN_ENABLE_CL37
82 #define AUTONEG_CL73 SHARED_HW_CFG_AN_ENABLE_CL73
83 #define AUTONEG_BAM SHARED_HW_CFG_AN_ENABLE_BAM
84 #define AUTONEG_PARALLEL \
85 SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
86 #define AUTONEG_SGMII_FIBER_AUTODET \
87 SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT
88 #define AUTONEG_REMOTE_PHY SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY
90 #define GP_STATUS_PAUSE_RSOLUTION_TXSIDE \
91 MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE
92 #define GP_STATUS_PAUSE_RSOLUTION_RXSIDE \
93 MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_RXSIDE
94 #define GP_STATUS_SPEED_MASK \
95 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_MASK
96 #define GP_STATUS_10M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10M
97 #define GP_STATUS_100M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_100M
98 #define GP_STATUS_1G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G
99 #define GP_STATUS_2_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_2_5G
100 #define GP_STATUS_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_5G
101 #define GP_STATUS_6G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_6G
102 #define GP_STATUS_10G_HIG \
103 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG
104 #define GP_STATUS_10G_CX4 \
105 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4
106 #define GP_STATUS_12G_HIG \
107 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12G_HIG
108 #define GP_STATUS_12_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12_5G
109 #define GP_STATUS_13G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_13G
110 #define GP_STATUS_15G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_15G
111 #define GP_STATUS_16G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G
112 #define GP_STATUS_1G_KX MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX
113 #define GP_STATUS_10G_KX4 \
114 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
116 #define LINK_10THD LINK_STATUS_SPEED_AND_DUPLEX_10THD
117 #define LINK_10TFD LINK_STATUS_SPEED_AND_DUPLEX_10TFD
118 #define LINK_100TXHD LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
119 #define LINK_100T4 LINK_STATUS_SPEED_AND_DUPLEX_100T4
120 #define LINK_100TXFD LINK_STATUS_SPEED_AND_DUPLEX_100TXFD
121 #define LINK_1000THD LINK_STATUS_SPEED_AND_DUPLEX_1000THD
122 #define LINK_1000TFD LINK_STATUS_SPEED_AND_DUPLEX_1000TFD
123 #define LINK_1000XFD LINK_STATUS_SPEED_AND_DUPLEX_1000XFD
124 #define LINK_2500THD LINK_STATUS_SPEED_AND_DUPLEX_2500THD
125 #define LINK_2500TFD LINK_STATUS_SPEED_AND_DUPLEX_2500TFD
126 #define LINK_2500XFD LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
127 #define LINK_10GTFD LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
128 #define LINK_10GXFD LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
129 #define LINK_12GTFD LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
130 #define LINK_12GXFD LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
131 #define LINK_12_5GTFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD
132 #define LINK_12_5GXFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD
133 #define LINK_13GTFD LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
134 #define LINK_13GXFD LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
135 #define LINK_15GTFD LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
136 #define LINK_15GXFD LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
137 #define LINK_16GTFD LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
138 #define LINK_16GXFD LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
140 #define PHY_XGXS_FLAG 0x1
141 #define PHY_SGMII_FLAG 0x2
142 #define PHY_SERDES_FLAG 0x4
144 /**********************************************************/
145 /* INTERFACE */
146 /**********************************************************/
147 #define CL45_WR_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
148 bnx2x_cl45_write(_bp, _port, 0, _phy_addr, \
149 DEFAULT_PHY_DEV_ADDR, \
150 (_bank + (_addr & 0xf)), \
151 _val)
153 #define CL45_RD_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
154 bnx2x_cl45_read(_bp, _port, 0, _phy_addr, \
155 DEFAULT_PHY_DEV_ADDR, \
156 (_bank + (_addr & 0xf)), \
157 _val)
159 static void bnx2x_set_phy_mdio(struct link_params *params)
161 struct bnx2x *bp = params->bp;
162 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
163 params->port*0x18, 0);
164 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
165 DEFAULT_PHY_DEV_ADDR);
168 static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
170 u32 val = REG_RD(bp, reg);
172 val |= bits;
173 REG_WR(bp, reg, val);
174 return val;
177 static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits)
179 u32 val = REG_RD(bp, reg);
181 val &= ~bits;
182 REG_WR(bp, reg, val);
183 return val;
186 static void bnx2x_emac_init(struct link_params *params,
187 struct link_vars *vars)
189 /* reset and unreset the emac core */
190 struct bnx2x *bp = params->bp;
191 u8 port = params->port;
192 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
193 u32 val;
194 u16 timeout;
196 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
197 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
198 udelay(5);
199 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
200 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
202 /* init emac - use read-modify-write */
203 /* self clear reset */
204 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
205 EMAC_WR(EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET));
207 timeout = 200;
210 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
211 DP(NETIF_MSG_LINK, "EMAC reset reg is %u\n", val);
212 if (!timeout) {
213 DP(NETIF_MSG_LINK, "EMAC timeout!\n");
214 return;
216 timeout--;
217 }while (val & EMAC_MODE_RESET);
219 /* Set mac address */
220 val = ((params->mac_addr[0] << 8) |
221 params->mac_addr[1]);
222 EMAC_WR(EMAC_REG_EMAC_MAC_MATCH, val);
224 val = ((params->mac_addr[2] << 24) |
225 (params->mac_addr[3] << 16) |
226 (params->mac_addr[4] << 8) |
227 params->mac_addr[5]);
228 EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + 4, val);
231 static u8 bnx2x_emac_enable(struct link_params *params,
232 struct link_vars *vars, u8 lb)
234 struct bnx2x *bp = params->bp;
235 u8 port = params->port;
236 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
237 u32 val;
239 DP(NETIF_MSG_LINK, "enabling EMAC\n");
241 /* enable emac and not bmac */
242 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
244 /* for paladium */
245 if (CHIP_REV_IS_EMUL(bp)) {
246 /* Use lane 1 (of lanes 0-3) */
247 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
248 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
249 port*4, 1);
251 /* for fpga */
252 else
254 if (CHIP_REV_IS_FPGA(bp)) {
255 /* Use lane 1 (of lanes 0-3) */
256 DP(NETIF_MSG_LINK, "bnx2x_emac_enable: Setting FPGA\n");
258 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
259 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4,
261 } else
262 /* ASIC */
263 if (vars->phy_flags & PHY_XGXS_FLAG) {
264 u32 ser_lane = ((params->lane_config &
265 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
266 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
268 DP(NETIF_MSG_LINK, "XGXS\n");
269 /* select the master lanes (out of 0-3) */
270 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 +
271 port*4, ser_lane);
272 /* select XGXS */
273 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
274 port*4, 1);
276 } else { /* SerDes */
277 DP(NETIF_MSG_LINK, "SerDes\n");
278 /* select SerDes */
279 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
280 port*4, 0);
283 /* enable emac */
284 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1);
286 if (CHIP_REV_IS_SLOW(bp)) {
287 /* config GMII mode */
288 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
289 EMAC_WR(EMAC_REG_EMAC_MODE,
290 (val | EMAC_MODE_PORT_GMII));
291 } else { /* ASIC */
292 /* pause enable/disable */
293 bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
294 EMAC_RX_MODE_FLOW_EN);
295 if (vars->flow_ctrl & FLOW_CTRL_RX)
296 bnx2x_bits_en(bp, emac_base +
297 EMAC_REG_EMAC_RX_MODE,
298 EMAC_RX_MODE_FLOW_EN);
300 bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
301 EMAC_TX_MODE_EXT_PAUSE_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);
308 /* KEEP_VLAN_TAG, promiscuous */
309 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
310 val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
311 EMAC_WR(EMAC_REG_EMAC_RX_MODE, val);
313 /* Set Loopback */
314 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
315 if (lb)
316 val |= 0x810;
317 else
318 val &= ~0x810;
319 EMAC_WR(EMAC_REG_EMAC_MODE, val);
321 /* enable emac for jumbo packets */
322 EMAC_WR(EMAC_REG_EMAC_RX_MTU_SIZE,
323 (EMAC_RX_MTU_SIZE_JUMBO_ENA |
324 (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD)));
326 /* strip CRC */
327 REG_WR(bp, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1);
329 /* disable the NIG in/out to the bmac */
330 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x0);
331 REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, 0x0);
332 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x0);
334 /* enable the NIG in/out to the emac */
335 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x1);
336 val = 0;
337 if (vars->flow_ctrl & FLOW_CTRL_TX)
338 val = 1;
340 REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
341 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x1);
343 if (CHIP_REV_IS_EMUL(bp)) {
344 /* take the BigMac out of reset */
345 REG_WR(bp,
346 GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
347 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
349 /* enable access for bmac registers */
350 REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
353 vars->mac_type = MAC_TYPE_EMAC;
354 return 0;
359 static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
360 u8 is_lb)
362 struct bnx2x *bp = params->bp;
363 u8 port = params->port;
364 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
365 NIG_REG_INGRESS_BMAC0_MEM;
366 u32 wb_data[2];
367 u32 val;
369 DP(NETIF_MSG_LINK, "Enabling BigMAC\n");
370 /* reset and unreset the BigMac */
371 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
372 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
373 msleep(1);
375 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
376 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
378 /* enable access for bmac registers */
379 REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
381 /* XGXS control */
382 wb_data[0] = 0x3c;
383 wb_data[1] = 0;
384 REG_WR_DMAE(bp, bmac_addr +
385 BIGMAC_REGISTER_BMAC_XGXS_CONTROL,
386 wb_data, 2);
388 /* tx MAC SA */
389 wb_data[0] = ((params->mac_addr[2] << 24) |
390 (params->mac_addr[3] << 16) |
391 (params->mac_addr[4] << 8) |
392 params->mac_addr[5]);
393 wb_data[1] = ((params->mac_addr[0] << 8) |
394 params->mac_addr[1]);
395 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR,
396 wb_data, 2);
398 /* tx control */
399 val = 0xc0;
400 if (vars->flow_ctrl & FLOW_CTRL_TX)
401 val |= 0x800000;
402 wb_data[0] = val;
403 wb_data[1] = 0;
404 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_CONTROL,
405 wb_data, 2);
407 /* mac control */
408 val = 0x3;
409 if (is_lb) {
410 val |= 0x4;
411 DP(NETIF_MSG_LINK, "enable bmac loopback\n");
413 wb_data[0] = val;
414 wb_data[1] = 0;
415 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
416 wb_data, 2);
419 /* set rx mtu */
420 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
421 wb_data[1] = 0;
422 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE,
423 wb_data, 2);
425 /* rx control set to don't strip crc */
426 val = 0x14;
427 if (vars->flow_ctrl & FLOW_CTRL_RX)
428 val |= 0x20;
429 wb_data[0] = val;
430 wb_data[1] = 0;
431 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_CONTROL,
432 wb_data, 2);
434 /* set tx mtu */
435 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
436 wb_data[1] = 0;
437 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE,
438 wb_data, 2);
440 /* set cnt max size */
441 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
442 wb_data[1] = 0;
443 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE,
444 wb_data, 2);
446 /* configure safc */
447 wb_data[0] = 0x1000200;
448 wb_data[1] = 0;
449 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
450 wb_data, 2);
451 /* fix for emulation */
452 if (CHIP_REV_IS_EMUL(bp)) {
453 wb_data[0] = 0xf000;
454 wb_data[1] = 0;
455 REG_WR_DMAE(bp,
456 bmac_addr + BIGMAC_REGISTER_TX_PAUSE_THRESHOLD,
457 wb_data, 2);
460 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
461 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
462 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
463 val = 0;
464 if (vars->flow_ctrl & FLOW_CTRL_TX)
465 val = 1;
466 REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
467 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
468 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x0);
469 REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, 0x0);
470 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x1);
471 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);
473 vars->mac_type = MAC_TYPE_BMAC;
474 return 0;
477 static void bnx2x_phy_deassert(struct link_params *params, u8 phy_flags)
479 struct bnx2x *bp = params->bp;
480 u32 val;
482 if (phy_flags & PHY_XGXS_FLAG) {
483 DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:XGXS\n");
484 val = XGXS_RESET_BITS;
486 } else { /* SerDes */
487 DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:SerDes\n");
488 val = SERDES_RESET_BITS;
491 val = val << (params->port*16);
493 /* reset and unreset the SerDes/XGXS */
494 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
495 val);
496 udelay(500);
497 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET,
498 val);
499 bnx2x_set_phy_mdio(params);
502 void bnx2x_link_status_update(struct link_params *params,
503 struct link_vars *vars)
505 struct bnx2x *bp = params->bp;
506 u8 link_10g;
507 u8 port = params->port;
509 if (params->switch_cfg == SWITCH_CFG_1G)
510 vars->phy_flags = PHY_SERDES_FLAG;
511 else
512 vars->phy_flags = PHY_XGXS_FLAG;
513 vars->link_status = REG_RD(bp, params->shmem_base +
514 offsetof(struct shmem_region,
515 port_mb[port].link_status));
517 vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
519 if (vars->link_up) {
520 DP(NETIF_MSG_LINK, "phy link up\n");
522 vars->phy_link_up = 1;
523 vars->duplex = DUPLEX_FULL;
524 switch (vars->link_status &
525 LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
526 case LINK_10THD:
527 vars->duplex = DUPLEX_HALF;
528 /* fall thru */
529 case LINK_10TFD:
530 vars->line_speed = SPEED_10;
531 break;
533 case LINK_100TXHD:
534 vars->duplex = DUPLEX_HALF;
535 /* fall thru */
536 case LINK_100T4:
537 case LINK_100TXFD:
538 vars->line_speed = SPEED_100;
539 break;
541 case LINK_1000THD:
542 vars->duplex = DUPLEX_HALF;
543 /* fall thru */
544 case LINK_1000TFD:
545 vars->line_speed = SPEED_1000;
546 break;
548 case LINK_2500THD:
549 vars->duplex = DUPLEX_HALF;
550 /* fall thru */
551 case LINK_2500TFD:
552 vars->line_speed = SPEED_2500;
553 break;
555 case LINK_10GTFD:
556 vars->line_speed = SPEED_10000;
557 break;
559 case LINK_12GTFD:
560 vars->line_speed = SPEED_12000;
561 break;
563 case LINK_12_5GTFD:
564 vars->line_speed = SPEED_12500;
565 break;
567 case LINK_13GTFD:
568 vars->line_speed = SPEED_13000;
569 break;
571 case LINK_15GTFD:
572 vars->line_speed = SPEED_15000;
573 break;
575 case LINK_16GTFD:
576 vars->line_speed = SPEED_16000;
577 break;
579 default:
580 break;
583 if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
584 vars->flow_ctrl |= FLOW_CTRL_TX;
585 else
586 vars->flow_ctrl &= ~FLOW_CTRL_TX;
588 if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
589 vars->flow_ctrl |= FLOW_CTRL_RX;
590 else
591 vars->flow_ctrl &= ~FLOW_CTRL_RX;
593 if (vars->phy_flags & PHY_XGXS_FLAG) {
594 if (params->req_line_speed &&
595 ((params->req_line_speed == SPEED_10) ||
596 (params->req_line_speed == SPEED_100))) {
597 vars->phy_flags |= PHY_SGMII_FLAG;
598 } else {
599 vars->phy_flags &= ~PHY_SGMII_FLAG;
603 /* anything 10 and over uses the bmac */
604 link_10g = ((vars->line_speed == SPEED_10000) ||
605 (vars->line_speed == SPEED_12000) ||
606 (vars->line_speed == SPEED_12500) ||
607 (vars->line_speed == SPEED_13000) ||
608 (vars->line_speed == SPEED_15000) ||
609 (vars->line_speed == SPEED_16000));
610 if (link_10g)
611 vars->mac_type = MAC_TYPE_BMAC;
612 else
613 vars->mac_type = MAC_TYPE_EMAC;
615 } else { /* link down */
616 DP(NETIF_MSG_LINK, "phy link down\n");
618 vars->phy_link_up = 0;
620 vars->line_speed = 0;
621 vars->duplex = DUPLEX_FULL;
622 vars->flow_ctrl = FLOW_CTRL_NONE;
624 /* indicate no mac active */
625 vars->mac_type = MAC_TYPE_NONE;
628 DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x\n",
629 vars->link_status, vars->phy_link_up);
630 DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n",
631 vars->line_speed, vars->duplex, vars->flow_ctrl);
634 static void bnx2x_update_mng(struct link_params *params, u32 link_status)
636 struct bnx2x *bp = params->bp;
637 REG_WR(bp, params->shmem_base +
638 offsetof(struct shmem_region,
639 port_mb[params->port].link_status),
640 link_status);
643 static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
645 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
646 NIG_REG_INGRESS_BMAC0_MEM;
647 u32 wb_data[2];
648 u32 nig_bmac_enable = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4);
650 /* Only if the bmac is out of reset */
651 if (REG_RD(bp, MISC_REG_RESET_REG_2) &
652 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) &&
653 nig_bmac_enable) {
655 /* Clear Rx Enable bit in BMAC_CONTROL register */
656 REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
657 wb_data, 2);
658 wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
659 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
660 wb_data, 2);
662 msleep(1);
666 static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
667 u32 line_speed)
669 struct bnx2x *bp = params->bp;
670 u8 port = params->port;
671 u32 init_crd, crd;
672 u32 count = 1000;
673 u32 pause = 0;
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 pause = 1;
698 REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, pause);
699 if (pause) {
700 /* update threshold */
701 REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, 0);
702 /* update init credit */
703 init_crd = 778; /* (800-18-4) */
705 } else {
706 u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
707 ETH_OVREHEAD)/16;
709 /* update threshold */
710 REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh);
711 /* update init credit */
712 switch (line_speed) {
713 case SPEED_10:
714 case SPEED_100:
715 case SPEED_1000:
716 init_crd = thresh + 55 - 22;
717 break;
719 case SPEED_2500:
720 init_crd = thresh + 138 - 22;
721 break;
723 case SPEED_10000:
724 init_crd = thresh + 553 - 22;
725 break;
727 case SPEED_12000:
728 init_crd = thresh + 664 - 22;
729 break;
731 case SPEED_13000:
732 init_crd = thresh + 742 - 22;
733 break;
735 case SPEED_16000:
736 init_crd = thresh + 778 - 22;
737 break;
738 default:
739 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
740 line_speed);
741 return -EINVAL;
742 break;
745 REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, init_crd);
746 DP(NETIF_MSG_LINK, "PBF updated to speed %d credit %d\n",
747 line_speed, init_crd);
749 /* probe the credit changes */
750 REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x1);
751 msleep(5);
752 REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x0);
754 /* enable port */
755 REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x0);
756 return 0;
759 static u32 bnx2x_get_emac_base(u32 ext_phy_type, u8 port)
761 u32 emac_base;
762 switch (ext_phy_type) {
763 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
764 emac_base = GRCBASE_EMAC0;
765 break;
766 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
767 emac_base = (port) ? GRCBASE_EMAC0: GRCBASE_EMAC1;
768 break;
769 default:
770 emac_base = (port) ? GRCBASE_EMAC1: GRCBASE_EMAC0;
771 break;
773 return emac_base;
777 u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type,
778 u8 phy_addr, u8 devad, u16 reg, u16 val)
780 u32 tmp, saved_mode;
781 u8 i, rc = 0;
782 u32 mdio_ctrl = bnx2x_get_emac_base(ext_phy_type, port);
784 /* set clause 45 mode, slow down the MDIO clock to 2.5MHz
785 * (a value of 49==0x31) and make sure that the AUTO poll is off
787 saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
788 tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
789 EMAC_MDIO_MODE_CLOCK_CNT);
790 tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
791 (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
792 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
793 REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
794 udelay(40);
796 /* address */
798 tmp = ((phy_addr << 21) | (devad << 16) | reg |
799 EMAC_MDIO_COMM_COMMAND_ADDRESS |
800 EMAC_MDIO_COMM_START_BUSY);
801 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
803 for (i = 0; i < 50; i++) {
804 udelay(10);
806 tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
807 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
808 udelay(5);
809 break;
812 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
813 DP(NETIF_MSG_LINK, "write phy register failed\n");
814 rc = -EFAULT;
815 } else {
816 /* data */
817 tmp = ((phy_addr << 21) | (devad << 16) | val |
818 EMAC_MDIO_COMM_COMMAND_WRITE_45 |
819 EMAC_MDIO_COMM_START_BUSY);
820 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
822 for (i = 0; i < 50; i++) {
823 udelay(10);
825 tmp = REG_RD(bp, mdio_ctrl +
826 EMAC_REG_EMAC_MDIO_COMM);
827 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
828 udelay(5);
829 break;
832 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
833 DP(NETIF_MSG_LINK, "write phy register failed\n");
834 rc = -EFAULT;
838 /* Restore the saved mode */
839 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
841 return rc;
844 u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type,
845 u8 phy_addr, u8 devad, u16 reg, u16 *ret_val)
847 u32 val, saved_mode;
848 u16 i;
849 u8 rc = 0;
851 u32 mdio_ctrl = bnx2x_get_emac_base(ext_phy_type, port);
852 /* set clause 45 mode, slow down the MDIO clock to 2.5MHz
853 * (a value of 49==0x31) and make sure that the AUTO poll is off
855 saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
856 val = saved_mode & ((EMAC_MDIO_MODE_AUTO_POLL |
857 EMAC_MDIO_MODE_CLOCK_CNT));
858 val |= (EMAC_MDIO_MODE_CLAUSE_45 |
859 (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
860 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
861 REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
862 udelay(40);
864 /* address */
865 val = ((phy_addr << 21) | (devad << 16) | reg |
866 EMAC_MDIO_COMM_COMMAND_ADDRESS |
867 EMAC_MDIO_COMM_START_BUSY);
868 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
870 for (i = 0; i < 50; i++) {
871 udelay(10);
873 val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
874 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
875 udelay(5);
876 break;
879 if (val & EMAC_MDIO_COMM_START_BUSY) {
880 DP(NETIF_MSG_LINK, "read phy register failed\n");
882 *ret_val = 0;
883 rc = -EFAULT;
885 } else {
886 /* data */
887 val = ((phy_addr << 21) | (devad << 16) |
888 EMAC_MDIO_COMM_COMMAND_READ_45 |
889 EMAC_MDIO_COMM_START_BUSY);
890 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
892 for (i = 0; i < 50; i++) {
893 udelay(10);
895 val = REG_RD(bp, mdio_ctrl +
896 EMAC_REG_EMAC_MDIO_COMM);
897 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
898 *ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
899 break;
902 if (val & EMAC_MDIO_COMM_START_BUSY) {
903 DP(NETIF_MSG_LINK, "read phy register failed\n");
905 *ret_val = 0;
906 rc = -EFAULT;
910 /* Restore the saved mode */
911 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
913 return rc;
916 static void bnx2x_set_aer_mmd(struct link_params *params,
917 struct link_vars *vars)
919 struct bnx2x *bp = params->bp;
920 u32 ser_lane;
921 u16 offset;
923 ser_lane = ((params->lane_config &
924 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
925 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
927 offset = (vars->phy_flags & PHY_XGXS_FLAG) ?
928 (params->phy_addr + ser_lane) : 0;
930 CL45_WR_OVER_CL22(bp, params->port,
931 params->phy_addr,
932 MDIO_REG_BANK_AER_BLOCK,
933 MDIO_AER_BLOCK_AER_REG, 0x3800 + offset);
936 static void bnx2x_set_master_ln(struct link_params *params)
938 struct bnx2x *bp = params->bp;
939 u16 new_master_ln, ser_lane;
940 ser_lane = ((params->lane_config &
941 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
942 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
944 /* set the master_ln for AN */
945 CL45_RD_OVER_CL22(bp, params->port,
946 params->phy_addr,
947 MDIO_REG_BANK_XGXS_BLOCK2,
948 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
949 &new_master_ln);
951 CL45_WR_OVER_CL22(bp, params->port,
952 params->phy_addr,
953 MDIO_REG_BANK_XGXS_BLOCK2 ,
954 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
955 (new_master_ln | ser_lane));
958 static u8 bnx2x_reset_unicore(struct link_params *params)
960 struct bnx2x *bp = params->bp;
961 u16 mii_control;
962 u16 i;
964 CL45_RD_OVER_CL22(bp, params->port,
965 params->phy_addr,
966 MDIO_REG_BANK_COMBO_IEEE0,
967 MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
969 /* reset the unicore */
970 CL45_WR_OVER_CL22(bp, params->port,
971 params->phy_addr,
972 MDIO_REG_BANK_COMBO_IEEE0,
973 MDIO_COMBO_IEEE0_MII_CONTROL,
974 (mii_control |
975 MDIO_COMBO_IEEO_MII_CONTROL_RESET));
977 /* wait for the reset to self clear */
978 for (i = 0; i < MDIO_ACCESS_TIMEOUT; i++) {
979 udelay(5);
981 /* the reset erased the previous bank value */
982 CL45_RD_OVER_CL22(bp, params->port,
983 params->phy_addr,
984 MDIO_REG_BANK_COMBO_IEEE0,
985 MDIO_COMBO_IEEE0_MII_CONTROL,
986 &mii_control);
988 if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) {
989 udelay(5);
990 return 0;
994 DP(NETIF_MSG_LINK, "BUG! XGXS is still in reset!\n");
995 return -EINVAL;
999 static void bnx2x_set_swap_lanes(struct link_params *params)
1001 struct bnx2x *bp = params->bp;
1002 /* Each two bits represents a lane number:
1003 No swap is 0123 => 0x1b no need to enable the swap */
1004 u16 ser_lane, rx_lane_swap, tx_lane_swap;
1006 ser_lane = ((params->lane_config &
1007 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
1008 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
1009 rx_lane_swap = ((params->lane_config &
1010 PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
1011 PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
1012 tx_lane_swap = ((params->lane_config &
1013 PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
1014 PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
1016 if (rx_lane_swap != 0x1b) {
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,
1021 (rx_lane_swap |
1022 MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
1023 MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
1024 } else {
1025 CL45_WR_OVER_CL22(bp, params->port,
1026 params->phy_addr,
1027 MDIO_REG_BANK_XGXS_BLOCK2,
1028 MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
1031 if (tx_lane_swap != 0x1b) {
1032 CL45_WR_OVER_CL22(bp, params->port,
1033 params->phy_addr,
1034 MDIO_REG_BANK_XGXS_BLOCK2,
1035 MDIO_XGXS_BLOCK2_TX_LN_SWAP,
1036 (tx_lane_swap |
1037 MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
1038 } else {
1039 CL45_WR_OVER_CL22(bp, params->port,
1040 params->phy_addr,
1041 MDIO_REG_BANK_XGXS_BLOCK2,
1042 MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
1046 static void bnx2x_set_parallel_detection(struct link_params *params,
1047 u8 phy_flags)
1049 struct bnx2x *bp = params->bp;
1050 u16 control2;
1052 CL45_RD_OVER_CL22(bp, params->port,
1053 params->phy_addr,
1054 MDIO_REG_BANK_SERDES_DIGITAL,
1055 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1056 &control2);
1059 control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
1062 CL45_WR_OVER_CL22(bp, params->port,
1063 params->phy_addr,
1064 MDIO_REG_BANK_SERDES_DIGITAL,
1065 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1066 control2);
1068 if (phy_flags & PHY_XGXS_FLAG) {
1069 DP(NETIF_MSG_LINK, "XGXS\n");
1071 CL45_WR_OVER_CL22(bp, params->port,
1072 params->phy_addr,
1073 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1074 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
1075 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
1077 CL45_RD_OVER_CL22(bp, params->port,
1078 params->phy_addr,
1079 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1080 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
1081 &control2);
1084 control2 |=
1085 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
1087 CL45_WR_OVER_CL22(bp, params->port,
1088 params->phy_addr,
1089 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1090 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
1091 control2);
1093 /* Disable parallel detection of HiG */
1094 CL45_WR_OVER_CL22(bp, params->port,
1095 params->phy_addr,
1096 MDIO_REG_BANK_XGXS_BLOCK2,
1097 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
1098 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
1099 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
1103 static void bnx2x_set_autoneg(struct link_params *params,
1104 struct link_vars *vars)
1106 struct bnx2x *bp = params->bp;
1107 u16 reg_val;
1109 /* CL37 Autoneg */
1111 CL45_RD_OVER_CL22(bp, params->port,
1112 params->phy_addr,
1113 MDIO_REG_BANK_COMBO_IEEE0,
1114 MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1116 /* CL37 Autoneg Enabled */
1117 if (params->req_line_speed == SPEED_AUTO_NEG)
1118 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN;
1119 else /* CL37 Autoneg Disabled */
1120 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1121 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);
1123 CL45_WR_OVER_CL22(bp, params->port,
1124 params->phy_addr,
1125 MDIO_REG_BANK_COMBO_IEEE0,
1126 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1128 /* Enable/Disable Autodetection */
1130 CL45_RD_OVER_CL22(bp, params->port,
1131 params->phy_addr,
1132 MDIO_REG_BANK_SERDES_DIGITAL,
1133 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
1134 reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN;
1135 if (params->req_line_speed == SPEED_AUTO_NEG)
1136 reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1137 else
1138 reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1140 CL45_WR_OVER_CL22(bp, params->port,
1141 params->phy_addr,
1142 MDIO_REG_BANK_SERDES_DIGITAL,
1143 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
1145 /* Enable TetonII and BAM autoneg */
1146 CL45_RD_OVER_CL22(bp, params->port,
1147 params->phy_addr,
1148 MDIO_REG_BANK_BAM_NEXT_PAGE,
1149 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1150 &reg_val);
1151 if (params->req_line_speed == SPEED_AUTO_NEG) {
1152 /* Enable BAM aneg Mode and TetonII aneg Mode */
1153 reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1154 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1155 } else {
1156 /* TetonII and BAM Autoneg Disabled */
1157 reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1158 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1160 CL45_WR_OVER_CL22(bp, params->port,
1161 params->phy_addr,
1162 MDIO_REG_BANK_BAM_NEXT_PAGE,
1163 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1164 reg_val);
1166 /* Enable Clause 73 Aneg */
1167 if ((params->req_line_speed == SPEED_AUTO_NEG) &&
1168 (SUPPORT_CL73)) {
1169 /* Enable BAM Station Manager */
1171 CL45_WR_OVER_CL22(bp, params->port,
1172 params->phy_addr,
1173 MDIO_REG_BANK_CL73_USERB0,
1174 MDIO_CL73_USERB0_CL73_BAM_CTRL1,
1175 (MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
1176 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN |
1177 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN));
1179 /* Merge CL73 and CL37 aneg resolution */
1180 CL45_RD_OVER_CL22(bp, params->port,
1181 params->phy_addr,
1182 MDIO_REG_BANK_CL73_USERB0,
1183 MDIO_CL73_USERB0_CL73_BAM_CTRL3,
1184 &reg_val);
1186 CL45_WR_OVER_CL22(bp, params->port,
1187 params->phy_addr,
1188 MDIO_REG_BANK_CL73_USERB0,
1189 MDIO_CL73_USERB0_CL73_BAM_CTRL3,
1190 (reg_val |
1191 MDIO_CL73_USERB0_CL73_BAM_CTRL3_USE_CL73_HCD_MR));
1193 /* Set the CL73 AN speed */
1195 CL45_RD_OVER_CL22(bp, params->port,
1196 params->phy_addr,
1197 MDIO_REG_BANK_CL73_IEEEB1,
1198 MDIO_CL73_IEEEB1_AN_ADV2, &reg_val);
1199 /* In the SerDes we support only the 1G.
1200 In the XGXS we support the 10G KX4
1201 but we currently do not support the KR */
1202 if (vars->phy_flags & PHY_XGXS_FLAG) {
1203 DP(NETIF_MSG_LINK, "XGXS\n");
1204 /* 10G KX4 */
1205 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
1206 } else {
1207 DP(NETIF_MSG_LINK, "SerDes\n");
1208 /* 1000M KX */
1209 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
1211 CL45_WR_OVER_CL22(bp, params->port,
1212 params->phy_addr,
1213 MDIO_REG_BANK_CL73_IEEEB1,
1214 MDIO_CL73_IEEEB1_AN_ADV2, reg_val);
1216 /* CL73 Autoneg Enabled */
1217 reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;
1218 } else {
1219 /* CL73 Autoneg Disabled */
1220 reg_val = 0;
1222 CL45_WR_OVER_CL22(bp, params->port,
1223 params->phy_addr,
1224 MDIO_REG_BANK_CL73_IEEEB0,
1225 MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
1228 /* program SerDes, forced speed */
1229 static void bnx2x_program_serdes(struct link_params *params)
1231 struct bnx2x *bp = params->bp;
1232 u16 reg_val;
1234 /* program duplex, disable autoneg */
1236 CL45_RD_OVER_CL22(bp, params->port,
1237 params->phy_addr,
1238 MDIO_REG_BANK_COMBO_IEEE0,
1239 MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1240 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
1241 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN);
1242 if (params->req_duplex == DUPLEX_FULL)
1243 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
1244 CL45_WR_OVER_CL22(bp, params->port,
1245 params->phy_addr,
1246 MDIO_REG_BANK_COMBO_IEEE0,
1247 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1249 /* program speed
1250 - needed only if the speed is greater than 1G (2.5G or 10G) */
1251 if (!((params->req_line_speed == SPEED_1000) ||
1252 (params->req_line_speed == SPEED_100) ||
1253 (params->req_line_speed == SPEED_10))) {
1254 CL45_RD_OVER_CL22(bp, params->port,
1255 params->phy_addr,
1256 MDIO_REG_BANK_SERDES_DIGITAL,
1257 MDIO_SERDES_DIGITAL_MISC1, &reg_val);
1258 /* clearing the speed value before setting the right speed */
1259 reg_val &= ~MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK;
1260 reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M |
1261 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
1262 if (params->req_line_speed == SPEED_10000)
1263 reg_val |=
1264 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
1265 if (params->req_line_speed == SPEED_13000)
1266 reg_val |=
1267 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_set_ieee_aneg_advertisment(struct link_params *params,
1299 u32 *ieee_fc)
1301 struct bnx2x *bp = params->bp;
1302 /* for AN, we are always publishing full duplex */
1303 u16 an_adv = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
1305 /* resolve pause mode and advertisement
1306 * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
1308 switch (params->req_flow_ctrl) {
1309 case FLOW_CTRL_AUTO:
1310 if (params->mtu <= MAX_MTU_SIZE) {
1311 an_adv |=
1312 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
1313 } else {
1314 an_adv |=
1315 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1317 break;
1318 case FLOW_CTRL_TX:
1319 an_adv |=
1320 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1321 break;
1323 case FLOW_CTRL_RX:
1324 case FLOW_CTRL_BOTH:
1325 an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
1326 break;
1328 case FLOW_CTRL_NONE:
1329 default:
1330 an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
1331 break;
1334 *ieee_fc = an_adv;
1336 CL45_WR_OVER_CL22(bp, params->port,
1337 params->phy_addr,
1338 MDIO_REG_BANK_COMBO_IEEE0,
1339 MDIO_COMBO_IEEE0_AUTO_NEG_ADV, an_adv);
1342 static void bnx2x_restart_autoneg(struct link_params *params)
1344 struct bnx2x *bp = params->bp;
1345 DP(NETIF_MSG_LINK, "bnx2x_restart_autoneg\n");
1346 if (SUPPORT_CL73) {
1347 /* enable and restart clause 73 aneg */
1348 u16 an_ctrl;
1350 CL45_RD_OVER_CL22(bp, params->port,
1351 params->phy_addr,
1352 MDIO_REG_BANK_CL73_IEEEB0,
1353 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1354 &an_ctrl);
1355 CL45_WR_OVER_CL22(bp, params->port,
1356 params->phy_addr,
1357 MDIO_REG_BANK_CL73_IEEEB0,
1358 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1359 (an_ctrl |
1360 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
1361 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
1363 } else {
1364 /* Enable and restart BAM/CL37 aneg */
1365 u16 mii_control;
1367 CL45_RD_OVER_CL22(bp, params->port,
1368 params->phy_addr,
1369 MDIO_REG_BANK_COMBO_IEEE0,
1370 MDIO_COMBO_IEEE0_MII_CONTROL,
1371 &mii_control);
1372 DP(NETIF_MSG_LINK,
1373 "bnx2x_restart_autoneg mii_control before = 0x%x\n",
1374 mii_control);
1375 CL45_WR_OVER_CL22(bp, params->port,
1376 params->phy_addr,
1377 MDIO_REG_BANK_COMBO_IEEE0,
1378 MDIO_COMBO_IEEE0_MII_CONTROL,
1379 (mii_control |
1380 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1381 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
1385 static void bnx2x_initialize_sgmii_process(struct link_params *params)
1387 struct bnx2x *bp = params->bp;
1388 u16 control1;
1390 /* in SGMII mode, the unicore is always slave */
1392 CL45_RD_OVER_CL22(bp, params->port,
1393 params->phy_addr,
1394 MDIO_REG_BANK_SERDES_DIGITAL,
1395 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1396 &control1);
1397 control1 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT;
1398 /* set sgmii mode (and not fiber) */
1399 control1 &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE |
1400 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET |
1401 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE);
1402 CL45_WR_OVER_CL22(bp, params->port,
1403 params->phy_addr,
1404 MDIO_REG_BANK_SERDES_DIGITAL,
1405 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1406 control1);
1408 /* if forced speed */
1409 if (!(params->req_line_speed == SPEED_AUTO_NEG)) {
1410 /* set speed, disable autoneg */
1411 u16 mii_control;
1413 CL45_RD_OVER_CL22(bp, params->port,
1414 params->phy_addr,
1415 MDIO_REG_BANK_COMBO_IEEE0,
1416 MDIO_COMBO_IEEE0_MII_CONTROL,
1417 &mii_control);
1418 mii_control &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1419 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK|
1420 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX);
1422 switch (params->req_line_speed) {
1423 case SPEED_100:
1424 mii_control |=
1425 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100;
1426 break;
1427 case SPEED_1000:
1428 mii_control |=
1429 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_1000;
1430 break;
1431 case SPEED_10:
1432 /* there is nothing to set for 10M */
1433 break;
1434 default:
1435 /* invalid speed for SGMII */
1436 DP(NETIF_MSG_LINK, "Invalid req_line_speed 0x%x\n",
1437 params->req_line_speed);
1438 break;
1441 /* setting the full duplex */
1442 if (params->req_duplex == DUPLEX_FULL)
1443 mii_control |=
1444 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
1445 CL45_WR_OVER_CL22(bp, params->port,
1446 params->phy_addr,
1447 MDIO_REG_BANK_COMBO_IEEE0,
1448 MDIO_COMBO_IEEE0_MII_CONTROL,
1449 mii_control);
1451 } else { /* AN mode */
1452 /* enable and restart AN */
1453 bnx2x_restart_autoneg(params);
1459 * link management
1462 static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
1464 switch (pause_result) { /* ASYM P ASYM P */
1465 case 0xb: /* 1 0 1 1 */
1466 vars->flow_ctrl = FLOW_CTRL_TX;
1467 break;
1469 case 0xe: /* 1 1 1 0 */
1470 vars->flow_ctrl = FLOW_CTRL_RX;
1471 break;
1473 case 0x5: /* 0 1 0 1 */
1474 case 0x7: /* 0 1 1 1 */
1475 case 0xd: /* 1 1 0 1 */
1476 case 0xf: /* 1 1 1 1 */
1477 vars->flow_ctrl = FLOW_CTRL_BOTH;
1478 break;
1480 default:
1481 break;
1485 static u8 bnx2x_ext_phy_resove_fc(struct link_params *params,
1486 struct link_vars *vars)
1488 struct bnx2x *bp = params->bp;
1489 u8 ext_phy_addr;
1490 u16 ld_pause; /* local */
1491 u16 lp_pause; /* link partner */
1492 u16 an_complete; /* AN complete */
1493 u16 pause_result;
1494 u8 ret = 0;
1495 u32 ext_phy_type;
1496 u8 port = params->port;
1497 ext_phy_addr = ((params->ext_phy_config &
1498 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1499 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1501 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1502 /* read twice */
1504 bnx2x_cl45_read(bp, port,
1505 ext_phy_type,
1506 ext_phy_addr,
1507 MDIO_AN_DEVAD,
1508 MDIO_AN_REG_STATUS, &an_complete);
1509 bnx2x_cl45_read(bp, port,
1510 ext_phy_type,
1511 ext_phy_addr,
1512 MDIO_AN_DEVAD,
1513 MDIO_AN_REG_STATUS, &an_complete);
1515 if (an_complete & MDIO_AN_REG_STATUS_AN_COMPLETE) {
1516 ret = 1;
1517 bnx2x_cl45_read(bp, port,
1518 ext_phy_type,
1519 ext_phy_addr,
1520 MDIO_AN_DEVAD,
1521 MDIO_AN_REG_ADV_PAUSE, &ld_pause);
1522 bnx2x_cl45_read(bp, port,
1523 ext_phy_type,
1524 ext_phy_addr,
1525 MDIO_AN_DEVAD,
1526 MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
1527 pause_result = (ld_pause &
1528 MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
1529 pause_result |= (lp_pause &
1530 MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
1531 DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x \n",
1532 pause_result);
1533 bnx2x_pause_resolve(vars, pause_result);
1535 return ret;
1539 static void bnx2x_flow_ctrl_resolve(struct link_params *params,
1540 struct link_vars *vars,
1541 u32 gp_status)
1543 struct bnx2x *bp = params->bp;
1544 u16 ld_pause; /* local driver */
1545 u16 lp_pause; /* link partner */
1546 u16 pause_result;
1548 vars->flow_ctrl = FLOW_CTRL_NONE;
1550 /* resolve from gp_status in case of AN complete and not sgmii */
1551 if ((params->req_flow_ctrl == FLOW_CTRL_AUTO) &&
1552 (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
1553 (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
1554 (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1555 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) {
1556 CL45_RD_OVER_CL22(bp, params->port,
1557 params->phy_addr,
1558 MDIO_REG_BANK_COMBO_IEEE0,
1559 MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
1560 &ld_pause);
1561 CL45_RD_OVER_CL22(bp, params->port,
1562 params->phy_addr,
1563 MDIO_REG_BANK_COMBO_IEEE0,
1564 MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
1565 &lp_pause);
1566 pause_result = (ld_pause &
1567 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
1568 pause_result |= (lp_pause &
1569 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
1570 DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result);
1571 bnx2x_pause_resolve(vars, pause_result);
1572 } else if ((params->req_flow_ctrl == FLOW_CTRL_AUTO) &&
1573 (bnx2x_ext_phy_resove_fc(params, vars))) {
1574 return;
1575 } else {
1576 vars->flow_ctrl = params->req_flow_ctrl;
1577 if (vars->flow_ctrl == FLOW_CTRL_AUTO) {
1578 if (params->mtu <= MAX_MTU_SIZE)
1579 vars->flow_ctrl = FLOW_CTRL_BOTH;
1580 else
1581 vars->flow_ctrl = FLOW_CTRL_TX;
1584 DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
1588 static u8 bnx2x_link_settings_status(struct link_params *params,
1589 struct link_vars *vars,
1590 u32 gp_status)
1592 struct bnx2x *bp = params->bp;
1593 u8 rc = 0;
1594 vars->link_status = 0;
1596 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
1597 DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
1598 gp_status);
1600 vars->phy_link_up = 1;
1601 vars->link_status |= LINK_STATUS_LINK_UP;
1603 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
1604 vars->duplex = DUPLEX_FULL;
1605 else
1606 vars->duplex = DUPLEX_HALF;
1608 bnx2x_flow_ctrl_resolve(params, vars, gp_status);
1610 switch (gp_status & GP_STATUS_SPEED_MASK) {
1611 case GP_STATUS_10M:
1612 vars->line_speed = SPEED_10;
1613 if (vars->duplex == DUPLEX_FULL)
1614 vars->link_status |= LINK_10TFD;
1615 else
1616 vars->link_status |= LINK_10THD;
1617 break;
1619 case GP_STATUS_100M:
1620 vars->line_speed = SPEED_100;
1621 if (vars->duplex == DUPLEX_FULL)
1622 vars->link_status |= LINK_100TXFD;
1623 else
1624 vars->link_status |= LINK_100TXHD;
1625 break;
1627 case GP_STATUS_1G:
1628 case GP_STATUS_1G_KX:
1629 vars->line_speed = SPEED_1000;
1630 if (vars->duplex == DUPLEX_FULL)
1631 vars->link_status |= LINK_1000TFD;
1632 else
1633 vars->link_status |= LINK_1000THD;
1634 break;
1636 case GP_STATUS_2_5G:
1637 vars->line_speed = SPEED_2500;
1638 if (vars->duplex == DUPLEX_FULL)
1639 vars->link_status |= LINK_2500TFD;
1640 else
1641 vars->link_status |= LINK_2500THD;
1642 break;
1644 case GP_STATUS_5G:
1645 case GP_STATUS_6G:
1646 DP(NETIF_MSG_LINK,
1647 "link speed unsupported gp_status 0x%x\n",
1648 gp_status);
1649 return -EINVAL;
1650 break;
1651 case GP_STATUS_10G_KX4:
1652 case GP_STATUS_10G_HIG:
1653 case GP_STATUS_10G_CX4:
1654 vars->line_speed = SPEED_10000;
1655 vars->link_status |= LINK_10GTFD;
1656 break;
1658 case GP_STATUS_12G_HIG:
1659 vars->line_speed = SPEED_12000;
1660 vars->link_status |= LINK_12GTFD;
1661 break;
1663 case GP_STATUS_12_5G:
1664 vars->line_speed = SPEED_12500;
1665 vars->link_status |= LINK_12_5GTFD;
1666 break;
1668 case GP_STATUS_13G:
1669 vars->line_speed = SPEED_13000;
1670 vars->link_status |= LINK_13GTFD;
1671 break;
1673 case GP_STATUS_15G:
1674 vars->line_speed = SPEED_15000;
1675 vars->link_status |= LINK_15GTFD;
1676 break;
1678 case GP_STATUS_16G:
1679 vars->line_speed = SPEED_16000;
1680 vars->link_status |= LINK_16GTFD;
1681 break;
1683 default:
1684 DP(NETIF_MSG_LINK,
1685 "link speed unsupported gp_status 0x%x\n",
1686 gp_status);
1687 return -EINVAL;
1688 break;
1691 vars->link_status |= LINK_STATUS_SERDES_LINK;
1693 if (params->req_line_speed == SPEED_AUTO_NEG) {
1694 vars->autoneg = AUTO_NEG_ENABLED;
1696 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
1697 vars->autoneg |= AUTO_NEG_COMPLETE;
1698 vars->link_status |=
1699 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
1702 vars->autoneg |= AUTO_NEG_PARALLEL_DETECTION_USED;
1703 vars->link_status |=
1704 LINK_STATUS_PARALLEL_DETECTION_USED;
1707 if (vars->flow_ctrl & FLOW_CTRL_TX)
1708 vars->link_status |=
1709 LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
1711 if (vars->flow_ctrl & FLOW_CTRL_RX)
1712 vars->link_status |=
1713 LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
1715 } else { /* link_down */
1716 DP(NETIF_MSG_LINK, "phy link down\n");
1718 vars->phy_link_up = 0;
1719 vars->line_speed = 0;
1720 vars->duplex = DUPLEX_FULL;
1721 vars->flow_ctrl = FLOW_CTRL_NONE;
1722 vars->autoneg = AUTO_NEG_DISABLED;
1723 vars->mac_type = MAC_TYPE_NONE;
1726 DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x \n",
1727 gp_status, vars->phy_link_up, vars->line_speed);
1728 DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x"
1729 " autoneg 0x%x\n",
1730 vars->duplex,
1731 vars->flow_ctrl, vars->autoneg);
1732 DP(NETIF_MSG_LINK, "link_status 0x%x\n", vars->link_status);
1734 return rc;
1737 static void bnx2x_set_sgmii_tx_driver(struct link_params *params)
1739 struct bnx2x *bp = params->bp;
1740 u16 lp_up2;
1741 u16 tx_driver;
1743 /* read precomp */
1745 CL45_RD_OVER_CL22(bp, params->port,
1746 params->phy_addr,
1747 MDIO_REG_BANK_OVER_1G,
1748 MDIO_OVER_1G_LP_UP2, &lp_up2);
1750 CL45_RD_OVER_CL22(bp, params->port,
1751 params->phy_addr,
1752 MDIO_REG_BANK_TX0,
1753 MDIO_TX0_TX_DRIVER, &tx_driver);
1755 /* bits [10:7] at lp_up2, positioned at [15:12] */
1756 lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >>
1757 MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT) <<
1758 MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT);
1760 if ((lp_up2 != 0) &&
1761 (lp_up2 != (tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK))) {
1762 /* replace tx_driver bits [15:12] */
1763 tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
1764 tx_driver |= lp_up2;
1765 CL45_WR_OVER_CL22(bp, params->port,
1766 params->phy_addr,
1767 MDIO_REG_BANK_TX0,
1768 MDIO_TX0_TX_DRIVER, tx_driver);
1772 static u8 bnx2x_emac_program(struct link_params *params,
1773 u32 line_speed, u32 duplex)
1775 struct bnx2x *bp = params->bp;
1776 u8 port = params->port;
1777 u16 mode = 0;
1779 DP(NETIF_MSG_LINK, "setting link speed & duplex\n");
1780 bnx2x_bits_dis(bp, GRCBASE_EMAC0 + port*0x400 +
1781 EMAC_REG_EMAC_MODE,
1782 (EMAC_MODE_25G_MODE |
1783 EMAC_MODE_PORT_MII_10M |
1784 EMAC_MODE_HALF_DUPLEX));
1785 switch (line_speed) {
1786 case SPEED_10:
1787 mode |= EMAC_MODE_PORT_MII_10M;
1788 break;
1790 case SPEED_100:
1791 mode |= EMAC_MODE_PORT_MII;
1792 break;
1794 case SPEED_1000:
1795 mode |= EMAC_MODE_PORT_GMII;
1796 break;
1798 case SPEED_2500:
1799 mode |= (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_GMII);
1800 break;
1802 default:
1803 /* 10G not valid for EMAC */
1804 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n", line_speed);
1805 return -EINVAL;
1808 if (duplex == DUPLEX_HALF)
1809 mode |= EMAC_MODE_HALF_DUPLEX;
1810 bnx2x_bits_en(bp,
1811 GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
1812 mode);
1814 bnx2x_set_led(bp, params->port, LED_MODE_OPER,
1815 line_speed, params->hw_led_mode, params->chip_id);
1816 return 0;
1819 /*****************************************************************************/
1820 /* External Phy section */
1821 /*****************************************************************************/
1822 static void bnx2x_hw_reset(struct bnx2x *bp)
1824 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1825 MISC_REGISTERS_GPIO_OUTPUT_LOW);
1826 msleep(1);
1827 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1828 MISC_REGISTERS_GPIO_OUTPUT_HIGH);
1831 static void bnx2x_ext_phy_reset(struct link_params *params,
1832 struct link_vars *vars)
1834 struct bnx2x *bp = params->bp;
1835 u32 ext_phy_type;
1836 u8 ext_phy_addr = ((params->ext_phy_config &
1837 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1838 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1839 DP(NETIF_MSG_LINK, "Port %x: bnx2x_ext_phy_reset\n", params->port);
1840 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1841 /* The PHY reset is controled by GPIO 1
1842 * Give it 1ms of reset pulse
1844 if (vars->phy_flags & PHY_XGXS_FLAG) {
1846 switch (ext_phy_type) {
1847 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
1848 DP(NETIF_MSG_LINK, "XGXS Direct\n");
1849 break;
1851 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
1852 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
1853 DP(NETIF_MSG_LINK, "XGXS 8705/8706\n");
1855 /* Restore normal power mode*/
1856 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1857 MISC_REGISTERS_GPIO_OUTPUT_HIGH);
1859 /* HW reset */
1860 bnx2x_hw_reset(bp);
1862 bnx2x_cl45_write(bp, params->port,
1863 ext_phy_type,
1864 ext_phy_addr,
1865 MDIO_PMA_DEVAD,
1866 MDIO_PMA_REG_CTRL, 0xa040);
1867 break;
1868 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
1869 /* Unset Low Power Mode and SW reset */
1870 /* Restore normal power mode*/
1871 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1872 MISC_REGISTERS_GPIO_OUTPUT_HIGH);
1874 DP(NETIF_MSG_LINK, "XGXS 8072\n");
1875 bnx2x_cl45_write(bp, params->port,
1876 ext_phy_type,
1877 ext_phy_addr,
1878 MDIO_PMA_DEVAD,
1879 MDIO_PMA_REG_CTRL,
1880 1<<15);
1881 break;
1882 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
1884 u16 emac_base;
1885 emac_base = (params->port) ? GRCBASE_EMAC0 :
1886 GRCBASE_EMAC1;
1888 /* Restore normal power mode*/
1889 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1890 MISC_REGISTERS_GPIO_OUTPUT_HIGH);
1892 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1893 MISC_REGISTERS_GPIO_OUTPUT_HIGH);
1895 DP(NETIF_MSG_LINK, "XGXS 8073\n");
1896 bnx2x_cl45_write(bp,
1897 params->port,
1898 ext_phy_type,
1899 ext_phy_addr,
1900 MDIO_PMA_DEVAD,
1901 MDIO_PMA_REG_CTRL,
1902 1<<15);
1904 break;
1906 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
1907 DP(NETIF_MSG_LINK, "XGXS SFX7101\n");
1909 /* Restore normal power mode*/
1910 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1911 MISC_REGISTERS_GPIO_OUTPUT_HIGH);
1913 /* HW reset */
1914 bnx2x_hw_reset(bp);
1916 break;
1918 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
1919 DP(NETIF_MSG_LINK, "XGXS PHY Failure detected\n");
1920 break;
1922 default:
1923 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
1924 params->ext_phy_config);
1925 break;
1928 } else { /* SerDes */
1929 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
1930 switch (ext_phy_type) {
1931 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
1932 DP(NETIF_MSG_LINK, "SerDes Direct\n");
1933 break;
1935 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
1936 DP(NETIF_MSG_LINK, "SerDes 5482\n");
1937 bnx2x_hw_reset(bp);
1938 break;
1940 default:
1941 DP(NETIF_MSG_LINK,
1942 "BAD SerDes ext_phy_config 0x%x\n",
1943 params->ext_phy_config);
1944 break;
1949 static void bnx2x_bcm8072_external_rom_boot(struct link_params *params)
1951 struct bnx2x *bp = params->bp;
1952 u8 port = params->port;
1953 u8 ext_phy_addr = ((params->ext_phy_config &
1954 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1955 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1956 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1957 u16 fw_ver1, fw_ver2;
1959 /* Need to wait 200ms after reset */
1960 msleep(200);
1961 /* Boot port from external ROM
1962 * Set ser_boot_ctl bit in the MISC_CTRL1 register
1964 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1965 MDIO_PMA_DEVAD,
1966 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
1968 /* Reset internal microprocessor */
1969 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1970 MDIO_PMA_DEVAD,
1971 MDIO_PMA_REG_GEN_CTRL,
1972 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
1973 /* set micro reset = 0 */
1974 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1975 MDIO_PMA_DEVAD,
1976 MDIO_PMA_REG_GEN_CTRL,
1977 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
1978 /* Reset internal microprocessor */
1979 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1980 MDIO_PMA_DEVAD,
1981 MDIO_PMA_REG_GEN_CTRL,
1982 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
1983 /* wait for 100ms for code download via SPI port */
1984 msleep(100);
1986 /* Clear ser_boot_ctl bit */
1987 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1988 MDIO_PMA_DEVAD,
1989 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
1990 /* Wait 100ms */
1991 msleep(100);
1993 /* Print the PHY FW version */
1994 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
1995 MDIO_PMA_DEVAD,
1996 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
1997 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
1998 MDIO_PMA_DEVAD,
1999 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
2000 DP(NETIF_MSG_LINK, "8072 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
2003 static u8 bnx2x_8073_is_snr_needed(struct link_params *params)
2005 /* This is only required for 8073A1, version 102 only */
2007 struct bnx2x *bp = params->bp;
2008 u8 ext_phy_addr = ((params->ext_phy_config &
2009 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2010 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2011 u16 val;
2013 /* Read 8073 HW revision*/
2014 bnx2x_cl45_read(bp, params->port,
2015 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2016 ext_phy_addr,
2017 MDIO_PMA_DEVAD,
2018 0xc801, &val);
2020 if (val != 1) {
2021 /* No need to workaround in 8073 A1 */
2022 return 0;
2025 bnx2x_cl45_read(bp, params->port,
2026 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2027 ext_phy_addr,
2028 MDIO_PMA_DEVAD,
2029 MDIO_PMA_REG_ROM_VER2, &val);
2031 /* SNR should be applied only for version 0x102 */
2032 if (val != 0x102)
2033 return 0;
2035 return 1;
2038 static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
2040 struct bnx2x *bp = params->bp;
2041 u8 ext_phy_addr = ((params->ext_phy_config &
2042 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2043 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2044 u16 val, cnt, cnt1 ;
2046 bnx2x_cl45_read(bp, params->port,
2047 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2048 ext_phy_addr,
2049 MDIO_PMA_DEVAD,
2050 0xc801, &val);
2052 if (val > 0) {
2053 /* No need to workaround in 8073 A1 */
2054 return 0;
2056 /* XAUI workaround in 8073 A0: */
2058 /* After loading the boot ROM and restarting Autoneg,
2059 poll Dev1, Reg $C820: */
2061 for (cnt = 0; cnt < 1000; cnt++) {
2062 bnx2x_cl45_read(bp, params->port,
2063 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2064 ext_phy_addr,
2065 MDIO_PMA_DEVAD,
2066 0xc820, &val);
2067 /* If bit [14] = 0 or bit [13] = 0, continue on with
2068 system initialization (XAUI work-around not required,
2069 as these bits indicate 2.5G or 1G link up). */
2070 if (!(val & (1<<14)) || !(val & (1<<13))) {
2071 DP(NETIF_MSG_LINK, "XAUI work-around not required\n");
2072 return 0;
2073 } else if (!(val & (1<<15))) {
2074 DP(NETIF_MSG_LINK, "clc bit 15 went off\n");
2075 /* If bit 15 is 0, then poll Dev1, Reg $C841 until
2076 it's MSB (bit 15) goes to 1 (indicating that the
2077 XAUI workaround has completed),
2078 then continue on with system initialization.*/
2079 for (cnt1 = 0; cnt1 < 1000; cnt1++) {
2080 bnx2x_cl45_read(bp, params->port,
2081 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2082 ext_phy_addr,
2083 MDIO_PMA_DEVAD,
2084 0xc841, &val);
2085 if (val & (1<<15)) {
2086 DP(NETIF_MSG_LINK,
2087 "XAUI workaround has completed\n");
2088 return 0;
2090 msleep(3);
2092 break;
2094 msleep(3);
2096 DP(NETIF_MSG_LINK, "Warning: XAUI work-around timeout !!!\n");
2097 return -EINVAL;
2101 static void bnx2x_bcm8073_external_rom_boot(struct link_params *params)
2103 struct bnx2x *bp = params->bp;
2104 u8 port = params->port;
2105 u8 ext_phy_addr = ((params->ext_phy_config &
2106 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2107 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2108 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2109 u16 fw_ver1, fw_ver2, val;
2110 /* Need to wait 100ms after reset */
2111 msleep(100);
2112 /* Boot port from external ROM */
2113 /* EDC grst */
2114 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2115 MDIO_PMA_DEVAD,
2116 MDIO_PMA_REG_GEN_CTRL,
2117 0x0001);
2119 /* ucode reboot and rst */
2120 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2121 MDIO_PMA_DEVAD,
2122 MDIO_PMA_REG_GEN_CTRL,
2123 0x008c);
2125 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2126 MDIO_PMA_DEVAD,
2127 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
2129 /* Reset internal microprocessor */
2130 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2131 MDIO_PMA_DEVAD,
2132 MDIO_PMA_REG_GEN_CTRL,
2133 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
2135 /* Release srst bit */
2136 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2137 MDIO_PMA_DEVAD,
2138 MDIO_PMA_REG_GEN_CTRL,
2139 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2141 /* wait for 100ms for code download via SPI port */
2142 msleep(100);
2144 /* Clear ser_boot_ctl bit */
2145 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2146 MDIO_PMA_DEVAD,
2147 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2149 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2150 MDIO_PMA_DEVAD,
2151 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
2152 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2153 MDIO_PMA_DEVAD,
2154 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
2155 DP(NETIF_MSG_LINK, "8073 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
2157 /* Only set bit 10 = 1 (Tx power down) */
2158 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2159 MDIO_PMA_DEVAD,
2160 MDIO_PMA_REG_TX_POWER_DOWN, &val);
2162 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2163 MDIO_PMA_DEVAD,
2164 MDIO_PMA_REG_TX_POWER_DOWN, (val | 1<<10));
2166 msleep(600);
2167 /* Release bit 10 (Release Tx power down) */
2168 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2169 MDIO_PMA_DEVAD,
2170 MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
2174 static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
2176 struct bnx2x *bp = params->bp;
2177 u8 port = params->port;
2178 u16 val;
2179 u8 ext_phy_addr = ((params->ext_phy_config &
2180 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2181 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2182 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2184 bnx2x_cl45_read(bp, params->port,
2185 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2186 ext_phy_addr,
2187 MDIO_PMA_DEVAD,
2188 0xc801, &val);
2190 if (val == 0) {
2191 /* Mustn't set low power mode in 8073 A0 */
2192 return;
2195 /* Disable PLL sequencer (use read-modify-write to clear bit 13) */
2196 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2197 MDIO_XS_DEVAD,
2198 MDIO_XS_PLL_SEQUENCER, &val);
2199 val &= ~(1<<13);
2200 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2201 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
2203 /* PLL controls */
2204 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2205 MDIO_XS_DEVAD, 0x805E, 0x1077);
2206 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2207 MDIO_XS_DEVAD, 0x805D, 0x0000);
2208 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2209 MDIO_XS_DEVAD, 0x805C, 0x030B);
2210 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2211 MDIO_XS_DEVAD, 0x805B, 0x1240);
2212 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2213 MDIO_XS_DEVAD, 0x805A, 0x2490);
2215 /* Tx Controls */
2216 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2217 MDIO_XS_DEVAD, 0x80A7, 0x0C74);
2218 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2219 MDIO_XS_DEVAD, 0x80A6, 0x9041);
2220 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2221 MDIO_XS_DEVAD, 0x80A5, 0x4640);
2223 /* Rx Controls */
2224 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2225 MDIO_XS_DEVAD, 0x80FE, 0x01C4);
2226 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2227 MDIO_XS_DEVAD, 0x80FD, 0x9249);
2228 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2229 MDIO_XS_DEVAD, 0x80FC, 0x2015);
2231 /* Enable PLL sequencer (use read-modify-write to set bit 13) */
2232 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2233 MDIO_XS_DEVAD,
2234 MDIO_XS_PLL_SEQUENCER, &val);
2235 val |= (1<<13);
2236 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2237 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
2239 static void bnx2x_bcm807x_force_10G(struct link_params *params)
2241 struct bnx2x *bp = params->bp;
2242 u8 port = params->port;
2243 u8 ext_phy_addr = ((params->ext_phy_config &
2244 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2245 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2246 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2248 /* Force KR or KX */
2249 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2250 MDIO_PMA_DEVAD,
2251 MDIO_PMA_REG_CTRL,
2252 0x2040);
2253 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2254 MDIO_PMA_DEVAD,
2255 MDIO_PMA_REG_10G_CTRL2,
2256 0x000b);
2257 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2258 MDIO_PMA_DEVAD,
2259 MDIO_PMA_REG_BCM_CTRL,
2260 0x0000);
2261 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2262 MDIO_AN_DEVAD,
2263 MDIO_AN_REG_CTRL,
2264 0x0000);
2267 static void bnx2x_ext_phy_set_pause(struct link_params *params,
2268 struct link_vars *vars)
2270 struct bnx2x *bp = params->bp;
2271 u16 val;
2272 u8 ext_phy_addr = ((params->ext_phy_config &
2273 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2274 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2275 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2277 /* read modify write pause advertizing */
2278 bnx2x_cl45_read(bp, params->port,
2279 ext_phy_type,
2280 ext_phy_addr,
2281 MDIO_AN_DEVAD,
2282 MDIO_AN_REG_ADV_PAUSE, &val);
2284 val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
2285 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
2287 if (vars->ieee_fc &
2288 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
2289 val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
2291 if (vars->ieee_fc &
2292 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
2293 val |=
2294 MDIO_AN_REG_ADV_PAUSE_PAUSE;
2296 DP(NETIF_MSG_LINK,
2297 "Ext phy AN advertize 0x%x\n", val);
2298 bnx2x_cl45_write(bp, params->port,
2299 ext_phy_type,
2300 ext_phy_addr,
2301 MDIO_AN_DEVAD,
2302 MDIO_AN_REG_ADV_PAUSE, val);
2305 static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
2307 struct bnx2x *bp = params->bp;
2308 u32 ext_phy_type;
2309 u8 ext_phy_addr;
2310 u16 cnt;
2311 u16 ctrl = 0;
2312 u16 val = 0;
2313 u8 rc = 0;
2314 if (vars->phy_flags & PHY_XGXS_FLAG) {
2315 ext_phy_addr = ((params->ext_phy_config &
2316 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2317 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2319 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2320 /* Make sure that the soft reset is off (expect for the 8072:
2321 * due to the lock, it will be done inside the specific
2322 * handling)
2324 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
2325 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
2326 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) &&
2327 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
2328 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
2329 /* Wait for soft reset to get cleared upto 1 sec */
2330 for (cnt = 0; cnt < 1000; cnt++) {
2331 bnx2x_cl45_read(bp, params->port,
2332 ext_phy_type,
2333 ext_phy_addr,
2334 MDIO_PMA_DEVAD,
2335 MDIO_PMA_REG_CTRL, &ctrl);
2336 if (!(ctrl & (1<<15)))
2337 break;
2338 msleep(1);
2340 DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n",
2341 ctrl, cnt);
2344 switch (ext_phy_type) {
2345 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
2346 DP(NETIF_MSG_LINK, "XGXS Direct\n");
2347 break;
2349 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2350 DP(NETIF_MSG_LINK, "XGXS 8705\n");
2352 bnx2x_cl45_write(bp, params->port,
2353 ext_phy_type,
2354 ext_phy_addr,
2355 MDIO_PMA_DEVAD,
2356 MDIO_PMA_REG_MISC_CTRL,
2357 0x8288);
2358 bnx2x_cl45_write(bp, params->port,
2359 ext_phy_type,
2360 ext_phy_addr,
2361 MDIO_PMA_DEVAD,
2362 MDIO_PMA_REG_PHY_IDENTIFIER,
2363 0x7fbf);
2364 bnx2x_cl45_write(bp, params->port,
2365 ext_phy_type,
2366 ext_phy_addr,
2367 MDIO_PMA_DEVAD,
2368 MDIO_PMA_REG_CMU_PLL_BYPASS,
2369 0x0100);
2370 bnx2x_cl45_write(bp, params->port,
2371 ext_phy_type,
2372 ext_phy_addr,
2373 MDIO_WIS_DEVAD,
2374 MDIO_WIS_REG_LASI_CNTL, 0x1);
2375 break;
2377 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2378 DP(NETIF_MSG_LINK, "XGXS 8706\n");
2380 msleep(10);
2381 /* Force speed */
2382 /* First enable LASI */
2383 bnx2x_cl45_write(bp, params->port,
2384 ext_phy_type,
2385 ext_phy_addr,
2386 MDIO_PMA_DEVAD,
2387 MDIO_PMA_REG_RX_ALARM_CTRL,
2388 0x0400);
2389 bnx2x_cl45_write(bp, params->port,
2390 ext_phy_type,
2391 ext_phy_addr,
2392 MDIO_PMA_DEVAD,
2393 MDIO_PMA_REG_LASI_CTRL, 0x0004);
2395 if (params->req_line_speed == SPEED_10000) {
2396 DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n");
2398 bnx2x_cl45_write(bp, params->port,
2399 ext_phy_type,
2400 ext_phy_addr,
2401 MDIO_PMA_DEVAD,
2402 MDIO_PMA_REG_DIGITAL_CTRL,
2403 0x400);
2404 } else {
2405 /* Force 1Gbps using autoneg with 1G
2406 advertisment */
2408 /* Allow CL37 through CL73 */
2409 DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
2410 bnx2x_cl45_write(bp, params->port,
2411 ext_phy_type,
2412 ext_phy_addr,
2413 MDIO_AN_DEVAD,
2414 MDIO_AN_REG_CL37_CL73,
2415 0x040c);
2417 /* Enable Full-Duplex advertisment on CL37 */
2418 bnx2x_cl45_write(bp, params->port,
2419 ext_phy_type,
2420 ext_phy_addr,
2421 MDIO_AN_DEVAD,
2422 MDIO_AN_REG_CL37_FD,
2423 0x0020);
2424 /* Enable CL37 AN */
2425 bnx2x_cl45_write(bp, params->port,
2426 ext_phy_type,
2427 ext_phy_addr,
2428 MDIO_AN_DEVAD,
2429 MDIO_AN_REG_CL37_AN,
2430 0x1000);
2431 /* 1G support */
2432 bnx2x_cl45_write(bp, params->port,
2433 ext_phy_type,
2434 ext_phy_addr,
2435 MDIO_AN_DEVAD,
2436 MDIO_AN_REG_ADV, (1<<5));
2438 /* Enable clause 73 AN */
2439 bnx2x_cl45_write(bp, params->port,
2440 ext_phy_type,
2441 ext_phy_addr,
2442 MDIO_AN_DEVAD,
2443 MDIO_AN_REG_CTRL,
2444 0x1200);
2448 break;
2450 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2451 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2453 u16 tmp1;
2454 u16 rx_alarm_ctrl_val;
2455 u16 lasi_ctrl_val;
2456 if (ext_phy_type ==
2457 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
2458 rx_alarm_ctrl_val = 0x400;
2459 lasi_ctrl_val = 0x0004;
2460 } else {
2461 /* In 8073, port1 is directed through emac0 and
2462 * port0 is directed through emac1
2464 rx_alarm_ctrl_val = (1<<2);
2465 /*lasi_ctrl_val = 0x0005;*/
2466 lasi_ctrl_val = 0x0004;
2469 /* Wait for soft reset to get cleared upto 1 sec */
2470 for (cnt = 0; cnt < 1000; cnt++) {
2471 bnx2x_cl45_read(bp, params->port,
2472 ext_phy_type,
2473 ext_phy_addr,
2474 MDIO_PMA_DEVAD,
2475 MDIO_PMA_REG_CTRL,
2476 &ctrl);
2477 if (!(ctrl & (1<<15)))
2478 break;
2479 msleep(1);
2481 DP(NETIF_MSG_LINK,
2482 "807x control reg 0x%x (after %d ms)\n",
2483 ctrl, cnt);
2485 if (ext_phy_type ==
2486 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072){
2487 bnx2x_bcm8072_external_rom_boot(params);
2488 } else {
2489 bnx2x_bcm8073_external_rom_boot(params);
2490 /* In case of 8073 with long xaui lines,
2491 don't set the 8073 xaui low power*/
2492 bnx2x_bcm8073_set_xaui_low_power_mode(params);
2495 /* enable LASI */
2496 bnx2x_cl45_write(bp, params->port,
2497 ext_phy_type,
2498 ext_phy_addr,
2499 MDIO_PMA_DEVAD,
2500 MDIO_PMA_REG_RX_ALARM_CTRL,
2501 rx_alarm_ctrl_val);
2503 bnx2x_cl45_write(bp, params->port,
2504 ext_phy_type,
2505 ext_phy_addr,
2506 MDIO_PMA_DEVAD,
2507 MDIO_PMA_REG_LASI_CTRL,
2508 lasi_ctrl_val);
2510 bnx2x_cl45_read(bp, params->port,
2511 ext_phy_type,
2512 ext_phy_addr,
2513 MDIO_PMA_DEVAD,
2514 MDIO_PMA_REG_RX_ALARM, &tmp1);
2516 DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1):"
2517 "0x%x\n", tmp1);
2519 /* If this is forced speed, set to KR or KX
2520 * (all other are not supported)
2522 if (!(params->req_line_speed == SPEED_AUTO_NEG)) {
2523 if (params->req_line_speed == SPEED_10000) {
2524 bnx2x_bcm807x_force_10G(params);
2525 DP(NETIF_MSG_LINK,
2526 "Forced speed 10G on 807X\n");
2527 break;
2528 } else if (params->req_line_speed ==
2529 SPEED_2500) {
2530 val = (1<<5);
2531 /* Note that 2.5G works only
2532 when used with 1G advertisment */
2533 } else
2534 val = (1<<5);
2535 } else {
2537 val = 0;
2538 if (params->speed_cap_mask &
2539 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
2540 val |= (1<<7);
2542 if (params->speed_cap_mask &
2543 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
2544 val |= (1<<5);
2545 DP(NETIF_MSG_LINK, "807x autoneg val = 0x%x\n", val);
2546 /*val = ((1<<5)|(1<<7));*/
2549 bnx2x_cl45_write(bp, params->port,
2550 ext_phy_type,
2551 ext_phy_addr,
2552 MDIO_AN_DEVAD,
2553 MDIO_AN_REG_ADV, val);
2555 if (ext_phy_type ==
2556 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
2557 /* Disable 2.5Ghz */
2558 bnx2x_cl45_read(bp, params->port,
2559 ext_phy_type,
2560 ext_phy_addr,
2561 MDIO_AN_DEVAD,
2562 0x8329, &tmp1);
2563 /* SUPPORT_SPEED_CAPABILITY
2564 (Due to the nature of the link order, its not
2565 possible to enable 2.5G within the autoneg
2566 capabilities)
2567 if (params->speed_cap_mask &
2568 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
2570 if (params->req_line_speed == SPEED_2500) {
2571 u16 phy_ver;
2572 /* Allow 2.5G for A1 and above */
2573 bnx2x_cl45_read(bp, params->port,
2574 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2575 ext_phy_addr,
2576 MDIO_PMA_DEVAD,
2577 0xc801, &phy_ver);
2579 if (phy_ver > 0)
2580 tmp1 |= 1;
2581 else
2582 tmp1 &= 0xfffe;
2584 else
2585 tmp1 &= 0xfffe;
2587 bnx2x_cl45_write(bp, params->port,
2588 ext_phy_type,
2589 ext_phy_addr,
2590 MDIO_AN_DEVAD,
2591 0x8329, tmp1);
2593 /* Add support for CL37 (passive mode) I */
2594 bnx2x_cl45_write(bp, params->port,
2595 ext_phy_type,
2596 ext_phy_addr,
2597 MDIO_AN_DEVAD,
2598 MDIO_AN_REG_CL37_CL73, 0x040c);
2599 /* Add support for CL37 (passive mode) II */
2600 bnx2x_cl45_write(bp, params->port,
2601 ext_phy_type,
2602 ext_phy_addr,
2603 MDIO_AN_DEVAD,
2604 MDIO_AN_REG_CL37_FD, 0x20);
2605 /* Add support for CL37 (passive mode) III */
2606 bnx2x_cl45_write(bp, params->port,
2607 ext_phy_type,
2608 ext_phy_addr,
2609 MDIO_AN_DEVAD,
2610 MDIO_AN_REG_CL37_AN, 0x1000);
2611 /* Restart autoneg */
2612 msleep(500);
2614 if (ext_phy_type ==
2615 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
2617 /* The SNR will improve about 2db by changing the
2618 BW and FEE main tap. Rest commands are executed
2619 after link is up*/
2620 /* Change FFE main cursor to 5 in EDC register */
2621 if (bnx2x_8073_is_snr_needed(params))
2622 bnx2x_cl45_write(bp, params->port,
2623 ext_phy_type,
2624 ext_phy_addr,
2625 MDIO_PMA_DEVAD,
2626 MDIO_PMA_REG_EDC_FFE_MAIN,
2627 0xFB0C);
2629 /* Enable FEC (Forware Error Correction)
2630 Request in the AN */
2631 bnx2x_cl45_read(bp, params->port,
2632 ext_phy_type,
2633 ext_phy_addr,
2634 MDIO_AN_DEVAD,
2635 MDIO_AN_REG_ADV2, &tmp1);
2637 tmp1 |= (1<<15);
2639 bnx2x_cl45_write(bp, params->port,
2640 ext_phy_type,
2641 ext_phy_addr,
2642 MDIO_AN_DEVAD,
2643 MDIO_AN_REG_ADV2, tmp1);
2646 bnx2x_ext_phy_set_pause(params, vars);
2648 bnx2x_cl45_write(bp, params->port,
2649 ext_phy_type,
2650 ext_phy_addr,
2651 MDIO_AN_DEVAD,
2652 MDIO_AN_REG_CTRL, 0x1200);
2653 DP(NETIF_MSG_LINK, "807x Autoneg Restart: "
2654 "Advertise 1G=%x, 10G=%x\n",
2655 ((val & (1<<5)) > 0),
2656 ((val & (1<<7)) > 0));
2657 break;
2659 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
2660 DP(NETIF_MSG_LINK,
2661 "Setting the SFX7101 LASI indication\n");
2663 bnx2x_cl45_write(bp, params->port,
2664 ext_phy_type,
2665 ext_phy_addr,
2666 MDIO_PMA_DEVAD,
2667 MDIO_PMA_REG_LASI_CTRL, 0x1);
2668 DP(NETIF_MSG_LINK,
2669 "Setting the SFX7101 LED to blink on traffic\n");
2670 bnx2x_cl45_write(bp, params->port,
2671 ext_phy_type,
2672 ext_phy_addr,
2673 MDIO_PMA_DEVAD,
2674 MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
2676 bnx2x_ext_phy_set_pause(params, vars);
2677 /* Restart autoneg */
2678 bnx2x_cl45_read(bp, params->port,
2679 ext_phy_type,
2680 ext_phy_addr,
2681 MDIO_AN_DEVAD,
2682 MDIO_AN_REG_CTRL, &val);
2683 val |= 0x200;
2684 bnx2x_cl45_write(bp, params->port,
2685 ext_phy_type,
2686 ext_phy_addr,
2687 MDIO_AN_DEVAD,
2688 MDIO_AN_REG_CTRL, val);
2689 break;
2690 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
2691 DP(NETIF_MSG_LINK,
2692 "XGXS PHY Failure detected 0x%x\n",
2693 params->ext_phy_config);
2694 rc = -EINVAL;
2695 break;
2696 default:
2697 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
2698 params->ext_phy_config);
2699 rc = -EINVAL;
2700 break;
2703 } else { /* SerDes */
2704 /* ext_phy_addr = ((bp->ext_phy_config &
2705 PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK) >>
2706 PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT);
2708 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
2709 switch (ext_phy_type) {
2710 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
2711 DP(NETIF_MSG_LINK, "SerDes Direct\n");
2712 break;
2714 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
2715 DP(NETIF_MSG_LINK, "SerDes 5482\n");
2716 break;
2718 default:
2719 DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
2720 params->ext_phy_config);
2721 break;
2724 return rc;
2728 static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
2729 struct link_vars *vars)
2731 struct bnx2x *bp = params->bp;
2732 u32 ext_phy_type;
2733 u8 ext_phy_addr;
2734 u16 val1 = 0, val2;
2735 u16 rx_sd, pcs_status;
2736 u8 ext_phy_link_up = 0;
2737 u8 port = params->port;
2738 if (vars->phy_flags & PHY_XGXS_FLAG) {
2739 ext_phy_addr = ((params->ext_phy_config &
2740 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2741 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2743 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2744 switch (ext_phy_type) {
2745 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
2746 DP(NETIF_MSG_LINK, "XGXS Direct\n");
2747 ext_phy_link_up = 1;
2748 break;
2750 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2751 DP(NETIF_MSG_LINK, "XGXS 8705\n");
2752 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2753 ext_phy_addr,
2754 MDIO_WIS_DEVAD,
2755 MDIO_WIS_REG_LASI_STATUS, &val1);
2756 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
2758 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2759 ext_phy_addr,
2760 MDIO_WIS_DEVAD,
2761 MDIO_WIS_REG_LASI_STATUS, &val1);
2762 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
2764 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2765 ext_phy_addr,
2766 MDIO_PMA_DEVAD,
2767 MDIO_PMA_REG_RX_SD, &rx_sd);
2768 DP(NETIF_MSG_LINK, "8705 rx_sd 0x%x\n", rx_sd);
2769 ext_phy_link_up = (rx_sd & 0x1);
2770 break;
2772 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2773 DP(NETIF_MSG_LINK, "XGXS 8706\n");
2774 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2775 ext_phy_addr,
2776 MDIO_PMA_DEVAD,
2777 MDIO_PMA_REG_LASI_STATUS, &val1);
2778 DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
2780 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2781 ext_phy_addr,
2782 MDIO_PMA_DEVAD,
2783 MDIO_PMA_REG_LASI_STATUS, &val1);
2784 DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
2786 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2787 ext_phy_addr,
2788 MDIO_PMA_DEVAD,
2789 MDIO_PMA_REG_RX_SD, &rx_sd);
2790 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2791 ext_phy_addr,
2792 MDIO_PCS_DEVAD,
2793 MDIO_PCS_REG_STATUS, &pcs_status);
2795 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2796 ext_phy_addr,
2797 MDIO_AN_DEVAD,
2798 MDIO_AN_REG_LINK_STATUS, &val2);
2799 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2800 ext_phy_addr,
2801 MDIO_AN_DEVAD,
2802 MDIO_AN_REG_LINK_STATUS, &val2);
2804 DP(NETIF_MSG_LINK, "8706 rx_sd 0x%x"
2805 " pcs_status 0x%x 1Gbps link_status 0x%x\n",
2806 rx_sd, pcs_status, val2);
2807 /* link is up if both bit 0 of pmd_rx_sd and
2808 * bit 0 of pcs_status are set, or if the autoneg bit
2809 1 is set
2811 ext_phy_link_up = ((rx_sd & pcs_status & 0x1) ||
2812 (val2 & (1<<1)));
2813 /* clear LASI indication*/
2814 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2815 ext_phy_addr,
2816 MDIO_PMA_DEVAD,
2817 MDIO_PMA_REG_RX_ALARM, &val2);
2818 break;
2820 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2821 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2823 if (ext_phy_type ==
2824 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
2825 bnx2x_cl45_read(bp, params->port,
2826 ext_phy_type,
2827 ext_phy_addr,
2828 MDIO_PCS_DEVAD,
2829 MDIO_PCS_REG_LASI_STATUS, &val1);
2830 bnx2x_cl45_read(bp, params->port,
2831 ext_phy_type,
2832 ext_phy_addr,
2833 MDIO_PCS_DEVAD,
2834 MDIO_PCS_REG_LASI_STATUS, &val2);
2835 DP(NETIF_MSG_LINK,
2836 "870x LASI status 0x%x->0x%x\n",
2837 val1, val2);
2839 } else {
2840 /* In 8073, port1 is directed through emac0 and
2841 * port0 is directed through emac1
2843 bnx2x_cl45_read(bp, params->port,
2844 ext_phy_type,
2845 ext_phy_addr,
2846 MDIO_PMA_DEVAD,
2847 MDIO_PMA_REG_LASI_STATUS, &val1);
2849 bnx2x_cl45_read(bp, params->port,
2850 ext_phy_type,
2851 ext_phy_addr,
2852 MDIO_PMA_DEVAD,
2853 MDIO_PMA_REG_LASI_STATUS, &val2);
2854 DP(NETIF_MSG_LINK,
2855 "8703 LASI status 0x%x->0x%x\n",
2856 val1, val2);
2859 /* clear the interrupt LASI status register */
2860 bnx2x_cl45_read(bp, params->port,
2861 ext_phy_type,
2862 ext_phy_addr,
2863 MDIO_PCS_DEVAD,
2864 MDIO_PCS_REG_STATUS, &val2);
2865 bnx2x_cl45_read(bp, params->port,
2866 ext_phy_type,
2867 ext_phy_addr,
2868 MDIO_PCS_DEVAD,
2869 MDIO_PCS_REG_STATUS, &val1);
2870 DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n",
2871 val2, val1);
2872 /* Check the LASI */
2873 bnx2x_cl45_read(bp, params->port,
2874 ext_phy_type,
2875 ext_phy_addr,
2876 MDIO_PMA_DEVAD,
2877 MDIO_PMA_REG_RX_ALARM, &val2);
2878 bnx2x_cl45_read(bp, params->port,
2879 ext_phy_type,
2880 ext_phy_addr,
2881 MDIO_PMA_DEVAD,
2882 MDIO_PMA_REG_RX_ALARM,
2883 &val1);
2884 DP(NETIF_MSG_LINK, "KR 0x9003 0x%x->0x%x\n",
2885 val2, val1);
2886 /* Check the link status */
2887 bnx2x_cl45_read(bp, params->port,
2888 ext_phy_type,
2889 ext_phy_addr,
2890 MDIO_PCS_DEVAD,
2891 MDIO_PCS_REG_STATUS, &val2);
2892 DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
2894 bnx2x_cl45_read(bp, params->port,
2895 ext_phy_type,
2896 ext_phy_addr,
2897 MDIO_PMA_DEVAD,
2898 MDIO_PMA_REG_STATUS, &val2);
2899 bnx2x_cl45_read(bp, params->port,
2900 ext_phy_type,
2901 ext_phy_addr,
2902 MDIO_PMA_DEVAD,
2903 MDIO_PMA_REG_STATUS, &val1);
2904 ext_phy_link_up = ((val1 & 4) == 4);
2905 DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
2906 if (ext_phy_type ==
2907 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
2908 u16 an1000_status = 0;
2909 if (ext_phy_link_up &&
2911 (params->req_line_speed != SPEED_10000)
2912 )) {
2913 if (bnx2x_bcm8073_xaui_wa(params)
2914 != 0) {
2915 ext_phy_link_up = 0;
2916 break;
2918 bnx2x_cl45_read(bp, params->port,
2919 ext_phy_type,
2920 ext_phy_addr,
2921 MDIO_XS_DEVAD,
2922 0x8304,
2923 &an1000_status);
2924 bnx2x_cl45_read(bp, params->port,
2925 ext_phy_type,
2926 ext_phy_addr,
2927 MDIO_XS_DEVAD,
2928 0x8304,
2929 &an1000_status);
2931 /* Check the link status on 1.1.2 */
2932 bnx2x_cl45_read(bp, params->port,
2933 ext_phy_type,
2934 ext_phy_addr,
2935 MDIO_PMA_DEVAD,
2936 MDIO_PMA_REG_STATUS, &val2);
2937 bnx2x_cl45_read(bp, params->port,
2938 ext_phy_type,
2939 ext_phy_addr,
2940 MDIO_PMA_DEVAD,
2941 MDIO_PMA_REG_STATUS, &val1);
2942 DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x,"
2943 "an_link_status=0x%x\n",
2944 val2, val1, an1000_status);
2946 ext_phy_link_up = (((val1 & 4) == 4) ||
2947 (an1000_status & (1<<1)));
2948 if (ext_phy_link_up &&
2949 bnx2x_8073_is_snr_needed(params)) {
2950 /* The SNR will improve about 2dbby
2951 changing the BW and FEE main tap.*/
2953 /* The 1st write to change FFE main
2954 tap is set before restart AN */
2955 /* Change PLL Bandwidth in EDC
2956 register */
2957 bnx2x_cl45_write(bp, port, ext_phy_type,
2958 ext_phy_addr,
2959 MDIO_PMA_DEVAD,
2960 MDIO_PMA_REG_PLL_BANDWIDTH,
2961 0x26BC);
2963 /* Change CDR Bandwidth in EDC
2964 register */
2965 bnx2x_cl45_write(bp, port, ext_phy_type,
2966 ext_phy_addr,
2967 MDIO_PMA_DEVAD,
2968 MDIO_PMA_REG_CDR_BANDWIDTH,
2969 0x0333);
2973 break;
2975 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
2976 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2977 ext_phy_addr,
2978 MDIO_PMA_DEVAD,
2979 MDIO_PMA_REG_LASI_STATUS, &val2);
2980 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2981 ext_phy_addr,
2982 MDIO_PMA_DEVAD,
2983 MDIO_PMA_REG_LASI_STATUS, &val1);
2984 DP(NETIF_MSG_LINK,
2985 "10G-base-T LASI status 0x%x->0x%x\n",
2986 val2, val1);
2987 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2988 ext_phy_addr,
2989 MDIO_PMA_DEVAD,
2990 MDIO_PMA_REG_STATUS, &val2);
2991 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2992 ext_phy_addr,
2993 MDIO_PMA_DEVAD,
2994 MDIO_PMA_REG_STATUS, &val1);
2995 DP(NETIF_MSG_LINK,
2996 "10G-base-T PMA status 0x%x->0x%x\n",
2997 val2, val1);
2998 ext_phy_link_up = ((val1 & 4) == 4);
2999 /* if link is up
3000 * print the AN outcome of the SFX7101 PHY
3002 if (ext_phy_link_up) {
3003 bnx2x_cl45_read(bp, params->port,
3004 ext_phy_type,
3005 ext_phy_addr,
3006 MDIO_AN_DEVAD,
3007 MDIO_AN_REG_MASTER_STATUS,
3008 &val2);
3009 DP(NETIF_MSG_LINK,
3010 "SFX7101 AN status 0x%x->Master=%x\n",
3011 val2,
3012 (val2 & (1<<14)));
3014 break;
3016 default:
3017 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
3018 params->ext_phy_config);
3019 ext_phy_link_up = 0;
3020 break;
3023 } else { /* SerDes */
3024 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3025 switch (ext_phy_type) {
3026 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
3027 DP(NETIF_MSG_LINK, "SerDes Direct\n");
3028 ext_phy_link_up = 1;
3029 break;
3031 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
3032 DP(NETIF_MSG_LINK, "SerDes 5482\n");
3033 ext_phy_link_up = 1;
3034 break;
3036 default:
3037 DP(NETIF_MSG_LINK,
3038 "BAD SerDes ext_phy_config 0x%x\n",
3039 params->ext_phy_config);
3040 ext_phy_link_up = 0;
3041 break;
3045 return ext_phy_link_up;
3048 static void bnx2x_link_int_enable(struct link_params *params)
3050 u8 port = params->port;
3051 u32 ext_phy_type;
3052 u32 mask;
3053 struct bnx2x *bp = params->bp;
3054 /* setting the status to report on link up
3055 for either XGXS or SerDes */
3057 if (params->switch_cfg == SWITCH_CFG_10G) {
3058 mask = (NIG_MASK_XGXS0_LINK10G |
3059 NIG_MASK_XGXS0_LINK_STATUS);
3060 DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
3061 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3062 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
3063 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
3064 (ext_phy_type !=
3065 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) {
3066 mask |= NIG_MASK_MI_INT;
3067 DP(NETIF_MSG_LINK, "enabled external phy int\n");
3070 } else { /* SerDes */
3071 mask = NIG_MASK_SERDES0_LINK_STATUS;
3072 DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n");
3073 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3074 if ((ext_phy_type !=
3075 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
3076 (ext_phy_type !=
3077 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN)) {
3078 mask |= NIG_MASK_MI_INT;
3079 DP(NETIF_MSG_LINK, "enabled external phy int\n");
3082 bnx2x_bits_en(bp,
3083 NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
3084 mask);
3085 DP(NETIF_MSG_LINK, "port %x, is_xgxs=%x, int_status 0x%x\n", port,
3086 (params->switch_cfg == SWITCH_CFG_10G),
3087 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
3089 DP(NETIF_MSG_LINK, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n",
3090 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
3091 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
3092 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS+port*0x3c));
3093 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
3094 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
3095 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
3100 * link management
3102 static void bnx2x_link_int_ack(struct link_params *params,
3103 struct link_vars *vars, u16 is_10g)
3105 struct bnx2x *bp = params->bp;
3106 u8 port = params->port;
3108 /* first reset all status
3109 * we assume only one line will be change at a time */
3110 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3111 (NIG_STATUS_XGXS0_LINK10G |
3112 NIG_STATUS_XGXS0_LINK_STATUS |
3113 NIG_STATUS_SERDES0_LINK_STATUS));
3114 if (vars->phy_link_up) {
3115 if (is_10g) {
3116 /* Disable the 10G link interrupt
3117 * by writing 1 to the status register
3119 DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
3120 bnx2x_bits_en(bp,
3121 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3122 NIG_STATUS_XGXS0_LINK10G);
3124 } else if (params->switch_cfg == SWITCH_CFG_10G) {
3125 /* Disable the link interrupt
3126 * by writing 1 to the relevant lane
3127 * in the status register
3129 u32 ser_lane = ((params->lane_config &
3130 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
3131 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
3133 DP(NETIF_MSG_LINK, "1G XGXS phy link up\n");
3134 bnx2x_bits_en(bp,
3135 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3136 ((1 << ser_lane) <<
3137 NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
3139 } else { /* SerDes */
3140 DP(NETIF_MSG_LINK, "SerDes phy link up\n");
3141 /* Disable the link interrupt
3142 * by writing 1 to the status register
3144 bnx2x_bits_en(bp,
3145 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3146 NIG_STATUS_SERDES0_LINK_STATUS);
3149 } else { /* link_down */
3153 static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len)
3155 u8 *str_ptr = str;
3156 u32 mask = 0xf0000000;
3157 u8 shift = 8*4;
3158 u8 digit;
3159 if (len < 10) {
3160 /* Need more then 10chars for this format */
3161 *str_ptr = '\0';
3162 return -EINVAL;
3164 while (shift > 0) {
3166 shift -= 4;
3167 digit = ((num & mask) >> shift);
3168 if (digit < 0xa)
3169 *str_ptr = digit + '0';
3170 else
3171 *str_ptr = digit - 0xa + 'a';
3172 str_ptr++;
3173 mask = mask >> 4;
3174 if (shift == 4*4) {
3175 *str_ptr = ':';
3176 str_ptr++;
3179 *str_ptr = '\0';
3180 return 0;
3184 static void bnx2x_turn_on_sf(struct bnx2x *bp, u8 port, u8 ext_phy_addr)
3186 u32 cnt = 0;
3187 u16 ctrl = 0;
3188 /* Enable EMAC0 in to enable MDIO */
3189 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
3190 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
3191 msleep(5);
3193 /* take ext phy out of reset */
3194 bnx2x_set_gpio(bp,
3195 MISC_REGISTERS_GPIO_2,
3196 MISC_REGISTERS_GPIO_HIGH);
3198 bnx2x_set_gpio(bp,
3199 MISC_REGISTERS_GPIO_1,
3200 MISC_REGISTERS_GPIO_HIGH);
3202 /* wait for 5ms */
3203 msleep(5);
3205 for (cnt = 0; cnt < 1000; cnt++) {
3206 msleep(1);
3207 bnx2x_cl45_read(bp, port,
3208 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
3209 ext_phy_addr,
3210 MDIO_PMA_DEVAD,
3211 MDIO_PMA_REG_CTRL,
3212 &ctrl);
3213 if (!(ctrl & (1<<15))) {
3214 DP(NETIF_MSG_LINK, "Reset completed\n\n");
3215 break;
3220 static void bnx2x_turn_off_sf(struct bnx2x *bp)
3222 /* put sf to reset */
3223 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_LOW);
3224 bnx2x_set_gpio(bp,
3225 MISC_REGISTERS_GPIO_2,
3226 MISC_REGISTERS_GPIO_LOW);
3229 u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
3230 u8 *version, u16 len)
3232 struct bnx2x *bp = params->bp;
3233 u32 ext_phy_type = 0;
3234 u16 val = 0;
3235 u8 ext_phy_addr = 0 ;
3236 u8 status = 0 ;
3237 u32 ver_num;
3239 if (version == NULL || params == NULL)
3240 return -EINVAL;
3242 /* reset the returned value to zero */
3243 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3244 ext_phy_addr = ((params->ext_phy_config &
3245 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
3246 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
3248 switch (ext_phy_type) {
3249 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3251 if (len < 5)
3252 return -EINVAL;
3254 /* Take ext phy out of reset */
3255 if (!driver_loaded)
3256 bnx2x_turn_on_sf(bp, params->port, ext_phy_addr);
3258 /* wait for 1ms */
3259 msleep(1);
3261 bnx2x_cl45_read(bp, params->port,
3262 ext_phy_type,
3263 ext_phy_addr,
3264 MDIO_PMA_DEVAD,
3265 MDIO_PMA_REG_7101_VER1, &val);
3266 version[2] = (val & 0xFF);
3267 version[3] = ((val & 0xFF00)>>8);
3269 bnx2x_cl45_read(bp, params->port,
3270 ext_phy_type,
3271 ext_phy_addr,
3272 MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2,
3273 &val);
3274 version[0] = (val & 0xFF);
3275 version[1] = ((val & 0xFF00)>>8);
3276 version[4] = '\0';
3278 if (!driver_loaded)
3279 bnx2x_turn_off_sf(bp);
3280 break;
3281 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
3282 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
3284 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3285 ext_phy_addr,
3286 MDIO_PMA_DEVAD,
3287 MDIO_PMA_REG_ROM_VER1, &val);
3288 ver_num = val<<16;
3289 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3290 ext_phy_addr,
3291 MDIO_PMA_DEVAD,
3292 MDIO_PMA_REG_ROM_VER2, &val);
3293 ver_num |= val;
3294 status = bnx2x_format_ver(ver_num, version, len);
3295 break;
3297 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
3298 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
3300 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3301 ext_phy_addr,
3302 MDIO_PMA_DEVAD,
3303 MDIO_PMA_REG_ROM_VER1, &val);
3304 ver_num = val<<16;
3305 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3306 ext_phy_addr,
3307 MDIO_PMA_DEVAD,
3308 MDIO_PMA_REG_ROM_VER2, &val);
3309 ver_num |= val;
3310 status = bnx2x_format_ver(ver_num, version, len);
3311 break;
3313 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3314 break;
3316 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
3317 DP(NETIF_MSG_LINK, "bnx2x_get_ext_phy_fw_version:"
3318 " type is FAILURE!\n");
3319 status = -EINVAL;
3320 break;
3322 default:
3323 break;
3325 return status;
3328 static void bnx2x_set_xgxs_loopback(struct link_params *params,
3329 struct link_vars *vars,
3330 u8 is_10g)
3332 u8 port = params->port;
3333 struct bnx2x *bp = params->bp;
3335 if (is_10g) {
3336 u32 md_devad;
3338 DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
3340 /* change the uni_phy_addr in the nig */
3341 md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
3342 port*0x18));
3344 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
3346 bnx2x_cl45_write(bp, port, 0,
3347 params->phy_addr,
3349 (MDIO_REG_BANK_AER_BLOCK +
3350 (MDIO_AER_BLOCK_AER_REG & 0xf)),
3351 0x2800);
3353 bnx2x_cl45_write(bp, port, 0,
3354 params->phy_addr,
3356 (MDIO_REG_BANK_CL73_IEEEB0 +
3357 (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
3358 0x6041);
3360 /* set aer mmd back */
3361 bnx2x_set_aer_mmd(params, vars);
3363 /* and md_devad */
3364 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
3365 md_devad);
3367 } else {
3368 u16 mii_control;
3370 DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
3372 CL45_RD_OVER_CL22(bp, port,
3373 params->phy_addr,
3374 MDIO_REG_BANK_COMBO_IEEE0,
3375 MDIO_COMBO_IEEE0_MII_CONTROL,
3376 &mii_control);
3378 CL45_WR_OVER_CL22(bp, port,
3379 params->phy_addr,
3380 MDIO_REG_BANK_COMBO_IEEE0,
3381 MDIO_COMBO_IEEE0_MII_CONTROL,
3382 (mii_control |
3383 MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK));
3388 static void bnx2x_ext_phy_loopback(struct link_params *params)
3390 struct bnx2x *bp = params->bp;
3391 u8 ext_phy_addr;
3392 u32 ext_phy_type;
3394 if (params->switch_cfg == SWITCH_CFG_10G) {
3395 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3396 /* CL37 Autoneg Enabled */
3397 ext_phy_addr = ((params->ext_phy_config &
3398 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
3399 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
3400 switch (ext_phy_type) {
3401 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3402 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
3403 DP(NETIF_MSG_LINK,
3404 "ext_phy_loopback: We should not get here\n");
3405 break;
3406 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
3407 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8705\n");
3408 break;
3409 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
3410 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8706\n");
3411 break;
3412 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3413 /* SFX7101_XGXS_TEST1 */
3414 bnx2x_cl45_write(bp, params->port, ext_phy_type,
3415 ext_phy_addr,
3416 MDIO_XS_DEVAD,
3417 MDIO_XS_SFX7101_XGXS_TEST1,
3418 0x100);
3419 DP(NETIF_MSG_LINK,
3420 "ext_phy_loopback: set ext phy loopback\n");
3421 break;
3422 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
3424 break;
3425 } /* switch external PHY type */
3426 } else {
3427 /* serdes */
3428 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3429 ext_phy_addr = (params->ext_phy_config &
3430 PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK)
3431 >> PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT;
3437 *------------------------------------------------------------------------
3438 * bnx2x_override_led_value -
3440 * Override the led value of the requsted led
3442 *------------------------------------------------------------------------
3444 u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port,
3445 u32 led_idx, u32 value)
3447 u32 reg_val;
3449 /* If port 0 then use EMAC0, else use EMAC1*/
3450 u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
3452 DP(NETIF_MSG_LINK,
3453 "bnx2x_override_led_value() port %x led_idx %d value %d\n",
3454 port, led_idx, value);
3456 switch (led_idx) {
3457 case 0: /* 10MB led */
3458 /* Read the current value of the LED register in
3459 the EMAC block */
3460 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3461 /* Set the OVERRIDE bit to 1 */
3462 reg_val |= EMAC_LED_OVERRIDE;
3463 /* If value is 1, set the 10M_OVERRIDE bit,
3464 otherwise reset it.*/
3465 reg_val = (value == 1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) :
3466 (reg_val & ~EMAC_LED_10MB_OVERRIDE);
3467 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3468 break;
3469 case 1: /*100MB led */
3470 /*Read the current value of the LED register in
3471 the EMAC block */
3472 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3473 /* Set the OVERRIDE bit to 1 */
3474 reg_val |= EMAC_LED_OVERRIDE;
3475 /* If value is 1, set the 100M_OVERRIDE bit,
3476 otherwise reset it.*/
3477 reg_val = (value == 1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) :
3478 (reg_val & ~EMAC_LED_100MB_OVERRIDE);
3479 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3480 break;
3481 case 2: /* 1000MB led */
3482 /* Read the current value of the LED register in the
3483 EMAC block */
3484 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3485 /* Set the OVERRIDE bit to 1 */
3486 reg_val |= EMAC_LED_OVERRIDE;
3487 /* If value is 1, set the 1000M_OVERRIDE bit, otherwise
3488 reset it. */
3489 reg_val = (value == 1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) :
3490 (reg_val & ~EMAC_LED_1000MB_OVERRIDE);
3491 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3492 break;
3493 case 3: /* 2500MB led */
3494 /* Read the current value of the LED register in the
3495 EMAC block*/
3496 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3497 /* Set the OVERRIDE bit to 1 */
3498 reg_val |= EMAC_LED_OVERRIDE;
3499 /* If value is 1, set the 2500M_OVERRIDE bit, otherwise
3500 reset it.*/
3501 reg_val = (value == 1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) :
3502 (reg_val & ~EMAC_LED_2500MB_OVERRIDE);
3503 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3504 break;
3505 case 4: /*10G led */
3506 if (port == 0) {
3507 REG_WR(bp, NIG_REG_LED_10G_P0,
3508 value);
3509 } else {
3510 REG_WR(bp, NIG_REG_LED_10G_P1,
3511 value);
3513 break;
3514 case 5: /* TRAFFIC led */
3515 /* Find if the traffic control is via BMAC or EMAC */
3516 if (port == 0)
3517 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC0_EN);
3518 else
3519 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC1_EN);
3521 /* Override the traffic led in the EMAC:*/
3522 if (reg_val == 1) {
3523 /* Read the current value of the LED register in
3524 the EMAC block */
3525 reg_val = REG_RD(bp, emac_base +
3526 EMAC_REG_EMAC_LED);
3527 /* Set the TRAFFIC_OVERRIDE bit to 1 */
3528 reg_val |= EMAC_LED_OVERRIDE;
3529 /* If value is 1, set the TRAFFIC bit, otherwise
3530 reset it.*/
3531 reg_val = (value == 1) ? (reg_val | EMAC_LED_TRAFFIC) :
3532 (reg_val & ~EMAC_LED_TRAFFIC);
3533 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3534 } else { /* Override the traffic led in the BMAC: */
3535 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
3536 + port*4, 1);
3537 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port*4,
3538 value);
3540 break;
3541 default:
3542 DP(NETIF_MSG_LINK,
3543 "bnx2x_override_led_value() unknown led index %d "
3544 "(should be 0-5)\n", led_idx);
3545 return -EINVAL;
3548 return 0;
3552 u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
3553 u16 hw_led_mode, u32 chip_id)
3555 u8 rc = 0;
3556 DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
3557 DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
3558 speed, hw_led_mode);
3559 switch (mode) {
3560 case LED_MODE_OFF:
3561 REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0);
3562 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
3563 SHARED_HW_CFG_LED_MAC1);
3564 break;
3566 case LED_MODE_OPER:
3567 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode);
3568 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
3569 port*4, 0);
3570 /* Set blinking rate to ~15.9Hz */
3571 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
3572 LED_BLINK_RATE_VAL);
3573 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
3574 port*4, 1);
3575 if (!CHIP_IS_E1H(bp) &&
3576 ((speed == SPEED_2500) ||
3577 (speed == SPEED_1000) ||
3578 (speed == SPEED_100) ||
3579 (speed == SPEED_10))) {
3580 /* On Everest 1 Ax chip versions for speeds less than
3581 10G LED scheme is different */
3582 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
3583 + port*4, 1);
3584 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
3585 port*4, 0);
3586 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
3587 port*4, 1);
3589 break;
3591 default:
3592 rc = -EINVAL;
3593 DP(NETIF_MSG_LINK, "bnx2x_set_led: Invalid led mode %d\n",
3594 mode);
3595 break;
3597 return rc;
3601 u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars)
3603 struct bnx2x *bp = params->bp;
3604 u16 gp_status = 0;
3606 CL45_RD_OVER_CL22(bp, params->port,
3607 params->phy_addr,
3608 MDIO_REG_BANK_GP_STATUS,
3609 MDIO_GP_STATUS_TOP_AN_STATUS1,
3610 &gp_status);
3611 /* link is up only if both local phy and external phy are up */
3612 if ((gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) &&
3613 bnx2x_ext_phy_is_link_up(params, vars))
3614 return 0;
3616 return -ESRCH;
3619 static u8 bnx2x_link_initialize(struct link_params *params,
3620 struct link_vars *vars)
3622 struct bnx2x *bp = params->bp;
3623 u8 port = params->port;
3624 u8 rc = 0;
3626 /* Activate the external PHY */
3627 bnx2x_ext_phy_reset(params, vars);
3629 bnx2x_set_aer_mmd(params, vars);
3631 if (vars->phy_flags & PHY_XGXS_FLAG)
3632 bnx2x_set_master_ln(params);
3634 rc = bnx2x_reset_unicore(params);
3635 /* reset the SerDes and wait for reset bit return low */
3636 if (rc != 0)
3637 return rc;
3639 bnx2x_set_aer_mmd(params, vars);
3641 /* setting the masterLn_def again after the reset */
3642 if (vars->phy_flags & PHY_XGXS_FLAG) {
3643 bnx2x_set_master_ln(params);
3644 bnx2x_set_swap_lanes(params);
3647 /* Set Parallel Detect */
3648 if (params->req_line_speed == SPEED_AUTO_NEG)
3649 bnx2x_set_parallel_detection(params, vars->phy_flags);
3651 if (vars->phy_flags & PHY_XGXS_FLAG) {
3652 if (params->req_line_speed &&
3653 ((params->req_line_speed == SPEED_100) ||
3654 (params->req_line_speed == SPEED_10))) {
3655 vars->phy_flags |= PHY_SGMII_FLAG;
3656 } else {
3657 vars->phy_flags &= ~PHY_SGMII_FLAG;
3661 if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
3662 u16 bank, rx_eq;
3664 rx_eq = ((params->serdes_config &
3665 PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK) >>
3666 PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT);
3668 DP(NETIF_MSG_LINK, "setting rx eq to 0x%x\n", rx_eq);
3669 for (bank = MDIO_REG_BANK_RX0; bank <= MDIO_REG_BANK_RX_ALL;
3670 bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0)) {
3671 CL45_WR_OVER_CL22(bp, port,
3672 params->phy_addr,
3673 bank ,
3674 MDIO_RX0_RX_EQ_BOOST,
3675 ((rx_eq &
3676 MDIO_RX0_RX_EQ_BOOST_EQUALIZER_CTRL_MASK) |
3677 MDIO_RX0_RX_EQ_BOOST_OFFSET_CTRL));
3680 /* forced speed requested? */
3681 if (params->req_line_speed != SPEED_AUTO_NEG) {
3682 DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
3684 /* disable autoneg */
3685 bnx2x_set_autoneg(params, vars);
3687 /* program speed and duplex */
3688 bnx2x_program_serdes(params);
3689 vars->ieee_fc =
3690 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
3692 } else { /* AN_mode */
3693 DP(NETIF_MSG_LINK, "not SGMII, AN\n");
3695 /* AN enabled */
3696 bnx2x_set_brcm_cl37_advertisment(params);
3698 /* program duplex & pause advertisement (for aneg) */
3699 bnx2x_set_ieee_aneg_advertisment(params,
3700 &vars->ieee_fc);
3702 /* enable autoneg */
3703 bnx2x_set_autoneg(params, vars);
3705 /* enable and restart AN */
3706 bnx2x_restart_autoneg(params);
3709 } else { /* SGMII mode */
3710 DP(NETIF_MSG_LINK, "SGMII\n");
3712 bnx2x_initialize_sgmii_process(params);
3715 /* init ext phy and enable link state int */
3716 rc |= bnx2x_ext_phy_init(params, vars);
3718 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3719 (NIG_STATUS_XGXS0_LINK10G |
3720 NIG_STATUS_XGXS0_LINK_STATUS |
3721 NIG_STATUS_SERDES0_LINK_STATUS));
3723 return rc;
3728 u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
3730 struct bnx2x *bp = params->bp;
3732 u32 val;
3733 DP(NETIF_MSG_LINK, "Phy Initialization started\n");
3734 DP(NETIF_MSG_LINK, "req_speed = %d, req_flowctrl=%d\n",
3735 params->req_line_speed, params->req_flow_ctrl);
3736 vars->link_status = 0;
3737 if (params->switch_cfg == SWITCH_CFG_1G)
3738 vars->phy_flags = PHY_SERDES_FLAG;
3739 else
3740 vars->phy_flags = PHY_XGXS_FLAG;
3742 /* disable attentions */
3743 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
3744 (NIG_MASK_XGXS0_LINK_STATUS |
3745 NIG_MASK_XGXS0_LINK10G |
3746 NIG_MASK_SERDES0_LINK_STATUS |
3747 NIG_MASK_MI_INT));
3749 bnx2x_emac_init(params, vars);
3751 if (CHIP_REV_IS_FPGA(bp)) {
3752 vars->link_up = 1;
3753 vars->line_speed = SPEED_10000;
3754 vars->duplex = DUPLEX_FULL;
3755 vars->flow_ctrl = FLOW_CTRL_NONE;
3756 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
3757 /* enable on E1.5 FPGA */
3758 if (CHIP_IS_E1H(bp)) {
3759 vars->flow_ctrl |=
3760 (FLOW_CTRL_TX | FLOW_CTRL_RX);
3761 vars->link_status |=
3762 (LINK_STATUS_TX_FLOW_CONTROL_ENABLED |
3763 LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
3766 bnx2x_emac_enable(params, vars, 0);
3767 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
3768 /* disable drain */
3769 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
3770 + params->port*4, 0);
3772 /* update shared memory */
3773 bnx2x_update_mng(params, vars->link_status);
3775 return 0;
3777 } else
3778 if (CHIP_REV_IS_EMUL(bp)) {
3780 vars->link_up = 1;
3781 vars->line_speed = SPEED_10000;
3782 vars->duplex = DUPLEX_FULL;
3783 vars->flow_ctrl = FLOW_CTRL_NONE;
3784 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
3786 bnx2x_bmac_enable(params, vars, 0);
3788 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
3789 /* Disable drain */
3790 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
3791 + params->port*4, 0);
3793 /* update shared memory */
3794 bnx2x_update_mng(params, vars->link_status);
3796 return 0;
3798 } else
3799 if (params->loopback_mode == LOOPBACK_BMAC) {
3800 vars->link_up = 1;
3801 vars->line_speed = SPEED_10000;
3802 vars->duplex = DUPLEX_FULL;
3803 vars->flow_ctrl = FLOW_CTRL_NONE;
3804 vars->mac_type = MAC_TYPE_BMAC;
3806 vars->phy_flags = PHY_XGXS_FLAG;
3808 bnx2x_phy_deassert(params, vars->phy_flags);
3809 /* set bmac loopback */
3810 bnx2x_bmac_enable(params, vars, 1);
3812 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
3813 params->port*4, 0);
3814 } else if (params->loopback_mode == LOOPBACK_EMAC) {
3815 vars->link_up = 1;
3816 vars->line_speed = SPEED_1000;
3817 vars->duplex = DUPLEX_FULL;
3818 vars->flow_ctrl = FLOW_CTRL_NONE;
3819 vars->mac_type = MAC_TYPE_EMAC;
3821 vars->phy_flags = PHY_XGXS_FLAG;
3823 bnx2x_phy_deassert(params, vars->phy_flags);
3824 /* set bmac loopback */
3825 bnx2x_emac_enable(params, vars, 1);
3826 bnx2x_emac_program(params, vars->line_speed,
3827 vars->duplex);
3828 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
3829 params->port*4, 0);
3830 } else if ((params->loopback_mode == LOOPBACK_XGXS_10) ||
3831 (params->loopback_mode == LOOPBACK_EXT_PHY)) {
3832 vars->link_up = 1;
3833 vars->line_speed = SPEED_10000;
3834 vars->duplex = DUPLEX_FULL;
3835 vars->flow_ctrl = FLOW_CTRL_NONE;
3837 vars->phy_flags = PHY_XGXS_FLAG;
3839 val = REG_RD(bp,
3840 NIG_REG_XGXS0_CTRL_PHY_ADDR+
3841 params->port*0x18);
3842 params->phy_addr = (u8)val;
3844 bnx2x_phy_deassert(params, vars->phy_flags);
3845 bnx2x_link_initialize(params, vars);
3847 vars->mac_type = MAC_TYPE_BMAC;
3849 bnx2x_bmac_enable(params, vars, 0);
3851 if (params->loopback_mode == LOOPBACK_XGXS_10) {
3852 /* set 10G XGXS loopback */
3853 bnx2x_set_xgxs_loopback(params, vars, 1);
3854 } else {
3855 /* set external phy loopback */
3856 bnx2x_ext_phy_loopback(params);
3858 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
3859 params->port*4, 0);
3860 } else
3861 /* No loopback */
3864 bnx2x_phy_deassert(params, vars->phy_flags);
3865 switch (params->switch_cfg) {
3866 case SWITCH_CFG_1G:
3867 vars->phy_flags |= PHY_SERDES_FLAG;
3868 if ((params->ext_phy_config &
3869 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK) ==
3870 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482) {
3871 vars->phy_flags |=
3872 PHY_SGMII_FLAG;
3875 val = REG_RD(bp,
3876 NIG_REG_SERDES0_CTRL_PHY_ADDR+
3877 params->port*0x10);
3879 params->phy_addr = (u8)val;
3881 break;
3882 case SWITCH_CFG_10G:
3883 vars->phy_flags |= PHY_XGXS_FLAG;
3884 val = REG_RD(bp,
3885 NIG_REG_XGXS0_CTRL_PHY_ADDR+
3886 params->port*0x18);
3887 params->phy_addr = (u8)val;
3889 break;
3890 default:
3891 DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
3892 return -EINVAL;
3893 break;
3896 bnx2x_link_initialize(params, vars);
3897 bnx2x_link_int_enable(params);
3899 return 0;
3902 u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars)
3905 struct bnx2x *bp = params->bp;
3906 u32 ext_phy_config = params->ext_phy_config;
3907 u16 hw_led_mode = params->hw_led_mode;
3908 u32 chip_id = params->chip_id;
3909 u8 port = params->port;
3910 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
3911 /* disable attentions */
3913 vars->link_status = 0;
3914 bnx2x_update_mng(params, vars->link_status);
3915 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
3916 (NIG_MASK_XGXS0_LINK_STATUS |
3917 NIG_MASK_XGXS0_LINK10G |
3918 NIG_MASK_SERDES0_LINK_STATUS |
3919 NIG_MASK_MI_INT));
3921 /* activate nig drain */
3922 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
3924 /* disable nig egress interface */
3925 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
3926 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
3928 /* Stop BigMac rx */
3929 bnx2x_bmac_rx_disable(bp, port);
3931 /* disable emac */
3932 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
3934 msleep(10);
3935 /* The PHY reset is controled by GPIO 1
3936 * Hold it as vars low
3938 /* clear link led */
3939 bnx2x_set_led(bp, port, LED_MODE_OFF, 0, hw_led_mode, chip_id);
3940 if (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
3941 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
3942 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
3943 /* HW reset */
3945 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
3946 MISC_REGISTERS_GPIO_OUTPUT_LOW);
3948 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
3949 MISC_REGISTERS_GPIO_OUTPUT_LOW);
3951 DP(NETIF_MSG_LINK, "reset external PHY\n");
3952 } else {
3954 u8 ext_phy_addr = ((ext_phy_config &
3955 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
3956 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
3958 /* SW reset */
3959 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
3960 MDIO_PMA_DEVAD,
3961 MDIO_PMA_REG_CTRL,
3962 1<<15);
3964 /* Set Low Power Mode */
3965 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
3966 MDIO_PMA_DEVAD,
3967 MDIO_PMA_REG_CTRL,
3968 1<<11);
3971 if (ext_phy_type ==
3972 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
3973 DP(NETIF_MSG_LINK, "Setting 8073 port %d into"
3974 "low power mode\n",
3975 port);
3976 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
3977 MISC_REGISTERS_GPIO_OUTPUT_LOW);
3981 /* reset the SerDes/XGXS */
3982 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
3983 (0x1ff << (port*16)));
3985 /* reset BigMac */
3986 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
3987 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
3989 /* disable nig ingress interface */
3990 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
3991 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
3992 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
3993 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
3994 vars->link_up = 0;
3995 return 0;
3998 /* This function should called upon link interrupt */
3999 /* In case vars->link_up, driver needs to
4000 1. Update the pbf
4001 2. Disable drain
4002 3. Update the shared memory
4003 4. Indicate link up
4004 5. Set LEDs
4005 Otherwise,
4006 1. Update shared memory
4007 2. Reset BigMac
4008 3. Report link down
4009 4. Unset LEDs
4011 u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
4013 struct bnx2x *bp = params->bp;
4014 u8 port = params->port;
4015 u16 i;
4016 u16 gp_status;
4017 u16 link_10g;
4018 u8 rc = 0;
4020 DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
4021 port,
4022 (vars->phy_flags & PHY_XGXS_FLAG),
4023 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
4025 DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
4026 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
4027 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
4028 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
4030 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
4031 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
4032 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
4035 /* avoid fast toggling */
4036 for (i = 0; i < 10; i++) {
4037 msleep(10);
4038 CL45_RD_OVER_CL22(bp, port, params->phy_addr,
4039 MDIO_REG_BANK_GP_STATUS,
4040 MDIO_GP_STATUS_TOP_AN_STATUS1,
4041 &gp_status);
4044 rc = bnx2x_link_settings_status(params, vars, gp_status);
4045 if (rc != 0)
4046 return rc;
4048 /* anything 10 and over uses the bmac */
4049 link_10g = ((vars->line_speed == SPEED_10000) ||
4050 (vars->line_speed == SPEED_12000) ||
4051 (vars->line_speed == SPEED_12500) ||
4052 (vars->line_speed == SPEED_13000) ||
4053 (vars->line_speed == SPEED_15000) ||
4054 (vars->line_speed == SPEED_16000));
4056 bnx2x_link_int_ack(params, vars, link_10g);
4058 /* link is up only if both local phy and external phy are up */
4059 vars->link_up = (vars->phy_link_up &&
4060 bnx2x_ext_phy_is_link_up(params, vars));
4062 if (!vars->phy_link_up &&
4063 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18)) {
4064 bnx2x_ext_phy_is_link_up(params, vars); /* Clear interrupt */
4067 if (vars->link_up) {
4068 vars->link_status |= LINK_STATUS_LINK_UP;
4069 if (link_10g) {
4070 bnx2x_bmac_enable(params, vars, 0);
4071 bnx2x_set_led(bp, port, LED_MODE_OPER,
4072 SPEED_10000, params->hw_led_mode,
4073 params->chip_id);
4075 } else {
4076 bnx2x_emac_enable(params, vars, 0);
4077 rc = bnx2x_emac_program(params, vars->line_speed,
4078 vars->duplex);
4080 /* AN complete? */
4081 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
4082 if (!(vars->phy_flags &
4083 PHY_SGMII_FLAG))
4084 bnx2x_set_sgmii_tx_driver(params);
4088 /* PBF - link up */
4089 rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
4090 vars->line_speed);
4092 /* disable drain */
4093 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
4095 /* update shared memory */
4096 bnx2x_update_mng(params, vars->link_status);
4098 } else { /* link down */
4099 DP(NETIF_MSG_LINK, "Port %x: Link is down\n", params->port);
4100 bnx2x_set_led(bp, port, LED_MODE_OFF,
4101 0, params->hw_led_mode,
4102 params->chip_id);
4104 /* indicate no mac active */
4105 vars->mac_type = MAC_TYPE_NONE;
4107 /* update shared memory */
4108 vars->link_status = 0;
4109 bnx2x_update_mng(params, vars->link_status);
4111 /* activate nig drain */
4112 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
4114 /* reset BigMac */
4115 bnx2x_bmac_rx_disable(bp, params->port);
4116 REG_WR(bp, GRCBASE_MISC +
4117 MISC_REGISTERS_RESET_REG_2_CLEAR,
4118 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
4122 return rc;
4125 static void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
4127 u16 val, cnt;
4129 bnx2x_cl45_read(bp, port,
4130 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4131 phy_addr,
4132 MDIO_PMA_DEVAD,
4133 MDIO_PMA_REG_7101_RESET, &val);
4135 for (cnt = 0; cnt < 10; cnt++) {
4136 msleep(50);
4137 /* Writes a self-clearing reset */
4138 bnx2x_cl45_write(bp, port,
4139 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4140 phy_addr,
4141 MDIO_PMA_DEVAD,
4142 MDIO_PMA_REG_7101_RESET,
4143 (val | (1<<15)));
4144 /* Wait for clear */
4145 bnx2x_cl45_read(bp, port,
4146 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4147 phy_addr,
4148 MDIO_PMA_DEVAD,
4149 MDIO_PMA_REG_7101_RESET, &val);
4151 if ((val & (1<<15)) == 0)
4152 break;
4155 #define RESERVED_SIZE 256
4156 /* max application is 160K bytes - data at end of RAM */
4157 #define MAX_APP_SIZE 160*1024 - RESERVED_SIZE
4159 /* Header is 14 bytes */
4160 #define HEADER_SIZE 14
4161 #define DATA_OFFSET HEADER_SIZE
4163 #define SPI_START_TRANSFER(bp, port, ext_phy_addr) \
4164 bnx2x_cl45_write(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101, \
4165 ext_phy_addr, \
4166 MDIO_PCS_DEVAD, \
4167 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 1)
4169 /* Programs an image to DSP's flash via the SPI port*/
4170 static u8 bnx2x_sfx7101_flash_download(struct bnx2x *bp, u8 port,
4171 u8 ext_phy_addr,
4172 char data[], u32 size)
4174 const u16 num_trans = size/4; /* 4 bytes can be sent at a time */
4175 /* Doesn't include last trans!*/
4176 const u16 last_trans_size = size%4; /* Num bytes on last trans */
4177 u16 trans_cnt, byte_cnt;
4178 u32 data_index;
4179 u16 tmp;
4180 u16 code_started = 0;
4181 u16 image_revision1, image_revision2;
4182 u16 cnt;
4184 DP(NETIF_MSG_LINK, "bnx2x_sfx7101_flash_download file_size=%d\n", size);
4185 /* Going to flash*/
4186 if ((size-HEADER_SIZE) > MAX_APP_SIZE) {
4187 /* This very often will be the case, because the image is built
4188 with 160Kbytes size whereas the total image size must actually
4189 be 160Kbytes-RESERVED_SIZE */
4190 DP(NETIF_MSG_LINK, "Warning, file size was %d bytes "
4191 "truncated to %d bytes\n", size, MAX_APP_SIZE);
4192 size = MAX_APP_SIZE+HEADER_SIZE;
4194 DP(NETIF_MSG_LINK, "File version is %c%c\n", data[0x14e], data[0x14f]);
4195 DP(NETIF_MSG_LINK, " %c%c\n", data[0x150], data[0x151]);
4196 /* Put the DSP in download mode by setting FLASH_CFG[2] to 1
4197 and issuing a reset.*/
4199 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
4200 MISC_REGISTERS_GPIO_HIGH);
4202 bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
4204 /* wait 0.5 sec */
4205 for (cnt = 0; cnt < 100; cnt++)
4206 msleep(5);
4208 /* Make sure we can access the DSP
4209 And it's in the correct mode (waiting for download) */
4211 bnx2x_cl45_read(bp, port,
4212 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4213 ext_phy_addr,
4214 MDIO_PCS_DEVAD,
4215 MDIO_PCS_REG_7101_DSP_ACCESS, &tmp);
4217 if (tmp != 0x000A) {
4218 DP(NETIF_MSG_LINK, "DSP is not in waiting on download mode. "
4219 "Expected 0x000A, read 0x%04X\n", tmp);
4220 DP(NETIF_MSG_LINK, "Download failed\n");
4221 return -EINVAL;
4224 /* Mux the SPI interface away from the internal processor */
4225 bnx2x_cl45_write(bp, port,
4226 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4227 ext_phy_addr,
4228 MDIO_PCS_DEVAD,
4229 MDIO_PCS_REG_7101_SPI_MUX, 1);
4231 /* Reset the SPI port */
4232 bnx2x_cl45_write(bp, port,
4233 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4234 ext_phy_addr,
4235 MDIO_PCS_DEVAD,
4236 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
4237 bnx2x_cl45_write(bp, port,
4238 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4239 ext_phy_addr,
4240 MDIO_PCS_DEVAD,
4241 MDIO_PCS_REG_7101_SPI_CTRL_ADDR,
4242 (1<<MDIO_PCS_REG_7101_SPI_RESET_BIT));
4243 bnx2x_cl45_write(bp, port,
4244 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4245 ext_phy_addr,
4246 MDIO_PCS_DEVAD,
4247 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
4249 /* Erase the flash */
4250 bnx2x_cl45_write(bp, port,
4251 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4252 ext_phy_addr,
4253 MDIO_PCS_DEVAD,
4254 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4255 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4257 bnx2x_cl45_write(bp, port,
4258 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4259 ext_phy_addr,
4260 MDIO_PCS_DEVAD,
4261 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4264 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4265 bnx2x_cl45_write(bp, port,
4266 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4267 ext_phy_addr,
4268 MDIO_PCS_DEVAD,
4269 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4270 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_BULK_ERASE_CMD);
4272 bnx2x_cl45_write(bp, port,
4273 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4274 ext_phy_addr,
4275 MDIO_PCS_DEVAD,
4276 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4278 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4280 /* Wait 10 seconds, the maximum time for the erase to complete */
4281 DP(NETIF_MSG_LINK, "Erasing flash, this takes 10 seconds...\n");
4282 for (cnt = 0; cnt < 1000; cnt++)
4283 msleep(10);
4285 DP(NETIF_MSG_LINK, "Downloading flash, please wait...\n");
4286 data_index = 0;
4287 for (trans_cnt = 0; trans_cnt < num_trans; trans_cnt++) {
4288 bnx2x_cl45_write(bp, port,
4289 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4290 ext_phy_addr,
4291 MDIO_PCS_DEVAD,
4292 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4293 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4295 bnx2x_cl45_write(bp, port,
4296 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4297 ext_phy_addr,
4298 MDIO_PCS_DEVAD,
4299 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4301 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4303 bnx2x_cl45_write(bp, port,
4304 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4305 ext_phy_addr,
4306 MDIO_PCS_DEVAD,
4307 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4308 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
4310 /* Bits 23-16 of address */
4311 bnx2x_cl45_write(bp, port,
4312 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4313 ext_phy_addr,
4314 MDIO_PCS_DEVAD,
4315 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4316 (data_index>>16));
4317 /* Bits 15-8 of address */
4318 bnx2x_cl45_write(bp, port,
4319 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4320 ext_phy_addr,
4321 MDIO_PCS_DEVAD,
4322 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4323 (data_index>>8));
4325 /* Bits 7-0 of address */
4326 bnx2x_cl45_write(bp, port,
4327 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4328 ext_phy_addr,
4329 MDIO_PCS_DEVAD,
4330 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4331 ((u16)data_index));
4333 byte_cnt = 0;
4334 while (byte_cnt < 4 && data_index < size) {
4335 bnx2x_cl45_write(bp, port,
4336 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4337 ext_phy_addr,
4338 MDIO_PCS_DEVAD,
4339 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4340 data[data_index++]);
4341 byte_cnt++;
4344 bnx2x_cl45_write(bp, port,
4345 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4346 ext_phy_addr,
4347 MDIO_PCS_DEVAD,
4348 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4349 byte_cnt+4);
4351 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4352 msleep(5); /* Wait 5 ms minimum between transs */
4354 /* Let the user know something's going on.*/
4355 /* a pacifier ever 4K */
4356 if ((data_index % 1023) == 0)
4357 DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
4360 DP(NETIF_MSG_LINK, "\n");
4361 /* Transfer the last block if there is data remaining */
4362 if (last_trans_size) {
4363 bnx2x_cl45_write(bp, port,
4364 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4365 ext_phy_addr,
4366 MDIO_PCS_DEVAD,
4367 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4368 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4370 bnx2x_cl45_write(bp, port,
4371 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4372 ext_phy_addr,
4373 MDIO_PCS_DEVAD,
4374 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4377 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4379 bnx2x_cl45_write(bp, port,
4380 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4381 ext_phy_addr,
4382 MDIO_PCS_DEVAD,
4383 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4384 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
4386 /* Bits 23-16 of address */
4387 bnx2x_cl45_write(bp, port,
4388 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4389 ext_phy_addr,
4390 MDIO_PCS_DEVAD,
4391 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4392 (data_index>>16));
4393 /* Bits 15-8 of address */
4394 bnx2x_cl45_write(bp, port,
4395 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4396 ext_phy_addr,
4397 MDIO_PCS_DEVAD,
4398 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4399 (data_index>>8));
4401 /* Bits 7-0 of address */
4402 bnx2x_cl45_write(bp, port,
4403 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4404 ext_phy_addr,
4405 MDIO_PCS_DEVAD,
4406 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4407 ((u16)data_index));
4409 byte_cnt = 0;
4410 while (byte_cnt < last_trans_size && data_index < size) {
4411 /* Bits 7-0 of address */
4412 bnx2x_cl45_write(bp, port,
4413 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4414 ext_phy_addr,
4415 MDIO_PCS_DEVAD,
4416 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4417 data[data_index++]);
4418 byte_cnt++;
4421 bnx2x_cl45_write(bp, port,
4422 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4423 ext_phy_addr,
4424 MDIO_PCS_DEVAD,
4425 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4426 byte_cnt+4);
4428 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4431 /* DSP Remove Download Mode */
4432 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, MISC_REGISTERS_GPIO_LOW);
4434 bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
4436 /* wait 0.5 sec to allow it to run */
4437 for (cnt = 0; cnt < 100; cnt++)
4438 msleep(5);
4440 bnx2x_hw_reset(bp);
4442 for (cnt = 0; cnt < 100; cnt++)
4443 msleep(5);
4445 /* Check that the code is started. In case the download
4446 checksum failed, the code won't be started. */
4447 bnx2x_cl45_read(bp, port,
4448 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4449 ext_phy_addr,
4450 MDIO_PCS_DEVAD,
4451 MDIO_PCS_REG_7101_DSP_ACCESS,
4452 &tmp);
4454 code_started = (tmp & (1<<4));
4455 if (!code_started) {
4456 DP(NETIF_MSG_LINK, "Download failed. Please check file.\n");
4457 return -EINVAL;
4460 /* Verify that the file revision is now equal to the image
4461 revision within the DSP */
4462 bnx2x_cl45_read(bp, port,
4463 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4464 ext_phy_addr,
4465 MDIO_PMA_DEVAD,
4466 MDIO_PMA_REG_7101_VER1,
4467 &image_revision1);
4469 bnx2x_cl45_read(bp, port,
4470 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4471 ext_phy_addr,
4472 MDIO_PMA_DEVAD,
4473 MDIO_PMA_REG_7101_VER2,
4474 &image_revision2);
4476 if (data[0x14e] != (image_revision2&0xFF) ||
4477 data[0x14f] != ((image_revision2&0xFF00)>>8) ||
4478 data[0x150] != (image_revision1&0xFF) ||
4479 data[0x151] != ((image_revision1&0xFF00)>>8)) {
4480 DP(NETIF_MSG_LINK, "Download failed.\n");
4481 return -EINVAL;
4483 DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
4484 return 0;
4487 u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config,
4488 u8 driver_loaded, char data[], u32 size)
4490 u8 rc = 0;
4491 u32 ext_phy_type;
4492 u8 ext_phy_addr;
4493 ext_phy_addr = ((ext_phy_config &
4494 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
4495 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
4497 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
4499 switch (ext_phy_type) {
4500 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
4501 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
4502 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
4503 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
4504 DP(NETIF_MSG_LINK,
4505 "Flash download not supported for this ext phy\n");
4506 rc = -EINVAL;
4507 break;
4508 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
4509 /* Take ext phy out of reset */
4510 if (!driver_loaded)
4511 bnx2x_turn_on_sf(bp, port, ext_phy_addr);
4512 rc = bnx2x_sfx7101_flash_download(bp, port, ext_phy_addr,
4513 data, size);
4514 if (!driver_loaded)
4515 bnx2x_turn_off_sf(bp);
4516 break;
4517 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
4518 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
4519 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
4520 default:
4521 DP(NETIF_MSG_LINK, "Invalid ext phy type\n");
4522 rc = -EINVAL;
4523 break;
4525 return rc;