uwb: fix oops when terminating an already terminated reservation
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / net / bnx2x_link.c
blob4ce7fe9c5251143745985b70cb449df9f394edfd
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>
25 #include "bnx2x_reg.h"
26 #include "bnx2x_fw_defs.h"
27 #include "bnx2x_hsi.h"
28 #include "bnx2x_link.h"
29 #include "bnx2x.h"
31 /********************************************************/
32 #define SUPPORT_CL73 0 /* Currently no */
33 #define ETH_HLEN 14
34 #define ETH_OVREHEAD (ETH_HLEN + 8)/* 8 for CRC + VLAN*/
35 #define ETH_MIN_PACKET_SIZE 60
36 #define ETH_MAX_PACKET_SIZE 1500
37 #define ETH_MAX_JUMBO_PACKET_SIZE 9600
38 #define MDIO_ACCESS_TIMEOUT 1000
39 #define BMAC_CONTROL_RX_ENABLE 2
41 /***********************************************************/
42 /* Shortcut definitions */
43 /***********************************************************/
45 #define NIG_STATUS_XGXS0_LINK10G \
46 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G
47 #define NIG_STATUS_XGXS0_LINK_STATUS \
48 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS
49 #define NIG_STATUS_XGXS0_LINK_STATUS_SIZE \
50 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE
51 #define NIG_STATUS_SERDES0_LINK_STATUS \
52 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS
53 #define NIG_MASK_MI_INT \
54 NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT
55 #define NIG_MASK_XGXS0_LINK10G \
56 NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G
57 #define NIG_MASK_XGXS0_LINK_STATUS \
58 NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK_STATUS
59 #define NIG_MASK_SERDES0_LINK_STATUS \
60 NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS
62 #define MDIO_AN_CL73_OR_37_COMPLETE \
63 (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | \
64 MDIO_GP_STATUS_TOP_AN_STATUS1_CL37_AUTONEG_COMPLETE)
66 #define XGXS_RESET_BITS \
67 (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW | \
68 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_IDDQ | \
69 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN | \
70 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN_SD | \
71 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB)
73 #define SERDES_RESET_BITS \
74 (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_RSTB_HW | \
75 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ | \
76 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN | \
77 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN_SD)
79 #define AUTONEG_CL37 SHARED_HW_CFG_AN_ENABLE_CL37
80 #define AUTONEG_CL73 SHARED_HW_CFG_AN_ENABLE_CL73
81 #define AUTONEG_BAM SHARED_HW_CFG_AN_ENABLE_BAM
82 #define AUTONEG_PARALLEL \
83 SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
84 #define AUTONEG_SGMII_FIBER_AUTODET \
85 SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT
86 #define AUTONEG_REMOTE_PHY SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY
88 #define GP_STATUS_PAUSE_RSOLUTION_TXSIDE \
89 MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE
90 #define GP_STATUS_PAUSE_RSOLUTION_RXSIDE \
91 MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_RXSIDE
92 #define GP_STATUS_SPEED_MASK \
93 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_MASK
94 #define GP_STATUS_10M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10M
95 #define GP_STATUS_100M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_100M
96 #define GP_STATUS_1G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G
97 #define GP_STATUS_2_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_2_5G
98 #define GP_STATUS_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_5G
99 #define GP_STATUS_6G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_6G
100 #define GP_STATUS_10G_HIG \
101 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG
102 #define GP_STATUS_10G_CX4 \
103 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4
104 #define GP_STATUS_12G_HIG \
105 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12G_HIG
106 #define GP_STATUS_12_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12_5G
107 #define GP_STATUS_13G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_13G
108 #define GP_STATUS_15G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_15G
109 #define GP_STATUS_16G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G
110 #define GP_STATUS_1G_KX MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX
111 #define GP_STATUS_10G_KX4 \
112 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
114 #define LINK_10THD LINK_STATUS_SPEED_AND_DUPLEX_10THD
115 #define LINK_10TFD LINK_STATUS_SPEED_AND_DUPLEX_10TFD
116 #define LINK_100TXHD LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
117 #define LINK_100T4 LINK_STATUS_SPEED_AND_DUPLEX_100T4
118 #define LINK_100TXFD LINK_STATUS_SPEED_AND_DUPLEX_100TXFD
119 #define LINK_1000THD LINK_STATUS_SPEED_AND_DUPLEX_1000THD
120 #define LINK_1000TFD LINK_STATUS_SPEED_AND_DUPLEX_1000TFD
121 #define LINK_1000XFD LINK_STATUS_SPEED_AND_DUPLEX_1000XFD
122 #define LINK_2500THD LINK_STATUS_SPEED_AND_DUPLEX_2500THD
123 #define LINK_2500TFD LINK_STATUS_SPEED_AND_DUPLEX_2500TFD
124 #define LINK_2500XFD LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
125 #define LINK_10GTFD LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
126 #define LINK_10GXFD LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
127 #define LINK_12GTFD LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
128 #define LINK_12GXFD LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
129 #define LINK_12_5GTFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD
130 #define LINK_12_5GXFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD
131 #define LINK_13GTFD LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
132 #define LINK_13GXFD LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
133 #define LINK_15GTFD LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
134 #define LINK_15GXFD LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
135 #define LINK_16GTFD LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
136 #define LINK_16GXFD LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
138 #define PHY_XGXS_FLAG 0x1
139 #define PHY_SGMII_FLAG 0x2
140 #define PHY_SERDES_FLAG 0x4
142 /**********************************************************/
143 /* INTERFACE */
144 /**********************************************************/
145 #define CL45_WR_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
146 bnx2x_cl45_write(_bp, _port, 0, _phy_addr, \
147 DEFAULT_PHY_DEV_ADDR, \
148 (_bank + (_addr & 0xf)), \
149 _val)
151 #define CL45_RD_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
152 bnx2x_cl45_read(_bp, _port, 0, _phy_addr, \
153 DEFAULT_PHY_DEV_ADDR, \
154 (_bank + (_addr & 0xf)), \
155 _val)
157 static void bnx2x_set_phy_mdio(struct link_params *params)
159 struct bnx2x *bp = params->bp;
160 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
161 params->port*0x18, 0);
162 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
163 DEFAULT_PHY_DEV_ADDR);
166 static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
168 u32 val = REG_RD(bp, reg);
170 val |= bits;
171 REG_WR(bp, reg, val);
172 return val;
175 static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits)
177 u32 val = REG_RD(bp, reg);
179 val &= ~bits;
180 REG_WR(bp, reg, val);
181 return val;
184 static void bnx2x_emac_init(struct link_params *params,
185 struct link_vars *vars)
187 /* reset and unreset the emac core */
188 struct bnx2x *bp = params->bp;
189 u8 port = params->port;
190 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
191 u32 val;
192 u16 timeout;
194 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
195 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
196 udelay(5);
197 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
198 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
200 /* init emac - use read-modify-write */
201 /* self clear reset */
202 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
203 EMAC_WR(bp, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET));
205 timeout = 200;
206 do {
207 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
208 DP(NETIF_MSG_LINK, "EMAC reset reg is %u\n", val);
209 if (!timeout) {
210 DP(NETIF_MSG_LINK, "EMAC timeout!\n");
211 return;
213 timeout--;
214 } while (val & EMAC_MODE_RESET);
216 /* Set mac address */
217 val = ((params->mac_addr[0] << 8) |
218 params->mac_addr[1]);
219 EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH, val);
221 val = ((params->mac_addr[2] << 24) |
222 (params->mac_addr[3] << 16) |
223 (params->mac_addr[4] << 8) |
224 params->mac_addr[5]);
225 EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + 4, val);
228 static u8 bnx2x_emac_enable(struct link_params *params,
229 struct link_vars *vars, u8 lb)
231 struct bnx2x *bp = params->bp;
232 u8 port = params->port;
233 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
234 u32 val;
236 DP(NETIF_MSG_LINK, "enabling EMAC\n");
238 /* enable emac and not bmac */
239 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
241 /* for paladium */
242 if (CHIP_REV_IS_EMUL(bp)) {
243 /* Use lane 1 (of lanes 0-3) */
244 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
245 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
246 port*4, 1);
248 /* for fpga */
249 else
251 if (CHIP_REV_IS_FPGA(bp)) {
252 /* Use lane 1 (of lanes 0-3) */
253 DP(NETIF_MSG_LINK, "bnx2x_emac_enable: Setting FPGA\n");
255 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
256 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4,
258 } else
259 /* ASIC */
260 if (vars->phy_flags & PHY_XGXS_FLAG) {
261 u32 ser_lane = ((params->lane_config &
262 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
263 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
265 DP(NETIF_MSG_LINK, "XGXS\n");
266 /* select the master lanes (out of 0-3) */
267 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 +
268 port*4, ser_lane);
269 /* select XGXS */
270 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
271 port*4, 1);
273 } else { /* SerDes */
274 DP(NETIF_MSG_LINK, "SerDes\n");
275 /* select SerDes */
276 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
277 port*4, 0);
280 /* enable emac */
281 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1);
283 if (CHIP_REV_IS_SLOW(bp)) {
284 /* config GMII mode */
285 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
286 EMAC_WR(bp, EMAC_REG_EMAC_MODE,
287 (val | EMAC_MODE_PORT_GMII));
288 } else { /* ASIC */
289 /* pause enable/disable */
290 bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
291 EMAC_RX_MODE_FLOW_EN);
292 if (vars->flow_ctrl & FLOW_CTRL_RX)
293 bnx2x_bits_en(bp, emac_base +
294 EMAC_REG_EMAC_RX_MODE,
295 EMAC_RX_MODE_FLOW_EN);
297 bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
298 (EMAC_TX_MODE_EXT_PAUSE_EN |
299 EMAC_TX_MODE_FLOW_EN));
300 if (vars->flow_ctrl & FLOW_CTRL_TX)
301 bnx2x_bits_en(bp, emac_base +
302 EMAC_REG_EMAC_TX_MODE,
303 (EMAC_TX_MODE_EXT_PAUSE_EN |
304 EMAC_TX_MODE_FLOW_EN));
307 /* KEEP_VLAN_TAG, promiscuous */
308 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
309 val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
310 EMAC_WR(bp, EMAC_REG_EMAC_RX_MODE, val);
312 /* Set Loopback */
313 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
314 if (lb)
315 val |= 0x810;
316 else
317 val &= ~0x810;
318 EMAC_WR(bp, EMAC_REG_EMAC_MODE, val);
320 /* enable emac for jumbo packets */
321 EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE,
322 (EMAC_RX_MTU_SIZE_JUMBO_ENA |
323 (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD)));
325 /* strip CRC */
326 REG_WR(bp, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1);
328 /* disable the NIG in/out to the bmac */
329 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x0);
330 REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, 0x0);
331 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x0);
333 /* enable the NIG in/out to the emac */
334 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x1);
335 val = 0;
336 if (vars->flow_ctrl & FLOW_CTRL_TX)
337 val = 1;
339 REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
340 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x1);
342 if (CHIP_REV_IS_EMUL(bp)) {
343 /* take the BigMac out of reset */
344 REG_WR(bp,
345 GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
346 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
348 /* enable access for bmac registers */
349 REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
352 vars->mac_type = MAC_TYPE_EMAC;
353 return 0;
358 static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
359 u8 is_lb)
361 struct bnx2x *bp = params->bp;
362 u8 port = params->port;
363 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
364 NIG_REG_INGRESS_BMAC0_MEM;
365 u32 wb_data[2];
366 u32 val;
368 DP(NETIF_MSG_LINK, "Enabling BigMAC\n");
369 /* reset and unreset the BigMac */
370 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
371 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
372 msleep(1);
374 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
375 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
377 /* enable access for bmac registers */
378 REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
380 /* XGXS control */
381 wb_data[0] = 0x3c;
382 wb_data[1] = 0;
383 REG_WR_DMAE(bp, bmac_addr +
384 BIGMAC_REGISTER_BMAC_XGXS_CONTROL,
385 wb_data, 2);
387 /* tx MAC SA */
388 wb_data[0] = ((params->mac_addr[2] << 24) |
389 (params->mac_addr[3] << 16) |
390 (params->mac_addr[4] << 8) |
391 params->mac_addr[5]);
392 wb_data[1] = ((params->mac_addr[0] << 8) |
393 params->mac_addr[1]);
394 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR,
395 wb_data, 2);
397 /* tx control */
398 val = 0xc0;
399 if (vars->flow_ctrl & FLOW_CTRL_TX)
400 val |= 0x800000;
401 wb_data[0] = val;
402 wb_data[1] = 0;
403 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_CONTROL,
404 wb_data, 2);
406 /* mac control */
407 val = 0x3;
408 if (is_lb) {
409 val |= 0x4;
410 DP(NETIF_MSG_LINK, "enable bmac loopback\n");
412 wb_data[0] = val;
413 wb_data[1] = 0;
414 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
415 wb_data, 2);
418 /* set rx mtu */
419 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
420 wb_data[1] = 0;
421 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE,
422 wb_data, 2);
424 /* rx control set to don't strip crc */
425 val = 0x14;
426 if (vars->flow_ctrl & FLOW_CTRL_RX)
427 val |= 0x20;
428 wb_data[0] = val;
429 wb_data[1] = 0;
430 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_CONTROL,
431 wb_data, 2);
433 /* set tx mtu */
434 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
435 wb_data[1] = 0;
436 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE,
437 wb_data, 2);
439 /* set cnt max size */
440 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
441 wb_data[1] = 0;
442 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE,
443 wb_data, 2);
445 /* configure safc */
446 wb_data[0] = 0x1000200;
447 wb_data[1] = 0;
448 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
449 wb_data, 2);
450 /* fix for emulation */
451 if (CHIP_REV_IS_EMUL(bp)) {
452 wb_data[0] = 0xf000;
453 wb_data[1] = 0;
454 REG_WR_DMAE(bp,
455 bmac_addr + BIGMAC_REGISTER_TX_PAUSE_THRESHOLD,
456 wb_data, 2);
459 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
460 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
461 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
462 val = 0;
463 if (vars->flow_ctrl & FLOW_CTRL_TX)
464 val = 1;
465 REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
466 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
467 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x0);
468 REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, 0x0);
469 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x1);
470 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);
472 vars->mac_type = MAC_TYPE_BMAC;
473 return 0;
476 static void bnx2x_phy_deassert(struct link_params *params, u8 phy_flags)
478 struct bnx2x *bp = params->bp;
479 u32 val;
481 if (phy_flags & PHY_XGXS_FLAG) {
482 DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:XGXS\n");
483 val = XGXS_RESET_BITS;
485 } else { /* SerDes */
486 DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:SerDes\n");
487 val = SERDES_RESET_BITS;
490 val = val << (params->port*16);
492 /* reset and unreset the SerDes/XGXS */
493 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
494 val);
495 udelay(500);
496 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET,
497 val);
498 bnx2x_set_phy_mdio(params);
501 void bnx2x_link_status_update(struct link_params *params,
502 struct link_vars *vars)
504 struct bnx2x *bp = params->bp;
505 u8 link_10g;
506 u8 port = params->port;
508 if (params->switch_cfg == SWITCH_CFG_1G)
509 vars->phy_flags = PHY_SERDES_FLAG;
510 else
511 vars->phy_flags = PHY_XGXS_FLAG;
512 vars->link_status = REG_RD(bp, params->shmem_base +
513 offsetof(struct shmem_region,
514 port_mb[port].link_status));
516 vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
518 if (vars->link_up) {
519 DP(NETIF_MSG_LINK, "phy link up\n");
521 vars->phy_link_up = 1;
522 vars->duplex = DUPLEX_FULL;
523 switch (vars->link_status &
524 LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
525 case LINK_10THD:
526 vars->duplex = DUPLEX_HALF;
527 /* fall thru */
528 case LINK_10TFD:
529 vars->line_speed = SPEED_10;
530 break;
532 case LINK_100TXHD:
533 vars->duplex = DUPLEX_HALF;
534 /* fall thru */
535 case LINK_100T4:
536 case LINK_100TXFD:
537 vars->line_speed = SPEED_100;
538 break;
540 case LINK_1000THD:
541 vars->duplex = DUPLEX_HALF;
542 /* fall thru */
543 case LINK_1000TFD:
544 vars->line_speed = SPEED_1000;
545 break;
547 case LINK_2500THD:
548 vars->duplex = DUPLEX_HALF;
549 /* fall thru */
550 case LINK_2500TFD:
551 vars->line_speed = SPEED_2500;
552 break;
554 case LINK_10GTFD:
555 vars->line_speed = SPEED_10000;
556 break;
558 case LINK_12GTFD:
559 vars->line_speed = SPEED_12000;
560 break;
562 case LINK_12_5GTFD:
563 vars->line_speed = SPEED_12500;
564 break;
566 case LINK_13GTFD:
567 vars->line_speed = SPEED_13000;
568 break;
570 case LINK_15GTFD:
571 vars->line_speed = SPEED_15000;
572 break;
574 case LINK_16GTFD:
575 vars->line_speed = SPEED_16000;
576 break;
578 default:
579 break;
582 if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
583 vars->flow_ctrl |= FLOW_CTRL_TX;
584 else
585 vars->flow_ctrl &= ~FLOW_CTRL_TX;
587 if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
588 vars->flow_ctrl |= FLOW_CTRL_RX;
589 else
590 vars->flow_ctrl &= ~FLOW_CTRL_RX;
592 if (vars->phy_flags & PHY_XGXS_FLAG) {
593 if (vars->line_speed &&
594 ((vars->line_speed == SPEED_10) ||
595 (vars->line_speed == SPEED_100))) {
596 vars->phy_flags |= PHY_SGMII_FLAG;
597 } else {
598 vars->phy_flags &= ~PHY_SGMII_FLAG;
602 /* anything 10 and over uses the bmac */
603 link_10g = ((vars->line_speed == SPEED_10000) ||
604 (vars->line_speed == SPEED_12000) ||
605 (vars->line_speed == SPEED_12500) ||
606 (vars->line_speed == SPEED_13000) ||
607 (vars->line_speed == SPEED_15000) ||
608 (vars->line_speed == SPEED_16000));
609 if (link_10g)
610 vars->mac_type = MAC_TYPE_BMAC;
611 else
612 vars->mac_type = MAC_TYPE_EMAC;
614 } else { /* link down */
615 DP(NETIF_MSG_LINK, "phy link down\n");
617 vars->phy_link_up = 0;
619 vars->line_speed = 0;
620 vars->duplex = DUPLEX_FULL;
621 vars->flow_ctrl = FLOW_CTRL_NONE;
623 /* indicate no mac active */
624 vars->mac_type = MAC_TYPE_NONE;
627 DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x\n",
628 vars->link_status, vars->phy_link_up);
629 DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n",
630 vars->line_speed, vars->duplex, vars->flow_ctrl);
633 static void bnx2x_update_mng(struct link_params *params, u32 link_status)
635 struct bnx2x *bp = params->bp;
636 REG_WR(bp, params->shmem_base +
637 offsetof(struct shmem_region,
638 port_mb[params->port].link_status),
639 link_status);
642 static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
644 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
645 NIG_REG_INGRESS_BMAC0_MEM;
646 u32 wb_data[2];
647 u32 nig_bmac_enable = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4);
649 /* Only if the bmac is out of reset */
650 if (REG_RD(bp, MISC_REG_RESET_REG_2) &
651 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) &&
652 nig_bmac_enable) {
654 /* Clear Rx Enable bit in BMAC_CONTROL register */
655 REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
656 wb_data, 2);
657 wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
658 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
659 wb_data, 2);
661 msleep(1);
665 static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
666 u32 line_speed)
668 struct bnx2x *bp = params->bp;
669 u8 port = params->port;
670 u32 init_crd, crd;
671 u32 count = 1000;
673 /* disable port */
674 REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1);
676 /* wait for init credit */
677 init_crd = REG_RD(bp, PBF_REG_P0_INIT_CRD + port*4);
678 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
679 DP(NETIF_MSG_LINK, "init_crd 0x%x crd 0x%x\n", init_crd, crd);
681 while ((init_crd != crd) && count) {
682 msleep(5);
684 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
685 count--;
687 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
688 if (init_crd != crd) {
689 DP(NETIF_MSG_LINK, "BUG! init_crd 0x%x != crd 0x%x\n",
690 init_crd, crd);
691 return -EINVAL;
694 if (flow_ctrl & FLOW_CTRL_RX ||
695 line_speed == SPEED_10 ||
696 line_speed == SPEED_100 ||
697 line_speed == SPEED_1000 ||
698 line_speed == SPEED_2500) {
699 REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 1);
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;
708 REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
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_10000:
714 init_crd = thresh + 553 - 22;
715 break;
717 case SPEED_12000:
718 init_crd = thresh + 664 - 22;
719 break;
721 case SPEED_13000:
722 init_crd = thresh + 742 - 22;
723 break;
725 case SPEED_16000:
726 init_crd = thresh + 778 - 22;
727 break;
728 default:
729 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
730 line_speed);
731 return -EINVAL;
732 break;
735 REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, init_crd);
736 DP(NETIF_MSG_LINK, "PBF updated to speed %d credit %d\n",
737 line_speed, init_crd);
739 /* probe the credit changes */
740 REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x1);
741 msleep(5);
742 REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x0);
744 /* enable port */
745 REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x0);
746 return 0;
749 static u32 bnx2x_get_emac_base(u32 ext_phy_type, u8 port)
751 u32 emac_base;
752 switch (ext_phy_type) {
753 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
754 emac_base = GRCBASE_EMAC0;
755 break;
756 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
757 emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
758 break;
759 default:
760 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
761 break;
763 return emac_base;
767 u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type,
768 u8 phy_addr, u8 devad, u16 reg, u16 val)
770 u32 tmp, saved_mode;
771 u8 i, rc = 0;
772 u32 mdio_ctrl = bnx2x_get_emac_base(ext_phy_type, port);
774 /* set clause 45 mode, slow down the MDIO clock to 2.5MHz
775 * (a value of 49==0x31) and make sure that the AUTO poll is off
777 saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
778 tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
779 EMAC_MDIO_MODE_CLOCK_CNT);
780 tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
781 (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
782 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
783 REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
784 udelay(40);
786 /* address */
788 tmp = ((phy_addr << 21) | (devad << 16) | reg |
789 EMAC_MDIO_COMM_COMMAND_ADDRESS |
790 EMAC_MDIO_COMM_START_BUSY);
791 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
793 for (i = 0; i < 50; i++) {
794 udelay(10);
796 tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
797 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
798 udelay(5);
799 break;
802 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
803 DP(NETIF_MSG_LINK, "write phy register failed\n");
804 rc = -EFAULT;
805 } else {
806 /* data */
807 tmp = ((phy_addr << 21) | (devad << 16) | val |
808 EMAC_MDIO_COMM_COMMAND_WRITE_45 |
809 EMAC_MDIO_COMM_START_BUSY);
810 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
812 for (i = 0; i < 50; i++) {
813 udelay(10);
815 tmp = REG_RD(bp, mdio_ctrl +
816 EMAC_REG_EMAC_MDIO_COMM);
817 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
818 udelay(5);
819 break;
822 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
823 DP(NETIF_MSG_LINK, "write phy register failed\n");
824 rc = -EFAULT;
828 /* Restore the saved mode */
829 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
831 return rc;
834 u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type,
835 u8 phy_addr, u8 devad, u16 reg, u16 *ret_val)
837 u32 val, saved_mode;
838 u16 i;
839 u8 rc = 0;
841 u32 mdio_ctrl = bnx2x_get_emac_base(ext_phy_type, port);
842 /* set clause 45 mode, slow down the MDIO clock to 2.5MHz
843 * (a value of 49==0x31) and make sure that the AUTO poll is off
845 saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
846 val = saved_mode & ((EMAC_MDIO_MODE_AUTO_POLL |
847 EMAC_MDIO_MODE_CLOCK_CNT));
848 val |= (EMAC_MDIO_MODE_CLAUSE_45 |
849 (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
850 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
851 REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
852 udelay(40);
854 /* address */
855 val = ((phy_addr << 21) | (devad << 16) | reg |
856 EMAC_MDIO_COMM_COMMAND_ADDRESS |
857 EMAC_MDIO_COMM_START_BUSY);
858 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
860 for (i = 0; i < 50; i++) {
861 udelay(10);
863 val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
864 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
865 udelay(5);
866 break;
869 if (val & EMAC_MDIO_COMM_START_BUSY) {
870 DP(NETIF_MSG_LINK, "read phy register failed\n");
872 *ret_val = 0;
873 rc = -EFAULT;
875 } else {
876 /* data */
877 val = ((phy_addr << 21) | (devad << 16) |
878 EMAC_MDIO_COMM_COMMAND_READ_45 |
879 EMAC_MDIO_COMM_START_BUSY);
880 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
882 for (i = 0; i < 50; i++) {
883 udelay(10);
885 val = REG_RD(bp, mdio_ctrl +
886 EMAC_REG_EMAC_MDIO_COMM);
887 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
888 *ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
889 break;
892 if (val & EMAC_MDIO_COMM_START_BUSY) {
893 DP(NETIF_MSG_LINK, "read phy register failed\n");
895 *ret_val = 0;
896 rc = -EFAULT;
900 /* Restore the saved mode */
901 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
903 return rc;
906 static void bnx2x_set_aer_mmd(struct link_params *params,
907 struct link_vars *vars)
909 struct bnx2x *bp = params->bp;
910 u32 ser_lane;
911 u16 offset;
913 ser_lane = ((params->lane_config &
914 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
915 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
917 offset = (vars->phy_flags & PHY_XGXS_FLAG) ?
918 (params->phy_addr + ser_lane) : 0;
920 CL45_WR_OVER_CL22(bp, params->port,
921 params->phy_addr,
922 MDIO_REG_BANK_AER_BLOCK,
923 MDIO_AER_BLOCK_AER_REG, 0x3800 + offset);
926 static void bnx2x_set_master_ln(struct link_params *params)
928 struct bnx2x *bp = params->bp;
929 u16 new_master_ln, ser_lane;
930 ser_lane = ((params->lane_config &
931 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
932 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
934 /* set the master_ln for AN */
935 CL45_RD_OVER_CL22(bp, params->port,
936 params->phy_addr,
937 MDIO_REG_BANK_XGXS_BLOCK2,
938 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
939 &new_master_ln);
941 CL45_WR_OVER_CL22(bp, params->port,
942 params->phy_addr,
943 MDIO_REG_BANK_XGXS_BLOCK2 ,
944 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
945 (new_master_ln | ser_lane));
948 static u8 bnx2x_reset_unicore(struct link_params *params)
950 struct bnx2x *bp = params->bp;
951 u16 mii_control;
952 u16 i;
954 CL45_RD_OVER_CL22(bp, params->port,
955 params->phy_addr,
956 MDIO_REG_BANK_COMBO_IEEE0,
957 MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
959 /* reset the unicore */
960 CL45_WR_OVER_CL22(bp, params->port,
961 params->phy_addr,
962 MDIO_REG_BANK_COMBO_IEEE0,
963 MDIO_COMBO_IEEE0_MII_CONTROL,
964 (mii_control |
965 MDIO_COMBO_IEEO_MII_CONTROL_RESET));
967 /* wait for the reset to self clear */
968 for (i = 0; i < MDIO_ACCESS_TIMEOUT; i++) {
969 udelay(5);
971 /* the reset erased the previous bank value */
972 CL45_RD_OVER_CL22(bp, params->port,
973 params->phy_addr,
974 MDIO_REG_BANK_COMBO_IEEE0,
975 MDIO_COMBO_IEEE0_MII_CONTROL,
976 &mii_control);
978 if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) {
979 udelay(5);
980 return 0;
984 DP(NETIF_MSG_LINK, "BUG! XGXS is still in reset!\n");
985 return -EINVAL;
989 static void bnx2x_set_swap_lanes(struct link_params *params)
991 struct bnx2x *bp = params->bp;
992 /* Each two bits represents a lane number:
993 No swap is 0123 => 0x1b no need to enable the swap */
994 u16 ser_lane, rx_lane_swap, tx_lane_swap;
996 ser_lane = ((params->lane_config &
997 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
998 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
999 rx_lane_swap = ((params->lane_config &
1000 PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
1001 PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
1002 tx_lane_swap = ((params->lane_config &
1003 PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
1004 PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
1006 if (rx_lane_swap != 0x1b) {
1007 CL45_WR_OVER_CL22(bp, params->port,
1008 params->phy_addr,
1009 MDIO_REG_BANK_XGXS_BLOCK2,
1010 MDIO_XGXS_BLOCK2_RX_LN_SWAP,
1011 (rx_lane_swap |
1012 MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
1013 MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
1014 } else {
1015 CL45_WR_OVER_CL22(bp, params->port,
1016 params->phy_addr,
1017 MDIO_REG_BANK_XGXS_BLOCK2,
1018 MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
1021 if (tx_lane_swap != 0x1b) {
1022 CL45_WR_OVER_CL22(bp, params->port,
1023 params->phy_addr,
1024 MDIO_REG_BANK_XGXS_BLOCK2,
1025 MDIO_XGXS_BLOCK2_TX_LN_SWAP,
1026 (tx_lane_swap |
1027 MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
1028 } else {
1029 CL45_WR_OVER_CL22(bp, params->port,
1030 params->phy_addr,
1031 MDIO_REG_BANK_XGXS_BLOCK2,
1032 MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
1036 static void bnx2x_set_parallel_detection(struct link_params *params,
1037 u8 phy_flags)
1039 struct bnx2x *bp = params->bp;
1040 u16 control2;
1042 CL45_RD_OVER_CL22(bp, params->port,
1043 params->phy_addr,
1044 MDIO_REG_BANK_SERDES_DIGITAL,
1045 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1046 &control2);
1049 control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
1052 CL45_WR_OVER_CL22(bp, params->port,
1053 params->phy_addr,
1054 MDIO_REG_BANK_SERDES_DIGITAL,
1055 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1056 control2);
1058 if (phy_flags & PHY_XGXS_FLAG) {
1059 DP(NETIF_MSG_LINK, "XGXS\n");
1061 CL45_WR_OVER_CL22(bp, params->port,
1062 params->phy_addr,
1063 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1064 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
1065 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
1067 CL45_RD_OVER_CL22(bp, params->port,
1068 params->phy_addr,
1069 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1070 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
1071 &control2);
1074 control2 |=
1075 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
1077 CL45_WR_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);
1083 /* Disable parallel detection of HiG */
1084 CL45_WR_OVER_CL22(bp, params->port,
1085 params->phy_addr,
1086 MDIO_REG_BANK_XGXS_BLOCK2,
1087 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
1088 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
1089 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
1093 static void bnx2x_set_autoneg(struct link_params *params,
1094 struct link_vars *vars)
1096 struct bnx2x *bp = params->bp;
1097 u16 reg_val;
1099 /* CL37 Autoneg */
1101 CL45_RD_OVER_CL22(bp, params->port,
1102 params->phy_addr,
1103 MDIO_REG_BANK_COMBO_IEEE0,
1104 MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1106 /* CL37 Autoneg Enabled */
1107 if (vars->line_speed == SPEED_AUTO_NEG)
1108 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN;
1109 else /* CL37 Autoneg Disabled */
1110 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1111 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);
1113 CL45_WR_OVER_CL22(bp, params->port,
1114 params->phy_addr,
1115 MDIO_REG_BANK_COMBO_IEEE0,
1116 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1118 /* Enable/Disable Autodetection */
1120 CL45_RD_OVER_CL22(bp, params->port,
1121 params->phy_addr,
1122 MDIO_REG_BANK_SERDES_DIGITAL,
1123 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
1124 reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN;
1125 if (vars->line_speed == SPEED_AUTO_NEG)
1126 reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1127 else
1128 reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1130 CL45_WR_OVER_CL22(bp, params->port,
1131 params->phy_addr,
1132 MDIO_REG_BANK_SERDES_DIGITAL,
1133 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
1135 /* Enable TetonII and BAM autoneg */
1136 CL45_RD_OVER_CL22(bp, params->port,
1137 params->phy_addr,
1138 MDIO_REG_BANK_BAM_NEXT_PAGE,
1139 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1140 &reg_val);
1141 if (vars->line_speed == SPEED_AUTO_NEG) {
1142 /* Enable BAM aneg Mode and TetonII aneg Mode */
1143 reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1144 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1145 } else {
1146 /* TetonII and BAM Autoneg Disabled */
1147 reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1148 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1150 CL45_WR_OVER_CL22(bp, params->port,
1151 params->phy_addr,
1152 MDIO_REG_BANK_BAM_NEXT_PAGE,
1153 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1154 reg_val);
1156 /* Enable Clause 73 Aneg */
1157 if ((vars->line_speed == SPEED_AUTO_NEG) &&
1158 (SUPPORT_CL73)) {
1159 /* Enable BAM Station Manager */
1161 CL45_WR_OVER_CL22(bp, params->port,
1162 params->phy_addr,
1163 MDIO_REG_BANK_CL73_USERB0,
1164 MDIO_CL73_USERB0_CL73_BAM_CTRL1,
1165 (MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
1166 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN |
1167 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN));
1169 /* Merge CL73 and CL37 aneg resolution */
1170 CL45_RD_OVER_CL22(bp, params->port,
1171 params->phy_addr,
1172 MDIO_REG_BANK_CL73_USERB0,
1173 MDIO_CL73_USERB0_CL73_BAM_CTRL3,
1174 &reg_val);
1176 CL45_WR_OVER_CL22(bp, params->port,
1177 params->phy_addr,
1178 MDIO_REG_BANK_CL73_USERB0,
1179 MDIO_CL73_USERB0_CL73_BAM_CTRL3,
1180 (reg_val |
1181 MDIO_CL73_USERB0_CL73_BAM_CTRL3_USE_CL73_HCD_MR));
1183 /* Set the CL73 AN speed */
1185 CL45_RD_OVER_CL22(bp, params->port,
1186 params->phy_addr,
1187 MDIO_REG_BANK_CL73_IEEEB1,
1188 MDIO_CL73_IEEEB1_AN_ADV2, &reg_val);
1189 /* In the SerDes we support only the 1G.
1190 In the XGXS we support the 10G KX4
1191 but we currently do not support the KR */
1192 if (vars->phy_flags & PHY_XGXS_FLAG) {
1193 DP(NETIF_MSG_LINK, "XGXS\n");
1194 /* 10G KX4 */
1195 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
1196 } else {
1197 DP(NETIF_MSG_LINK, "SerDes\n");
1198 /* 1000M KX */
1199 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
1201 CL45_WR_OVER_CL22(bp, params->port,
1202 params->phy_addr,
1203 MDIO_REG_BANK_CL73_IEEEB1,
1204 MDIO_CL73_IEEEB1_AN_ADV2, reg_val);
1206 /* CL73 Autoneg Enabled */
1207 reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;
1208 } else {
1209 /* CL73 Autoneg Disabled */
1210 reg_val = 0;
1212 CL45_WR_OVER_CL22(bp, params->port,
1213 params->phy_addr,
1214 MDIO_REG_BANK_CL73_IEEEB0,
1215 MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
1218 /* program SerDes, forced speed */
1219 static void bnx2x_program_serdes(struct link_params *params,
1220 struct link_vars *vars)
1222 struct bnx2x *bp = params->bp;
1223 u16 reg_val;
1225 /* program duplex, disable autoneg */
1227 CL45_RD_OVER_CL22(bp, params->port,
1228 params->phy_addr,
1229 MDIO_REG_BANK_COMBO_IEEE0,
1230 MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1231 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
1232 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN);
1233 if (params->req_duplex == DUPLEX_FULL)
1234 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
1235 CL45_WR_OVER_CL22(bp, params->port,
1236 params->phy_addr,
1237 MDIO_REG_BANK_COMBO_IEEE0,
1238 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1240 /* program speed
1241 - needed only if the speed is greater than 1G (2.5G or 10G) */
1242 CL45_RD_OVER_CL22(bp, params->port,
1243 params->phy_addr,
1244 MDIO_REG_BANK_SERDES_DIGITAL,
1245 MDIO_SERDES_DIGITAL_MISC1, &reg_val);
1246 /* clearing the speed value before setting the right speed */
1247 DP(NETIF_MSG_LINK, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x\n", reg_val);
1249 reg_val &= ~(MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK |
1250 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
1252 if (!((vars->line_speed == SPEED_1000) ||
1253 (vars->line_speed == SPEED_100) ||
1254 (vars->line_speed == SPEED_10))) {
1256 reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M |
1257 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
1258 if (vars->line_speed == SPEED_10000)
1259 reg_val |=
1260 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
1261 if (vars->line_speed == SPEED_13000)
1262 reg_val |=
1263 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
1266 CL45_WR_OVER_CL22(bp, params->port,
1267 params->phy_addr,
1268 MDIO_REG_BANK_SERDES_DIGITAL,
1269 MDIO_SERDES_DIGITAL_MISC1, reg_val);
1273 static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params)
1275 struct bnx2x *bp = params->bp;
1276 u16 val = 0;
1278 /* configure the 48 bits for BAM AN */
1280 /* set extended capabilities */
1281 if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
1282 val |= MDIO_OVER_1G_UP1_2_5G;
1283 if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
1284 val |= MDIO_OVER_1G_UP1_10G;
1285 CL45_WR_OVER_CL22(bp, params->port,
1286 params->phy_addr,
1287 MDIO_REG_BANK_OVER_1G,
1288 MDIO_OVER_1G_UP1, val);
1290 CL45_WR_OVER_CL22(bp, params->port,
1291 params->phy_addr,
1292 MDIO_REG_BANK_OVER_1G,
1293 MDIO_OVER_1G_UP3, 0);
1296 static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u32 *ieee_fc)
1298 *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
1299 /* resolve pause mode and advertisement
1300 * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
1302 switch (params->req_flow_ctrl) {
1303 case FLOW_CTRL_AUTO:
1304 if (params->req_fc_auto_adv == FLOW_CTRL_BOTH) {
1305 *ieee_fc |=
1306 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
1307 } else {
1308 *ieee_fc |=
1309 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1311 break;
1312 case FLOW_CTRL_TX:
1313 *ieee_fc |=
1314 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1315 break;
1317 case FLOW_CTRL_RX:
1318 case FLOW_CTRL_BOTH:
1319 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
1320 break;
1322 case FLOW_CTRL_NONE:
1323 default:
1324 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
1325 break;
1329 static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params,
1330 u32 ieee_fc)
1332 struct bnx2x *bp = params->bp;
1333 /* for AN, we are always publishing full duplex */
1335 CL45_WR_OVER_CL22(bp, params->port,
1336 params->phy_addr,
1337 MDIO_REG_BANK_COMBO_IEEE0,
1338 MDIO_COMBO_IEEE0_AUTO_NEG_ADV, (u16)ieee_fc);
1341 static void bnx2x_restart_autoneg(struct link_params *params)
1343 struct bnx2x *bp = params->bp;
1344 DP(NETIF_MSG_LINK, "bnx2x_restart_autoneg\n");
1345 if (SUPPORT_CL73) {
1346 /* enable and restart clause 73 aneg */
1347 u16 an_ctrl;
1349 CL45_RD_OVER_CL22(bp, params->port,
1350 params->phy_addr,
1351 MDIO_REG_BANK_CL73_IEEEB0,
1352 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1353 &an_ctrl);
1354 CL45_WR_OVER_CL22(bp, params->port,
1355 params->phy_addr,
1356 MDIO_REG_BANK_CL73_IEEEB0,
1357 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1358 (an_ctrl |
1359 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
1360 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
1362 } else {
1363 /* Enable and restart BAM/CL37 aneg */
1364 u16 mii_control;
1366 CL45_RD_OVER_CL22(bp, params->port,
1367 params->phy_addr,
1368 MDIO_REG_BANK_COMBO_IEEE0,
1369 MDIO_COMBO_IEEE0_MII_CONTROL,
1370 &mii_control);
1371 DP(NETIF_MSG_LINK,
1372 "bnx2x_restart_autoneg mii_control before = 0x%x\n",
1373 mii_control);
1374 CL45_WR_OVER_CL22(bp, params->port,
1375 params->phy_addr,
1376 MDIO_REG_BANK_COMBO_IEEE0,
1377 MDIO_COMBO_IEEE0_MII_CONTROL,
1378 (mii_control |
1379 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1380 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
1384 static void bnx2x_initialize_sgmii_process(struct link_params *params,
1385 struct link_vars *vars)
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 (!(vars->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 (vars->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 line_speed 0x%x\n",
1437 vars->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)
1463 { /* LD LP */
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);
1534 if (vars->flow_ctrl == FLOW_CTRL_NONE &&
1535 ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
1536 bnx2x_cl45_read(bp, port,
1537 ext_phy_type,
1538 ext_phy_addr,
1539 MDIO_AN_DEVAD,
1540 MDIO_AN_REG_CL37_FC_LD, &ld_pause);
1542 bnx2x_cl45_read(bp, port,
1543 ext_phy_type,
1544 ext_phy_addr,
1545 MDIO_AN_DEVAD,
1546 MDIO_AN_REG_CL37_FC_LP, &lp_pause);
1547 pause_result = (ld_pause &
1548 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
1549 pause_result |= (lp_pause &
1550 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
1552 bnx2x_pause_resolve(vars, pause_result);
1553 DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x \n",
1554 pause_result);
1557 return ret;
1561 static void bnx2x_flow_ctrl_resolve(struct link_params *params,
1562 struct link_vars *vars,
1563 u32 gp_status)
1565 struct bnx2x *bp = params->bp;
1566 u16 ld_pause; /* local driver */
1567 u16 lp_pause; /* link partner */
1568 u16 pause_result;
1570 vars->flow_ctrl = FLOW_CTRL_NONE;
1572 /* resolve from gp_status in case of AN complete and not sgmii */
1573 if ((params->req_flow_ctrl == FLOW_CTRL_AUTO) &&
1574 (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
1575 (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
1576 (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1577 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) {
1578 CL45_RD_OVER_CL22(bp, params->port,
1579 params->phy_addr,
1580 MDIO_REG_BANK_COMBO_IEEE0,
1581 MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
1582 &ld_pause);
1583 CL45_RD_OVER_CL22(bp, params->port,
1584 params->phy_addr,
1585 MDIO_REG_BANK_COMBO_IEEE0,
1586 MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
1587 &lp_pause);
1588 pause_result = (ld_pause &
1589 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
1590 pause_result |= (lp_pause &
1591 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
1592 DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result);
1593 bnx2x_pause_resolve(vars, pause_result);
1594 } else if ((params->req_flow_ctrl == FLOW_CTRL_AUTO) &&
1595 (bnx2x_ext_phy_resove_fc(params, vars))) {
1596 return;
1597 } else {
1598 if (params->req_flow_ctrl == FLOW_CTRL_AUTO)
1599 vars->flow_ctrl = params->req_fc_auto_adv;
1600 else
1601 vars->flow_ctrl = params->req_flow_ctrl;
1603 DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
1607 static u8 bnx2x_link_settings_status(struct link_params *params,
1608 struct link_vars *vars,
1609 u32 gp_status)
1611 struct bnx2x *bp = params->bp;
1613 u8 rc = 0;
1614 vars->link_status = 0;
1616 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
1617 DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
1618 gp_status);
1620 vars->phy_link_up = 1;
1621 vars->link_status |= LINK_STATUS_LINK_UP;
1623 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
1624 vars->duplex = DUPLEX_FULL;
1625 else
1626 vars->duplex = DUPLEX_HALF;
1628 bnx2x_flow_ctrl_resolve(params, vars, gp_status);
1630 switch (gp_status & GP_STATUS_SPEED_MASK) {
1631 case GP_STATUS_10M:
1632 vars->line_speed = SPEED_10;
1633 if (vars->duplex == DUPLEX_FULL)
1634 vars->link_status |= LINK_10TFD;
1635 else
1636 vars->link_status |= LINK_10THD;
1637 break;
1639 case GP_STATUS_100M:
1640 vars->line_speed = SPEED_100;
1641 if (vars->duplex == DUPLEX_FULL)
1642 vars->link_status |= LINK_100TXFD;
1643 else
1644 vars->link_status |= LINK_100TXHD;
1645 break;
1647 case GP_STATUS_1G:
1648 case GP_STATUS_1G_KX:
1649 vars->line_speed = SPEED_1000;
1650 if (vars->duplex == DUPLEX_FULL)
1651 vars->link_status |= LINK_1000TFD;
1652 else
1653 vars->link_status |= LINK_1000THD;
1654 break;
1656 case GP_STATUS_2_5G:
1657 vars->line_speed = SPEED_2500;
1658 if (vars->duplex == DUPLEX_FULL)
1659 vars->link_status |= LINK_2500TFD;
1660 else
1661 vars->link_status |= LINK_2500THD;
1662 break;
1664 case GP_STATUS_5G:
1665 case GP_STATUS_6G:
1666 DP(NETIF_MSG_LINK,
1667 "link speed unsupported gp_status 0x%x\n",
1668 gp_status);
1669 return -EINVAL;
1670 break;
1671 case GP_STATUS_10G_KX4:
1672 case GP_STATUS_10G_HIG:
1673 case GP_STATUS_10G_CX4:
1674 vars->line_speed = SPEED_10000;
1675 vars->link_status |= LINK_10GTFD;
1676 break;
1678 case GP_STATUS_12G_HIG:
1679 vars->line_speed = SPEED_12000;
1680 vars->link_status |= LINK_12GTFD;
1681 break;
1683 case GP_STATUS_12_5G:
1684 vars->line_speed = SPEED_12500;
1685 vars->link_status |= LINK_12_5GTFD;
1686 break;
1688 case GP_STATUS_13G:
1689 vars->line_speed = SPEED_13000;
1690 vars->link_status |= LINK_13GTFD;
1691 break;
1693 case GP_STATUS_15G:
1694 vars->line_speed = SPEED_15000;
1695 vars->link_status |= LINK_15GTFD;
1696 break;
1698 case GP_STATUS_16G:
1699 vars->line_speed = SPEED_16000;
1700 vars->link_status |= LINK_16GTFD;
1701 break;
1703 default:
1704 DP(NETIF_MSG_LINK,
1705 "link speed unsupported gp_status 0x%x\n",
1706 gp_status);
1707 return -EINVAL;
1708 break;
1711 vars->link_status |= LINK_STATUS_SERDES_LINK;
1713 if ((params->req_line_speed == SPEED_AUTO_NEG) &&
1714 ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1715 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
1716 (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1717 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705))) {
1718 vars->autoneg = AUTO_NEG_ENABLED;
1720 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
1721 vars->autoneg |= AUTO_NEG_COMPLETE;
1722 vars->link_status |=
1723 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
1726 vars->autoneg |= AUTO_NEG_PARALLEL_DETECTION_USED;
1727 vars->link_status |=
1728 LINK_STATUS_PARALLEL_DETECTION_USED;
1731 if (vars->flow_ctrl & FLOW_CTRL_TX)
1732 vars->link_status |=
1733 LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
1735 if (vars->flow_ctrl & FLOW_CTRL_RX)
1736 vars->link_status |=
1737 LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
1739 } else { /* link_down */
1740 DP(NETIF_MSG_LINK, "phy link down\n");
1742 vars->phy_link_up = 0;
1744 vars->duplex = DUPLEX_FULL;
1745 vars->flow_ctrl = FLOW_CTRL_NONE;
1746 vars->autoneg = AUTO_NEG_DISABLED;
1747 vars->mac_type = MAC_TYPE_NONE;
1750 DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x \n",
1751 gp_status, vars->phy_link_up, vars->line_speed);
1752 DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x"
1753 " autoneg 0x%x\n",
1754 vars->duplex,
1755 vars->flow_ctrl, vars->autoneg);
1756 DP(NETIF_MSG_LINK, "link_status 0x%x\n", vars->link_status);
1758 return rc;
1761 static void bnx2x_set_sgmii_tx_driver(struct link_params *params)
1763 struct bnx2x *bp = params->bp;
1764 u16 lp_up2;
1765 u16 tx_driver;
1767 /* read precomp */
1769 CL45_RD_OVER_CL22(bp, params->port,
1770 params->phy_addr,
1771 MDIO_REG_BANK_OVER_1G,
1772 MDIO_OVER_1G_LP_UP2, &lp_up2);
1774 CL45_RD_OVER_CL22(bp, params->port,
1775 params->phy_addr,
1776 MDIO_REG_BANK_TX0,
1777 MDIO_TX0_TX_DRIVER, &tx_driver);
1779 /* bits [10:7] at lp_up2, positioned at [15:12] */
1780 lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >>
1781 MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT) <<
1782 MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT);
1784 if ((lp_up2 != 0) &&
1785 (lp_up2 != (tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK))) {
1786 /* replace tx_driver bits [15:12] */
1787 tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
1788 tx_driver |= lp_up2;
1789 CL45_WR_OVER_CL22(bp, params->port,
1790 params->phy_addr,
1791 MDIO_REG_BANK_TX0,
1792 MDIO_TX0_TX_DRIVER, tx_driver);
1796 static u8 bnx2x_emac_program(struct link_params *params,
1797 u32 line_speed, u32 duplex)
1799 struct bnx2x *bp = params->bp;
1800 u8 port = params->port;
1801 u16 mode = 0;
1803 DP(NETIF_MSG_LINK, "setting link speed & duplex\n");
1804 bnx2x_bits_dis(bp, GRCBASE_EMAC0 + port*0x400 +
1805 EMAC_REG_EMAC_MODE,
1806 (EMAC_MODE_25G_MODE |
1807 EMAC_MODE_PORT_MII_10M |
1808 EMAC_MODE_HALF_DUPLEX));
1809 switch (line_speed) {
1810 case SPEED_10:
1811 mode |= EMAC_MODE_PORT_MII_10M;
1812 break;
1814 case SPEED_100:
1815 mode |= EMAC_MODE_PORT_MII;
1816 break;
1818 case SPEED_1000:
1819 mode |= EMAC_MODE_PORT_GMII;
1820 break;
1822 case SPEED_2500:
1823 mode |= (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_GMII);
1824 break;
1826 default:
1827 /* 10G not valid for EMAC */
1828 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n", line_speed);
1829 return -EINVAL;
1832 if (duplex == DUPLEX_HALF)
1833 mode |= EMAC_MODE_HALF_DUPLEX;
1834 bnx2x_bits_en(bp,
1835 GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
1836 mode);
1838 bnx2x_set_led(bp, params->port, LED_MODE_OPER,
1839 line_speed, params->hw_led_mode, params->chip_id);
1840 return 0;
1843 /*****************************************************************************/
1844 /* External Phy section */
1845 /*****************************************************************************/
1846 static void bnx2x_hw_reset(struct bnx2x *bp, u8 port)
1848 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1849 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
1850 msleep(1);
1851 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1852 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
1855 static void bnx2x_ext_phy_reset(struct link_params *params,
1856 struct link_vars *vars)
1858 struct bnx2x *bp = params->bp;
1859 u32 ext_phy_type;
1860 u8 ext_phy_addr = ((params->ext_phy_config &
1861 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1862 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1863 DP(NETIF_MSG_LINK, "Port %x: bnx2x_ext_phy_reset\n", params->port);
1864 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1865 /* The PHY reset is controled by GPIO 1
1866 * Give it 1ms of reset pulse
1868 if (vars->phy_flags & PHY_XGXS_FLAG) {
1870 switch (ext_phy_type) {
1871 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
1872 DP(NETIF_MSG_LINK, "XGXS Direct\n");
1873 break;
1875 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
1876 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
1877 DP(NETIF_MSG_LINK, "XGXS 8705/8706\n");
1879 /* Restore normal power mode*/
1880 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1881 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1882 params->port);
1884 /* HW reset */
1885 bnx2x_hw_reset(bp, params->port);
1887 bnx2x_cl45_write(bp, params->port,
1888 ext_phy_type,
1889 ext_phy_addr,
1890 MDIO_PMA_DEVAD,
1891 MDIO_PMA_REG_CTRL, 0xa040);
1892 break;
1893 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
1894 /* Unset Low Power Mode and SW reset */
1895 /* Restore normal power mode*/
1896 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1897 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1898 params->port);
1900 DP(NETIF_MSG_LINK, "XGXS 8072\n");
1901 bnx2x_cl45_write(bp, params->port,
1902 ext_phy_type,
1903 ext_phy_addr,
1904 MDIO_PMA_DEVAD,
1905 MDIO_PMA_REG_CTRL,
1906 1<<15);
1907 break;
1908 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
1910 u16 emac_base;
1911 emac_base = (params->port) ? GRCBASE_EMAC0 :
1912 GRCBASE_EMAC1;
1914 /* Restore normal power mode*/
1915 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1916 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1917 params->port);
1919 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1920 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1921 params->port);
1923 DP(NETIF_MSG_LINK, "XGXS 8073\n");
1925 break;
1927 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
1928 DP(NETIF_MSG_LINK, "XGXS SFX7101\n");
1930 /* Restore normal power mode*/
1931 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1932 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1933 params->port);
1935 /* HW reset */
1936 bnx2x_hw_reset(bp, params->port);
1938 break;
1940 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
1941 DP(NETIF_MSG_LINK, "XGXS PHY Failure detected\n");
1942 break;
1944 default:
1945 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
1946 params->ext_phy_config);
1947 break;
1950 } else { /* SerDes */
1951 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
1952 switch (ext_phy_type) {
1953 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
1954 DP(NETIF_MSG_LINK, "SerDes Direct\n");
1955 break;
1957 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
1958 DP(NETIF_MSG_LINK, "SerDes 5482\n");
1959 bnx2x_hw_reset(bp, params->port);
1960 break;
1962 default:
1963 DP(NETIF_MSG_LINK,
1964 "BAD SerDes ext_phy_config 0x%x\n",
1965 params->ext_phy_config);
1966 break;
1971 static void bnx2x_bcm8072_external_rom_boot(struct link_params *params)
1973 struct bnx2x *bp = params->bp;
1974 u8 port = params->port;
1975 u8 ext_phy_addr = ((params->ext_phy_config &
1976 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1977 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1978 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1979 u16 fw_ver1, fw_ver2;
1981 /* Need to wait 200ms after reset */
1982 msleep(200);
1983 /* Boot port from external ROM
1984 * Set ser_boot_ctl bit in the MISC_CTRL1 register
1986 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1987 MDIO_PMA_DEVAD,
1988 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
1990 /* Reset internal microprocessor */
1991 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1992 MDIO_PMA_DEVAD,
1993 MDIO_PMA_REG_GEN_CTRL,
1994 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
1995 /* set micro reset = 0 */
1996 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1997 MDIO_PMA_DEVAD,
1998 MDIO_PMA_REG_GEN_CTRL,
1999 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
2000 /* Reset internal microprocessor */
2001 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2002 MDIO_PMA_DEVAD,
2003 MDIO_PMA_REG_GEN_CTRL,
2004 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2005 /* wait for 100ms for code download via SPI port */
2006 msleep(100);
2008 /* Clear ser_boot_ctl bit */
2009 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2010 MDIO_PMA_DEVAD,
2011 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2012 /* Wait 100ms */
2013 msleep(100);
2015 /* Print the PHY FW version */
2016 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2017 MDIO_PMA_DEVAD,
2018 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
2019 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2020 MDIO_PMA_DEVAD,
2021 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
2022 DP(NETIF_MSG_LINK, "8072 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
2025 static u8 bnx2x_8073_is_snr_needed(struct link_params *params)
2027 /* This is only required for 8073A1, version 102 only */
2029 struct bnx2x *bp = params->bp;
2030 u8 ext_phy_addr = ((params->ext_phy_config &
2031 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2032 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2033 u16 val;
2035 /* Read 8073 HW revision*/
2036 bnx2x_cl45_read(bp, params->port,
2037 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2038 ext_phy_addr,
2039 MDIO_PMA_DEVAD,
2040 0xc801, &val);
2042 if (val != 1) {
2043 /* No need to workaround in 8073 A1 */
2044 return 0;
2047 bnx2x_cl45_read(bp, params->port,
2048 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2049 ext_phy_addr,
2050 MDIO_PMA_DEVAD,
2051 MDIO_PMA_REG_ROM_VER2, &val);
2053 /* SNR should be applied only for version 0x102 */
2054 if (val != 0x102)
2055 return 0;
2057 return 1;
2060 static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
2062 struct bnx2x *bp = params->bp;
2063 u8 ext_phy_addr = ((params->ext_phy_config &
2064 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2065 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2066 u16 val, cnt, cnt1 ;
2068 bnx2x_cl45_read(bp, params->port,
2069 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2070 ext_phy_addr,
2071 MDIO_PMA_DEVAD,
2072 0xc801, &val);
2074 if (val > 0) {
2075 /* No need to workaround in 8073 A1 */
2076 return 0;
2078 /* XAUI workaround in 8073 A0: */
2080 /* After loading the boot ROM and restarting Autoneg,
2081 poll Dev1, Reg $C820: */
2083 for (cnt = 0; cnt < 1000; cnt++) {
2084 bnx2x_cl45_read(bp, params->port,
2085 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2086 ext_phy_addr,
2087 MDIO_PMA_DEVAD,
2088 0xc820, &val);
2089 /* If bit [14] = 0 or bit [13] = 0, continue on with
2090 system initialization (XAUI work-around not required,
2091 as these bits indicate 2.5G or 1G link up). */
2092 if (!(val & (1<<14)) || !(val & (1<<13))) {
2093 DP(NETIF_MSG_LINK, "XAUI work-around not required\n");
2094 return 0;
2095 } else if (!(val & (1<<15))) {
2096 DP(NETIF_MSG_LINK, "clc bit 15 went off\n");
2097 /* If bit 15 is 0, then poll Dev1, Reg $C841 until
2098 it's MSB (bit 15) goes to 1 (indicating that the
2099 XAUI workaround has completed),
2100 then continue on with system initialization.*/
2101 for (cnt1 = 0; cnt1 < 1000; cnt1++) {
2102 bnx2x_cl45_read(bp, params->port,
2103 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2104 ext_phy_addr,
2105 MDIO_PMA_DEVAD,
2106 0xc841, &val);
2107 if (val & (1<<15)) {
2108 DP(NETIF_MSG_LINK,
2109 "XAUI workaround has completed\n");
2110 return 0;
2112 msleep(3);
2114 break;
2116 msleep(3);
2118 DP(NETIF_MSG_LINK, "Warning: XAUI work-around timeout !!!\n");
2119 return -EINVAL;
2123 static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
2124 u8 ext_phy_addr)
2126 u16 fw_ver1, fw_ver2;
2127 /* Boot port from external ROM */
2128 /* EDC grst */
2129 bnx2x_cl45_write(bp, port,
2130 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2131 ext_phy_addr,
2132 MDIO_PMA_DEVAD,
2133 MDIO_PMA_REG_GEN_CTRL,
2134 0x0001);
2136 /* ucode reboot and rst */
2137 bnx2x_cl45_write(bp, port,
2138 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2139 ext_phy_addr,
2140 MDIO_PMA_DEVAD,
2141 MDIO_PMA_REG_GEN_CTRL,
2142 0x008c);
2144 bnx2x_cl45_write(bp, port,
2145 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2146 ext_phy_addr,
2147 MDIO_PMA_DEVAD,
2148 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
2150 /* Reset internal microprocessor */
2151 bnx2x_cl45_write(bp, port,
2152 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2153 ext_phy_addr,
2154 MDIO_PMA_DEVAD,
2155 MDIO_PMA_REG_GEN_CTRL,
2156 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
2158 /* Release srst bit */
2159 bnx2x_cl45_write(bp, port,
2160 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2161 ext_phy_addr,
2162 MDIO_PMA_DEVAD,
2163 MDIO_PMA_REG_GEN_CTRL,
2164 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2166 /* wait for 100ms for code download via SPI port */
2167 msleep(100);
2169 /* Clear ser_boot_ctl bit */
2170 bnx2x_cl45_write(bp, port,
2171 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2172 ext_phy_addr,
2173 MDIO_PMA_DEVAD,
2174 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2176 bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2177 ext_phy_addr,
2178 MDIO_PMA_DEVAD,
2179 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
2180 bnx2x_cl45_read(bp, port,
2181 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2182 ext_phy_addr,
2183 MDIO_PMA_DEVAD,
2184 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
2185 DP(NETIF_MSG_LINK, "8073 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
2189 static void bnx2x_bcm807x_force_10G(struct link_params *params)
2191 struct bnx2x *bp = params->bp;
2192 u8 port = params->port;
2193 u8 ext_phy_addr = ((params->ext_phy_config &
2194 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2195 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2196 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2198 /* Force KR or KX */
2199 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2200 MDIO_PMA_DEVAD,
2201 MDIO_PMA_REG_CTRL,
2202 0x2040);
2203 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2204 MDIO_PMA_DEVAD,
2205 MDIO_PMA_REG_10G_CTRL2,
2206 0x000b);
2207 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2208 MDIO_PMA_DEVAD,
2209 MDIO_PMA_REG_BCM_CTRL,
2210 0x0000);
2211 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2212 MDIO_AN_DEVAD,
2213 MDIO_AN_REG_CTRL,
2214 0x0000);
2216 static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
2218 struct bnx2x *bp = params->bp;
2219 u8 port = params->port;
2220 u16 val;
2221 u8 ext_phy_addr = ((params->ext_phy_config &
2222 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2223 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2224 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2226 bnx2x_cl45_read(bp, params->port,
2227 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2228 ext_phy_addr,
2229 MDIO_PMA_DEVAD,
2230 0xc801, &val);
2232 if (val == 0) {
2233 /* Mustn't set low power mode in 8073 A0 */
2234 return;
2237 /* Disable PLL sequencer (use read-modify-write to clear bit 13) */
2238 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2239 MDIO_XS_DEVAD,
2240 MDIO_XS_PLL_SEQUENCER, &val);
2241 val &= ~(1<<13);
2242 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2243 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
2245 /* PLL controls */
2246 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2247 MDIO_XS_DEVAD, 0x805E, 0x1077);
2248 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2249 MDIO_XS_DEVAD, 0x805D, 0x0000);
2250 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2251 MDIO_XS_DEVAD, 0x805C, 0x030B);
2252 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2253 MDIO_XS_DEVAD, 0x805B, 0x1240);
2254 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2255 MDIO_XS_DEVAD, 0x805A, 0x2490);
2257 /* Tx Controls */
2258 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2259 MDIO_XS_DEVAD, 0x80A7, 0x0C74);
2260 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2261 MDIO_XS_DEVAD, 0x80A6, 0x9041);
2262 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2263 MDIO_XS_DEVAD, 0x80A5, 0x4640);
2265 /* Rx Controls */
2266 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2267 MDIO_XS_DEVAD, 0x80FE, 0x01C4);
2268 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2269 MDIO_XS_DEVAD, 0x80FD, 0x9249);
2270 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2271 MDIO_XS_DEVAD, 0x80FC, 0x2015);
2273 /* Enable PLL sequencer (use read-modify-write to set bit 13) */
2274 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2275 MDIO_XS_DEVAD,
2276 MDIO_XS_PLL_SEQUENCER, &val);
2277 val |= (1<<13);
2278 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2279 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
2282 static void bnx2x_8073_set_pause_cl37(struct link_params *params,
2283 struct link_vars *vars)
2286 struct bnx2x *bp = params->bp;
2287 u16 cl37_val;
2288 u8 ext_phy_addr = ((params->ext_phy_config &
2289 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2290 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2291 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2293 bnx2x_cl45_read(bp, params->port,
2294 ext_phy_type,
2295 ext_phy_addr,
2296 MDIO_AN_DEVAD,
2297 MDIO_AN_REG_CL37_FC_LD, &cl37_val);
2299 cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
2300 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
2302 if ((vars->ieee_fc &
2303 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
2304 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
2305 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
2307 if ((vars->ieee_fc &
2308 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
2309 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
2310 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
2312 if ((vars->ieee_fc &
2313 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
2314 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
2315 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
2317 DP(NETIF_MSG_LINK,
2318 "Ext phy AN advertize cl37 0x%x\n", cl37_val);
2320 bnx2x_cl45_write(bp, params->port,
2321 ext_phy_type,
2322 ext_phy_addr,
2323 MDIO_AN_DEVAD,
2324 MDIO_AN_REG_CL37_FC_LD, cl37_val);
2325 msleep(500);
2328 static void bnx2x_ext_phy_set_pause(struct link_params *params,
2329 struct link_vars *vars)
2331 struct bnx2x *bp = params->bp;
2332 u16 val;
2333 u8 ext_phy_addr = ((params->ext_phy_config &
2334 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2335 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2336 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2338 /* read modify write pause advertizing */
2339 bnx2x_cl45_read(bp, params->port,
2340 ext_phy_type,
2341 ext_phy_addr,
2342 MDIO_AN_DEVAD,
2343 MDIO_AN_REG_ADV_PAUSE, &val);
2345 val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
2347 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
2349 if ((vars->ieee_fc &
2350 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
2351 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
2352 val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
2354 if ((vars->ieee_fc &
2355 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
2356 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
2357 val |=
2358 MDIO_AN_REG_ADV_PAUSE_PAUSE;
2360 DP(NETIF_MSG_LINK,
2361 "Ext phy AN advertize 0x%x\n", val);
2362 bnx2x_cl45_write(bp, params->port,
2363 ext_phy_type,
2364 ext_phy_addr,
2365 MDIO_AN_DEVAD,
2366 MDIO_AN_REG_ADV_PAUSE, val);
2370 static void bnx2x_init_internal_phy(struct link_params *params,
2371 struct link_vars *vars)
2373 struct bnx2x *bp = params->bp;
2374 u8 port = params->port;
2375 if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
2376 u16 bank, rx_eq;
2378 rx_eq = ((params->serdes_config &
2379 PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK) >>
2380 PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT);
2382 DP(NETIF_MSG_LINK, "setting rx eq to 0x%x\n", rx_eq);
2383 for (bank = MDIO_REG_BANK_RX0; bank <= MDIO_REG_BANK_RX_ALL;
2384 bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0)) {
2385 CL45_WR_OVER_CL22(bp, port,
2386 params->phy_addr,
2387 bank ,
2388 MDIO_RX0_RX_EQ_BOOST,
2389 ((rx_eq &
2390 MDIO_RX0_RX_EQ_BOOST_EQUALIZER_CTRL_MASK) |
2391 MDIO_RX0_RX_EQ_BOOST_OFFSET_CTRL));
2394 /* forced speed requested? */
2395 if (vars->line_speed != SPEED_AUTO_NEG) {
2396 DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
2398 /* disable autoneg */
2399 bnx2x_set_autoneg(params, vars);
2401 /* program speed and duplex */
2402 bnx2x_program_serdes(params, vars);
2404 } else { /* AN_mode */
2405 DP(NETIF_MSG_LINK, "not SGMII, AN\n");
2407 /* AN enabled */
2408 bnx2x_set_brcm_cl37_advertisment(params);
2410 /* program duplex & pause advertisement (for aneg) */
2411 bnx2x_set_ieee_aneg_advertisment(params,
2412 vars->ieee_fc);
2414 /* enable autoneg */
2415 bnx2x_set_autoneg(params, vars);
2417 /* enable and restart AN */
2418 bnx2x_restart_autoneg(params);
2421 } else { /* SGMII mode */
2422 DP(NETIF_MSG_LINK, "SGMII\n");
2424 bnx2x_initialize_sgmii_process(params, vars);
2428 static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
2430 struct bnx2x *bp = params->bp;
2431 u32 ext_phy_type;
2432 u8 ext_phy_addr;
2433 u16 cnt;
2434 u16 ctrl = 0;
2435 u16 val = 0;
2436 u8 rc = 0;
2437 if (vars->phy_flags & PHY_XGXS_FLAG) {
2438 ext_phy_addr = ((params->ext_phy_config &
2439 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2440 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2442 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2443 /* Make sure that the soft reset is off (expect for the 8072:
2444 * due to the lock, it will be done inside the specific
2445 * handling)
2447 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
2448 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
2449 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) &&
2450 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
2451 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
2452 /* Wait for soft reset to get cleared upto 1 sec */
2453 for (cnt = 0; cnt < 1000; cnt++) {
2454 bnx2x_cl45_read(bp, params->port,
2455 ext_phy_type,
2456 ext_phy_addr,
2457 MDIO_PMA_DEVAD,
2458 MDIO_PMA_REG_CTRL, &ctrl);
2459 if (!(ctrl & (1<<15)))
2460 break;
2461 msleep(1);
2463 DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n",
2464 ctrl, cnt);
2467 switch (ext_phy_type) {
2468 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
2469 break;
2471 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2472 DP(NETIF_MSG_LINK, "XGXS 8705\n");
2474 bnx2x_cl45_write(bp, params->port,
2475 ext_phy_type,
2476 ext_phy_addr,
2477 MDIO_PMA_DEVAD,
2478 MDIO_PMA_REG_MISC_CTRL,
2479 0x8288);
2480 bnx2x_cl45_write(bp, params->port,
2481 ext_phy_type,
2482 ext_phy_addr,
2483 MDIO_PMA_DEVAD,
2484 MDIO_PMA_REG_PHY_IDENTIFIER,
2485 0x7fbf);
2486 bnx2x_cl45_write(bp, params->port,
2487 ext_phy_type,
2488 ext_phy_addr,
2489 MDIO_PMA_DEVAD,
2490 MDIO_PMA_REG_CMU_PLL_BYPASS,
2491 0x0100);
2492 bnx2x_cl45_write(bp, params->port,
2493 ext_phy_type,
2494 ext_phy_addr,
2495 MDIO_WIS_DEVAD,
2496 MDIO_WIS_REG_LASI_CNTL, 0x1);
2497 break;
2499 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2500 DP(NETIF_MSG_LINK, "XGXS 8706\n");
2502 msleep(10);
2503 /* Force speed */
2504 /* First enable LASI */
2505 bnx2x_cl45_write(bp, params->port,
2506 ext_phy_type,
2507 ext_phy_addr,
2508 MDIO_PMA_DEVAD,
2509 MDIO_PMA_REG_RX_ALARM_CTRL,
2510 0x0400);
2511 bnx2x_cl45_write(bp, params->port,
2512 ext_phy_type,
2513 ext_phy_addr,
2514 MDIO_PMA_DEVAD,
2515 MDIO_PMA_REG_LASI_CTRL, 0x0004);
2517 if (params->req_line_speed == SPEED_10000) {
2518 DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n");
2520 bnx2x_cl45_write(bp, params->port,
2521 ext_phy_type,
2522 ext_phy_addr,
2523 MDIO_PMA_DEVAD,
2524 MDIO_PMA_REG_DIGITAL_CTRL,
2525 0x400);
2526 } else {
2527 /* Force 1Gbps using autoneg with 1G
2528 advertisment */
2530 /* Allow CL37 through CL73 */
2531 DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
2532 bnx2x_cl45_write(bp, params->port,
2533 ext_phy_type,
2534 ext_phy_addr,
2535 MDIO_AN_DEVAD,
2536 MDIO_AN_REG_CL37_CL73,
2537 0x040c);
2539 /* Enable Full-Duplex advertisment on CL37 */
2540 bnx2x_cl45_write(bp, params->port,
2541 ext_phy_type,
2542 ext_phy_addr,
2543 MDIO_AN_DEVAD,
2544 MDIO_AN_REG_CL37_FC_LP,
2545 0x0020);
2546 /* Enable CL37 AN */
2547 bnx2x_cl45_write(bp, params->port,
2548 ext_phy_type,
2549 ext_phy_addr,
2550 MDIO_AN_DEVAD,
2551 MDIO_AN_REG_CL37_AN,
2552 0x1000);
2553 /* 1G support */
2554 bnx2x_cl45_write(bp, params->port,
2555 ext_phy_type,
2556 ext_phy_addr,
2557 MDIO_AN_DEVAD,
2558 MDIO_AN_REG_ADV, (1<<5));
2560 /* Enable clause 73 AN */
2561 bnx2x_cl45_write(bp, params->port,
2562 ext_phy_type,
2563 ext_phy_addr,
2564 MDIO_AN_DEVAD,
2565 MDIO_AN_REG_CTRL,
2566 0x1200);
2570 break;
2572 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2573 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2575 u16 tmp1;
2576 u16 rx_alarm_ctrl_val;
2577 u16 lasi_ctrl_val;
2578 if (ext_phy_type ==
2579 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
2580 rx_alarm_ctrl_val = 0x400;
2581 lasi_ctrl_val = 0x0004;
2582 } else {
2583 rx_alarm_ctrl_val = (1<<2);
2584 lasi_ctrl_val = 0x0004;
2587 /* enable LASI */
2588 bnx2x_cl45_write(bp, params->port,
2589 ext_phy_type,
2590 ext_phy_addr,
2591 MDIO_PMA_DEVAD,
2592 MDIO_PMA_REG_RX_ALARM_CTRL,
2593 rx_alarm_ctrl_val);
2595 bnx2x_cl45_write(bp, params->port,
2596 ext_phy_type,
2597 ext_phy_addr,
2598 MDIO_PMA_DEVAD,
2599 MDIO_PMA_REG_LASI_CTRL,
2600 lasi_ctrl_val);
2602 bnx2x_8073_set_pause_cl37(params, vars);
2604 if (ext_phy_type ==
2605 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072){
2606 bnx2x_bcm8072_external_rom_boot(params);
2607 } else {
2609 /* In case of 8073 with long xaui lines,
2610 don't set the 8073 xaui low power*/
2611 bnx2x_bcm8073_set_xaui_low_power_mode(params);
2614 bnx2x_cl45_read(bp, params->port,
2615 ext_phy_type,
2616 ext_phy_addr,
2617 MDIO_PMA_DEVAD,
2618 0xca13,
2619 &tmp1);
2621 bnx2x_cl45_read(bp, params->port,
2622 ext_phy_type,
2623 ext_phy_addr,
2624 MDIO_PMA_DEVAD,
2625 MDIO_PMA_REG_RX_ALARM, &tmp1);
2627 DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1):"
2628 "0x%x\n", tmp1);
2630 /* If this is forced speed, set to KR or KX
2631 * (all other are not supported)
2633 if (params->loopback_mode == LOOPBACK_EXT) {
2634 bnx2x_bcm807x_force_10G(params);
2635 DP(NETIF_MSG_LINK,
2636 "Forced speed 10G on 807X\n");
2637 break;
2638 } else {
2639 bnx2x_cl45_write(bp, params->port,
2640 ext_phy_type, ext_phy_addr,
2641 MDIO_PMA_DEVAD,
2642 MDIO_PMA_REG_BCM_CTRL,
2643 0x0002);
2645 if (params->req_line_speed != SPEED_AUTO_NEG) {
2646 if (params->req_line_speed == SPEED_10000) {
2647 val = (1<<7);
2648 } else if (params->req_line_speed ==
2649 SPEED_2500) {
2650 val = (1<<5);
2651 /* Note that 2.5G works only
2652 when used with 1G advertisment */
2653 } else
2654 val = (1<<5);
2655 } else {
2657 val = 0;
2658 if (params->speed_cap_mask &
2659 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
2660 val |= (1<<7);
2662 /* Note that 2.5G works only when
2663 used with 1G advertisment */
2664 if (params->speed_cap_mask &
2665 (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
2666 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
2667 val |= (1<<5);
2668 DP(NETIF_MSG_LINK,
2669 "807x autoneg val = 0x%x\n", val);
2672 bnx2x_cl45_write(bp, params->port,
2673 ext_phy_type,
2674 ext_phy_addr,
2675 MDIO_AN_DEVAD,
2676 MDIO_AN_REG_ADV, val);
2678 if (ext_phy_type ==
2679 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
2681 bnx2x_cl45_read(bp, params->port,
2682 ext_phy_type,
2683 ext_phy_addr,
2684 MDIO_AN_DEVAD,
2685 0x8329, &tmp1);
2687 if (((params->speed_cap_mask &
2688 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
2689 (params->req_line_speed ==
2690 SPEED_AUTO_NEG)) ||
2691 (params->req_line_speed ==
2692 SPEED_2500)) {
2693 u16 phy_ver;
2694 /* Allow 2.5G for A1 and above */
2695 bnx2x_cl45_read(bp, params->port,
2696 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2697 ext_phy_addr,
2698 MDIO_PMA_DEVAD,
2699 0xc801, &phy_ver);
2700 DP(NETIF_MSG_LINK, "Add 2.5G\n");
2701 if (phy_ver > 0)
2702 tmp1 |= 1;
2703 else
2704 tmp1 &= 0xfffe;
2705 } else {
2706 DP(NETIF_MSG_LINK, "Disable 2.5G\n");
2707 tmp1 &= 0xfffe;
2710 bnx2x_cl45_write(bp, params->port,
2711 ext_phy_type,
2712 ext_phy_addr,
2713 MDIO_AN_DEVAD,
2714 0x8329, tmp1);
2717 /* Add support for CL37 (passive mode) II */
2719 bnx2x_cl45_read(bp, params->port,
2720 ext_phy_type,
2721 ext_phy_addr,
2722 MDIO_AN_DEVAD,
2723 MDIO_AN_REG_CL37_FC_LD,
2724 &tmp1);
2726 bnx2x_cl45_write(bp, params->port,
2727 ext_phy_type,
2728 ext_phy_addr,
2729 MDIO_AN_DEVAD,
2730 MDIO_AN_REG_CL37_FC_LD, (tmp1 |
2731 ((params->req_duplex == DUPLEX_FULL) ?
2732 0x20 : 0x40)));
2734 /* Add support for CL37 (passive mode) III */
2735 bnx2x_cl45_write(bp, params->port,
2736 ext_phy_type,
2737 ext_phy_addr,
2738 MDIO_AN_DEVAD,
2739 MDIO_AN_REG_CL37_AN, 0x1000);
2741 if (ext_phy_type ==
2742 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
2743 /* The SNR will improve about 2db by changing
2744 BW and FEE main tap. Rest commands are executed
2745 after link is up*/
2746 /*Change FFE main cursor to 5 in EDC register*/
2747 if (bnx2x_8073_is_snr_needed(params))
2748 bnx2x_cl45_write(bp, params->port,
2749 ext_phy_type,
2750 ext_phy_addr,
2751 MDIO_PMA_DEVAD,
2752 MDIO_PMA_REG_EDC_FFE_MAIN,
2753 0xFB0C);
2755 /* Enable FEC (Forware Error Correction)
2756 Request in the AN */
2757 bnx2x_cl45_read(bp, params->port,
2758 ext_phy_type,
2759 ext_phy_addr,
2760 MDIO_AN_DEVAD,
2761 MDIO_AN_REG_ADV2, &tmp1);
2763 tmp1 |= (1<<15);
2765 bnx2x_cl45_write(bp, params->port,
2766 ext_phy_type,
2767 ext_phy_addr,
2768 MDIO_AN_DEVAD,
2769 MDIO_AN_REG_ADV2, tmp1);
2773 bnx2x_ext_phy_set_pause(params, vars);
2775 /* Restart autoneg */
2776 msleep(500);
2777 bnx2x_cl45_write(bp, params->port,
2778 ext_phy_type,
2779 ext_phy_addr,
2780 MDIO_AN_DEVAD,
2781 MDIO_AN_REG_CTRL, 0x1200);
2782 DP(NETIF_MSG_LINK, "807x Autoneg Restart: "
2783 "Advertise 1G=%x, 10G=%x\n",
2784 ((val & (1<<5)) > 0),
2785 ((val & (1<<7)) > 0));
2786 break;
2788 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
2789 DP(NETIF_MSG_LINK,
2790 "Setting the SFX7101 LASI indication\n");
2792 bnx2x_cl45_write(bp, params->port,
2793 ext_phy_type,
2794 ext_phy_addr,
2795 MDIO_PMA_DEVAD,
2796 MDIO_PMA_REG_LASI_CTRL, 0x1);
2797 DP(NETIF_MSG_LINK,
2798 "Setting the SFX7101 LED to blink on traffic\n");
2799 bnx2x_cl45_write(bp, params->port,
2800 ext_phy_type,
2801 ext_phy_addr,
2802 MDIO_PMA_DEVAD,
2803 MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
2805 bnx2x_ext_phy_set_pause(params, vars);
2806 /* Restart autoneg */
2807 bnx2x_cl45_read(bp, params->port,
2808 ext_phy_type,
2809 ext_phy_addr,
2810 MDIO_AN_DEVAD,
2811 MDIO_AN_REG_CTRL, &val);
2812 val |= 0x200;
2813 bnx2x_cl45_write(bp, params->port,
2814 ext_phy_type,
2815 ext_phy_addr,
2816 MDIO_AN_DEVAD,
2817 MDIO_AN_REG_CTRL, val);
2818 break;
2819 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
2820 DP(NETIF_MSG_LINK,
2821 "XGXS PHY Failure detected 0x%x\n",
2822 params->ext_phy_config);
2823 rc = -EINVAL;
2824 break;
2825 default:
2826 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
2827 params->ext_phy_config);
2828 rc = -EINVAL;
2829 break;
2832 } else { /* SerDes */
2834 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
2835 switch (ext_phy_type) {
2836 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
2837 DP(NETIF_MSG_LINK, "SerDes Direct\n");
2838 break;
2840 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
2841 DP(NETIF_MSG_LINK, "SerDes 5482\n");
2842 break;
2844 default:
2845 DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
2846 params->ext_phy_config);
2847 break;
2850 return rc;
2854 static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
2855 struct link_vars *vars)
2857 struct bnx2x *bp = params->bp;
2858 u32 ext_phy_type;
2859 u8 ext_phy_addr;
2860 u16 val1 = 0, val2;
2861 u16 rx_sd, pcs_status;
2862 u8 ext_phy_link_up = 0;
2863 u8 port = params->port;
2864 if (vars->phy_flags & PHY_XGXS_FLAG) {
2865 ext_phy_addr = ((params->ext_phy_config &
2866 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2867 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2869 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2870 switch (ext_phy_type) {
2871 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
2872 DP(NETIF_MSG_LINK, "XGXS Direct\n");
2873 ext_phy_link_up = 1;
2874 break;
2876 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2877 DP(NETIF_MSG_LINK, "XGXS 8705\n");
2878 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2879 ext_phy_addr,
2880 MDIO_WIS_DEVAD,
2881 MDIO_WIS_REG_LASI_STATUS, &val1);
2882 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
2884 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2885 ext_phy_addr,
2886 MDIO_WIS_DEVAD,
2887 MDIO_WIS_REG_LASI_STATUS, &val1);
2888 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
2890 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2891 ext_phy_addr,
2892 MDIO_PMA_DEVAD,
2893 MDIO_PMA_REG_RX_SD, &rx_sd);
2894 DP(NETIF_MSG_LINK, "8705 rx_sd 0x%x\n", rx_sd);
2895 ext_phy_link_up = (rx_sd & 0x1);
2896 if (ext_phy_link_up)
2897 vars->line_speed = SPEED_10000;
2898 break;
2900 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2901 DP(NETIF_MSG_LINK, "XGXS 8706\n");
2902 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2903 ext_phy_addr,
2904 MDIO_PMA_DEVAD,
2905 MDIO_PMA_REG_LASI_STATUS, &val1);
2906 DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
2908 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2909 ext_phy_addr,
2910 MDIO_PMA_DEVAD,
2911 MDIO_PMA_REG_LASI_STATUS, &val1);
2912 DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
2914 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2915 ext_phy_addr,
2916 MDIO_PMA_DEVAD,
2917 MDIO_PMA_REG_RX_SD, &rx_sd);
2918 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2919 ext_phy_addr,
2920 MDIO_PCS_DEVAD,
2921 MDIO_PCS_REG_STATUS, &pcs_status);
2923 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2924 ext_phy_addr,
2925 MDIO_AN_DEVAD,
2926 MDIO_AN_REG_LINK_STATUS, &val2);
2927 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2928 ext_phy_addr,
2929 MDIO_AN_DEVAD,
2930 MDIO_AN_REG_LINK_STATUS, &val2);
2932 DP(NETIF_MSG_LINK, "8706 rx_sd 0x%x"
2933 " pcs_status 0x%x 1Gbps link_status 0x%x\n",
2934 rx_sd, pcs_status, val2);
2935 /* link is up if both bit 0 of pmd_rx_sd and
2936 * bit 0 of pcs_status are set, or if the autoneg bit
2937 1 is set
2939 ext_phy_link_up = ((rx_sd & pcs_status & 0x1) ||
2940 (val2 & (1<<1)));
2941 if (ext_phy_link_up) {
2942 if (val2 & (1<<1))
2943 vars->line_speed = SPEED_1000;
2944 else
2945 vars->line_speed = SPEED_10000;
2948 /* clear LASI indication*/
2949 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2950 ext_phy_addr,
2951 MDIO_PMA_DEVAD,
2952 MDIO_PMA_REG_RX_ALARM, &val2);
2953 break;
2955 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2956 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2958 u16 link_status = 0;
2959 u16 an1000_status = 0;
2960 if (ext_phy_type ==
2961 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
2962 bnx2x_cl45_read(bp, params->port,
2963 ext_phy_type,
2964 ext_phy_addr,
2965 MDIO_PCS_DEVAD,
2966 MDIO_PCS_REG_LASI_STATUS, &val1);
2967 bnx2x_cl45_read(bp, params->port,
2968 ext_phy_type,
2969 ext_phy_addr,
2970 MDIO_PCS_DEVAD,
2971 MDIO_PCS_REG_LASI_STATUS, &val2);
2972 DP(NETIF_MSG_LINK,
2973 "870x LASI status 0x%x->0x%x\n",
2974 val1, val2);
2976 } else {
2977 /* In 8073, port1 is directed through emac0 and
2978 * port0 is directed through emac1
2980 bnx2x_cl45_read(bp, params->port,
2981 ext_phy_type,
2982 ext_phy_addr,
2983 MDIO_PMA_DEVAD,
2984 MDIO_PMA_REG_LASI_STATUS, &val1);
2986 DP(NETIF_MSG_LINK,
2987 "8703 LASI status 0x%x\n",
2988 val1);
2991 /* clear the interrupt LASI status register */
2992 bnx2x_cl45_read(bp, params->port,
2993 ext_phy_type,
2994 ext_phy_addr,
2995 MDIO_PCS_DEVAD,
2996 MDIO_PCS_REG_STATUS, &val2);
2997 bnx2x_cl45_read(bp, params->port,
2998 ext_phy_type,
2999 ext_phy_addr,
3000 MDIO_PCS_DEVAD,
3001 MDIO_PCS_REG_STATUS, &val1);
3002 DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n",
3003 val2, val1);
3004 /* Clear MSG-OUT */
3005 bnx2x_cl45_read(bp, params->port,
3006 ext_phy_type,
3007 ext_phy_addr,
3008 MDIO_PMA_DEVAD,
3009 0xca13,
3010 &val1);
3012 /* Check the LASI */
3013 bnx2x_cl45_read(bp, params->port,
3014 ext_phy_type,
3015 ext_phy_addr,
3016 MDIO_PMA_DEVAD,
3017 MDIO_PMA_REG_RX_ALARM, &val2);
3019 DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
3021 /* Check the link status */
3022 bnx2x_cl45_read(bp, params->port,
3023 ext_phy_type,
3024 ext_phy_addr,
3025 MDIO_PCS_DEVAD,
3026 MDIO_PCS_REG_STATUS, &val2);
3027 DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
3029 bnx2x_cl45_read(bp, params->port,
3030 ext_phy_type,
3031 ext_phy_addr,
3032 MDIO_PMA_DEVAD,
3033 MDIO_PMA_REG_STATUS, &val2);
3034 bnx2x_cl45_read(bp, params->port,
3035 ext_phy_type,
3036 ext_phy_addr,
3037 MDIO_PMA_DEVAD,
3038 MDIO_PMA_REG_STATUS, &val1);
3039 ext_phy_link_up = ((val1 & 4) == 4);
3040 DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
3041 if (ext_phy_type ==
3042 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
3044 if (ext_phy_link_up &&
3045 ((params->req_line_speed !=
3046 SPEED_10000))) {
3047 if (bnx2x_bcm8073_xaui_wa(params)
3048 != 0) {
3049 ext_phy_link_up = 0;
3050 break;
3053 bnx2x_cl45_read(bp, params->port,
3054 ext_phy_type,
3055 ext_phy_addr,
3056 MDIO_AN_DEVAD,
3057 0x8304,
3058 &an1000_status);
3059 bnx2x_cl45_read(bp, params->port,
3060 ext_phy_type,
3061 ext_phy_addr,
3062 MDIO_AN_DEVAD,
3063 0x8304,
3064 &an1000_status);
3066 /* Check the link status on 1.1.2 */
3067 bnx2x_cl45_read(bp, params->port,
3068 ext_phy_type,
3069 ext_phy_addr,
3070 MDIO_PMA_DEVAD,
3071 MDIO_PMA_REG_STATUS, &val2);
3072 bnx2x_cl45_read(bp, params->port,
3073 ext_phy_type,
3074 ext_phy_addr,
3075 MDIO_PMA_DEVAD,
3076 MDIO_PMA_REG_STATUS, &val1);
3077 DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x,"
3078 "an_link_status=0x%x\n",
3079 val2, val1, an1000_status);
3081 ext_phy_link_up = (((val1 & 4) == 4) ||
3082 (an1000_status & (1<<1)));
3083 if (ext_phy_link_up &&
3084 bnx2x_8073_is_snr_needed(params)) {
3085 /* The SNR will improve about 2dbby
3086 changing the BW and FEE main tap.*/
3088 /* The 1st write to change FFE main
3089 tap is set before restart AN */
3090 /* Change PLL Bandwidth in EDC
3091 register */
3092 bnx2x_cl45_write(bp, port, ext_phy_type,
3093 ext_phy_addr,
3094 MDIO_PMA_DEVAD,
3095 MDIO_PMA_REG_PLL_BANDWIDTH,
3096 0x26BC);
3098 /* Change CDR Bandwidth in EDC
3099 register */
3100 bnx2x_cl45_write(bp, port, ext_phy_type,
3101 ext_phy_addr,
3102 MDIO_PMA_DEVAD,
3103 MDIO_PMA_REG_CDR_BANDWIDTH,
3104 0x0333);
3108 bnx2x_cl45_read(bp, params->port,
3109 ext_phy_type,
3110 ext_phy_addr,
3111 MDIO_PMA_DEVAD,
3112 0xc820,
3113 &link_status);
3115 /* Bits 0..2 --> speed detected,
3116 bits 13..15--> link is down */
3117 if ((link_status & (1<<2)) &&
3118 (!(link_status & (1<<15)))) {
3119 ext_phy_link_up = 1;
3120 vars->line_speed = SPEED_10000;
3121 DP(NETIF_MSG_LINK,
3122 "port %x: External link"
3123 " up in 10G\n", params->port);
3124 } else if ((link_status & (1<<1)) &&
3125 (!(link_status & (1<<14)))) {
3126 ext_phy_link_up = 1;
3127 vars->line_speed = SPEED_2500;
3128 DP(NETIF_MSG_LINK,
3129 "port %x: External link"
3130 " up in 2.5G\n", params->port);
3131 } else if ((link_status & (1<<0)) &&
3132 (!(link_status & (1<<13)))) {
3133 ext_phy_link_up = 1;
3134 vars->line_speed = SPEED_1000;
3135 DP(NETIF_MSG_LINK,
3136 "port %x: External link"
3137 " up in 1G\n", params->port);
3138 } else {
3139 ext_phy_link_up = 0;
3140 DP(NETIF_MSG_LINK,
3141 "port %x: External link"
3142 " is down\n", params->port);
3144 } else {
3145 /* See if 1G link is up for the 8072 */
3146 bnx2x_cl45_read(bp, params->port,
3147 ext_phy_type,
3148 ext_phy_addr,
3149 MDIO_AN_DEVAD,
3150 0x8304,
3151 &an1000_status);
3152 bnx2x_cl45_read(bp, params->port,
3153 ext_phy_type,
3154 ext_phy_addr,
3155 MDIO_AN_DEVAD,
3156 0x8304,
3157 &an1000_status);
3158 if (an1000_status & (1<<1)) {
3159 ext_phy_link_up = 1;
3160 vars->line_speed = SPEED_1000;
3161 DP(NETIF_MSG_LINK,
3162 "port %x: External link"
3163 " up in 1G\n", params->port);
3164 } else if (ext_phy_link_up) {
3165 ext_phy_link_up = 1;
3166 vars->line_speed = SPEED_10000;
3167 DP(NETIF_MSG_LINK,
3168 "port %x: External link"
3169 " up in 10G\n", params->port);
3174 break;
3176 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3177 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3178 ext_phy_addr,
3179 MDIO_PMA_DEVAD,
3180 MDIO_PMA_REG_LASI_STATUS, &val2);
3181 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3182 ext_phy_addr,
3183 MDIO_PMA_DEVAD,
3184 MDIO_PMA_REG_LASI_STATUS, &val1);
3185 DP(NETIF_MSG_LINK,
3186 "10G-base-T LASI status 0x%x->0x%x\n",
3187 val2, val1);
3188 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3189 ext_phy_addr,
3190 MDIO_PMA_DEVAD,
3191 MDIO_PMA_REG_STATUS, &val2);
3192 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3193 ext_phy_addr,
3194 MDIO_PMA_DEVAD,
3195 MDIO_PMA_REG_STATUS, &val1);
3196 DP(NETIF_MSG_LINK,
3197 "10G-base-T PMA status 0x%x->0x%x\n",
3198 val2, val1);
3199 ext_phy_link_up = ((val1 & 4) == 4);
3200 /* if link is up
3201 * print the AN outcome of the SFX7101 PHY
3203 if (ext_phy_link_up) {
3204 bnx2x_cl45_read(bp, params->port,
3205 ext_phy_type,
3206 ext_phy_addr,
3207 MDIO_AN_DEVAD,
3208 MDIO_AN_REG_MASTER_STATUS,
3209 &val2);
3210 vars->line_speed = SPEED_10000;
3211 DP(NETIF_MSG_LINK,
3212 "SFX7101 AN status 0x%x->Master=%x\n",
3213 val2,
3214 (val2 & (1<<14)));
3216 break;
3218 default:
3219 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
3220 params->ext_phy_config);
3221 ext_phy_link_up = 0;
3222 break;
3225 } else { /* SerDes */
3226 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3227 switch (ext_phy_type) {
3228 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
3229 DP(NETIF_MSG_LINK, "SerDes Direct\n");
3230 ext_phy_link_up = 1;
3231 break;
3233 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
3234 DP(NETIF_MSG_LINK, "SerDes 5482\n");
3235 ext_phy_link_up = 1;
3236 break;
3238 default:
3239 DP(NETIF_MSG_LINK,
3240 "BAD SerDes ext_phy_config 0x%x\n",
3241 params->ext_phy_config);
3242 ext_phy_link_up = 0;
3243 break;
3247 return ext_phy_link_up;
3250 static void bnx2x_link_int_enable(struct link_params *params)
3252 u8 port = params->port;
3253 u32 ext_phy_type;
3254 u32 mask;
3255 struct bnx2x *bp = params->bp;
3256 /* setting the status to report on link up
3257 for either XGXS or SerDes */
3259 if (params->switch_cfg == SWITCH_CFG_10G) {
3260 mask = (NIG_MASK_XGXS0_LINK10G |
3261 NIG_MASK_XGXS0_LINK_STATUS);
3262 DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
3263 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3264 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
3265 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
3266 (ext_phy_type !=
3267 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) {
3268 mask |= NIG_MASK_MI_INT;
3269 DP(NETIF_MSG_LINK, "enabled external phy int\n");
3272 } else { /* SerDes */
3273 mask = NIG_MASK_SERDES0_LINK_STATUS;
3274 DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n");
3275 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3276 if ((ext_phy_type !=
3277 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
3278 (ext_phy_type !=
3279 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN)) {
3280 mask |= NIG_MASK_MI_INT;
3281 DP(NETIF_MSG_LINK, "enabled external phy int\n");
3284 bnx2x_bits_en(bp,
3285 NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
3286 mask);
3287 DP(NETIF_MSG_LINK, "port %x, is_xgxs=%x, int_status 0x%x\n", port,
3288 (params->switch_cfg == SWITCH_CFG_10G),
3289 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
3291 DP(NETIF_MSG_LINK, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n",
3292 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
3293 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
3294 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS+port*0x3c));
3295 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
3296 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
3297 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
3302 * link management
3304 static void bnx2x_link_int_ack(struct link_params *params,
3305 struct link_vars *vars, u8 is_10g)
3307 struct bnx2x *bp = params->bp;
3308 u8 port = params->port;
3310 /* first reset all status
3311 * we assume only one line will be change at a time */
3312 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3313 (NIG_STATUS_XGXS0_LINK10G |
3314 NIG_STATUS_XGXS0_LINK_STATUS |
3315 NIG_STATUS_SERDES0_LINK_STATUS));
3316 if (vars->phy_link_up) {
3317 if (is_10g) {
3318 /* Disable the 10G link interrupt
3319 * by writing 1 to the status register
3321 DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
3322 bnx2x_bits_en(bp,
3323 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3324 NIG_STATUS_XGXS0_LINK10G);
3326 } else if (params->switch_cfg == SWITCH_CFG_10G) {
3327 /* Disable the link interrupt
3328 * by writing 1 to the relevant lane
3329 * in the status register
3331 u32 ser_lane = ((params->lane_config &
3332 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
3333 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
3335 DP(NETIF_MSG_LINK, "1G XGXS phy link up\n");
3336 bnx2x_bits_en(bp,
3337 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3338 ((1 << ser_lane) <<
3339 NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
3341 } else { /* SerDes */
3342 DP(NETIF_MSG_LINK, "SerDes phy link up\n");
3343 /* Disable the link interrupt
3344 * by writing 1 to the status register
3346 bnx2x_bits_en(bp,
3347 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3348 NIG_STATUS_SERDES0_LINK_STATUS);
3351 } else { /* link_down */
3355 static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len)
3357 u8 *str_ptr = str;
3358 u32 mask = 0xf0000000;
3359 u8 shift = 8*4;
3360 u8 digit;
3361 if (len < 10) {
3362 /* Need more then 10chars for this format */
3363 *str_ptr = '\0';
3364 return -EINVAL;
3366 while (shift > 0) {
3368 shift -= 4;
3369 digit = ((num & mask) >> shift);
3370 if (digit < 0xa)
3371 *str_ptr = digit + '0';
3372 else
3373 *str_ptr = digit - 0xa + 'a';
3374 str_ptr++;
3375 mask = mask >> 4;
3376 if (shift == 4*4) {
3377 *str_ptr = ':';
3378 str_ptr++;
3381 *str_ptr = '\0';
3382 return 0;
3386 static void bnx2x_turn_on_ef(struct bnx2x *bp, u8 port, u8 ext_phy_addr,
3387 u32 ext_phy_type)
3389 u32 cnt = 0;
3390 u16 ctrl = 0;
3391 /* Enable EMAC0 in to enable MDIO */
3392 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
3393 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
3394 msleep(5);
3396 /* take ext phy out of reset */
3397 bnx2x_set_gpio(bp,
3398 MISC_REGISTERS_GPIO_2,
3399 MISC_REGISTERS_GPIO_HIGH,
3400 port);
3402 bnx2x_set_gpio(bp,
3403 MISC_REGISTERS_GPIO_1,
3404 MISC_REGISTERS_GPIO_HIGH,
3405 port);
3407 /* wait for 5ms */
3408 msleep(5);
3410 for (cnt = 0; cnt < 1000; cnt++) {
3411 msleep(1);
3412 bnx2x_cl45_read(bp, port,
3413 ext_phy_type,
3414 ext_phy_addr,
3415 MDIO_PMA_DEVAD,
3416 MDIO_PMA_REG_CTRL,
3417 &ctrl);
3418 if (!(ctrl & (1<<15))) {
3419 DP(NETIF_MSG_LINK, "Reset completed\n\n");
3420 break;
3425 static void bnx2x_turn_off_sf(struct bnx2x *bp, u8 port)
3427 /* put sf to reset */
3428 bnx2x_set_gpio(bp,
3429 MISC_REGISTERS_GPIO_1,
3430 MISC_REGISTERS_GPIO_LOW,
3431 port);
3432 bnx2x_set_gpio(bp,
3433 MISC_REGISTERS_GPIO_2,
3434 MISC_REGISTERS_GPIO_LOW,
3435 port);
3438 u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
3439 u8 *version, u16 len)
3441 struct bnx2x *bp = params->bp;
3442 u32 ext_phy_type = 0;
3443 u16 val = 0;
3444 u8 ext_phy_addr = 0 ;
3445 u8 status = 0 ;
3446 u32 ver_num;
3448 if (version == NULL || params == NULL)
3449 return -EINVAL;
3451 /* reset the returned value to zero */
3452 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3453 ext_phy_addr = ((params->ext_phy_config &
3454 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
3455 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
3457 switch (ext_phy_type) {
3458 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3460 if (len < 5)
3461 return -EINVAL;
3463 /* Take ext phy out of reset */
3464 if (!driver_loaded)
3465 bnx2x_turn_on_ef(bp, params->port, ext_phy_addr,
3466 ext_phy_type);
3468 /* wait for 1ms */
3469 msleep(1);
3471 bnx2x_cl45_read(bp, params->port,
3472 ext_phy_type,
3473 ext_phy_addr,
3474 MDIO_PMA_DEVAD,
3475 MDIO_PMA_REG_7101_VER1, &val);
3476 version[2] = (val & 0xFF);
3477 version[3] = ((val & 0xFF00)>>8);
3479 bnx2x_cl45_read(bp, params->port,
3480 ext_phy_type,
3481 ext_phy_addr,
3482 MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2,
3483 &val);
3484 version[0] = (val & 0xFF);
3485 version[1] = ((val & 0xFF00)>>8);
3486 version[4] = '\0';
3488 if (!driver_loaded)
3489 bnx2x_turn_off_sf(bp, params->port);
3490 break;
3491 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
3492 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
3494 /* Take ext phy out of reset */
3495 if (!driver_loaded)
3496 bnx2x_turn_on_ef(bp, params->port, ext_phy_addr,
3497 ext_phy_type);
3499 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3500 ext_phy_addr,
3501 MDIO_PMA_DEVAD,
3502 MDIO_PMA_REG_ROM_VER1, &val);
3503 ver_num = val<<16;
3504 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3505 ext_phy_addr,
3506 MDIO_PMA_DEVAD,
3507 MDIO_PMA_REG_ROM_VER2, &val);
3508 ver_num |= val;
3509 status = bnx2x_format_ver(ver_num, version, len);
3510 break;
3512 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
3513 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
3515 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3516 ext_phy_addr,
3517 MDIO_PMA_DEVAD,
3518 MDIO_PMA_REG_ROM_VER1, &val);
3519 ver_num = val<<16;
3520 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3521 ext_phy_addr,
3522 MDIO_PMA_DEVAD,
3523 MDIO_PMA_REG_ROM_VER2, &val);
3524 ver_num |= val;
3525 status = bnx2x_format_ver(ver_num, version, len);
3526 break;
3528 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3529 break;
3531 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
3532 DP(NETIF_MSG_LINK, "bnx2x_get_ext_phy_fw_version:"
3533 " type is FAILURE!\n");
3534 status = -EINVAL;
3535 break;
3537 default:
3538 break;
3540 return status;
3543 static void bnx2x_set_xgxs_loopback(struct link_params *params,
3544 struct link_vars *vars,
3545 u8 is_10g)
3547 u8 port = params->port;
3548 struct bnx2x *bp = params->bp;
3550 if (is_10g) {
3551 u32 md_devad;
3553 DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
3555 /* change the uni_phy_addr in the nig */
3556 md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
3557 port*0x18));
3559 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
3561 bnx2x_cl45_write(bp, port, 0,
3562 params->phy_addr,
3564 (MDIO_REG_BANK_AER_BLOCK +
3565 (MDIO_AER_BLOCK_AER_REG & 0xf)),
3566 0x2800);
3568 bnx2x_cl45_write(bp, port, 0,
3569 params->phy_addr,
3571 (MDIO_REG_BANK_CL73_IEEEB0 +
3572 (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
3573 0x6041);
3575 /* set aer mmd back */
3576 bnx2x_set_aer_mmd(params, vars);
3578 /* and md_devad */
3579 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
3580 md_devad);
3582 } else {
3583 u16 mii_control;
3585 DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
3587 CL45_RD_OVER_CL22(bp, port,
3588 params->phy_addr,
3589 MDIO_REG_BANK_COMBO_IEEE0,
3590 MDIO_COMBO_IEEE0_MII_CONTROL,
3591 &mii_control);
3593 CL45_WR_OVER_CL22(bp, port,
3594 params->phy_addr,
3595 MDIO_REG_BANK_COMBO_IEEE0,
3596 MDIO_COMBO_IEEE0_MII_CONTROL,
3597 (mii_control |
3598 MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK));
3603 static void bnx2x_ext_phy_loopback(struct link_params *params)
3605 struct bnx2x *bp = params->bp;
3606 u8 ext_phy_addr;
3607 u32 ext_phy_type;
3609 if (params->switch_cfg == SWITCH_CFG_10G) {
3610 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3611 /* CL37 Autoneg Enabled */
3612 ext_phy_addr = ((params->ext_phy_config &
3613 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
3614 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
3615 switch (ext_phy_type) {
3616 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3617 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
3618 DP(NETIF_MSG_LINK,
3619 "ext_phy_loopback: We should not get here\n");
3620 break;
3621 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
3622 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8705\n");
3623 break;
3624 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
3625 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8706\n");
3626 break;
3627 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3628 /* SFX7101_XGXS_TEST1 */
3629 bnx2x_cl45_write(bp, params->port, ext_phy_type,
3630 ext_phy_addr,
3631 MDIO_XS_DEVAD,
3632 MDIO_XS_SFX7101_XGXS_TEST1,
3633 0x100);
3634 DP(NETIF_MSG_LINK,
3635 "ext_phy_loopback: set ext phy loopback\n");
3636 break;
3637 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
3639 break;
3640 } /* switch external PHY type */
3641 } else {
3642 /* serdes */
3643 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3644 ext_phy_addr = (params->ext_phy_config &
3645 PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK)
3646 >> PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT;
3652 *------------------------------------------------------------------------
3653 * bnx2x_override_led_value -
3655 * Override the led value of the requsted led
3657 *------------------------------------------------------------------------
3659 u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port,
3660 u32 led_idx, u32 value)
3662 u32 reg_val;
3664 /* If port 0 then use EMAC0, else use EMAC1*/
3665 u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
3667 DP(NETIF_MSG_LINK,
3668 "bnx2x_override_led_value() port %x led_idx %d value %d\n",
3669 port, led_idx, value);
3671 switch (led_idx) {
3672 case 0: /* 10MB led */
3673 /* Read the current value of the LED register in
3674 the EMAC block */
3675 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3676 /* Set the OVERRIDE bit to 1 */
3677 reg_val |= EMAC_LED_OVERRIDE;
3678 /* If value is 1, set the 10M_OVERRIDE bit,
3679 otherwise reset it.*/
3680 reg_val = (value == 1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) :
3681 (reg_val & ~EMAC_LED_10MB_OVERRIDE);
3682 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3683 break;
3684 case 1: /*100MB led */
3685 /*Read the current value of the LED register in
3686 the EMAC block */
3687 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3688 /* Set the OVERRIDE bit to 1 */
3689 reg_val |= EMAC_LED_OVERRIDE;
3690 /* If value is 1, set the 100M_OVERRIDE bit,
3691 otherwise reset it.*/
3692 reg_val = (value == 1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) :
3693 (reg_val & ~EMAC_LED_100MB_OVERRIDE);
3694 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3695 break;
3696 case 2: /* 1000MB led */
3697 /* Read the current value of the LED register in the
3698 EMAC block */
3699 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3700 /* Set the OVERRIDE bit to 1 */
3701 reg_val |= EMAC_LED_OVERRIDE;
3702 /* If value is 1, set the 1000M_OVERRIDE bit, otherwise
3703 reset it. */
3704 reg_val = (value == 1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) :
3705 (reg_val & ~EMAC_LED_1000MB_OVERRIDE);
3706 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3707 break;
3708 case 3: /* 2500MB led */
3709 /* Read the current value of the LED register in the
3710 EMAC block*/
3711 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3712 /* Set the OVERRIDE bit to 1 */
3713 reg_val |= EMAC_LED_OVERRIDE;
3714 /* If value is 1, set the 2500M_OVERRIDE bit, otherwise
3715 reset it.*/
3716 reg_val = (value == 1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) :
3717 (reg_val & ~EMAC_LED_2500MB_OVERRIDE);
3718 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3719 break;
3720 case 4: /*10G led */
3721 if (port == 0) {
3722 REG_WR(bp, NIG_REG_LED_10G_P0,
3723 value);
3724 } else {
3725 REG_WR(bp, NIG_REG_LED_10G_P1,
3726 value);
3728 break;
3729 case 5: /* TRAFFIC led */
3730 /* Find if the traffic control is via BMAC or EMAC */
3731 if (port == 0)
3732 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC0_EN);
3733 else
3734 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC1_EN);
3736 /* Override the traffic led in the EMAC:*/
3737 if (reg_val == 1) {
3738 /* Read the current value of the LED register in
3739 the EMAC block */
3740 reg_val = REG_RD(bp, emac_base +
3741 EMAC_REG_EMAC_LED);
3742 /* Set the TRAFFIC_OVERRIDE bit to 1 */
3743 reg_val |= EMAC_LED_OVERRIDE;
3744 /* If value is 1, set the TRAFFIC bit, otherwise
3745 reset it.*/
3746 reg_val = (value == 1) ? (reg_val | EMAC_LED_TRAFFIC) :
3747 (reg_val & ~EMAC_LED_TRAFFIC);
3748 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3749 } else { /* Override the traffic led in the BMAC: */
3750 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
3751 + port*4, 1);
3752 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port*4,
3753 value);
3755 break;
3756 default:
3757 DP(NETIF_MSG_LINK,
3758 "bnx2x_override_led_value() unknown led index %d "
3759 "(should be 0-5)\n", led_idx);
3760 return -EINVAL;
3763 return 0;
3767 u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
3768 u16 hw_led_mode, u32 chip_id)
3770 u8 rc = 0;
3771 u32 tmp;
3772 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
3773 DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
3774 DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
3775 speed, hw_led_mode);
3776 switch (mode) {
3777 case LED_MODE_OFF:
3778 REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0);
3779 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
3780 SHARED_HW_CFG_LED_MAC1);
3782 tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
3783 EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE));
3784 break;
3786 case LED_MODE_OPER:
3787 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode);
3788 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
3789 port*4, 0);
3790 /* Set blinking rate to ~15.9Hz */
3791 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
3792 LED_BLINK_RATE_VAL);
3793 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
3794 port*4, 1);
3795 tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
3796 EMAC_WR(bp, EMAC_REG_EMAC_LED,
3797 (tmp & (~EMAC_LED_OVERRIDE)));
3799 if (!CHIP_IS_E1H(bp) &&
3800 ((speed == SPEED_2500) ||
3801 (speed == SPEED_1000) ||
3802 (speed == SPEED_100) ||
3803 (speed == SPEED_10))) {
3804 /* On Everest 1 Ax chip versions for speeds less than
3805 10G LED scheme is different */
3806 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
3807 + port*4, 1);
3808 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
3809 port*4, 0);
3810 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
3811 port*4, 1);
3813 break;
3815 default:
3816 rc = -EINVAL;
3817 DP(NETIF_MSG_LINK, "bnx2x_set_led: Invalid led mode %d\n",
3818 mode);
3819 break;
3821 return rc;
3825 u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars)
3827 struct bnx2x *bp = params->bp;
3828 u16 gp_status = 0;
3830 CL45_RD_OVER_CL22(bp, params->port,
3831 params->phy_addr,
3832 MDIO_REG_BANK_GP_STATUS,
3833 MDIO_GP_STATUS_TOP_AN_STATUS1,
3834 &gp_status);
3835 /* link is up only if both local phy and external phy are up */
3836 if ((gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) &&
3837 bnx2x_ext_phy_is_link_up(params, vars))
3838 return 0;
3840 return -ESRCH;
3843 static u8 bnx2x_link_initialize(struct link_params *params,
3844 struct link_vars *vars)
3846 struct bnx2x *bp = params->bp;
3847 u8 port = params->port;
3848 u8 rc = 0;
3849 u8 non_ext_phy;
3850 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3851 /* Activate the external PHY */
3852 bnx2x_ext_phy_reset(params, vars);
3854 bnx2x_set_aer_mmd(params, vars);
3856 if (vars->phy_flags & PHY_XGXS_FLAG)
3857 bnx2x_set_master_ln(params);
3859 rc = bnx2x_reset_unicore(params);
3860 /* reset the SerDes and wait for reset bit return low */
3861 if (rc != 0)
3862 return rc;
3864 bnx2x_set_aer_mmd(params, vars);
3866 /* setting the masterLn_def again after the reset */
3867 if (vars->phy_flags & PHY_XGXS_FLAG) {
3868 bnx2x_set_master_ln(params);
3869 bnx2x_set_swap_lanes(params);
3872 if (vars->phy_flags & PHY_XGXS_FLAG) {
3873 if (params->req_line_speed &&
3874 ((params->req_line_speed == SPEED_100) ||
3875 (params->req_line_speed == SPEED_10))) {
3876 vars->phy_flags |= PHY_SGMII_FLAG;
3877 } else {
3878 vars->phy_flags &= ~PHY_SGMII_FLAG;
3881 /* In case of external phy existance, the line speed would be the
3882 line speed linked up by the external phy. In case it is direct only,
3883 then the line_speed during initialization will be equal to the
3884 req_line_speed*/
3885 vars->line_speed = params->req_line_speed;
3887 bnx2x_calc_ieee_aneg_adv(params, &vars->ieee_fc);
3889 /* init ext phy and enable link state int */
3890 non_ext_phy = ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
3891 (params->loopback_mode == LOOPBACK_XGXS_10) ||
3892 (params->loopback_mode == LOOPBACK_EXT_PHY));
3894 if (non_ext_phy ||
3895 (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705)) {
3896 if (params->req_line_speed == SPEED_AUTO_NEG)
3897 bnx2x_set_parallel_detection(params, vars->phy_flags);
3898 bnx2x_init_internal_phy(params, vars);
3901 if (!non_ext_phy)
3902 rc |= bnx2x_ext_phy_init(params, vars);
3904 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3905 (NIG_STATUS_XGXS0_LINK10G |
3906 NIG_STATUS_XGXS0_LINK_STATUS |
3907 NIG_STATUS_SERDES0_LINK_STATUS));
3909 return rc;
3914 u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
3916 struct bnx2x *bp = params->bp;
3918 u32 val;
3919 DP(NETIF_MSG_LINK, "Phy Initialization started \n");
3920 DP(NETIF_MSG_LINK, "req_speed = %d, req_flowctrl=%d\n",
3921 params->req_line_speed, params->req_flow_ctrl);
3922 vars->link_status = 0;
3923 vars->phy_link_up = 0;
3924 vars->link_up = 0;
3925 vars->line_speed = 0;
3926 vars->duplex = DUPLEX_FULL;
3927 vars->flow_ctrl = FLOW_CTRL_NONE;
3928 vars->mac_type = MAC_TYPE_NONE;
3930 if (params->switch_cfg == SWITCH_CFG_1G)
3931 vars->phy_flags = PHY_SERDES_FLAG;
3932 else
3933 vars->phy_flags = PHY_XGXS_FLAG;
3936 /* disable attentions */
3937 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
3938 (NIG_MASK_XGXS0_LINK_STATUS |
3939 NIG_MASK_XGXS0_LINK10G |
3940 NIG_MASK_SERDES0_LINK_STATUS |
3941 NIG_MASK_MI_INT));
3943 bnx2x_emac_init(params, vars);
3945 if (CHIP_REV_IS_FPGA(bp)) {
3946 vars->link_up = 1;
3947 vars->line_speed = SPEED_10000;
3948 vars->duplex = DUPLEX_FULL;
3949 vars->flow_ctrl = FLOW_CTRL_NONE;
3950 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
3951 /* enable on E1.5 FPGA */
3952 if (CHIP_IS_E1H(bp)) {
3953 vars->flow_ctrl |=
3954 (FLOW_CTRL_TX | FLOW_CTRL_RX);
3955 vars->link_status |=
3956 (LINK_STATUS_TX_FLOW_CONTROL_ENABLED |
3957 LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
3960 bnx2x_emac_enable(params, vars, 0);
3961 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
3962 /* disable drain */
3963 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
3964 + params->port*4, 0);
3966 /* update shared memory */
3967 bnx2x_update_mng(params, vars->link_status);
3969 return 0;
3971 } else
3972 if (CHIP_REV_IS_EMUL(bp)) {
3974 vars->link_up = 1;
3975 vars->line_speed = SPEED_10000;
3976 vars->duplex = DUPLEX_FULL;
3977 vars->flow_ctrl = FLOW_CTRL_NONE;
3978 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
3980 bnx2x_bmac_enable(params, vars, 0);
3982 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
3983 /* Disable drain */
3984 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
3985 + params->port*4, 0);
3987 /* update shared memory */
3988 bnx2x_update_mng(params, vars->link_status);
3990 return 0;
3992 } else
3993 if (params->loopback_mode == LOOPBACK_BMAC) {
3994 vars->link_up = 1;
3995 vars->line_speed = SPEED_10000;
3996 vars->duplex = DUPLEX_FULL;
3997 vars->flow_ctrl = FLOW_CTRL_NONE;
3998 vars->mac_type = MAC_TYPE_BMAC;
4000 vars->phy_flags = PHY_XGXS_FLAG;
4002 bnx2x_phy_deassert(params, vars->phy_flags);
4003 /* set bmac loopback */
4004 bnx2x_bmac_enable(params, vars, 1);
4006 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
4007 params->port*4, 0);
4008 } else if (params->loopback_mode == LOOPBACK_EMAC) {
4009 vars->link_up = 1;
4010 vars->line_speed = SPEED_1000;
4011 vars->duplex = DUPLEX_FULL;
4012 vars->flow_ctrl = FLOW_CTRL_NONE;
4013 vars->mac_type = MAC_TYPE_EMAC;
4015 vars->phy_flags = PHY_XGXS_FLAG;
4017 bnx2x_phy_deassert(params, vars->phy_flags);
4018 /* set bmac loopback */
4019 bnx2x_emac_enable(params, vars, 1);
4020 bnx2x_emac_program(params, vars->line_speed,
4021 vars->duplex);
4022 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
4023 params->port*4, 0);
4024 } else if ((params->loopback_mode == LOOPBACK_XGXS_10) ||
4025 (params->loopback_mode == LOOPBACK_EXT_PHY)) {
4026 vars->link_up = 1;
4027 vars->line_speed = SPEED_10000;
4028 vars->duplex = DUPLEX_FULL;
4029 vars->flow_ctrl = FLOW_CTRL_NONE;
4031 vars->phy_flags = PHY_XGXS_FLAG;
4033 val = REG_RD(bp,
4034 NIG_REG_XGXS0_CTRL_PHY_ADDR+
4035 params->port*0x18);
4036 params->phy_addr = (u8)val;
4038 bnx2x_phy_deassert(params, vars->phy_flags);
4039 bnx2x_link_initialize(params, vars);
4041 vars->mac_type = MAC_TYPE_BMAC;
4043 bnx2x_bmac_enable(params, vars, 0);
4045 if (params->loopback_mode == LOOPBACK_XGXS_10) {
4046 /* set 10G XGXS loopback */
4047 bnx2x_set_xgxs_loopback(params, vars, 1);
4048 } else {
4049 /* set external phy loopback */
4050 bnx2x_ext_phy_loopback(params);
4052 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
4053 params->port*4, 0);
4054 } else
4055 /* No loopback */
4058 bnx2x_phy_deassert(params, vars->phy_flags);
4059 switch (params->switch_cfg) {
4060 case SWITCH_CFG_1G:
4061 vars->phy_flags |= PHY_SERDES_FLAG;
4062 if ((params->ext_phy_config &
4063 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK) ==
4064 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482) {
4065 vars->phy_flags |=
4066 PHY_SGMII_FLAG;
4069 val = REG_RD(bp,
4070 NIG_REG_SERDES0_CTRL_PHY_ADDR+
4071 params->port*0x10);
4073 params->phy_addr = (u8)val;
4075 break;
4076 case SWITCH_CFG_10G:
4077 vars->phy_flags |= PHY_XGXS_FLAG;
4078 val = REG_RD(bp,
4079 NIG_REG_XGXS0_CTRL_PHY_ADDR+
4080 params->port*0x18);
4081 params->phy_addr = (u8)val;
4083 break;
4084 default:
4085 DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
4086 return -EINVAL;
4087 break;
4090 bnx2x_link_initialize(params, vars);
4091 msleep(30);
4092 bnx2x_link_int_enable(params);
4094 return 0;
4097 u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars)
4100 struct bnx2x *bp = params->bp;
4101 u32 ext_phy_config = params->ext_phy_config;
4102 u16 hw_led_mode = params->hw_led_mode;
4103 u32 chip_id = params->chip_id;
4104 u8 port = params->port;
4105 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
4106 /* disable attentions */
4108 vars->link_status = 0;
4109 bnx2x_update_mng(params, vars->link_status);
4110 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
4111 (NIG_MASK_XGXS0_LINK_STATUS |
4112 NIG_MASK_XGXS0_LINK10G |
4113 NIG_MASK_SERDES0_LINK_STATUS |
4114 NIG_MASK_MI_INT));
4116 /* activate nig drain */
4117 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
4119 /* disable nig egress interface */
4120 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
4121 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
4123 /* Stop BigMac rx */
4124 bnx2x_bmac_rx_disable(bp, port);
4126 /* disable emac */
4127 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
4129 msleep(10);
4130 /* The PHY reset is controled by GPIO 1
4131 * Hold it as vars low
4133 /* clear link led */
4134 bnx2x_set_led(bp, port, LED_MODE_OFF, 0, hw_led_mode, chip_id);
4135 if (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
4136 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
4137 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
4138 /* HW reset */
4140 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
4141 MISC_REGISTERS_GPIO_OUTPUT_LOW,
4142 port);
4144 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4145 MISC_REGISTERS_GPIO_OUTPUT_LOW,
4146 port);
4148 DP(NETIF_MSG_LINK, "reset external PHY\n");
4149 } else if (ext_phy_type ==
4150 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
4151 DP(NETIF_MSG_LINK, "Setting 8073 port %d into "
4152 "low power mode\n",
4153 port);
4154 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4155 MISC_REGISTERS_GPIO_OUTPUT_LOW,
4156 port);
4159 /* reset the SerDes/XGXS */
4160 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
4161 (0x1ff << (port*16)));
4163 /* reset BigMac */
4164 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
4165 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
4167 /* disable nig ingress interface */
4168 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
4169 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
4170 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
4171 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
4172 vars->link_up = 0;
4173 return 0;
4176 static u8 bnx2x_update_link_down(struct link_params *params,
4177 struct link_vars *vars)
4179 struct bnx2x *bp = params->bp;
4180 u8 port = params->port;
4181 DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
4182 bnx2x_set_led(bp, port, LED_MODE_OFF,
4183 0, params->hw_led_mode,
4184 params->chip_id);
4186 /* indicate no mac active */
4187 vars->mac_type = MAC_TYPE_NONE;
4189 /* update shared memory */
4190 vars->link_status = 0;
4191 vars->line_speed = 0;
4192 bnx2x_update_mng(params, vars->link_status);
4194 /* activate nig drain */
4195 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
4197 /* reset BigMac */
4198 bnx2x_bmac_rx_disable(bp, params->port);
4199 REG_WR(bp, GRCBASE_MISC +
4200 MISC_REGISTERS_RESET_REG_2_CLEAR,
4201 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
4202 return 0;
4205 static u8 bnx2x_update_link_up(struct link_params *params,
4206 struct link_vars *vars,
4207 u8 link_10g, u32 gp_status)
4209 struct bnx2x *bp = params->bp;
4210 u8 port = params->port;
4211 u8 rc = 0;
4212 vars->link_status |= LINK_STATUS_LINK_UP;
4213 if (link_10g) {
4214 bnx2x_bmac_enable(params, vars, 0);
4215 bnx2x_set_led(bp, port, LED_MODE_OPER,
4216 SPEED_10000, params->hw_led_mode,
4217 params->chip_id);
4219 } else {
4220 bnx2x_emac_enable(params, vars, 0);
4221 rc = bnx2x_emac_program(params, vars->line_speed,
4222 vars->duplex);
4224 /* AN complete? */
4225 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
4226 if (!(vars->phy_flags &
4227 PHY_SGMII_FLAG))
4228 bnx2x_set_sgmii_tx_driver(params);
4232 /* PBF - link up */
4233 rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
4234 vars->line_speed);
4236 /* disable drain */
4237 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
4239 /* update shared memory */
4240 bnx2x_update_mng(params, vars->link_status);
4241 return rc;
4243 /* This function should called upon link interrupt */
4244 /* In case vars->link_up, driver needs to
4245 1. Update the pbf
4246 2. Disable drain
4247 3. Update the shared memory
4248 4. Indicate link up
4249 5. Set LEDs
4250 Otherwise,
4251 1. Update shared memory
4252 2. Reset BigMac
4253 3. Report link down
4254 4. Unset LEDs
4256 u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
4258 struct bnx2x *bp = params->bp;
4259 u8 port = params->port;
4260 u16 gp_status;
4261 u8 link_10g;
4262 u8 ext_phy_link_up, rc = 0;
4263 u32 ext_phy_type;
4265 DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
4266 port,
4267 (vars->phy_flags & PHY_XGXS_FLAG),
4268 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
4270 DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
4271 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
4272 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
4273 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
4275 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
4276 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
4277 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
4279 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
4281 /* Check external link change only for non-direct */
4282 ext_phy_link_up = bnx2x_ext_phy_is_link_up(params, vars);
4284 /* Read gp_status */
4285 CL45_RD_OVER_CL22(bp, port, params->phy_addr,
4286 MDIO_REG_BANK_GP_STATUS,
4287 MDIO_GP_STATUS_TOP_AN_STATUS1,
4288 &gp_status);
4290 rc = bnx2x_link_settings_status(params, vars, gp_status);
4291 if (rc != 0)
4292 return rc;
4294 /* anything 10 and over uses the bmac */
4295 link_10g = ((vars->line_speed == SPEED_10000) ||
4296 (vars->line_speed == SPEED_12000) ||
4297 (vars->line_speed == SPEED_12500) ||
4298 (vars->line_speed == SPEED_13000) ||
4299 (vars->line_speed == SPEED_15000) ||
4300 (vars->line_speed == SPEED_16000));
4302 bnx2x_link_int_ack(params, vars, link_10g);
4304 /* In case external phy link is up, and internal link is down
4305 ( not initialized yet probably after link initialization, it needs
4306 to be initialized.
4307 Note that after link down-up as result of cable plug,
4308 the xgxs link would probably become up again without the need to
4309 initialize it*/
4311 if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
4312 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) &&
4313 (ext_phy_link_up && !vars->phy_link_up))
4314 bnx2x_init_internal_phy(params, vars);
4316 /* link is up only if both local phy and external phy are up */
4317 vars->link_up = (ext_phy_link_up && vars->phy_link_up);
4319 if (vars->link_up)
4320 rc = bnx2x_update_link_up(params, vars, link_10g, gp_status);
4321 else
4322 rc = bnx2x_update_link_down(params, vars);
4324 return rc;
4327 static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
4329 u8 ext_phy_addr[PORT_MAX];
4330 u16 val;
4331 s8 port;
4333 /* PART1 - Reset both phys */
4334 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4335 /* Extract the ext phy address for the port */
4336 u32 ext_phy_config = REG_RD(bp, shmem_base +
4337 offsetof(struct shmem_region,
4338 dev_info.port_hw_config[port].external_phy_config));
4340 /* disable attentions */
4341 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
4342 (NIG_MASK_XGXS0_LINK_STATUS |
4343 NIG_MASK_XGXS0_LINK10G |
4344 NIG_MASK_SERDES0_LINK_STATUS |
4345 NIG_MASK_MI_INT));
4347 ext_phy_addr[port] =
4348 ((ext_phy_config &
4349 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
4350 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
4352 /* Need to take the phy out of low power mode in order
4353 to write to access its registers */
4354 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4355 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
4357 /* Reset the phy */
4358 bnx2x_cl45_write(bp, port,
4359 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4360 ext_phy_addr[port],
4361 MDIO_PMA_DEVAD,
4362 MDIO_PMA_REG_CTRL,
4363 1<<15);
4366 /* Add delay of 150ms after reset */
4367 msleep(150);
4369 /* PART2 - Download firmware to both phys */
4370 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4371 u16 fw_ver1;
4373 bnx2x_bcm8073_external_rom_boot(bp, port,
4374 ext_phy_addr[port]);
4376 bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4377 ext_phy_addr[port],
4378 MDIO_PMA_DEVAD,
4379 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
4380 if (fw_ver1 == 0) {
4381 DP(NETIF_MSG_LINK,
4382 "bnx2x_8073_common_init_phy port %x "
4383 "fw Download failed\n", port);
4384 return -EINVAL;
4387 /* Only set bit 10 = 1 (Tx power down) */
4388 bnx2x_cl45_read(bp, port,
4389 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4390 ext_phy_addr[port],
4391 MDIO_PMA_DEVAD,
4392 MDIO_PMA_REG_TX_POWER_DOWN, &val);
4394 /* Phase1 of TX_POWER_DOWN reset */
4395 bnx2x_cl45_write(bp, port,
4396 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4397 ext_phy_addr[port],
4398 MDIO_PMA_DEVAD,
4399 MDIO_PMA_REG_TX_POWER_DOWN,
4400 (val | 1<<10));
4403 /* Toggle Transmitter: Power down and then up with 600ms
4404 delay between */
4405 msleep(600);
4407 /* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low */
4408 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4409 /* Phase2 of POWER_DOWN_RESET*/
4410 /* Release bit 10 (Release Tx power down) */
4411 bnx2x_cl45_read(bp, port,
4412 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4413 ext_phy_addr[port],
4414 MDIO_PMA_DEVAD,
4415 MDIO_PMA_REG_TX_POWER_DOWN, &val);
4417 bnx2x_cl45_write(bp, port,
4418 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4419 ext_phy_addr[port],
4420 MDIO_PMA_DEVAD,
4421 MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
4422 msleep(15);
4424 /* Read modify write the SPI-ROM version select register */
4425 bnx2x_cl45_read(bp, port,
4426 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4427 ext_phy_addr[port],
4428 MDIO_PMA_DEVAD,
4429 MDIO_PMA_REG_EDC_FFE_MAIN, &val);
4430 bnx2x_cl45_write(bp, port,
4431 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4432 ext_phy_addr[port],
4433 MDIO_PMA_DEVAD,
4434 MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
4436 /* set GPIO2 back to LOW */
4437 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4438 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
4440 return 0;
4444 u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base)
4446 u8 rc = 0;
4447 u32 ext_phy_type;
4449 DP(NETIF_MSG_LINK, "bnx2x_common_init_phy\n");
4451 /* Read the ext_phy_type for arbitrary port(0) */
4452 ext_phy_type = XGXS_EXT_PHY_TYPE(
4453 REG_RD(bp, shmem_base +
4454 offsetof(struct shmem_region,
4455 dev_info.port_hw_config[0].external_phy_config)));
4457 switch (ext_phy_type) {
4458 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
4460 rc = bnx2x_8073_common_init_phy(bp, shmem_base);
4461 break;
4463 default:
4464 DP(NETIF_MSG_LINK,
4465 "bnx2x_common_init_phy: ext_phy 0x%x not required\n",
4466 ext_phy_type);
4467 break;
4470 return rc;
4475 static void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
4477 u16 val, cnt;
4479 bnx2x_cl45_read(bp, port,
4480 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4481 phy_addr,
4482 MDIO_PMA_DEVAD,
4483 MDIO_PMA_REG_7101_RESET, &val);
4485 for (cnt = 0; cnt < 10; cnt++) {
4486 msleep(50);
4487 /* Writes a self-clearing reset */
4488 bnx2x_cl45_write(bp, port,
4489 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4490 phy_addr,
4491 MDIO_PMA_DEVAD,
4492 MDIO_PMA_REG_7101_RESET,
4493 (val | (1<<15)));
4494 /* Wait for clear */
4495 bnx2x_cl45_read(bp, port,
4496 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4497 phy_addr,
4498 MDIO_PMA_DEVAD,
4499 MDIO_PMA_REG_7101_RESET, &val);
4501 if ((val & (1<<15)) == 0)
4502 break;
4505 #define RESERVED_SIZE 256
4506 /* max application is 160K bytes - data at end of RAM */
4507 #define MAX_APP_SIZE (160*1024 - RESERVED_SIZE)
4509 /* Header is 14 bytes */
4510 #define HEADER_SIZE 14
4511 #define DATA_OFFSET HEADER_SIZE
4513 #define SPI_START_TRANSFER(bp, port, ext_phy_addr) \
4514 bnx2x_cl45_write(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101, \
4515 ext_phy_addr, \
4516 MDIO_PCS_DEVAD, \
4517 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 1)
4519 /* Programs an image to DSP's flash via the SPI port*/
4520 static u8 bnx2x_sfx7101_flash_download(struct bnx2x *bp, u8 port,
4521 u8 ext_phy_addr,
4522 char data[], u32 size)
4524 const u16 num_trans = size/4; /* 4 bytes can be sent at a time */
4525 /* Doesn't include last trans!*/
4526 const u16 last_trans_size = size%4; /* Num bytes on last trans */
4527 u16 trans_cnt, byte_cnt;
4528 u32 data_index;
4529 u16 tmp;
4530 u16 code_started = 0;
4531 u16 image_revision1, image_revision2;
4532 u16 cnt;
4534 DP(NETIF_MSG_LINK, "bnx2x_sfx7101_flash_download file_size=%d\n", size);
4535 /* Going to flash*/
4536 if ((size-HEADER_SIZE) > MAX_APP_SIZE) {
4537 /* This very often will be the case, because the image is built
4538 with 160Kbytes size whereas the total image size must actually
4539 be 160Kbytes-RESERVED_SIZE */
4540 DP(NETIF_MSG_LINK, "Warning, file size was %d bytes "
4541 "truncated to %d bytes\n", size, MAX_APP_SIZE);
4542 size = MAX_APP_SIZE+HEADER_SIZE;
4544 DP(NETIF_MSG_LINK, "File version is %c%c\n", data[0x14e], data[0x14f]);
4545 DP(NETIF_MSG_LINK, " %c%c\n", data[0x150], data[0x151]);
4546 /* Put the DSP in download mode by setting FLASH_CFG[2] to 1
4547 and issuing a reset.*/
4549 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
4550 MISC_REGISTERS_GPIO_HIGH, port);
4552 bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
4554 /* wait 0.5 sec */
4555 for (cnt = 0; cnt < 100; cnt++)
4556 msleep(5);
4558 /* Make sure we can access the DSP
4559 And it's in the correct mode (waiting for download) */
4561 bnx2x_cl45_read(bp, port,
4562 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4563 ext_phy_addr,
4564 MDIO_PCS_DEVAD,
4565 MDIO_PCS_REG_7101_DSP_ACCESS, &tmp);
4567 if (tmp != 0x000A) {
4568 DP(NETIF_MSG_LINK, "DSP is not in waiting on download mode. "
4569 "Expected 0x000A, read 0x%04X\n", tmp);
4570 DP(NETIF_MSG_LINK, "Download failed\n");
4571 return -EINVAL;
4574 /* Mux the SPI interface away from the internal processor */
4575 bnx2x_cl45_write(bp, port,
4576 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4577 ext_phy_addr,
4578 MDIO_PCS_DEVAD,
4579 MDIO_PCS_REG_7101_SPI_MUX, 1);
4581 /* Reset the SPI port */
4582 bnx2x_cl45_write(bp, port,
4583 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4584 ext_phy_addr,
4585 MDIO_PCS_DEVAD,
4586 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
4587 bnx2x_cl45_write(bp, port,
4588 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4589 ext_phy_addr,
4590 MDIO_PCS_DEVAD,
4591 MDIO_PCS_REG_7101_SPI_CTRL_ADDR,
4592 (1<<MDIO_PCS_REG_7101_SPI_RESET_BIT));
4593 bnx2x_cl45_write(bp, port,
4594 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4595 ext_phy_addr,
4596 MDIO_PCS_DEVAD,
4597 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
4599 /* Erase the flash */
4600 bnx2x_cl45_write(bp, port,
4601 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4602 ext_phy_addr,
4603 MDIO_PCS_DEVAD,
4604 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4605 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4607 bnx2x_cl45_write(bp, port,
4608 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4609 ext_phy_addr,
4610 MDIO_PCS_DEVAD,
4611 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4614 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4615 bnx2x_cl45_write(bp, port,
4616 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4617 ext_phy_addr,
4618 MDIO_PCS_DEVAD,
4619 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4620 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_BULK_ERASE_CMD);
4622 bnx2x_cl45_write(bp, port,
4623 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4624 ext_phy_addr,
4625 MDIO_PCS_DEVAD,
4626 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4628 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4630 /* Wait 10 seconds, the maximum time for the erase to complete */
4631 DP(NETIF_MSG_LINK, "Erasing flash, this takes 10 seconds...\n");
4632 for (cnt = 0; cnt < 1000; cnt++)
4633 msleep(10);
4635 DP(NETIF_MSG_LINK, "Downloading flash, please wait...\n");
4636 data_index = 0;
4637 for (trans_cnt = 0; trans_cnt < num_trans; trans_cnt++) {
4638 bnx2x_cl45_write(bp, port,
4639 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4640 ext_phy_addr,
4641 MDIO_PCS_DEVAD,
4642 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4643 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4645 bnx2x_cl45_write(bp, port,
4646 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4647 ext_phy_addr,
4648 MDIO_PCS_DEVAD,
4649 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4651 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4653 bnx2x_cl45_write(bp, port,
4654 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4655 ext_phy_addr,
4656 MDIO_PCS_DEVAD,
4657 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4658 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
4660 /* Bits 23-16 of address */
4661 bnx2x_cl45_write(bp, port,
4662 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4663 ext_phy_addr,
4664 MDIO_PCS_DEVAD,
4665 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4666 (data_index>>16));
4667 /* Bits 15-8 of address */
4668 bnx2x_cl45_write(bp, port,
4669 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4670 ext_phy_addr,
4671 MDIO_PCS_DEVAD,
4672 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4673 (data_index>>8));
4675 /* Bits 7-0 of address */
4676 bnx2x_cl45_write(bp, port,
4677 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4678 ext_phy_addr,
4679 MDIO_PCS_DEVAD,
4680 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4681 ((u16)data_index));
4683 byte_cnt = 0;
4684 while (byte_cnt < 4 && data_index < size) {
4685 bnx2x_cl45_write(bp, port,
4686 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4687 ext_phy_addr,
4688 MDIO_PCS_DEVAD,
4689 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4690 data[data_index++]);
4691 byte_cnt++;
4694 bnx2x_cl45_write(bp, port,
4695 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4696 ext_phy_addr,
4697 MDIO_PCS_DEVAD,
4698 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4699 byte_cnt+4);
4701 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4702 msleep(5); /* Wait 5 ms minimum between transs */
4704 /* Let the user know something's going on.*/
4705 /* a pacifier ever 4K */
4706 if ((data_index % 1023) == 0)
4707 DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
4710 DP(NETIF_MSG_LINK, "\n");
4711 /* Transfer the last block if there is data remaining */
4712 if (last_trans_size) {
4713 bnx2x_cl45_write(bp, port,
4714 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4715 ext_phy_addr,
4716 MDIO_PCS_DEVAD,
4717 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4718 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4720 bnx2x_cl45_write(bp, port,
4721 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4722 ext_phy_addr,
4723 MDIO_PCS_DEVAD,
4724 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4727 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4729 bnx2x_cl45_write(bp, port,
4730 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4731 ext_phy_addr,
4732 MDIO_PCS_DEVAD,
4733 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4734 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
4736 /* Bits 23-16 of address */
4737 bnx2x_cl45_write(bp, port,
4738 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4739 ext_phy_addr,
4740 MDIO_PCS_DEVAD,
4741 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4742 (data_index>>16));
4743 /* Bits 15-8 of address */
4744 bnx2x_cl45_write(bp, port,
4745 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4746 ext_phy_addr,
4747 MDIO_PCS_DEVAD,
4748 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4749 (data_index>>8));
4751 /* Bits 7-0 of address */
4752 bnx2x_cl45_write(bp, port,
4753 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4754 ext_phy_addr,
4755 MDIO_PCS_DEVAD,
4756 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4757 ((u16)data_index));
4759 byte_cnt = 0;
4760 while (byte_cnt < last_trans_size && data_index < size) {
4761 /* Bits 7-0 of address */
4762 bnx2x_cl45_write(bp, port,
4763 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4764 ext_phy_addr,
4765 MDIO_PCS_DEVAD,
4766 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4767 data[data_index++]);
4768 byte_cnt++;
4771 bnx2x_cl45_write(bp, port,
4772 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4773 ext_phy_addr,
4774 MDIO_PCS_DEVAD,
4775 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4776 byte_cnt+4);
4778 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4781 /* DSP Remove Download Mode */
4782 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
4783 MISC_REGISTERS_GPIO_LOW, port);
4785 bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
4787 /* wait 0.5 sec to allow it to run */
4788 for (cnt = 0; cnt < 100; cnt++)
4789 msleep(5);
4791 bnx2x_hw_reset(bp, port);
4793 for (cnt = 0; cnt < 100; cnt++)
4794 msleep(5);
4796 /* Check that the code is started. In case the download
4797 checksum failed, the code won't be started. */
4798 bnx2x_cl45_read(bp, port,
4799 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4800 ext_phy_addr,
4801 MDIO_PCS_DEVAD,
4802 MDIO_PCS_REG_7101_DSP_ACCESS,
4803 &tmp);
4805 code_started = (tmp & (1<<4));
4806 if (!code_started) {
4807 DP(NETIF_MSG_LINK, "Download failed. Please check file.\n");
4808 return -EINVAL;
4811 /* Verify that the file revision is now equal to the image
4812 revision within the DSP */
4813 bnx2x_cl45_read(bp, port,
4814 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4815 ext_phy_addr,
4816 MDIO_PMA_DEVAD,
4817 MDIO_PMA_REG_7101_VER1,
4818 &image_revision1);
4820 bnx2x_cl45_read(bp, port,
4821 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4822 ext_phy_addr,
4823 MDIO_PMA_DEVAD,
4824 MDIO_PMA_REG_7101_VER2,
4825 &image_revision2);
4827 if (data[0x14e] != (image_revision2&0xFF) ||
4828 data[0x14f] != ((image_revision2&0xFF00)>>8) ||
4829 data[0x150] != (image_revision1&0xFF) ||
4830 data[0x151] != ((image_revision1&0xFF00)>>8)) {
4831 DP(NETIF_MSG_LINK, "Download failed.\n");
4832 return -EINVAL;
4834 DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
4835 return 0;
4838 u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config,
4839 u8 driver_loaded, char data[], u32 size)
4841 u8 rc = 0;
4842 u32 ext_phy_type;
4843 u8 ext_phy_addr;
4844 ext_phy_addr = ((ext_phy_config &
4845 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
4846 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
4848 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
4850 switch (ext_phy_type) {
4851 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
4852 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
4853 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
4854 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
4855 DP(NETIF_MSG_LINK,
4856 "Flash download not supported for this ext phy\n");
4857 rc = -EINVAL;
4858 break;
4859 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
4860 /* Take ext phy out of reset */
4861 if (!driver_loaded)
4862 bnx2x_turn_on_ef(bp, port, ext_phy_addr, ext_phy_type);
4863 rc = bnx2x_sfx7101_flash_download(bp, port, ext_phy_addr,
4864 data, size);
4865 if (!driver_loaded)
4866 bnx2x_turn_off_sf(bp, port);
4867 break;
4868 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
4869 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
4870 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
4871 default:
4872 DP(NETIF_MSG_LINK, "Invalid ext phy type\n");
4873 rc = -EINVAL;
4874 break;
4876 return rc;