bnx2x: 1G-10G toggling race
[linux-2.6-block.git] / drivers / net / bnx2x_link.c
CommitLineData
ea4e040a
YR
1/* Copyright 2008 Broadcom Corporation
2 *
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").
7 *
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.
12 *
13 * Written by Yaniv Rosner
14 *
15 */
16
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>
ea4e040a
YR
24
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"
30
31/********************************************************/
32#define SUPPORT_CL73 0 /* Currently no */
3196a88a 33#define ETH_HLEN 14
ea4e040a
YR
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
ea4e040a
YR
40
41/***********************************************************/
3196a88a 42/* Shortcut definitions */
ea4e040a
YR
43/***********************************************************/
44
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
61
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)
65
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)
72
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)
78
79#define AUTONEG_CL37 SHARED_HW_CFG_AN_ENABLE_CL37
80#define AUTONEG_CL73 SHARED_HW_CFG_AN_ENABLE_CL73
3196a88a
EG
81#define AUTONEG_BAM SHARED_HW_CFG_AN_ENABLE_BAM
82#define AUTONEG_PARALLEL \
ea4e040a 83 SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
3196a88a 84#define AUTONEG_SGMII_FIBER_AUTODET \
ea4e040a 85 SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT
3196a88a 86#define AUTONEG_REMOTE_PHY SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY
ea4e040a
YR
87
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
113
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
137
138#define PHY_XGXS_FLAG 0x1
139#define PHY_SGMII_FLAG 0x2
140#define PHY_SERDES_FLAG 0x4
141
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)
150
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)
156
157static void bnx2x_set_phy_mdio(struct link_params *params)
158{
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);
164}
165
166static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
167{
168 u32 val = REG_RD(bp, reg);
169
170 val |= bits;
171 REG_WR(bp, reg, val);
172 return val;
173}
174
175static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits)
176{
177 u32 val = REG_RD(bp, reg);
178
179 val &= ~bits;
180 REG_WR(bp, reg, val);
181 return val;
182}
183
184static void bnx2x_emac_init(struct link_params *params,
185 struct link_vars *vars)
186{
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;
193
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));
199
200 /* init emac - use read-modify-write */
201 /* self clear reset */
202 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
3196a88a 203 EMAC_WR(bp, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET));
ea4e040a
YR
204
205 timeout = 200;
3196a88a 206 do {
ea4e040a
YR
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;
212 }
213 timeout--;
3196a88a 214 } while (val & EMAC_MODE_RESET);
ea4e040a
YR
215
216 /* Set mac address */
217 val = ((params->mac_addr[0] << 8) |
218 params->mac_addr[1]);
3196a88a 219 EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH, val);
ea4e040a
YR
220
221 val = ((params->mac_addr[2] << 24) |
222 (params->mac_addr[3] << 16) |
223 (params->mac_addr[4] << 8) |
224 params->mac_addr[5]);
3196a88a 225 EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + 4, val);
ea4e040a
YR
226}
227
228static u8 bnx2x_emac_enable(struct link_params *params,
229 struct link_vars *vars, u8 lb)
230{
231 struct bnx2x *bp = params->bp;
232 u8 port = params->port;
233 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
234 u32 val;
235
236 DP(NETIF_MSG_LINK, "enabling EMAC\n");
237
238 /* enable emac and not bmac */
239 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
240
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);
247 }
248 /* for fpga */
249 else
250
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");
254
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,
257 0);
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);
264
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);
272
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);
278 }
279
280 /* enable emac */
281 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1);
282
283 if (CHIP_REV_IS_SLOW(bp)) {
284 /* config GMII mode */
285 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
3196a88a 286 EMAC_WR(bp, EMAC_REG_EMAC_MODE,
ea4e040a
YR
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);
c0700f90 292 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
ea4e040a
YR
293 bnx2x_bits_en(bp, emac_base +
294 EMAC_REG_EMAC_RX_MODE,
295 EMAC_RX_MODE_FLOW_EN);
296
297 bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
8c99e7b0
YR
298 (EMAC_TX_MODE_EXT_PAUSE_EN |
299 EMAC_TX_MODE_FLOW_EN));
c0700f90 300 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
ea4e040a
YR
301 bnx2x_bits_en(bp, emac_base +
302 EMAC_REG_EMAC_TX_MODE,
8c99e7b0
YR
303 (EMAC_TX_MODE_EXT_PAUSE_EN |
304 EMAC_TX_MODE_FLOW_EN));
ea4e040a
YR
305 }
306
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;
3196a88a 310 EMAC_WR(bp, EMAC_REG_EMAC_RX_MODE, val);
ea4e040a
YR
311
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;
3196a88a 318 EMAC_WR(bp, EMAC_REG_EMAC_MODE, val);
ea4e040a 319
6c55c3cd
EG
320 /* enable emac */
321 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1);
322
ea4e040a 323 /* enable emac for jumbo packets */
3196a88a 324 EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE,
ea4e040a
YR
325 (EMAC_RX_MTU_SIZE_JUMBO_ENA |
326 (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD)));
327
328 /* strip CRC */
329 REG_WR(bp, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1);
330
331 /* disable the NIG in/out to the bmac */
332 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x0);
333 REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, 0x0);
334 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x0);
335
336 /* enable the NIG in/out to the emac */
337 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x1);
338 val = 0;
c0700f90 339 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
ea4e040a
YR
340 val = 1;
341
342 REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
343 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x1);
344
345 if (CHIP_REV_IS_EMUL(bp)) {
346 /* take the BigMac out of reset */
347 REG_WR(bp,
348 GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
349 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
350
351 /* enable access for bmac registers */
352 REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
353 }
354
355 vars->mac_type = MAC_TYPE_EMAC;
356 return 0;
357}
358
359
360
361static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
362 u8 is_lb)
363{
364 struct bnx2x *bp = params->bp;
365 u8 port = params->port;
366 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
367 NIG_REG_INGRESS_BMAC0_MEM;
368 u32 wb_data[2];
369 u32 val;
370
371 DP(NETIF_MSG_LINK, "Enabling BigMAC\n");
372 /* reset and unreset the BigMac */
373 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
374 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
375 msleep(1);
376
377 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
378 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
379
380 /* enable access for bmac registers */
381 REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
382
383 /* XGXS control */
384 wb_data[0] = 0x3c;
385 wb_data[1] = 0;
386 REG_WR_DMAE(bp, bmac_addr +
387 BIGMAC_REGISTER_BMAC_XGXS_CONTROL,
388 wb_data, 2);
389
390 /* tx MAC SA */
391 wb_data[0] = ((params->mac_addr[2] << 24) |
392 (params->mac_addr[3] << 16) |
393 (params->mac_addr[4] << 8) |
394 params->mac_addr[5]);
395 wb_data[1] = ((params->mac_addr[0] << 8) |
396 params->mac_addr[1]);
397 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR,
398 wb_data, 2);
399
400 /* tx control */
401 val = 0xc0;
c0700f90 402 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
ea4e040a
YR
403 val |= 0x800000;
404 wb_data[0] = val;
405 wb_data[1] = 0;
406 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_CONTROL,
407 wb_data, 2);
408
409 /* mac control */
410 val = 0x3;
411 if (is_lb) {
412 val |= 0x4;
413 DP(NETIF_MSG_LINK, "enable bmac loopback\n");
414 }
415 wb_data[0] = val;
416 wb_data[1] = 0;
417 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
418 wb_data, 2);
419
420
421 /* set rx mtu */
422 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
423 wb_data[1] = 0;
424 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE,
425 wb_data, 2);
426
427 /* rx control set to don't strip crc */
428 val = 0x14;
c0700f90 429 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
ea4e040a
YR
430 val |= 0x20;
431 wb_data[0] = val;
432 wb_data[1] = 0;
433 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_CONTROL,
434 wb_data, 2);
435
436 /* set tx mtu */
437 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
438 wb_data[1] = 0;
439 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE,
440 wb_data, 2);
441
442 /* set cnt max size */
443 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
444 wb_data[1] = 0;
445 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE,
446 wb_data, 2);
447
448 /* configure safc */
449 wb_data[0] = 0x1000200;
450 wb_data[1] = 0;
451 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
452 wb_data, 2);
453 /* fix for emulation */
454 if (CHIP_REV_IS_EMUL(bp)) {
455 wb_data[0] = 0xf000;
456 wb_data[1] = 0;
457 REG_WR_DMAE(bp,
458 bmac_addr + BIGMAC_REGISTER_TX_PAUSE_THRESHOLD,
459 wb_data, 2);
460 }
461
462 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
463 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
464 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
465 val = 0;
c0700f90 466 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
ea4e040a
YR
467 val = 1;
468 REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
469 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
470 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x0);
471 REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, 0x0);
472 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x1);
473 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);
474
475 vars->mac_type = MAC_TYPE_BMAC;
476 return 0;
477}
478
479static void bnx2x_phy_deassert(struct link_params *params, u8 phy_flags)
480{
481 struct bnx2x *bp = params->bp;
482 u32 val;
483
484 if (phy_flags & PHY_XGXS_FLAG) {
485 DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:XGXS\n");
486 val = XGXS_RESET_BITS;
487
488 } else { /* SerDes */
489 DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:SerDes\n");
490 val = SERDES_RESET_BITS;
491 }
492
493 val = val << (params->port*16);
494
495 /* reset and unreset the SerDes/XGXS */
496 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
497 val);
498 udelay(500);
499 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET,
500 val);
501 bnx2x_set_phy_mdio(params);
502}
503
504void bnx2x_link_status_update(struct link_params *params,
505 struct link_vars *vars)
506{
507 struct bnx2x *bp = params->bp;
508 u8 link_10g;
509 u8 port = params->port;
510
511 if (params->switch_cfg == SWITCH_CFG_1G)
512 vars->phy_flags = PHY_SERDES_FLAG;
513 else
514 vars->phy_flags = PHY_XGXS_FLAG;
515 vars->link_status = REG_RD(bp, params->shmem_base +
516 offsetof(struct shmem_region,
517 port_mb[port].link_status));
518
519 vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
520
521 if (vars->link_up) {
522 DP(NETIF_MSG_LINK, "phy link up\n");
523
524 vars->phy_link_up = 1;
525 vars->duplex = DUPLEX_FULL;
526 switch (vars->link_status &
527 LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
528 case LINK_10THD:
529 vars->duplex = DUPLEX_HALF;
530 /* fall thru */
531 case LINK_10TFD:
532 vars->line_speed = SPEED_10;
533 break;
534
535 case LINK_100TXHD:
536 vars->duplex = DUPLEX_HALF;
537 /* fall thru */
538 case LINK_100T4:
539 case LINK_100TXFD:
540 vars->line_speed = SPEED_100;
541 break;
542
543 case LINK_1000THD:
544 vars->duplex = DUPLEX_HALF;
545 /* fall thru */
546 case LINK_1000TFD:
547 vars->line_speed = SPEED_1000;
548 break;
549
550 case LINK_2500THD:
551 vars->duplex = DUPLEX_HALF;
552 /* fall thru */
553 case LINK_2500TFD:
554 vars->line_speed = SPEED_2500;
555 break;
556
557 case LINK_10GTFD:
558 vars->line_speed = SPEED_10000;
559 break;
560
561 case LINK_12GTFD:
562 vars->line_speed = SPEED_12000;
563 break;
564
565 case LINK_12_5GTFD:
566 vars->line_speed = SPEED_12500;
567 break;
568
569 case LINK_13GTFD:
570 vars->line_speed = SPEED_13000;
571 break;
572
573 case LINK_15GTFD:
574 vars->line_speed = SPEED_15000;
575 break;
576
577 case LINK_16GTFD:
578 vars->line_speed = SPEED_16000;
579 break;
580
581 default:
582 break;
583 }
584
585 if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
c0700f90 586 vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
ea4e040a 587 else
c0700f90 588 vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_TX;
ea4e040a
YR
589
590 if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
c0700f90 591 vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
ea4e040a 592 else
c0700f90 593 vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_RX;
ea4e040a
YR
594
595 if (vars->phy_flags & PHY_XGXS_FLAG) {
8c99e7b0
YR
596 if (vars->line_speed &&
597 ((vars->line_speed == SPEED_10) ||
598 (vars->line_speed == SPEED_100))) {
ea4e040a
YR
599 vars->phy_flags |= PHY_SGMII_FLAG;
600 } else {
601 vars->phy_flags &= ~PHY_SGMII_FLAG;
602 }
603 }
604
605 /* anything 10 and over uses the bmac */
606 link_10g = ((vars->line_speed == SPEED_10000) ||
607 (vars->line_speed == SPEED_12000) ||
608 (vars->line_speed == SPEED_12500) ||
609 (vars->line_speed == SPEED_13000) ||
610 (vars->line_speed == SPEED_15000) ||
611 (vars->line_speed == SPEED_16000));
612 if (link_10g)
613 vars->mac_type = MAC_TYPE_BMAC;
614 else
615 vars->mac_type = MAC_TYPE_EMAC;
616
617 } else { /* link down */
618 DP(NETIF_MSG_LINK, "phy link down\n");
619
620 vars->phy_link_up = 0;
621
622 vars->line_speed = 0;
623 vars->duplex = DUPLEX_FULL;
c0700f90 624 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
ea4e040a
YR
625
626 /* indicate no mac active */
627 vars->mac_type = MAC_TYPE_NONE;
628 }
629
630 DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x\n",
631 vars->link_status, vars->phy_link_up);
632 DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n",
633 vars->line_speed, vars->duplex, vars->flow_ctrl);
634}
635
636static void bnx2x_update_mng(struct link_params *params, u32 link_status)
637{
638 struct bnx2x *bp = params->bp;
639 REG_WR(bp, params->shmem_base +
640 offsetof(struct shmem_region,
641 port_mb[params->port].link_status),
642 link_status);
643}
644
645static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
646{
647 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
648 NIG_REG_INGRESS_BMAC0_MEM;
649 u32 wb_data[2];
3196a88a 650 u32 nig_bmac_enable = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4);
ea4e040a
YR
651
652 /* Only if the bmac is out of reset */
653 if (REG_RD(bp, MISC_REG_RESET_REG_2) &
654 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) &&
655 nig_bmac_enable) {
656
657 /* Clear Rx Enable bit in BMAC_CONTROL register */
658 REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
659 wb_data, 2);
660 wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
661 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
662 wb_data, 2);
663
664 msleep(1);
665 }
666}
667
668static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
669 u32 line_speed)
670{
671 struct bnx2x *bp = params->bp;
672 u8 port = params->port;
673 u32 init_crd, crd;
674 u32 count = 1000;
ea4e040a
YR
675
676 /* disable port */
677 REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1);
678
679 /* wait for init credit */
680 init_crd = REG_RD(bp, PBF_REG_P0_INIT_CRD + port*4);
681 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
682 DP(NETIF_MSG_LINK, "init_crd 0x%x crd 0x%x\n", init_crd, crd);
683
684 while ((init_crd != crd) && count) {
685 msleep(5);
686
687 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
688 count--;
689 }
690 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
691 if (init_crd != crd) {
692 DP(NETIF_MSG_LINK, "BUG! init_crd 0x%x != crd 0x%x\n",
693 init_crd, crd);
694 return -EINVAL;
695 }
696
c0700f90 697 if (flow_ctrl & BNX2X_FLOW_CTRL_RX ||
8c99e7b0
YR
698 line_speed == SPEED_10 ||
699 line_speed == SPEED_100 ||
700 line_speed == SPEED_1000 ||
701 line_speed == SPEED_2500) {
702 REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 1);
ea4e040a
YR
703 /* update threshold */
704 REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, 0);
705 /* update init credit */
8c99e7b0 706 init_crd = 778; /* (800-18-4) */
ea4e040a
YR
707
708 } else {
709 u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
710 ETH_OVREHEAD)/16;
8c99e7b0 711 REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
ea4e040a
YR
712 /* update threshold */
713 REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh);
714 /* update init credit */
715 switch (line_speed) {
ea4e040a
YR
716 case SPEED_10000:
717 init_crd = thresh + 553 - 22;
718 break;
719
720 case SPEED_12000:
721 init_crd = thresh + 664 - 22;
722 break;
723
724 case SPEED_13000:
725 init_crd = thresh + 742 - 22;
726 break;
727
728 case SPEED_16000:
729 init_crd = thresh + 778 - 22;
730 break;
731 default:
732 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
733 line_speed);
734 return -EINVAL;
735 break;
736 }
737 }
738 REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, init_crd);
739 DP(NETIF_MSG_LINK, "PBF updated to speed %d credit %d\n",
740 line_speed, init_crd);
741
742 /* probe the credit changes */
743 REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x1);
744 msleep(5);
745 REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x0);
746
747 /* enable port */
748 REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x0);
749 return 0;
750}
751
752static u32 bnx2x_get_emac_base(u32 ext_phy_type, u8 port)
753{
754 u32 emac_base;
755 switch (ext_phy_type) {
756 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
757 emac_base = GRCBASE_EMAC0;
758 break;
759 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
6378c025 760 emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
ea4e040a
YR
761 break;
762 default:
6378c025 763 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
ea4e040a
YR
764 break;
765 }
766 return emac_base;
767
768}
769
770u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type,
771 u8 phy_addr, u8 devad, u16 reg, u16 val)
772{
773 u32 tmp, saved_mode;
774 u8 i, rc = 0;
775 u32 mdio_ctrl = bnx2x_get_emac_base(ext_phy_type, port);
776
777 /* set clause 45 mode, slow down the MDIO clock to 2.5MHz
778 * (a value of 49==0x31) and make sure that the AUTO poll is off
779 */
780 saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
781 tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
782 EMAC_MDIO_MODE_CLOCK_CNT);
783 tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
784 (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
785 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
786 REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
787 udelay(40);
788
789 /* address */
790
791 tmp = ((phy_addr << 21) | (devad << 16) | reg |
792 EMAC_MDIO_COMM_COMMAND_ADDRESS |
793 EMAC_MDIO_COMM_START_BUSY);
794 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
795
796 for (i = 0; i < 50; i++) {
797 udelay(10);
798
799 tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
800 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
801 udelay(5);
802 break;
803 }
804 }
805 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
806 DP(NETIF_MSG_LINK, "write phy register failed\n");
807 rc = -EFAULT;
808 } else {
809 /* data */
810 tmp = ((phy_addr << 21) | (devad << 16) | val |
811 EMAC_MDIO_COMM_COMMAND_WRITE_45 |
812 EMAC_MDIO_COMM_START_BUSY);
813 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
814
815 for (i = 0; i < 50; i++) {
816 udelay(10);
817
818 tmp = REG_RD(bp, mdio_ctrl +
819 EMAC_REG_EMAC_MDIO_COMM);
820 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
821 udelay(5);
822 break;
823 }
824 }
825 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
826 DP(NETIF_MSG_LINK, "write phy register failed\n");
827 rc = -EFAULT;
828 }
829 }
830
831 /* Restore the saved mode */
832 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
833
834 return rc;
835}
836
837u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type,
838 u8 phy_addr, u8 devad, u16 reg, u16 *ret_val)
839{
840 u32 val, saved_mode;
841 u16 i;
842 u8 rc = 0;
843
844 u32 mdio_ctrl = bnx2x_get_emac_base(ext_phy_type, port);
845 /* set clause 45 mode, slow down the MDIO clock to 2.5MHz
846 * (a value of 49==0x31) and make sure that the AUTO poll is off
847 */
848 saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
849 val = saved_mode & ((EMAC_MDIO_MODE_AUTO_POLL |
850 EMAC_MDIO_MODE_CLOCK_CNT));
851 val |= (EMAC_MDIO_MODE_CLAUSE_45 |
852 (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
853 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
854 REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
855 udelay(40);
856
857 /* address */
858 val = ((phy_addr << 21) | (devad << 16) | reg |
859 EMAC_MDIO_COMM_COMMAND_ADDRESS |
860 EMAC_MDIO_COMM_START_BUSY);
861 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
862
863 for (i = 0; i < 50; i++) {
864 udelay(10);
865
866 val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
867 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
868 udelay(5);
869 break;
870 }
871 }
872 if (val & EMAC_MDIO_COMM_START_BUSY) {
873 DP(NETIF_MSG_LINK, "read phy register failed\n");
874
875 *ret_val = 0;
876 rc = -EFAULT;
877
878 } else {
879 /* data */
880 val = ((phy_addr << 21) | (devad << 16) |
881 EMAC_MDIO_COMM_COMMAND_READ_45 |
882 EMAC_MDIO_COMM_START_BUSY);
883 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
884
885 for (i = 0; i < 50; i++) {
886 udelay(10);
887
888 val = REG_RD(bp, mdio_ctrl +
889 EMAC_REG_EMAC_MDIO_COMM);
890 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
891 *ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
892 break;
893 }
894 }
895 if (val & EMAC_MDIO_COMM_START_BUSY) {
896 DP(NETIF_MSG_LINK, "read phy register failed\n");
897
898 *ret_val = 0;
899 rc = -EFAULT;
900 }
901 }
902
903 /* Restore the saved mode */
904 REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
905
906 return rc;
907}
908
909static void bnx2x_set_aer_mmd(struct link_params *params,
910 struct link_vars *vars)
911{
912 struct bnx2x *bp = params->bp;
913 u32 ser_lane;
914 u16 offset;
915
916 ser_lane = ((params->lane_config &
917 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
918 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
919
920 offset = (vars->phy_flags & PHY_XGXS_FLAG) ?
921 (params->phy_addr + ser_lane) : 0;
922
923 CL45_WR_OVER_CL22(bp, params->port,
924 params->phy_addr,
925 MDIO_REG_BANK_AER_BLOCK,
926 MDIO_AER_BLOCK_AER_REG, 0x3800 + offset);
927}
928
929static void bnx2x_set_master_ln(struct link_params *params)
930{
931 struct bnx2x *bp = params->bp;
932 u16 new_master_ln, ser_lane;
933 ser_lane = ((params->lane_config &
934 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
935 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
936
937 /* set the master_ln for AN */
938 CL45_RD_OVER_CL22(bp, params->port,
939 params->phy_addr,
940 MDIO_REG_BANK_XGXS_BLOCK2,
941 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
942 &new_master_ln);
943
944 CL45_WR_OVER_CL22(bp, params->port,
945 params->phy_addr,
946 MDIO_REG_BANK_XGXS_BLOCK2 ,
947 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
948 (new_master_ln | ser_lane));
949}
950
951static u8 bnx2x_reset_unicore(struct link_params *params)
952{
953 struct bnx2x *bp = params->bp;
954 u16 mii_control;
955 u16 i;
956
957 CL45_RD_OVER_CL22(bp, params->port,
958 params->phy_addr,
959 MDIO_REG_BANK_COMBO_IEEE0,
960 MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
961
962 /* reset the unicore */
963 CL45_WR_OVER_CL22(bp, params->port,
964 params->phy_addr,
965 MDIO_REG_BANK_COMBO_IEEE0,
966 MDIO_COMBO_IEEE0_MII_CONTROL,
967 (mii_control |
968 MDIO_COMBO_IEEO_MII_CONTROL_RESET));
969
970 /* wait for the reset to self clear */
971 for (i = 0; i < MDIO_ACCESS_TIMEOUT; i++) {
972 udelay(5);
973
974 /* the reset erased the previous bank value */
975 CL45_RD_OVER_CL22(bp, params->port,
976 params->phy_addr,
977 MDIO_REG_BANK_COMBO_IEEE0,
978 MDIO_COMBO_IEEE0_MII_CONTROL,
979 &mii_control);
980
981 if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) {
982 udelay(5);
983 return 0;
984 }
985 }
986
987 DP(NETIF_MSG_LINK, "BUG! XGXS is still in reset!\n");
988 return -EINVAL;
989
990}
991
992static void bnx2x_set_swap_lanes(struct link_params *params)
993{
994 struct bnx2x *bp = params->bp;
995 /* Each two bits represents a lane number:
996 No swap is 0123 => 0x1b no need to enable the swap */
997 u16 ser_lane, rx_lane_swap, tx_lane_swap;
998
999 ser_lane = ((params->lane_config &
1000 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
1001 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
1002 rx_lane_swap = ((params->lane_config &
1003 PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
1004 PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
1005 tx_lane_swap = ((params->lane_config &
1006 PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
1007 PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
1008
1009 if (rx_lane_swap != 0x1b) {
1010 CL45_WR_OVER_CL22(bp, params->port,
1011 params->phy_addr,
1012 MDIO_REG_BANK_XGXS_BLOCK2,
1013 MDIO_XGXS_BLOCK2_RX_LN_SWAP,
1014 (rx_lane_swap |
1015 MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
1016 MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
1017 } else {
1018 CL45_WR_OVER_CL22(bp, params->port,
1019 params->phy_addr,
1020 MDIO_REG_BANK_XGXS_BLOCK2,
1021 MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
1022 }
1023
1024 if (tx_lane_swap != 0x1b) {
1025 CL45_WR_OVER_CL22(bp, params->port,
1026 params->phy_addr,
1027 MDIO_REG_BANK_XGXS_BLOCK2,
1028 MDIO_XGXS_BLOCK2_TX_LN_SWAP,
1029 (tx_lane_swap |
1030 MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
1031 } else {
1032 CL45_WR_OVER_CL22(bp, params->port,
1033 params->phy_addr,
1034 MDIO_REG_BANK_XGXS_BLOCK2,
1035 MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
1036 }
1037}
1038
1039static void bnx2x_set_parallel_detection(struct link_params *params,
3196a88a 1040 u8 phy_flags)
ea4e040a
YR
1041{
1042 struct bnx2x *bp = params->bp;
1043 u16 control2;
1044
1045 CL45_RD_OVER_CL22(bp, params->port,
1046 params->phy_addr,
1047 MDIO_REG_BANK_SERDES_DIGITAL,
1048 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1049 &control2);
1050
1051
1052 control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
1053
1054
1055 CL45_WR_OVER_CL22(bp, params->port,
1056 params->phy_addr,
1057 MDIO_REG_BANK_SERDES_DIGITAL,
1058 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1059 control2);
1060
1061 if (phy_flags & PHY_XGXS_FLAG) {
1062 DP(NETIF_MSG_LINK, "XGXS\n");
1063
1064 CL45_WR_OVER_CL22(bp, params->port,
1065 params->phy_addr,
1066 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1067 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
1068 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
1069
1070 CL45_RD_OVER_CL22(bp, params->port,
1071 params->phy_addr,
1072 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1073 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
1074 &control2);
1075
1076
1077 control2 |=
1078 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
1079
1080 CL45_WR_OVER_CL22(bp, params->port,
1081 params->phy_addr,
1082 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1083 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
1084 control2);
1085
1086 /* Disable parallel detection of HiG */
1087 CL45_WR_OVER_CL22(bp, params->port,
1088 params->phy_addr,
1089 MDIO_REG_BANK_XGXS_BLOCK2,
1090 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
1091 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
1092 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
1093 }
1094}
1095
1096static void bnx2x_set_autoneg(struct link_params *params,
1097 struct link_vars *vars)
1098{
1099 struct bnx2x *bp = params->bp;
1100 u16 reg_val;
1101
1102 /* CL37 Autoneg */
1103
1104 CL45_RD_OVER_CL22(bp, params->port,
1105 params->phy_addr,
1106 MDIO_REG_BANK_COMBO_IEEE0,
1107 MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1108
1109 /* CL37 Autoneg Enabled */
8c99e7b0 1110 if (vars->line_speed == SPEED_AUTO_NEG)
ea4e040a
YR
1111 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN;
1112 else /* CL37 Autoneg Disabled */
1113 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1114 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);
1115
1116 CL45_WR_OVER_CL22(bp, params->port,
1117 params->phy_addr,
1118 MDIO_REG_BANK_COMBO_IEEE0,
1119 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1120
1121 /* Enable/Disable Autodetection */
1122
1123 CL45_RD_OVER_CL22(bp, params->port,
1124 params->phy_addr,
1125 MDIO_REG_BANK_SERDES_DIGITAL,
1126 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
1127 reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN;
8c99e7b0 1128 if (vars->line_speed == SPEED_AUTO_NEG)
ea4e040a
YR
1129 reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1130 else
1131 reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1132
1133 CL45_WR_OVER_CL22(bp, params->port,
1134 params->phy_addr,
1135 MDIO_REG_BANK_SERDES_DIGITAL,
1136 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
1137
1138 /* Enable TetonII and BAM autoneg */
1139 CL45_RD_OVER_CL22(bp, params->port,
1140 params->phy_addr,
1141 MDIO_REG_BANK_BAM_NEXT_PAGE,
1142 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1143 &reg_val);
8c99e7b0 1144 if (vars->line_speed == SPEED_AUTO_NEG) {
ea4e040a
YR
1145 /* Enable BAM aneg Mode and TetonII aneg Mode */
1146 reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1147 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1148 } else {
1149 /* TetonII and BAM Autoneg Disabled */
1150 reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1151 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1152 }
1153 CL45_WR_OVER_CL22(bp, params->port,
1154 params->phy_addr,
1155 MDIO_REG_BANK_BAM_NEXT_PAGE,
1156 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1157 reg_val);
1158
1159 /* Enable Clause 73 Aneg */
8c99e7b0 1160 if ((vars->line_speed == SPEED_AUTO_NEG) &&
ea4e040a
YR
1161 (SUPPORT_CL73)) {
1162 /* Enable BAM Station Manager */
1163
1164 CL45_WR_OVER_CL22(bp, params->port,
1165 params->phy_addr,
1166 MDIO_REG_BANK_CL73_USERB0,
1167 MDIO_CL73_USERB0_CL73_BAM_CTRL1,
1168 (MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
1169 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN |
1170 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN));
1171
1172 /* Merge CL73 and CL37 aneg resolution */
1173 CL45_RD_OVER_CL22(bp, params->port,
1174 params->phy_addr,
1175 MDIO_REG_BANK_CL73_USERB0,
1176 MDIO_CL73_USERB0_CL73_BAM_CTRL3,
1177 &reg_val);
1178
1179 CL45_WR_OVER_CL22(bp, params->port,
1180 params->phy_addr,
1181 MDIO_REG_BANK_CL73_USERB0,
1182 MDIO_CL73_USERB0_CL73_BAM_CTRL3,
1183 (reg_val |
1184 MDIO_CL73_USERB0_CL73_BAM_CTRL3_USE_CL73_HCD_MR));
1185
1186 /* Set the CL73 AN speed */
1187
1188 CL45_RD_OVER_CL22(bp, params->port,
1189 params->phy_addr,
1190 MDIO_REG_BANK_CL73_IEEEB1,
1191 MDIO_CL73_IEEEB1_AN_ADV2, &reg_val);
1192 /* In the SerDes we support only the 1G.
1193 In the XGXS we support the 10G KX4
1194 but we currently do not support the KR */
1195 if (vars->phy_flags & PHY_XGXS_FLAG) {
1196 DP(NETIF_MSG_LINK, "XGXS\n");
1197 /* 10G KX4 */
1198 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
1199 } else {
1200 DP(NETIF_MSG_LINK, "SerDes\n");
1201 /* 1000M KX */
1202 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
1203 }
1204 CL45_WR_OVER_CL22(bp, params->port,
1205 params->phy_addr,
1206 MDIO_REG_BANK_CL73_IEEEB1,
1207 MDIO_CL73_IEEEB1_AN_ADV2, reg_val);
1208
1209 /* CL73 Autoneg Enabled */
1210 reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;
1211 } else {
1212 /* CL73 Autoneg Disabled */
1213 reg_val = 0;
1214 }
1215 CL45_WR_OVER_CL22(bp, params->port,
1216 params->phy_addr,
1217 MDIO_REG_BANK_CL73_IEEEB0,
1218 MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
1219}
1220
1221/* program SerDes, forced speed */
8c99e7b0
YR
1222static void bnx2x_program_serdes(struct link_params *params,
1223 struct link_vars *vars)
ea4e040a
YR
1224{
1225 struct bnx2x *bp = params->bp;
1226 u16 reg_val;
1227
1228 /* program duplex, disable autoneg */
1229
1230 CL45_RD_OVER_CL22(bp, params->port,
1231 params->phy_addr,
1232 MDIO_REG_BANK_COMBO_IEEE0,
1233 MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1234 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
1235 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN);
1236 if (params->req_duplex == DUPLEX_FULL)
1237 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
1238 CL45_WR_OVER_CL22(bp, params->port,
1239 params->phy_addr,
1240 MDIO_REG_BANK_COMBO_IEEE0,
1241 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1242
1243 /* program speed
1244 - needed only if the speed is greater than 1G (2.5G or 10G) */
8c99e7b0 1245 CL45_RD_OVER_CL22(bp, params->port,
ea4e040a
YR
1246 params->phy_addr,
1247 MDIO_REG_BANK_SERDES_DIGITAL,
1248 MDIO_SERDES_DIGITAL_MISC1, &reg_val);
8c99e7b0
YR
1249 /* clearing the speed value before setting the right speed */
1250 DP(NETIF_MSG_LINK, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x\n", reg_val);
1251
1252 reg_val &= ~(MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK |
1253 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
1254
1255 if (!((vars->line_speed == SPEED_1000) ||
1256 (vars->line_speed == SPEED_100) ||
1257 (vars->line_speed == SPEED_10))) {
1258
ea4e040a
YR
1259 reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M |
1260 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
8c99e7b0 1261 if (vars->line_speed == SPEED_10000)
ea4e040a
YR
1262 reg_val |=
1263 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
8c99e7b0 1264 if (vars->line_speed == SPEED_13000)
ea4e040a
YR
1265 reg_val |=
1266 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
8c99e7b0
YR
1267 }
1268
1269 CL45_WR_OVER_CL22(bp, params->port,
ea4e040a
YR
1270 params->phy_addr,
1271 MDIO_REG_BANK_SERDES_DIGITAL,
1272 MDIO_SERDES_DIGITAL_MISC1, reg_val);
8c99e7b0 1273
ea4e040a
YR
1274}
1275
1276static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params)
1277{
1278 struct bnx2x *bp = params->bp;
1279 u16 val = 0;
1280
1281 /* configure the 48 bits for BAM AN */
1282
1283 /* set extended capabilities */
1284 if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
1285 val |= MDIO_OVER_1G_UP1_2_5G;
1286 if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
1287 val |= MDIO_OVER_1G_UP1_10G;
1288 CL45_WR_OVER_CL22(bp, params->port,
1289 params->phy_addr,
1290 MDIO_REG_BANK_OVER_1G,
1291 MDIO_OVER_1G_UP1, val);
1292
1293 CL45_WR_OVER_CL22(bp, params->port,
1294 params->phy_addr,
1295 MDIO_REG_BANK_OVER_1G,
1296 MDIO_OVER_1G_UP3, 0);
1297}
1298
8c99e7b0 1299static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u32 *ieee_fc)
ea4e040a 1300{
8c99e7b0 1301 *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
ea4e040a
YR
1302 /* resolve pause mode and advertisement
1303 * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
1304
1305 switch (params->req_flow_ctrl) {
c0700f90
DM
1306 case BNX2X_FLOW_CTRL_AUTO:
1307 if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) {
8c99e7b0 1308 *ieee_fc |=
ea4e040a
YR
1309 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
1310 } else {
8c99e7b0 1311 *ieee_fc |=
ea4e040a
YR
1312 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1313 }
1314 break;
c0700f90 1315 case BNX2X_FLOW_CTRL_TX:
8c99e7b0 1316 *ieee_fc |=
ea4e040a
YR
1317 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1318 break;
1319
c0700f90
DM
1320 case BNX2X_FLOW_CTRL_RX:
1321 case BNX2X_FLOW_CTRL_BOTH:
8c99e7b0 1322 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
ea4e040a
YR
1323 break;
1324
c0700f90 1325 case BNX2X_FLOW_CTRL_NONE:
ea4e040a 1326 default:
8c99e7b0 1327 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
ea4e040a
YR
1328 break;
1329 }
8c99e7b0 1330}
ea4e040a 1331
8c99e7b0
YR
1332static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params,
1333 u32 ieee_fc)
1334{
1335 struct bnx2x *bp = params->bp;
1336 /* for AN, we are always publishing full duplex */
ea4e040a
YR
1337
1338 CL45_WR_OVER_CL22(bp, params->port,
1339 params->phy_addr,
1340 MDIO_REG_BANK_COMBO_IEEE0,
8c99e7b0 1341 MDIO_COMBO_IEEE0_AUTO_NEG_ADV, (u16)ieee_fc);
ea4e040a
YR
1342}
1343
1344static void bnx2x_restart_autoneg(struct link_params *params)
1345{
1346 struct bnx2x *bp = params->bp;
1347 DP(NETIF_MSG_LINK, "bnx2x_restart_autoneg\n");
1348 if (SUPPORT_CL73) {
1349 /* enable and restart clause 73 aneg */
1350 u16 an_ctrl;
1351
1352 CL45_RD_OVER_CL22(bp, params->port,
1353 params->phy_addr,
1354 MDIO_REG_BANK_CL73_IEEEB0,
1355 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1356 &an_ctrl);
1357 CL45_WR_OVER_CL22(bp, params->port,
1358 params->phy_addr,
1359 MDIO_REG_BANK_CL73_IEEEB0,
1360 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1361 (an_ctrl |
1362 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
1363 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
1364
1365 } else {
1366 /* Enable and restart BAM/CL37 aneg */
1367 u16 mii_control;
1368
1369 CL45_RD_OVER_CL22(bp, params->port,
1370 params->phy_addr,
1371 MDIO_REG_BANK_COMBO_IEEE0,
1372 MDIO_COMBO_IEEE0_MII_CONTROL,
1373 &mii_control);
1374 DP(NETIF_MSG_LINK,
1375 "bnx2x_restart_autoneg mii_control before = 0x%x\n",
1376 mii_control);
1377 CL45_WR_OVER_CL22(bp, params->port,
1378 params->phy_addr,
1379 MDIO_REG_BANK_COMBO_IEEE0,
1380 MDIO_COMBO_IEEE0_MII_CONTROL,
1381 (mii_control |
1382 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1383 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
1384 }
1385}
1386
8c99e7b0
YR
1387static void bnx2x_initialize_sgmii_process(struct link_params *params,
1388 struct link_vars *vars)
ea4e040a
YR
1389{
1390 struct bnx2x *bp = params->bp;
1391 u16 control1;
1392
1393 /* in SGMII mode, the unicore is always slave */
1394
1395 CL45_RD_OVER_CL22(bp, params->port,
1396 params->phy_addr,
1397 MDIO_REG_BANK_SERDES_DIGITAL,
1398 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1399 &control1);
1400 control1 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT;
1401 /* set sgmii mode (and not fiber) */
1402 control1 &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE |
1403 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET |
1404 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE);
1405 CL45_WR_OVER_CL22(bp, params->port,
1406 params->phy_addr,
1407 MDIO_REG_BANK_SERDES_DIGITAL,
1408 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1409 control1);
1410
1411 /* if forced speed */
8c99e7b0 1412 if (!(vars->line_speed == SPEED_AUTO_NEG)) {
ea4e040a
YR
1413 /* set speed, disable autoneg */
1414 u16 mii_control;
1415
1416 CL45_RD_OVER_CL22(bp, params->port,
1417 params->phy_addr,
1418 MDIO_REG_BANK_COMBO_IEEE0,
1419 MDIO_COMBO_IEEE0_MII_CONTROL,
1420 &mii_control);
1421 mii_control &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1422 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK|
1423 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX);
1424
8c99e7b0 1425 switch (vars->line_speed) {
ea4e040a
YR
1426 case SPEED_100:
1427 mii_control |=
1428 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100;
1429 break;
1430 case SPEED_1000:
1431 mii_control |=
1432 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_1000;
1433 break;
1434 case SPEED_10:
1435 /* there is nothing to set for 10M */
1436 break;
1437 default:
1438 /* invalid speed for SGMII */
8c99e7b0
YR
1439 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
1440 vars->line_speed);
ea4e040a
YR
1441 break;
1442 }
1443
1444 /* setting the full duplex */
1445 if (params->req_duplex == DUPLEX_FULL)
1446 mii_control |=
1447 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
1448 CL45_WR_OVER_CL22(bp, params->port,
1449 params->phy_addr,
1450 MDIO_REG_BANK_COMBO_IEEE0,
1451 MDIO_COMBO_IEEE0_MII_CONTROL,
1452 mii_control);
1453
1454 } else { /* AN mode */
1455 /* enable and restart AN */
1456 bnx2x_restart_autoneg(params);
1457 }
1458}
1459
1460
1461/*
1462 * link management
1463 */
1464
1465static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
8c99e7b0
YR
1466{ /* LD LP */
1467 switch (pause_result) { /* ASYM P ASYM P */
1468 case 0xb: /* 1 0 1 1 */
c0700f90 1469 vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
ea4e040a
YR
1470 break;
1471
8c99e7b0 1472 case 0xe: /* 1 1 1 0 */
c0700f90 1473 vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
ea4e040a
YR
1474 break;
1475
8c99e7b0
YR
1476 case 0x5: /* 0 1 0 1 */
1477 case 0x7: /* 0 1 1 1 */
1478 case 0xd: /* 1 1 0 1 */
1479 case 0xf: /* 1 1 1 1 */
c0700f90 1480 vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
ea4e040a
YR
1481 break;
1482
1483 default:
1484 break;
1485 }
1486}
1487
1488static u8 bnx2x_ext_phy_resove_fc(struct link_params *params,
1489 struct link_vars *vars)
1490{
1491 struct bnx2x *bp = params->bp;
1492 u8 ext_phy_addr;
3196a88a
EG
1493 u16 ld_pause; /* local */
1494 u16 lp_pause; /* link partner */
ea4e040a
YR
1495 u16 an_complete; /* AN complete */
1496 u16 pause_result;
1497 u8 ret = 0;
1498 u32 ext_phy_type;
1499 u8 port = params->port;
1500 ext_phy_addr = ((params->ext_phy_config &
1501 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1502 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1503
1504 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1505 /* read twice */
1506
1507 bnx2x_cl45_read(bp, port,
1508 ext_phy_type,
1509 ext_phy_addr,
1510 MDIO_AN_DEVAD,
1511 MDIO_AN_REG_STATUS, &an_complete);
1512 bnx2x_cl45_read(bp, port,
1513 ext_phy_type,
1514 ext_phy_addr,
1515 MDIO_AN_DEVAD,
1516 MDIO_AN_REG_STATUS, &an_complete);
1517
1518 if (an_complete & MDIO_AN_REG_STATUS_AN_COMPLETE) {
1519 ret = 1;
1520 bnx2x_cl45_read(bp, port,
1521 ext_phy_type,
1522 ext_phy_addr,
1523 MDIO_AN_DEVAD,
1524 MDIO_AN_REG_ADV_PAUSE, &ld_pause);
1525 bnx2x_cl45_read(bp, port,
1526 ext_phy_type,
1527 ext_phy_addr,
1528 MDIO_AN_DEVAD,
1529 MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
1530 pause_result = (ld_pause &
1531 MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
1532 pause_result |= (lp_pause &
1533 MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
1534 DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x \n",
1535 pause_result);
1536 bnx2x_pause_resolve(vars, pause_result);
c0700f90 1537 if (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE &&
8c99e7b0
YR
1538 ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
1539 bnx2x_cl45_read(bp, port,
1540 ext_phy_type,
1541 ext_phy_addr,
1542 MDIO_AN_DEVAD,
1543 MDIO_AN_REG_CL37_FC_LD, &ld_pause);
1544
1545 bnx2x_cl45_read(bp, port,
1546 ext_phy_type,
1547 ext_phy_addr,
1548 MDIO_AN_DEVAD,
1549 MDIO_AN_REG_CL37_FC_LP, &lp_pause);
1550 pause_result = (ld_pause &
1551 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
1552 pause_result |= (lp_pause &
1553 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
1554
1555 bnx2x_pause_resolve(vars, pause_result);
1556 DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x \n",
1557 pause_result);
1558 }
ea4e040a
YR
1559 }
1560 return ret;
1561}
1562
1563
1564static void bnx2x_flow_ctrl_resolve(struct link_params *params,
1565 struct link_vars *vars,
1566 u32 gp_status)
1567{
1568 struct bnx2x *bp = params->bp;
3196a88a
EG
1569 u16 ld_pause; /* local driver */
1570 u16 lp_pause; /* link partner */
ea4e040a
YR
1571 u16 pause_result;
1572
c0700f90 1573 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
ea4e040a
YR
1574
1575 /* resolve from gp_status in case of AN complete and not sgmii */
c0700f90 1576 if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
ea4e040a
YR
1577 (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
1578 (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
1579 (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1580 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) {
1581 CL45_RD_OVER_CL22(bp, params->port,
1582 params->phy_addr,
1583 MDIO_REG_BANK_COMBO_IEEE0,
1584 MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
1585 &ld_pause);
1586 CL45_RD_OVER_CL22(bp, params->port,
1587 params->phy_addr,
1588 MDIO_REG_BANK_COMBO_IEEE0,
1589 MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
1590 &lp_pause);
1591 pause_result = (ld_pause &
1592 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
1593 pause_result |= (lp_pause &
1594 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
1595 DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result);
1596 bnx2x_pause_resolve(vars, pause_result);
c0700f90 1597 } else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
ea4e040a
YR
1598 (bnx2x_ext_phy_resove_fc(params, vars))) {
1599 return;
1600 } else {
c0700f90 1601 if (params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
8c99e7b0
YR
1602 vars->flow_ctrl = params->req_fc_auto_adv;
1603 else
1604 vars->flow_ctrl = params->req_flow_ctrl;
ea4e040a
YR
1605 }
1606 DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
1607}
1608
1609
1610static u8 bnx2x_link_settings_status(struct link_params *params,
1611 struct link_vars *vars,
1612 u32 gp_status)
1613{
1614 struct bnx2x *bp = params->bp;
6c55c3cd 1615 u16 new_line_speed;
ea4e040a
YR
1616 u8 rc = 0;
1617 vars->link_status = 0;
1618
1619 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
1620 DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
1621 gp_status);
1622
1623 vars->phy_link_up = 1;
1624 vars->link_status |= LINK_STATUS_LINK_UP;
1625
1626 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
1627 vars->duplex = DUPLEX_FULL;
1628 else
1629 vars->duplex = DUPLEX_HALF;
1630
1631 bnx2x_flow_ctrl_resolve(params, vars, gp_status);
1632
1633 switch (gp_status & GP_STATUS_SPEED_MASK) {
1634 case GP_STATUS_10M:
6c55c3cd 1635 new_line_speed = SPEED_10;
ea4e040a
YR
1636 if (vars->duplex == DUPLEX_FULL)
1637 vars->link_status |= LINK_10TFD;
1638 else
1639 vars->link_status |= LINK_10THD;
1640 break;
1641
1642 case GP_STATUS_100M:
6c55c3cd 1643 new_line_speed = SPEED_100;
ea4e040a
YR
1644 if (vars->duplex == DUPLEX_FULL)
1645 vars->link_status |= LINK_100TXFD;
1646 else
1647 vars->link_status |= LINK_100TXHD;
1648 break;
1649
1650 case GP_STATUS_1G:
1651 case GP_STATUS_1G_KX:
6c55c3cd 1652 new_line_speed = SPEED_1000;
ea4e040a
YR
1653 if (vars->duplex == DUPLEX_FULL)
1654 vars->link_status |= LINK_1000TFD;
1655 else
1656 vars->link_status |= LINK_1000THD;
1657 break;
1658
1659 case GP_STATUS_2_5G:
6c55c3cd 1660 new_line_speed = SPEED_2500;
ea4e040a
YR
1661 if (vars->duplex == DUPLEX_FULL)
1662 vars->link_status |= LINK_2500TFD;
1663 else
1664 vars->link_status |= LINK_2500THD;
1665 break;
1666
1667 case GP_STATUS_5G:
1668 case GP_STATUS_6G:
1669 DP(NETIF_MSG_LINK,
1670 "link speed unsupported gp_status 0x%x\n",
1671 gp_status);
1672 return -EINVAL;
1673 break;
1674 case GP_STATUS_10G_KX4:
1675 case GP_STATUS_10G_HIG:
1676 case GP_STATUS_10G_CX4:
6c55c3cd 1677 new_line_speed = SPEED_10000;
ea4e040a
YR
1678 vars->link_status |= LINK_10GTFD;
1679 break;
1680
1681 case GP_STATUS_12G_HIG:
6c55c3cd 1682 new_line_speed = SPEED_12000;
ea4e040a
YR
1683 vars->link_status |= LINK_12GTFD;
1684 break;
1685
1686 case GP_STATUS_12_5G:
6c55c3cd 1687 new_line_speed = SPEED_12500;
ea4e040a
YR
1688 vars->link_status |= LINK_12_5GTFD;
1689 break;
1690
1691 case GP_STATUS_13G:
6c55c3cd 1692 new_line_speed = SPEED_13000;
ea4e040a
YR
1693 vars->link_status |= LINK_13GTFD;
1694 break;
1695
1696 case GP_STATUS_15G:
6c55c3cd 1697 new_line_speed = SPEED_15000;
ea4e040a
YR
1698 vars->link_status |= LINK_15GTFD;
1699 break;
1700
1701 case GP_STATUS_16G:
6c55c3cd 1702 new_line_speed = SPEED_16000;
ea4e040a
YR
1703 vars->link_status |= LINK_16GTFD;
1704 break;
1705
1706 default:
1707 DP(NETIF_MSG_LINK,
1708 "link speed unsupported gp_status 0x%x\n",
1709 gp_status);
1710 return -EINVAL;
1711 break;
1712 }
1713
6c55c3cd
EG
1714 /* Upon link speed change set the NIG into drain mode.
1715 Comes to deals with possible FIFO glitch due to clk change
1716 when speed is decreased without link down indicator */
1717 if (new_line_speed != vars->line_speed) {
1718 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
1719 + params->port*4, 0);
1720 msleep(1);
1721 }
1722 vars->line_speed = new_line_speed;
ea4e040a
YR
1723 vars->link_status |= LINK_STATUS_SERDES_LINK;
1724
57963ed9
YR
1725 if ((params->req_line_speed == SPEED_AUTO_NEG) &&
1726 ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1727 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
1728 (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1729 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705))) {
ea4e040a
YR
1730 vars->autoneg = AUTO_NEG_ENABLED;
1731
1732 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
1733 vars->autoneg |= AUTO_NEG_COMPLETE;
1734 vars->link_status |=
1735 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
1736 }
1737
1738 vars->autoneg |= AUTO_NEG_PARALLEL_DETECTION_USED;
1739 vars->link_status |=
1740 LINK_STATUS_PARALLEL_DETECTION_USED;
1741
1742 }
c0700f90 1743 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
8c99e7b0
YR
1744 vars->link_status |=
1745 LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
ea4e040a 1746
c0700f90 1747 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
8c99e7b0
YR
1748 vars->link_status |=
1749 LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
ea4e040a
YR
1750
1751 } else { /* link_down */
1752 DP(NETIF_MSG_LINK, "phy link down\n");
1753
1754 vars->phy_link_up = 0;
57963ed9 1755
ea4e040a 1756 vars->duplex = DUPLEX_FULL;
c0700f90 1757 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
ea4e040a
YR
1758 vars->autoneg = AUTO_NEG_DISABLED;
1759 vars->mac_type = MAC_TYPE_NONE;
1760 }
1761
1762 DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x \n",
1763 gp_status, vars->phy_link_up, vars->line_speed);
1764 DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x"
1765 " autoneg 0x%x\n",
1766 vars->duplex,
1767 vars->flow_ctrl, vars->autoneg);
1768 DP(NETIF_MSG_LINK, "link_status 0x%x\n", vars->link_status);
1769
1770 return rc;
1771}
1772
1773static void bnx2x_set_sgmii_tx_driver(struct link_params *params)
1774{
1775 struct bnx2x *bp = params->bp;
1776 u16 lp_up2;
1777 u16 tx_driver;
1778
1779 /* read precomp */
1780
1781 CL45_RD_OVER_CL22(bp, params->port,
1782 params->phy_addr,
1783 MDIO_REG_BANK_OVER_1G,
1784 MDIO_OVER_1G_LP_UP2, &lp_up2);
1785
1786 CL45_RD_OVER_CL22(bp, params->port,
1787 params->phy_addr,
1788 MDIO_REG_BANK_TX0,
1789 MDIO_TX0_TX_DRIVER, &tx_driver);
1790
1791 /* bits [10:7] at lp_up2, positioned at [15:12] */
1792 lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >>
1793 MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT) <<
1794 MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT);
1795
1796 if ((lp_up2 != 0) &&
1797 (lp_up2 != (tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK))) {
1798 /* replace tx_driver bits [15:12] */
1799 tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
1800 tx_driver |= lp_up2;
1801 CL45_WR_OVER_CL22(bp, params->port,
1802 params->phy_addr,
1803 MDIO_REG_BANK_TX0,
1804 MDIO_TX0_TX_DRIVER, tx_driver);
1805 }
1806}
1807
1808static u8 bnx2x_emac_program(struct link_params *params,
1809 u32 line_speed, u32 duplex)
1810{
1811 struct bnx2x *bp = params->bp;
1812 u8 port = params->port;
1813 u16 mode = 0;
1814
1815 DP(NETIF_MSG_LINK, "setting link speed & duplex\n");
1816 bnx2x_bits_dis(bp, GRCBASE_EMAC0 + port*0x400 +
1817 EMAC_REG_EMAC_MODE,
1818 (EMAC_MODE_25G_MODE |
1819 EMAC_MODE_PORT_MII_10M |
1820 EMAC_MODE_HALF_DUPLEX));
1821 switch (line_speed) {
1822 case SPEED_10:
1823 mode |= EMAC_MODE_PORT_MII_10M;
1824 break;
1825
1826 case SPEED_100:
1827 mode |= EMAC_MODE_PORT_MII;
1828 break;
1829
1830 case SPEED_1000:
1831 mode |= EMAC_MODE_PORT_GMII;
1832 break;
1833
1834 case SPEED_2500:
1835 mode |= (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_GMII);
1836 break;
1837
1838 default:
1839 /* 10G not valid for EMAC */
1840 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n", line_speed);
1841 return -EINVAL;
1842 }
1843
1844 if (duplex == DUPLEX_HALF)
1845 mode |= EMAC_MODE_HALF_DUPLEX;
1846 bnx2x_bits_en(bp,
1847 GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
1848 mode);
1849
1850 bnx2x_set_led(bp, params->port, LED_MODE_OPER,
1851 line_speed, params->hw_led_mode, params->chip_id);
1852 return 0;
1853}
1854
1855/*****************************************************************************/
17de50b7 1856/* External Phy section */
ea4e040a 1857/*****************************************************************************/
17de50b7 1858static void bnx2x_hw_reset(struct bnx2x *bp, u8 port)
ea4e040a
YR
1859{
1860 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
17de50b7 1861 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
ea4e040a
YR
1862 msleep(1);
1863 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
17de50b7 1864 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
ea4e040a
YR
1865}
1866
1867static void bnx2x_ext_phy_reset(struct link_params *params,
1868 struct link_vars *vars)
1869{
1870 struct bnx2x *bp = params->bp;
1871 u32 ext_phy_type;
1872 u8 ext_phy_addr = ((params->ext_phy_config &
1873 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1874 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1875 DP(NETIF_MSG_LINK, "Port %x: bnx2x_ext_phy_reset\n", params->port);
1876 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1877 /* The PHY reset is controled by GPIO 1
1878 * Give it 1ms of reset pulse
1879 */
1880 if (vars->phy_flags & PHY_XGXS_FLAG) {
1881
1882 switch (ext_phy_type) {
1883 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
1884 DP(NETIF_MSG_LINK, "XGXS Direct\n");
1885 break;
1886
1887 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
1888 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
1889 DP(NETIF_MSG_LINK, "XGXS 8705/8706\n");
1890
1891 /* Restore normal power mode*/
1892 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
17de50b7
EG
1893 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1894 params->port);
ea4e040a
YR
1895
1896 /* HW reset */
17de50b7 1897 bnx2x_hw_reset(bp, params->port);
ea4e040a
YR
1898
1899 bnx2x_cl45_write(bp, params->port,
1900 ext_phy_type,
1901 ext_phy_addr,
1902 MDIO_PMA_DEVAD,
1903 MDIO_PMA_REG_CTRL, 0xa040);
1904 break;
1905 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
1906 /* Unset Low Power Mode and SW reset */
1907 /* Restore normal power mode*/
1908 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
17de50b7
EG
1909 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1910 params->port);
ea4e040a
YR
1911
1912 DP(NETIF_MSG_LINK, "XGXS 8072\n");
1913 bnx2x_cl45_write(bp, params->port,
1914 ext_phy_type,
1915 ext_phy_addr,
1916 MDIO_PMA_DEVAD,
1917 MDIO_PMA_REG_CTRL,
1918 1<<15);
1919 break;
1920 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
1921 {
1922 u16 emac_base;
1923 emac_base = (params->port) ? GRCBASE_EMAC0 :
1924 GRCBASE_EMAC1;
1925
1926 /* Restore normal power mode*/
1927 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
17de50b7
EG
1928 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1929 params->port);
ea4e040a
YR
1930
1931 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
17de50b7
EG
1932 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1933 params->port);
ea4e040a
YR
1934
1935 DP(NETIF_MSG_LINK, "XGXS 8073\n");
ea4e040a
YR
1936 }
1937 break;
1938
1939 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
1940 DP(NETIF_MSG_LINK, "XGXS SFX7101\n");
1941
1942 /* Restore normal power mode*/
1943 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
17de50b7
EG
1944 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
1945 params->port);
ea4e040a
YR
1946
1947 /* HW reset */
17de50b7 1948 bnx2x_hw_reset(bp, params->port);
ea4e040a
YR
1949
1950 break;
1951
1952 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
1953 DP(NETIF_MSG_LINK, "XGXS PHY Failure detected\n");
1954 break;
1955
1956 default:
1957 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
1958 params->ext_phy_config);
1959 break;
1960 }
1961
1962 } else { /* SerDes */
1963 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
1964 switch (ext_phy_type) {
1965 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
1966 DP(NETIF_MSG_LINK, "SerDes Direct\n");
1967 break;
1968
1969 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
1970 DP(NETIF_MSG_LINK, "SerDes 5482\n");
17de50b7 1971 bnx2x_hw_reset(bp, params->port);
ea4e040a
YR
1972 break;
1973
1974 default:
1975 DP(NETIF_MSG_LINK,
1976 "BAD SerDes ext_phy_config 0x%x\n",
1977 params->ext_phy_config);
1978 break;
1979 }
1980 }
1981}
1982
1983static void bnx2x_bcm8072_external_rom_boot(struct link_params *params)
1984{
1985 struct bnx2x *bp = params->bp;
1986 u8 port = params->port;
1987 u8 ext_phy_addr = ((params->ext_phy_config &
1988 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1989 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1990 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1991 u16 fw_ver1, fw_ver2;
1992
1993 /* Need to wait 200ms after reset */
1994 msleep(200);
1995 /* Boot port from external ROM
1996 * Set ser_boot_ctl bit in the MISC_CTRL1 register
1997 */
1998 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1999 MDIO_PMA_DEVAD,
2000 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
2001
2002 /* Reset internal microprocessor */
2003 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2004 MDIO_PMA_DEVAD,
2005 MDIO_PMA_REG_GEN_CTRL,
2006 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2007 /* set micro reset = 0 */
2008 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2009 MDIO_PMA_DEVAD,
2010 MDIO_PMA_REG_GEN_CTRL,
2011 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
2012 /* Reset internal microprocessor */
2013 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2014 MDIO_PMA_DEVAD,
2015 MDIO_PMA_REG_GEN_CTRL,
2016 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2017 /* wait for 100ms for code download via SPI port */
2018 msleep(100);
2019
2020 /* Clear ser_boot_ctl bit */
2021 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2022 MDIO_PMA_DEVAD,
2023 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2024 /* Wait 100ms */
2025 msleep(100);
2026
2027 /* Print the PHY FW version */
2028 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2029 MDIO_PMA_DEVAD,
2030 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
2031 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2032 MDIO_PMA_DEVAD,
2033 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
2034 DP(NETIF_MSG_LINK, "8072 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
2035}
2036
2037static u8 bnx2x_8073_is_snr_needed(struct link_params *params)
2038{
2039 /* This is only required for 8073A1, version 102 only */
2040
2041 struct bnx2x *bp = params->bp;
2042 u8 ext_phy_addr = ((params->ext_phy_config &
2043 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2044 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2045 u16 val;
2046
2047 /* Read 8073 HW revision*/
2048 bnx2x_cl45_read(bp, params->port,
2049 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2050 ext_phy_addr,
2051 MDIO_PMA_DEVAD,
2052 0xc801, &val);
2053
2054 if (val != 1) {
2055 /* No need to workaround in 8073 A1 */
2056 return 0;
2057 }
2058
2059 bnx2x_cl45_read(bp, params->port,
2060 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2061 ext_phy_addr,
2062 MDIO_PMA_DEVAD,
2063 MDIO_PMA_REG_ROM_VER2, &val);
2064
2065 /* SNR should be applied only for version 0x102 */
2066 if (val != 0x102)
2067 return 0;
2068
2069 return 1;
2070}
2071
2072static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
2073{
2074 struct bnx2x *bp = params->bp;
2075 u8 ext_phy_addr = ((params->ext_phy_config &
2076 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2077 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2078 u16 val, cnt, cnt1 ;
2079
2080 bnx2x_cl45_read(bp, params->port,
2081 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2082 ext_phy_addr,
2083 MDIO_PMA_DEVAD,
2084 0xc801, &val);
2085
2086 if (val > 0) {
2087 /* No need to workaround in 8073 A1 */
2088 return 0;
2089 }
2090 /* XAUI workaround in 8073 A0: */
2091
2092 /* After loading the boot ROM and restarting Autoneg,
2093 poll Dev1, Reg $C820: */
2094
2095 for (cnt = 0; cnt < 1000; cnt++) {
2096 bnx2x_cl45_read(bp, params->port,
2097 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2098 ext_phy_addr,
2099 MDIO_PMA_DEVAD,
2100 0xc820, &val);
2101 /* If bit [14] = 0 or bit [13] = 0, continue on with
2102 system initialization (XAUI work-around not required,
2103 as these bits indicate 2.5G or 1G link up). */
2104 if (!(val & (1<<14)) || !(val & (1<<13))) {
2105 DP(NETIF_MSG_LINK, "XAUI work-around not required\n");
2106 return 0;
2107 } else if (!(val & (1<<15))) {
2108 DP(NETIF_MSG_LINK, "clc bit 15 went off\n");
2109 /* If bit 15 is 0, then poll Dev1, Reg $C841 until
2110 it's MSB (bit 15) goes to 1 (indicating that the
2111 XAUI workaround has completed),
2112 then continue on with system initialization.*/
2113 for (cnt1 = 0; cnt1 < 1000; cnt1++) {
2114 bnx2x_cl45_read(bp, params->port,
2115 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2116 ext_phy_addr,
2117 MDIO_PMA_DEVAD,
2118 0xc841, &val);
2119 if (val & (1<<15)) {
2120 DP(NETIF_MSG_LINK,
2121 "XAUI workaround has completed\n");
2122 return 0;
2123 }
2124 msleep(3);
2125 }
2126 break;
2127 }
2128 msleep(3);
2129 }
2130 DP(NETIF_MSG_LINK, "Warning: XAUI work-around timeout !!!\n");
2131 return -EINVAL;
2132
2133}
2134
6bbca910
YR
2135static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
2136 u8 ext_phy_addr)
ea4e040a 2137{
6bbca910
YR
2138 u16 fw_ver1, fw_ver2;
2139 /* Boot port from external ROM */
ea4e040a 2140 /* EDC grst */
6bbca910
YR
2141 bnx2x_cl45_write(bp, port,
2142 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2143 ext_phy_addr,
ea4e040a
YR
2144 MDIO_PMA_DEVAD,
2145 MDIO_PMA_REG_GEN_CTRL,
2146 0x0001);
2147
2148 /* ucode reboot and rst */
6bbca910
YR
2149 bnx2x_cl45_write(bp, port,
2150 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2151 ext_phy_addr,
ea4e040a
YR
2152 MDIO_PMA_DEVAD,
2153 MDIO_PMA_REG_GEN_CTRL,
2154 0x008c);
2155
6bbca910
YR
2156 bnx2x_cl45_write(bp, port,
2157 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2158 ext_phy_addr,
ea4e040a
YR
2159 MDIO_PMA_DEVAD,
2160 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
2161
2162 /* Reset internal microprocessor */
6bbca910
YR
2163 bnx2x_cl45_write(bp, port,
2164 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2165 ext_phy_addr,
ea4e040a
YR
2166 MDIO_PMA_DEVAD,
2167 MDIO_PMA_REG_GEN_CTRL,
2168 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
2169
2170 /* Release srst bit */
6bbca910
YR
2171 bnx2x_cl45_write(bp, port,
2172 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2173 ext_phy_addr,
ea4e040a
YR
2174 MDIO_PMA_DEVAD,
2175 MDIO_PMA_REG_GEN_CTRL,
2176 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2177
2178 /* wait for 100ms for code download via SPI port */
2179 msleep(100);
2180
2181 /* Clear ser_boot_ctl bit */
6bbca910
YR
2182 bnx2x_cl45_write(bp, port,
2183 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2184 ext_phy_addr,
ea4e040a
YR
2185 MDIO_PMA_DEVAD,
2186 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2187
6bbca910
YR
2188 bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2189 ext_phy_addr,
2190 MDIO_PMA_DEVAD,
2191 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
2192 bnx2x_cl45_read(bp, port,
2193 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2194 ext_phy_addr,
2195 MDIO_PMA_DEVAD,
2196 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
ea4e040a
YR
2197 DP(NETIF_MSG_LINK, "8073 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
2198
6bbca910 2199}
ea4e040a 2200
6bbca910
YR
2201static void bnx2x_bcm807x_force_10G(struct link_params *params)
2202{
2203 struct bnx2x *bp = params->bp;
2204 u8 port = params->port;
2205 u8 ext_phy_addr = ((params->ext_phy_config &
2206 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2207 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2208 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2209
2210 /* Force KR or KX */
ea4e040a
YR
2211 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2212 MDIO_PMA_DEVAD,
6bbca910
YR
2213 MDIO_PMA_REG_CTRL,
2214 0x2040);
ea4e040a
YR
2215 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2216 MDIO_PMA_DEVAD,
6bbca910
YR
2217 MDIO_PMA_REG_10G_CTRL2,
2218 0x000b);
2219 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2220 MDIO_PMA_DEVAD,
2221 MDIO_PMA_REG_BCM_CTRL,
2222 0x0000);
2223 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2224 MDIO_AN_DEVAD,
2225 MDIO_AN_REG_CTRL,
2226 0x0000);
ea4e040a 2227}
ea4e040a
YR
2228static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
2229{
2230 struct bnx2x *bp = params->bp;
2231 u8 port = params->port;
2232 u16 val;
2233 u8 ext_phy_addr = ((params->ext_phy_config &
2234 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2235 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2236 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2237
2238 bnx2x_cl45_read(bp, params->port,
2239 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2240 ext_phy_addr,
2241 MDIO_PMA_DEVAD,
2242 0xc801, &val);
2243
2244 if (val == 0) {
2245 /* Mustn't set low power mode in 8073 A0 */
2246 return;
2247 }
2248
2249 /* Disable PLL sequencer (use read-modify-write to clear bit 13) */
2250 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2251 MDIO_XS_DEVAD,
2252 MDIO_XS_PLL_SEQUENCER, &val);
2253 val &= ~(1<<13);
2254 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2255 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
2256
2257 /* PLL controls */
2258 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2259 MDIO_XS_DEVAD, 0x805E, 0x1077);
2260 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2261 MDIO_XS_DEVAD, 0x805D, 0x0000);
2262 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2263 MDIO_XS_DEVAD, 0x805C, 0x030B);
2264 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2265 MDIO_XS_DEVAD, 0x805B, 0x1240);
2266 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2267 MDIO_XS_DEVAD, 0x805A, 0x2490);
2268
2269 /* Tx Controls */
2270 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2271 MDIO_XS_DEVAD, 0x80A7, 0x0C74);
2272 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2273 MDIO_XS_DEVAD, 0x80A6, 0x9041);
2274 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2275 MDIO_XS_DEVAD, 0x80A5, 0x4640);
2276
2277 /* Rx Controls */
2278 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2279 MDIO_XS_DEVAD, 0x80FE, 0x01C4);
2280 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2281 MDIO_XS_DEVAD, 0x80FD, 0x9249);
2282 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2283 MDIO_XS_DEVAD, 0x80FC, 0x2015);
2284
2285 /* Enable PLL sequencer (use read-modify-write to set bit 13) */
2286 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2287 MDIO_XS_DEVAD,
2288 MDIO_XS_PLL_SEQUENCER, &val);
2289 val |= (1<<13);
2290 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2291 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
2292}
6bbca910
YR
2293
2294static void bnx2x_8073_set_pause_cl37(struct link_params *params,
2295 struct link_vars *vars)
ea4e040a 2296{
6bbca910 2297
ea4e040a 2298 struct bnx2x *bp = params->bp;
6bbca910 2299 u16 cl37_val;
ea4e040a
YR
2300 u8 ext_phy_addr = ((params->ext_phy_config &
2301 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2302 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2303 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2304
6bbca910
YR
2305 bnx2x_cl45_read(bp, params->port,
2306 ext_phy_type,
2307 ext_phy_addr,
2308 MDIO_AN_DEVAD,
2309 MDIO_AN_REG_CL37_FC_LD, &cl37_val);
2310
2311 cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
2312 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
2313
2314 if ((vars->ieee_fc &
2315 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
2316 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
2317 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
2318 }
2319 if ((vars->ieee_fc &
2320 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
2321 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
2322 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
2323 }
2324 if ((vars->ieee_fc &
2325 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
2326 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
2327 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
2328 }
2329 DP(NETIF_MSG_LINK,
2330 "Ext phy AN advertize cl37 0x%x\n", cl37_val);
2331
2332 bnx2x_cl45_write(bp, params->port,
2333 ext_phy_type,
2334 ext_phy_addr,
ea4e040a 2335 MDIO_AN_DEVAD,
6bbca910
YR
2336 MDIO_AN_REG_CL37_FC_LD, cl37_val);
2337 msleep(500);
ea4e040a
YR
2338}
2339
2340static void bnx2x_ext_phy_set_pause(struct link_params *params,
2341 struct link_vars *vars)
2342{
2343 struct bnx2x *bp = params->bp;
2344 u16 val;
2345 u8 ext_phy_addr = ((params->ext_phy_config &
2346 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2347 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2348 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2349
2350 /* read modify write pause advertizing */
2351 bnx2x_cl45_read(bp, params->port,
2352 ext_phy_type,
2353 ext_phy_addr,
2354 MDIO_AN_DEVAD,
2355 MDIO_AN_REG_ADV_PAUSE, &val);
2356
2357 val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
8c99e7b0 2358
ea4e040a
YR
2359 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
2360
8c99e7b0
YR
2361 if ((vars->ieee_fc &
2362 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
ea4e040a
YR
2363 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
2364 val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
2365 }
8c99e7b0
YR
2366 if ((vars->ieee_fc &
2367 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
ea4e040a
YR
2368 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
2369 val |=
2370 MDIO_AN_REG_ADV_PAUSE_PAUSE;
2371 }
2372 DP(NETIF_MSG_LINK,
2373 "Ext phy AN advertize 0x%x\n", val);
2374 bnx2x_cl45_write(bp, params->port,
2375 ext_phy_type,
2376 ext_phy_addr,
2377 MDIO_AN_DEVAD,
2378 MDIO_AN_REG_ADV_PAUSE, val);
2379}
2380
57963ed9
YR
2381
2382static void bnx2x_init_internal_phy(struct link_params *params,
2383 struct link_vars *vars)
2384{
2385 struct bnx2x *bp = params->bp;
2386 u8 port = params->port;
2387 if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
2388 u16 bank, rx_eq;
2389
2390 rx_eq = ((params->serdes_config &
2391 PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK) >>
2392 PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT);
2393
2394 DP(NETIF_MSG_LINK, "setting rx eq to 0x%x\n", rx_eq);
2395 for (bank = MDIO_REG_BANK_RX0; bank <= MDIO_REG_BANK_RX_ALL;
2396 bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0)) {
2397 CL45_WR_OVER_CL22(bp, port,
2398 params->phy_addr,
2399 bank ,
2400 MDIO_RX0_RX_EQ_BOOST,
2401 ((rx_eq &
2402 MDIO_RX0_RX_EQ_BOOST_EQUALIZER_CTRL_MASK) |
2403 MDIO_RX0_RX_EQ_BOOST_OFFSET_CTRL));
2404 }
2405
2406 /* forced speed requested? */
2407 if (vars->line_speed != SPEED_AUTO_NEG) {
2408 DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
2409
2410 /* disable autoneg */
2411 bnx2x_set_autoneg(params, vars);
2412
2413 /* program speed and duplex */
8c99e7b0 2414 bnx2x_program_serdes(params, vars);
57963ed9
YR
2415
2416 } else { /* AN_mode */
2417 DP(NETIF_MSG_LINK, "not SGMII, AN\n");
2418
2419 /* AN enabled */
2420 bnx2x_set_brcm_cl37_advertisment(params);
2421
2422 /* program duplex & pause advertisement (for aneg) */
2423 bnx2x_set_ieee_aneg_advertisment(params,
8c99e7b0 2424 vars->ieee_fc);
57963ed9
YR
2425
2426 /* enable autoneg */
2427 bnx2x_set_autoneg(params, vars);
2428
2429 /* enable and restart AN */
2430 bnx2x_restart_autoneg(params);
2431 }
2432
2433 } else { /* SGMII mode */
2434 DP(NETIF_MSG_LINK, "SGMII\n");
2435
8c99e7b0 2436 bnx2x_initialize_sgmii_process(params, vars);
57963ed9
YR
2437 }
2438}
2439
ea4e040a
YR
2440static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
2441{
2442 struct bnx2x *bp = params->bp;
2443 u32 ext_phy_type;
2444 u8 ext_phy_addr;
2445 u16 cnt;
2446 u16 ctrl = 0;
2447 u16 val = 0;
2448 u8 rc = 0;
2449 if (vars->phy_flags & PHY_XGXS_FLAG) {
2450 ext_phy_addr = ((params->ext_phy_config &
2451 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2452 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2453
2454 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2455 /* Make sure that the soft reset is off (expect for the 8072:
2456 * due to the lock, it will be done inside the specific
2457 * handling)
2458 */
2459 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
2460 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
2461 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) &&
2462 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
2463 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
2464 /* Wait for soft reset to get cleared upto 1 sec */
2465 for (cnt = 0; cnt < 1000; cnt++) {
2466 bnx2x_cl45_read(bp, params->port,
2467 ext_phy_type,
2468 ext_phy_addr,
2469 MDIO_PMA_DEVAD,
2470 MDIO_PMA_REG_CTRL, &ctrl);
2471 if (!(ctrl & (1<<15)))
2472 break;
2473 msleep(1);
2474 }
2475 DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n",
2476 ctrl, cnt);
2477 }
2478
2479 switch (ext_phy_type) {
2480 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
ea4e040a
YR
2481 break;
2482
2483 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2484 DP(NETIF_MSG_LINK, "XGXS 8705\n");
2485
2486 bnx2x_cl45_write(bp, params->port,
2487 ext_phy_type,
2488 ext_phy_addr,
2489 MDIO_PMA_DEVAD,
2490 MDIO_PMA_REG_MISC_CTRL,
2491 0x8288);
2492 bnx2x_cl45_write(bp, params->port,
2493 ext_phy_type,
2494 ext_phy_addr,
2495 MDIO_PMA_DEVAD,
2496 MDIO_PMA_REG_PHY_IDENTIFIER,
2497 0x7fbf);
2498 bnx2x_cl45_write(bp, params->port,
2499 ext_phy_type,
2500 ext_phy_addr,
2501 MDIO_PMA_DEVAD,
2502 MDIO_PMA_REG_CMU_PLL_BYPASS,
2503 0x0100);
2504 bnx2x_cl45_write(bp, params->port,
2505 ext_phy_type,
2506 ext_phy_addr,
2507 MDIO_WIS_DEVAD,
2508 MDIO_WIS_REG_LASI_CNTL, 0x1);
2509 break;
2510
2511 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2512 DP(NETIF_MSG_LINK, "XGXS 8706\n");
2513
2514 msleep(10);
2515 /* Force speed */
2516 /* First enable LASI */
2517 bnx2x_cl45_write(bp, params->port,
2518 ext_phy_type,
2519 ext_phy_addr,
2520 MDIO_PMA_DEVAD,
2521 MDIO_PMA_REG_RX_ALARM_CTRL,
2522 0x0400);
2523 bnx2x_cl45_write(bp, params->port,
2524 ext_phy_type,
2525 ext_phy_addr,
2526 MDIO_PMA_DEVAD,
2527 MDIO_PMA_REG_LASI_CTRL, 0x0004);
2528
2529 if (params->req_line_speed == SPEED_10000) {
2530 DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n");
2531
2532 bnx2x_cl45_write(bp, params->port,
2533 ext_phy_type,
2534 ext_phy_addr,
2535 MDIO_PMA_DEVAD,
2536 MDIO_PMA_REG_DIGITAL_CTRL,
2537 0x400);
2538 } else {
2539 /* Force 1Gbps using autoneg with 1G
2540 advertisment */
2541
2542 /* Allow CL37 through CL73 */
2543 DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
2544 bnx2x_cl45_write(bp, params->port,
2545 ext_phy_type,
2546 ext_phy_addr,
2547 MDIO_AN_DEVAD,
2548 MDIO_AN_REG_CL37_CL73,
2549 0x040c);
2550
2551 /* Enable Full-Duplex advertisment on CL37 */
2552 bnx2x_cl45_write(bp, params->port,
2553 ext_phy_type,
2554 ext_phy_addr,
2555 MDIO_AN_DEVAD,
8c99e7b0 2556 MDIO_AN_REG_CL37_FC_LP,
ea4e040a
YR
2557 0x0020);
2558 /* Enable CL37 AN */
2559 bnx2x_cl45_write(bp, params->port,
2560 ext_phy_type,
2561 ext_phy_addr,
2562 MDIO_AN_DEVAD,
2563 MDIO_AN_REG_CL37_AN,
2564 0x1000);
2565 /* 1G support */
2566 bnx2x_cl45_write(bp, params->port,
2567 ext_phy_type,
2568 ext_phy_addr,
2569 MDIO_AN_DEVAD,
2570 MDIO_AN_REG_ADV, (1<<5));
2571
2572 /* Enable clause 73 AN */
2573 bnx2x_cl45_write(bp, params->port,
2574 ext_phy_type,
2575 ext_phy_addr,
2576 MDIO_AN_DEVAD,
2577 MDIO_AN_REG_CTRL,
2578 0x1200);
2579
2580 }
2581
2582 break;
2583
2584 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2585 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2586 {
2587 u16 tmp1;
2588 u16 rx_alarm_ctrl_val;
2589 u16 lasi_ctrl_val;
2590 if (ext_phy_type ==
2591 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
2592 rx_alarm_ctrl_val = 0x400;
2593 lasi_ctrl_val = 0x0004;
2594 } else {
ea4e040a 2595 rx_alarm_ctrl_val = (1<<2);
ea4e040a
YR
2596 lasi_ctrl_val = 0x0004;
2597 }
2598
6bbca910
YR
2599 /* enable LASI */
2600 bnx2x_cl45_write(bp, params->port,
2601 ext_phy_type,
2602 ext_phy_addr,
2603 MDIO_PMA_DEVAD,
2604 MDIO_PMA_REG_RX_ALARM_CTRL,
2605 rx_alarm_ctrl_val);
2606
2607 bnx2x_cl45_write(bp, params->port,
2608 ext_phy_type,
2609 ext_phy_addr,
2610 MDIO_PMA_DEVAD,
2611 MDIO_PMA_REG_LASI_CTRL,
2612 lasi_ctrl_val);
2613
2614 bnx2x_8073_set_pause_cl37(params, vars);
ea4e040a
YR
2615
2616 if (ext_phy_type ==
2617 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072){
2618 bnx2x_bcm8072_external_rom_boot(params);
2619 } else {
6bbca910 2620
ea4e040a
YR
2621 /* In case of 8073 with long xaui lines,
2622 don't set the 8073 xaui low power*/
2623 bnx2x_bcm8073_set_xaui_low_power_mode(params);
2624 }
2625
6bbca910
YR
2626 bnx2x_cl45_read(bp, params->port,
2627 ext_phy_type,
2628 ext_phy_addr,
2629 MDIO_PMA_DEVAD,
2630 0xca13,
2631 &tmp1);
ea4e040a
YR
2632
2633 bnx2x_cl45_read(bp, params->port,
2634 ext_phy_type,
2635 ext_phy_addr,
2636 MDIO_PMA_DEVAD,
2637 MDIO_PMA_REG_RX_ALARM, &tmp1);
2638
2639 DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1):"
2640 "0x%x\n", tmp1);
2641
2642 /* If this is forced speed, set to KR or KX
2643 * (all other are not supported)
2644 */
6bbca910
YR
2645 if (params->loopback_mode == LOOPBACK_EXT) {
2646 bnx2x_bcm807x_force_10G(params);
2647 DP(NETIF_MSG_LINK,
2648 "Forced speed 10G on 807X\n");
2649 break;
2650 } else {
2651 bnx2x_cl45_write(bp, params->port,
2652 ext_phy_type, ext_phy_addr,
2653 MDIO_PMA_DEVAD,
2654 MDIO_PMA_REG_BCM_CTRL,
2655 0x0002);
2656 }
2657 if (params->req_line_speed != SPEED_AUTO_NEG) {
2658 if (params->req_line_speed == SPEED_10000) {
2659 val = (1<<7);
ea4e040a
YR
2660 } else if (params->req_line_speed ==
2661 SPEED_2500) {
2662 val = (1<<5);
2663 /* Note that 2.5G works only
2664 when used with 1G advertisment */
2665 } else
2666 val = (1<<5);
2667 } else {
2668
2669 val = 0;
2670 if (params->speed_cap_mask &
2671 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
2672 val |= (1<<7);
2673
6bbca910
YR
2674 /* Note that 2.5G works only when
2675 used with 1G advertisment */
ea4e040a 2676 if (params->speed_cap_mask &
6bbca910
YR
2677 (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
2678 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
ea4e040a 2679 val |= (1<<5);
6bbca910
YR
2680 DP(NETIF_MSG_LINK,
2681 "807x autoneg val = 0x%x\n", val);
ea4e040a
YR
2682 }
2683
2684 bnx2x_cl45_write(bp, params->port,
2685 ext_phy_type,
2686 ext_phy_addr,
2687 MDIO_AN_DEVAD,
2688 MDIO_AN_REG_ADV, val);
2689
2690 if (ext_phy_type ==
2691 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
6bbca910 2692
ea4e040a
YR
2693 bnx2x_cl45_read(bp, params->port,
2694 ext_phy_type,
2695 ext_phy_addr,
2696 MDIO_AN_DEVAD,
2697 0x8329, &tmp1);
6bbca910
YR
2698
2699 if (((params->speed_cap_mask &
2700 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
2701 (params->req_line_speed ==
2702 SPEED_AUTO_NEG)) ||
2703 (params->req_line_speed ==
2704 SPEED_2500)) {
ea4e040a
YR
2705 u16 phy_ver;
2706 /* Allow 2.5G for A1 and above */
2707 bnx2x_cl45_read(bp, params->port,
2708 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2709 ext_phy_addr,
2710 MDIO_PMA_DEVAD,
2711 0xc801, &phy_ver);
6bbca910 2712 DP(NETIF_MSG_LINK, "Add 2.5G\n");
ea4e040a
YR
2713 if (phy_ver > 0)
2714 tmp1 |= 1;
2715 else
2716 tmp1 &= 0xfffe;
6bbca910
YR
2717 } else {
2718 DP(NETIF_MSG_LINK, "Disable 2.5G\n");
ea4e040a 2719 tmp1 &= 0xfffe;
6bbca910 2720 }
ea4e040a 2721
6bbca910
YR
2722 bnx2x_cl45_write(bp, params->port,
2723 ext_phy_type,
2724 ext_phy_addr,
2725 MDIO_AN_DEVAD,
ea4e040a
YR
2726 0x8329, tmp1);
2727 }
6bbca910
YR
2728
2729 /* Add support for CL37 (passive mode) II */
2730
2731 bnx2x_cl45_read(bp, params->port,
ea4e040a
YR
2732 ext_phy_type,
2733 ext_phy_addr,
2734 MDIO_AN_DEVAD,
6bbca910
YR
2735 MDIO_AN_REG_CL37_FC_LD,
2736 &tmp1);
2737
ea4e040a
YR
2738 bnx2x_cl45_write(bp, params->port,
2739 ext_phy_type,
2740 ext_phy_addr,
2741 MDIO_AN_DEVAD,
6bbca910
YR
2742 MDIO_AN_REG_CL37_FC_LD, (tmp1 |
2743 ((params->req_duplex == DUPLEX_FULL) ?
2744 0x20 : 0x40)));
2745
ea4e040a
YR
2746 /* Add support for CL37 (passive mode) III */
2747 bnx2x_cl45_write(bp, params->port,
2748 ext_phy_type,
2749 ext_phy_addr,
2750 MDIO_AN_DEVAD,
2751 MDIO_AN_REG_CL37_AN, 0x1000);
ea4e040a
YR
2752
2753 if (ext_phy_type ==
2754 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
6bbca910 2755 /* The SNR will improve about 2db by changing
ea4e040a
YR
2756 BW and FEE main tap. Rest commands are executed
2757 after link is up*/
6bbca910 2758 /*Change FFE main cursor to 5 in EDC register*/
ea4e040a
YR
2759 if (bnx2x_8073_is_snr_needed(params))
2760 bnx2x_cl45_write(bp, params->port,
2761 ext_phy_type,
2762 ext_phy_addr,
2763 MDIO_PMA_DEVAD,
2764 MDIO_PMA_REG_EDC_FFE_MAIN,
2765 0xFB0C);
2766
6bbca910
YR
2767 /* Enable FEC (Forware Error Correction)
2768 Request in the AN */
2769 bnx2x_cl45_read(bp, params->port,
2770 ext_phy_type,
2771 ext_phy_addr,
2772 MDIO_AN_DEVAD,
2773 MDIO_AN_REG_ADV2, &tmp1);
ea4e040a 2774
6bbca910
YR
2775 tmp1 |= (1<<15);
2776
2777 bnx2x_cl45_write(bp, params->port,
2778 ext_phy_type,
2779 ext_phy_addr,
2780 MDIO_AN_DEVAD,
2781 MDIO_AN_REG_ADV2, tmp1);
ea4e040a 2782
ea4e040a
YR
2783 }
2784
2785 bnx2x_ext_phy_set_pause(params, vars);
2786
6bbca910
YR
2787 /* Restart autoneg */
2788 msleep(500);
ea4e040a
YR
2789 bnx2x_cl45_write(bp, params->port,
2790 ext_phy_type,
2791 ext_phy_addr,
2792 MDIO_AN_DEVAD,
2793 MDIO_AN_REG_CTRL, 0x1200);
2794 DP(NETIF_MSG_LINK, "807x Autoneg Restart: "
2795 "Advertise 1G=%x, 10G=%x\n",
2796 ((val & (1<<5)) > 0),
2797 ((val & (1<<7)) > 0));
2798 break;
2799 }
2800 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
2801 DP(NETIF_MSG_LINK,
2802 "Setting the SFX7101 LASI indication\n");
2803
2804 bnx2x_cl45_write(bp, params->port,
2805 ext_phy_type,
2806 ext_phy_addr,
2807 MDIO_PMA_DEVAD,
2808 MDIO_PMA_REG_LASI_CTRL, 0x1);
2809 DP(NETIF_MSG_LINK,
2810 "Setting the SFX7101 LED to blink on traffic\n");
2811 bnx2x_cl45_write(bp, params->port,
2812 ext_phy_type,
2813 ext_phy_addr,
2814 MDIO_PMA_DEVAD,
2815 MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
2816
2817 bnx2x_ext_phy_set_pause(params, vars);
2818 /* Restart autoneg */
2819 bnx2x_cl45_read(bp, params->port,
2820 ext_phy_type,
2821 ext_phy_addr,
2822 MDIO_AN_DEVAD,
2823 MDIO_AN_REG_CTRL, &val);
2824 val |= 0x200;
2825 bnx2x_cl45_write(bp, params->port,
2826 ext_phy_type,
2827 ext_phy_addr,
2828 MDIO_AN_DEVAD,
2829 MDIO_AN_REG_CTRL, val);
2830 break;
2831 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
2832 DP(NETIF_MSG_LINK,
2833 "XGXS PHY Failure detected 0x%x\n",
2834 params->ext_phy_config);
2835 rc = -EINVAL;
2836 break;
2837 default:
2838 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
2839 params->ext_phy_config);
2840 rc = -EINVAL;
2841 break;
2842 }
2843
2844 } else { /* SerDes */
57963ed9 2845
ea4e040a
YR
2846 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
2847 switch (ext_phy_type) {
2848 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
2849 DP(NETIF_MSG_LINK, "SerDes Direct\n");
2850 break;
2851
2852 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
2853 DP(NETIF_MSG_LINK, "SerDes 5482\n");
2854 break;
2855
2856 default:
2857 DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
2858 params->ext_phy_config);
2859 break;
2860 }
2861 }
2862 return rc;
2863}
2864
2865
2866static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
8c99e7b0 2867 struct link_vars *vars)
ea4e040a
YR
2868{
2869 struct bnx2x *bp = params->bp;
2870 u32 ext_phy_type;
2871 u8 ext_phy_addr;
2872 u16 val1 = 0, val2;
2873 u16 rx_sd, pcs_status;
2874 u8 ext_phy_link_up = 0;
2875 u8 port = params->port;
2876 if (vars->phy_flags & PHY_XGXS_FLAG) {
2877 ext_phy_addr = ((params->ext_phy_config &
2878 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2879 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2880
2881 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2882 switch (ext_phy_type) {
2883 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
2884 DP(NETIF_MSG_LINK, "XGXS Direct\n");
2885 ext_phy_link_up = 1;
2886 break;
2887
2888 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2889 DP(NETIF_MSG_LINK, "XGXS 8705\n");
2890 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2891 ext_phy_addr,
2892 MDIO_WIS_DEVAD,
2893 MDIO_WIS_REG_LASI_STATUS, &val1);
2894 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
2895
2896 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2897 ext_phy_addr,
2898 MDIO_WIS_DEVAD,
2899 MDIO_WIS_REG_LASI_STATUS, &val1);
2900 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
2901
2902 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2903 ext_phy_addr,
2904 MDIO_PMA_DEVAD,
2905 MDIO_PMA_REG_RX_SD, &rx_sd);
2906 DP(NETIF_MSG_LINK, "8705 rx_sd 0x%x\n", rx_sd);
2907 ext_phy_link_up = (rx_sd & 0x1);
8c99e7b0
YR
2908 if (ext_phy_link_up)
2909 vars->line_speed = SPEED_10000;
ea4e040a
YR
2910 break;
2911
2912 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2913 DP(NETIF_MSG_LINK, "XGXS 8706\n");
2914 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2915 ext_phy_addr,
2916 MDIO_PMA_DEVAD,
2917 MDIO_PMA_REG_LASI_STATUS, &val1);
2918 DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
2919
2920 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2921 ext_phy_addr,
2922 MDIO_PMA_DEVAD,
2923 MDIO_PMA_REG_LASI_STATUS, &val1);
2924 DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
2925
2926 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2927 ext_phy_addr,
2928 MDIO_PMA_DEVAD,
2929 MDIO_PMA_REG_RX_SD, &rx_sd);
2930 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2931 ext_phy_addr,
2932 MDIO_PCS_DEVAD,
2933 MDIO_PCS_REG_STATUS, &pcs_status);
2934
2935 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2936 ext_phy_addr,
2937 MDIO_AN_DEVAD,
2938 MDIO_AN_REG_LINK_STATUS, &val2);
2939 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2940 ext_phy_addr,
2941 MDIO_AN_DEVAD,
2942 MDIO_AN_REG_LINK_STATUS, &val2);
2943
2944 DP(NETIF_MSG_LINK, "8706 rx_sd 0x%x"
2945 " pcs_status 0x%x 1Gbps link_status 0x%x\n",
2946 rx_sd, pcs_status, val2);
2947 /* link is up if both bit 0 of pmd_rx_sd and
2948 * bit 0 of pcs_status are set, or if the autoneg bit
2949 1 is set
2950 */
2951 ext_phy_link_up = ((rx_sd & pcs_status & 0x1) ||
2952 (val2 & (1<<1)));
57963ed9
YR
2953 if (ext_phy_link_up) {
2954 if (val2 & (1<<1))
2955 vars->line_speed = SPEED_1000;
2956 else
2957 vars->line_speed = SPEED_10000;
2958 }
2959
ea4e040a
YR
2960 /* clear LASI indication*/
2961 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2962 ext_phy_addr,
2963 MDIO_PMA_DEVAD,
2964 MDIO_PMA_REG_RX_ALARM, &val2);
2965 break;
2966
2967 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2968 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2969 {
6bbca910
YR
2970 u16 link_status = 0;
2971 u16 an1000_status = 0;
ea4e040a
YR
2972 if (ext_phy_type ==
2973 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
2974 bnx2x_cl45_read(bp, params->port,
2975 ext_phy_type,
2976 ext_phy_addr,
2977 MDIO_PCS_DEVAD,
2978 MDIO_PCS_REG_LASI_STATUS, &val1);
2979 bnx2x_cl45_read(bp, params->port,
2980 ext_phy_type,
2981 ext_phy_addr,
2982 MDIO_PCS_DEVAD,
2983 MDIO_PCS_REG_LASI_STATUS, &val2);
2984 DP(NETIF_MSG_LINK,
2985 "870x LASI status 0x%x->0x%x\n",
2986 val1, val2);
2987
2988 } else {
2989 /* In 8073, port1 is directed through emac0 and
2990 * port0 is directed through emac1
2991 */
2992 bnx2x_cl45_read(bp, params->port,
2993 ext_phy_type,
2994 ext_phy_addr,
2995 MDIO_PMA_DEVAD,
2996 MDIO_PMA_REG_LASI_STATUS, &val1);
2997
ea4e040a 2998 DP(NETIF_MSG_LINK,
6bbca910
YR
2999 "8703 LASI status 0x%x\n",
3000 val1);
ea4e040a
YR
3001 }
3002
3003 /* clear the interrupt LASI status register */
3004 bnx2x_cl45_read(bp, params->port,
3005 ext_phy_type,
3006 ext_phy_addr,
3007 MDIO_PCS_DEVAD,
3008 MDIO_PCS_REG_STATUS, &val2);
3009 bnx2x_cl45_read(bp, params->port,
3010 ext_phy_type,
3011 ext_phy_addr,
3012 MDIO_PCS_DEVAD,
3013 MDIO_PCS_REG_STATUS, &val1);
3014 DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n",
3015 val2, val1);
6bbca910 3016 /* Clear MSG-OUT */
ea4e040a
YR
3017 bnx2x_cl45_read(bp, params->port,
3018 ext_phy_type,
3019 ext_phy_addr,
3020 MDIO_PMA_DEVAD,
6bbca910
YR
3021 0xca13,
3022 &val1);
3023
3024 /* Check the LASI */
ea4e040a
YR
3025 bnx2x_cl45_read(bp, params->port,
3026 ext_phy_type,
3027 ext_phy_addr,
3028 MDIO_PMA_DEVAD,
6bbca910
YR
3029 MDIO_PMA_REG_RX_ALARM, &val2);
3030
3031 DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
3032
ea4e040a
YR
3033 /* Check the link status */
3034 bnx2x_cl45_read(bp, params->port,
3035 ext_phy_type,
3036 ext_phy_addr,
3037 MDIO_PCS_DEVAD,
3038 MDIO_PCS_REG_STATUS, &val2);
3039 DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
3040
3041 bnx2x_cl45_read(bp, params->port,
3042 ext_phy_type,
3043 ext_phy_addr,
3044 MDIO_PMA_DEVAD,
3045 MDIO_PMA_REG_STATUS, &val2);
3046 bnx2x_cl45_read(bp, params->port,
3047 ext_phy_type,
3048 ext_phy_addr,
3049 MDIO_PMA_DEVAD,
3050 MDIO_PMA_REG_STATUS, &val1);
3051 ext_phy_link_up = ((val1 & 4) == 4);
3052 DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
3053 if (ext_phy_type ==
3054 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
6bbca910 3055
ea4e040a 3056 if (ext_phy_link_up &&
6bbca910
YR
3057 ((params->req_line_speed !=
3058 SPEED_10000))) {
ea4e040a
YR
3059 if (bnx2x_bcm8073_xaui_wa(params)
3060 != 0) {
3061 ext_phy_link_up = 0;
3062 break;
3063 }
6bbca910
YR
3064 }
3065 bnx2x_cl45_read(bp, params->port,
ea4e040a
YR
3066 ext_phy_type,
3067 ext_phy_addr,
6bbca910 3068 MDIO_AN_DEVAD,
ea4e040a
YR
3069 0x8304,
3070 &an1000_status);
6bbca910 3071 bnx2x_cl45_read(bp, params->port,
ea4e040a
YR
3072 ext_phy_type,
3073 ext_phy_addr,
6bbca910 3074 MDIO_AN_DEVAD,
ea4e040a
YR
3075 0x8304,
3076 &an1000_status);
6bbca910 3077
ea4e040a
YR
3078 /* Check the link status on 1.1.2 */
3079 bnx2x_cl45_read(bp, params->port,
3080 ext_phy_type,
3081 ext_phy_addr,
3082 MDIO_PMA_DEVAD,
3083 MDIO_PMA_REG_STATUS, &val2);
3084 bnx2x_cl45_read(bp, params->port,
3085 ext_phy_type,
3086 ext_phy_addr,
3087 MDIO_PMA_DEVAD,
3088 MDIO_PMA_REG_STATUS, &val1);
3089 DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x,"
3090 "an_link_status=0x%x\n",
3091 val2, val1, an1000_status);
3092
6bbca910
YR
3093 ext_phy_link_up = (((val1 & 4) == 4) ||
3094 (an1000_status & (1<<1)));
ea4e040a
YR
3095 if (ext_phy_link_up &&
3096 bnx2x_8073_is_snr_needed(params)) {
3097 /* The SNR will improve about 2dbby
3098 changing the BW and FEE main tap.*/
3099
3100 /* The 1st write to change FFE main
3101 tap is set before restart AN */
3102 /* Change PLL Bandwidth in EDC
3103 register */
3104 bnx2x_cl45_write(bp, port, ext_phy_type,
3105 ext_phy_addr,
3106 MDIO_PMA_DEVAD,
3107 MDIO_PMA_REG_PLL_BANDWIDTH,
3108 0x26BC);
3109
3110 /* Change CDR Bandwidth in EDC
3111 register */
3112 bnx2x_cl45_write(bp, port, ext_phy_type,
3113 ext_phy_addr,
3114 MDIO_PMA_DEVAD,
3115 MDIO_PMA_REG_CDR_BANDWIDTH,
3116 0x0333);
3117
6bbca910
YR
3118
3119 }
3120 bnx2x_cl45_read(bp, params->port,
3121 ext_phy_type,
3122 ext_phy_addr,
3123 MDIO_PMA_DEVAD,
3124 0xc820,
3125 &link_status);
3126
3127 /* Bits 0..2 --> speed detected,
3128 bits 13..15--> link is down */
3129 if ((link_status & (1<<2)) &&
3130 (!(link_status & (1<<15)))) {
3131 ext_phy_link_up = 1;
3132 vars->line_speed = SPEED_10000;
3133 DP(NETIF_MSG_LINK,
3134 "port %x: External link"
3135 " up in 10G\n", params->port);
3136 } else if ((link_status & (1<<1)) &&
3137 (!(link_status & (1<<14)))) {
3138 ext_phy_link_up = 1;
3139 vars->line_speed = SPEED_2500;
3140 DP(NETIF_MSG_LINK,
3141 "port %x: External link"
3142 " up in 2.5G\n", params->port);
3143 } else if ((link_status & (1<<0)) &&
3144 (!(link_status & (1<<13)))) {
3145 ext_phy_link_up = 1;
3146 vars->line_speed = SPEED_1000;
3147 DP(NETIF_MSG_LINK,
3148 "port %x: External link"
3149 " up in 1G\n", params->port);
3150 } else {
3151 ext_phy_link_up = 0;
3152 DP(NETIF_MSG_LINK,
3153 "port %x: External link"
3154 " is down\n", params->port);
3155 }
3156 } else {
3157 /* See if 1G link is up for the 8072 */
3158 bnx2x_cl45_read(bp, params->port,
3159 ext_phy_type,
3160 ext_phy_addr,
3161 MDIO_AN_DEVAD,
3162 0x8304,
3163 &an1000_status);
3164 bnx2x_cl45_read(bp, params->port,
3165 ext_phy_type,
3166 ext_phy_addr,
3167 MDIO_AN_DEVAD,
3168 0x8304,
3169 &an1000_status);
3170 if (an1000_status & (1<<1)) {
3171 ext_phy_link_up = 1;
3172 vars->line_speed = SPEED_1000;
3173 DP(NETIF_MSG_LINK,
3174 "port %x: External link"
3175 " up in 1G\n", params->port);
3176 } else if (ext_phy_link_up) {
3177 ext_phy_link_up = 1;
3178 vars->line_speed = SPEED_10000;
3179 DP(NETIF_MSG_LINK,
3180 "port %x: External link"
3181 " up in 10G\n", params->port);
ea4e040a
YR
3182 }
3183 }
6bbca910
YR
3184
3185
ea4e040a
YR
3186 break;
3187 }
3188 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3189 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3190 ext_phy_addr,
3191 MDIO_PMA_DEVAD,
3192 MDIO_PMA_REG_LASI_STATUS, &val2);
3193 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3194 ext_phy_addr,
3195 MDIO_PMA_DEVAD,
3196 MDIO_PMA_REG_LASI_STATUS, &val1);
3197 DP(NETIF_MSG_LINK,
3198 "10G-base-T LASI status 0x%x->0x%x\n",
3199 val2, val1);
3200 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3201 ext_phy_addr,
3202 MDIO_PMA_DEVAD,
3203 MDIO_PMA_REG_STATUS, &val2);
3204 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3205 ext_phy_addr,
3206 MDIO_PMA_DEVAD,
3207 MDIO_PMA_REG_STATUS, &val1);
3208 DP(NETIF_MSG_LINK,
3209 "10G-base-T PMA status 0x%x->0x%x\n",
3210 val2, val1);
3211 ext_phy_link_up = ((val1 & 4) == 4);
3212 /* if link is up
3213 * print the AN outcome of the SFX7101 PHY
3214 */
3215 if (ext_phy_link_up) {
3216 bnx2x_cl45_read(bp, params->port,
3217 ext_phy_type,
3218 ext_phy_addr,
3219 MDIO_AN_DEVAD,
3220 MDIO_AN_REG_MASTER_STATUS,
3221 &val2);
57963ed9 3222 vars->line_speed = SPEED_10000;
ea4e040a
YR
3223 DP(NETIF_MSG_LINK,
3224 "SFX7101 AN status 0x%x->Master=%x\n",
3225 val2,
3226 (val2 & (1<<14)));
3227 }
3228 break;
3229
3230 default:
3231 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
3232 params->ext_phy_config);
3233 ext_phy_link_up = 0;
3234 break;
3235 }
3236
3237 } else { /* SerDes */
3238 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3239 switch (ext_phy_type) {
3240 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
3241 DP(NETIF_MSG_LINK, "SerDes Direct\n");
3242 ext_phy_link_up = 1;
3243 break;
3244
3245 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
3246 DP(NETIF_MSG_LINK, "SerDes 5482\n");
3247 ext_phy_link_up = 1;
3248 break;
3249
3250 default:
3251 DP(NETIF_MSG_LINK,
3252 "BAD SerDes ext_phy_config 0x%x\n",
3253 params->ext_phy_config);
3254 ext_phy_link_up = 0;
3255 break;
3256 }
3257 }
3258
3259 return ext_phy_link_up;
3260}
3261
3262static void bnx2x_link_int_enable(struct link_params *params)
3263{
3264 u8 port = params->port;
3265 u32 ext_phy_type;
3266 u32 mask;
3267 struct bnx2x *bp = params->bp;
3268 /* setting the status to report on link up
3269 for either XGXS or SerDes */
3270
3271 if (params->switch_cfg == SWITCH_CFG_10G) {
3272 mask = (NIG_MASK_XGXS0_LINK10G |
3273 NIG_MASK_XGXS0_LINK_STATUS);
3274 DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
3275 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3276 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
3277 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
3278 (ext_phy_type !=
3279 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) {
3280 mask |= NIG_MASK_MI_INT;
3281 DP(NETIF_MSG_LINK, "enabled external phy int\n");
3282 }
3283
3284 } else { /* SerDes */
3285 mask = NIG_MASK_SERDES0_LINK_STATUS;
3286 DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n");
3287 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3288 if ((ext_phy_type !=
3289 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
3290 (ext_phy_type !=
3291 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN)) {
3292 mask |= NIG_MASK_MI_INT;
3293 DP(NETIF_MSG_LINK, "enabled external phy int\n");
3294 }
3295 }
3296 bnx2x_bits_en(bp,
3297 NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
3298 mask);
3299 DP(NETIF_MSG_LINK, "port %x, is_xgxs=%x, int_status 0x%x\n", port,
3300 (params->switch_cfg == SWITCH_CFG_10G),
3301 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
3302
3303 DP(NETIF_MSG_LINK, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n",
3304 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
3305 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
3306 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS+port*0x3c));
3307 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
3308 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
3309 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
3310}
3311
3312
3313/*
3314 * link management
3315 */
3316static void bnx2x_link_int_ack(struct link_params *params,
3196a88a 3317 struct link_vars *vars, u8 is_10g)
ea4e040a
YR
3318{
3319 struct bnx2x *bp = params->bp;
3320 u8 port = params->port;
3321
3322 /* first reset all status
3323 * we assume only one line will be change at a time */
3324 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3325 (NIG_STATUS_XGXS0_LINK10G |
3326 NIG_STATUS_XGXS0_LINK_STATUS |
3327 NIG_STATUS_SERDES0_LINK_STATUS));
3328 if (vars->phy_link_up) {
3329 if (is_10g) {
3330 /* Disable the 10G link interrupt
3331 * by writing 1 to the status register
3332 */
3333 DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
3334 bnx2x_bits_en(bp,
3335 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3336 NIG_STATUS_XGXS0_LINK10G);
3337
3338 } else if (params->switch_cfg == SWITCH_CFG_10G) {
3339 /* Disable the link interrupt
3340 * by writing 1 to the relevant lane
3341 * in the status register
3342 */
3343 u32 ser_lane = ((params->lane_config &
3344 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
3345 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
3346
3347 DP(NETIF_MSG_LINK, "1G XGXS phy link up\n");
3348 bnx2x_bits_en(bp,
3349 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3350 ((1 << ser_lane) <<
3351 NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
3352
3353 } else { /* SerDes */
3354 DP(NETIF_MSG_LINK, "SerDes phy link up\n");
3355 /* Disable the link interrupt
3356 * by writing 1 to the status register
3357 */
3358 bnx2x_bits_en(bp,
3359 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3360 NIG_STATUS_SERDES0_LINK_STATUS);
3361 }
3362
3363 } else { /* link_down */
3364 }
3365}
3366
3367static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len)
3368{
3369 u8 *str_ptr = str;
3370 u32 mask = 0xf0000000;
3371 u8 shift = 8*4;
3372 u8 digit;
3373 if (len < 10) {
025dfdaf 3374 /* Need more than 10chars for this format */
ea4e040a
YR
3375 *str_ptr = '\0';
3376 return -EINVAL;
3377 }
3378 while (shift > 0) {
3379
3380 shift -= 4;
3381 digit = ((num & mask) >> shift);
3382 if (digit < 0xa)
3383 *str_ptr = digit + '0';
3384 else
3385 *str_ptr = digit - 0xa + 'a';
3386 str_ptr++;
3387 mask = mask >> 4;
3388 if (shift == 4*4) {
3389 *str_ptr = ':';
3390 str_ptr++;
3391 }
3392 }
3393 *str_ptr = '\0';
3394 return 0;
3395}
3396
3397
57963ed9
YR
3398static void bnx2x_turn_on_ef(struct bnx2x *bp, u8 port, u8 ext_phy_addr,
3399 u32 ext_phy_type)
ea4e040a
YR
3400{
3401 u32 cnt = 0;
3402 u16 ctrl = 0;
3403 /* Enable EMAC0 in to enable MDIO */
3404 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
3405 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
3406 msleep(5);
3407
3408 /* take ext phy out of reset */
3409 bnx2x_set_gpio(bp,
17de50b7
EG
3410 MISC_REGISTERS_GPIO_2,
3411 MISC_REGISTERS_GPIO_HIGH,
3412 port);
ea4e040a
YR
3413
3414 bnx2x_set_gpio(bp,
17de50b7
EG
3415 MISC_REGISTERS_GPIO_1,
3416 MISC_REGISTERS_GPIO_HIGH,
3417 port);
ea4e040a
YR
3418
3419 /* wait for 5ms */
3420 msleep(5);
3421
3422 for (cnt = 0; cnt < 1000; cnt++) {
3423 msleep(1);
3424 bnx2x_cl45_read(bp, port,
57963ed9 3425 ext_phy_type,
ea4e040a
YR
3426 ext_phy_addr,
3427 MDIO_PMA_DEVAD,
3428 MDIO_PMA_REG_CTRL,
3429 &ctrl);
3430 if (!(ctrl & (1<<15))) {
3431 DP(NETIF_MSG_LINK, "Reset completed\n\n");
3432 break;
3433 }
3434 }
3435}
3436
17de50b7 3437static void bnx2x_turn_off_sf(struct bnx2x *bp, u8 port)
ea4e040a
YR
3438{
3439 /* put sf to reset */
ea4e040a 3440 bnx2x_set_gpio(bp,
17de50b7
EG
3441 MISC_REGISTERS_GPIO_1,
3442 MISC_REGISTERS_GPIO_LOW,
3443 port);
3444 bnx2x_set_gpio(bp,
3445 MISC_REGISTERS_GPIO_2,
3446 MISC_REGISTERS_GPIO_LOW,
3447 port);
ea4e040a
YR
3448}
3449
3450u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
3451 u8 *version, u16 len)
3452{
3453 struct bnx2x *bp = params->bp;
3454 u32 ext_phy_type = 0;
3455 u16 val = 0;
3456 u8 ext_phy_addr = 0 ;
3457 u8 status = 0 ;
3458 u32 ver_num;
3459
3460 if (version == NULL || params == NULL)
3461 return -EINVAL;
3462
3463 /* reset the returned value to zero */
3464 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3465 ext_phy_addr = ((params->ext_phy_config &
3466 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
3467 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
3468
3469 switch (ext_phy_type) {
3470 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3471
3472 if (len < 5)
3473 return -EINVAL;
3474
3475 /* Take ext phy out of reset */
3476 if (!driver_loaded)
57963ed9
YR
3477 bnx2x_turn_on_ef(bp, params->port, ext_phy_addr,
3478 ext_phy_type);
ea4e040a
YR
3479
3480 /* wait for 1ms */
3481 msleep(1);
3482
3483 bnx2x_cl45_read(bp, params->port,
3484 ext_phy_type,
3485 ext_phy_addr,
3486 MDIO_PMA_DEVAD,
3487 MDIO_PMA_REG_7101_VER1, &val);
3488 version[2] = (val & 0xFF);
3489 version[3] = ((val & 0xFF00)>>8);
3490
3491 bnx2x_cl45_read(bp, params->port,
3492 ext_phy_type,
3493 ext_phy_addr,
3494 MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2,
3495 &val);
3496 version[0] = (val & 0xFF);
3497 version[1] = ((val & 0xFF00)>>8);
3498 version[4] = '\0';
3499
3500 if (!driver_loaded)
17de50b7 3501 bnx2x_turn_off_sf(bp, params->port);
ea4e040a
YR
3502 break;
3503 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
3504 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
3505 {
57963ed9
YR
3506 /* Take ext phy out of reset */
3507 if (!driver_loaded)
3508 bnx2x_turn_on_ef(bp, params->port, ext_phy_addr,
3509 ext_phy_type);
3510
ea4e040a
YR
3511 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3512 ext_phy_addr,
3513 MDIO_PMA_DEVAD,
3514 MDIO_PMA_REG_ROM_VER1, &val);
3515 ver_num = val<<16;
3516 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3517 ext_phy_addr,
3518 MDIO_PMA_DEVAD,
3519 MDIO_PMA_REG_ROM_VER2, &val);
3520 ver_num |= val;
3521 status = bnx2x_format_ver(ver_num, version, len);
3522 break;
3523 }
3524 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
3525 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
3526
3527 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3528 ext_phy_addr,
3529 MDIO_PMA_DEVAD,
3530 MDIO_PMA_REG_ROM_VER1, &val);
3531 ver_num = val<<16;
3532 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3533 ext_phy_addr,
3534 MDIO_PMA_DEVAD,
3535 MDIO_PMA_REG_ROM_VER2, &val);
3536 ver_num |= val;
3537 status = bnx2x_format_ver(ver_num, version, len);
3538 break;
3539
3540 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3541 break;
3542
3543 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
3544 DP(NETIF_MSG_LINK, "bnx2x_get_ext_phy_fw_version:"
3545 " type is FAILURE!\n");
3546 status = -EINVAL;
3547 break;
3548
3549 default:
3550 break;
3551 }
3552 return status;
3553}
3554
3555static void bnx2x_set_xgxs_loopback(struct link_params *params,
3556 struct link_vars *vars,
3557 u8 is_10g)
3558{
3559 u8 port = params->port;
3560 struct bnx2x *bp = params->bp;
3561
3562 if (is_10g) {
6378c025 3563 u32 md_devad;
ea4e040a
YR
3564
3565 DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
3566
3567 /* change the uni_phy_addr in the nig */
3568 md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
3569 port*0x18));
3570
3571 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
3572
3573 bnx2x_cl45_write(bp, port, 0,
3574 params->phy_addr,
3575 5,
3576 (MDIO_REG_BANK_AER_BLOCK +
3577 (MDIO_AER_BLOCK_AER_REG & 0xf)),
3578 0x2800);
3579
3580 bnx2x_cl45_write(bp, port, 0,
3581 params->phy_addr,
3582 5,
3583 (MDIO_REG_BANK_CL73_IEEEB0 +
3584 (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
3585 0x6041);
3586
3587 /* set aer mmd back */
3588 bnx2x_set_aer_mmd(params, vars);
3589
3590 /* and md_devad */
3591 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
3592 md_devad);
3593
3594 } else {
3595 u16 mii_control;
3596
3597 DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
3598
3599 CL45_RD_OVER_CL22(bp, port,
3600 params->phy_addr,
3601 MDIO_REG_BANK_COMBO_IEEE0,
3602 MDIO_COMBO_IEEE0_MII_CONTROL,
3603 &mii_control);
3604
3605 CL45_WR_OVER_CL22(bp, port,
3606 params->phy_addr,
3607 MDIO_REG_BANK_COMBO_IEEE0,
3608 MDIO_COMBO_IEEE0_MII_CONTROL,
3609 (mii_control |
3610 MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK));
3611 }
3612}
3613
3614
3615static void bnx2x_ext_phy_loopback(struct link_params *params)
3616{
3617 struct bnx2x *bp = params->bp;
3618 u8 ext_phy_addr;
3619 u32 ext_phy_type;
3620
3621 if (params->switch_cfg == SWITCH_CFG_10G) {
3622 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3623 /* CL37 Autoneg Enabled */
3624 ext_phy_addr = ((params->ext_phy_config &
3625 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
3626 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
3627 switch (ext_phy_type) {
3628 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3629 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
3630 DP(NETIF_MSG_LINK,
3631 "ext_phy_loopback: We should not get here\n");
3632 break;
3633 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
3634 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8705\n");
3635 break;
3636 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
3637 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8706\n");
3638 break;
3639 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3640 /* SFX7101_XGXS_TEST1 */
3641 bnx2x_cl45_write(bp, params->port, ext_phy_type,
3642 ext_phy_addr,
3643 MDIO_XS_DEVAD,
3644 MDIO_XS_SFX7101_XGXS_TEST1,
3645 0x100);
3646 DP(NETIF_MSG_LINK,
3647 "ext_phy_loopback: set ext phy loopback\n");
3648 break;
3649 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
3650
3651 break;
3652 } /* switch external PHY type */
3653 } else {
3654 /* serdes */
3655 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3656 ext_phy_addr = (params->ext_phy_config &
3657 PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK)
3658 >> PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT;
3659 }
3660}
3661
3662
3663/*
3664 *------------------------------------------------------------------------
3665 * bnx2x_override_led_value -
3666 *
3667 * Override the led value of the requsted led
3668 *
3669 *------------------------------------------------------------------------
3670 */
3671u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port,
3672 u32 led_idx, u32 value)
3673{
3674 u32 reg_val;
3675
3676 /* If port 0 then use EMAC0, else use EMAC1*/
3677 u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
3678
3679 DP(NETIF_MSG_LINK,
3680 "bnx2x_override_led_value() port %x led_idx %d value %d\n",
3681 port, led_idx, value);
3682
3683 switch (led_idx) {
3684 case 0: /* 10MB led */
3685 /* Read the current value of the LED register in
3686 the EMAC block */
3687 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3688 /* Set the OVERRIDE bit to 1 */
3689 reg_val |= EMAC_LED_OVERRIDE;
3690 /* If value is 1, set the 10M_OVERRIDE bit,
3691 otherwise reset it.*/
3692 reg_val = (value == 1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) :
3693 (reg_val & ~EMAC_LED_10MB_OVERRIDE);
3694 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3695 break;
3696 case 1: /*100MB led */
3697 /*Read the current value of the LED register in
3698 the EMAC block */
3699 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3700 /* Set the OVERRIDE bit to 1 */
3701 reg_val |= EMAC_LED_OVERRIDE;
3702 /* If value is 1, set the 100M_OVERRIDE bit,
3703 otherwise reset it.*/
3704 reg_val = (value == 1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) :
3705 (reg_val & ~EMAC_LED_100MB_OVERRIDE);
3706 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3707 break;
3708 case 2: /* 1000MB led */
3709 /* Read the current value of the LED register in the
3710 EMAC block */
3711 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3712 /* Set the OVERRIDE bit to 1 */
3713 reg_val |= EMAC_LED_OVERRIDE;
3714 /* If value is 1, set the 1000M_OVERRIDE bit, otherwise
3715 reset it. */
3716 reg_val = (value == 1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) :
3717 (reg_val & ~EMAC_LED_1000MB_OVERRIDE);
3718 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3719 break;
3720 case 3: /* 2500MB led */
3721 /* Read the current value of the LED register in the
3722 EMAC block*/
3723 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3724 /* Set the OVERRIDE bit to 1 */
3725 reg_val |= EMAC_LED_OVERRIDE;
3726 /* If value is 1, set the 2500M_OVERRIDE bit, otherwise
3727 reset it.*/
3728 reg_val = (value == 1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) :
3729 (reg_val & ~EMAC_LED_2500MB_OVERRIDE);
3730 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3731 break;
3732 case 4: /*10G led */
3733 if (port == 0) {
3734 REG_WR(bp, NIG_REG_LED_10G_P0,
3735 value);
3736 } else {
3737 REG_WR(bp, NIG_REG_LED_10G_P1,
3738 value);
3739 }
3740 break;
3741 case 5: /* TRAFFIC led */
3742 /* Find if the traffic control is via BMAC or EMAC */
3743 if (port == 0)
3744 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC0_EN);
3745 else
3746 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC1_EN);
3747
3748 /* Override the traffic led in the EMAC:*/
3749 if (reg_val == 1) {
3750 /* Read the current value of the LED register in
3751 the EMAC block */
3752 reg_val = REG_RD(bp, emac_base +
3753 EMAC_REG_EMAC_LED);
3754 /* Set the TRAFFIC_OVERRIDE bit to 1 */
3755 reg_val |= EMAC_LED_OVERRIDE;
3756 /* If value is 1, set the TRAFFIC bit, otherwise
3757 reset it.*/
3758 reg_val = (value == 1) ? (reg_val | EMAC_LED_TRAFFIC) :
3759 (reg_val & ~EMAC_LED_TRAFFIC);
3760 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3761 } else { /* Override the traffic led in the BMAC: */
3762 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
3763 + port*4, 1);
3764 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port*4,
3765 value);
3766 }
3767 break;
3768 default:
3769 DP(NETIF_MSG_LINK,
3770 "bnx2x_override_led_value() unknown led index %d "
3771 "(should be 0-5)\n", led_idx);
3772 return -EINVAL;
3773 }
3774
3775 return 0;
3776}
3777
3778
3779u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
3780 u16 hw_led_mode, u32 chip_id)
3781{
3782 u8 rc = 0;
345b5d52
EG
3783 u32 tmp;
3784 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
ea4e040a
YR
3785 DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
3786 DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
3787 speed, hw_led_mode);
3788 switch (mode) {
3789 case LED_MODE_OFF:
3790 REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0);
3791 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
3792 SHARED_HW_CFG_LED_MAC1);
345b5d52
EG
3793
3794 tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
3196a88a 3795 EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE));
ea4e040a
YR
3796 break;
3797
3798 case LED_MODE_OPER:
3799 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode);
3800 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
3801 port*4, 0);
3802 /* Set blinking rate to ~15.9Hz */
3803 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
3804 LED_BLINK_RATE_VAL);
3805 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
3806 port*4, 1);
345b5d52 3807 tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
3196a88a 3808 EMAC_WR(bp, EMAC_REG_EMAC_LED,
345b5d52
EG
3809 (tmp & (~EMAC_LED_OVERRIDE)));
3810
34f80b04
EG
3811 if (!CHIP_IS_E1H(bp) &&
3812 ((speed == SPEED_2500) ||
ea4e040a
YR
3813 (speed == SPEED_1000) ||
3814 (speed == SPEED_100) ||
3815 (speed == SPEED_10))) {
3816 /* On Everest 1 Ax chip versions for speeds less than
3817 10G LED scheme is different */
3818 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
3819 + port*4, 1);
3820 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
3821 port*4, 0);
3822 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
3823 port*4, 1);
3824 }
3825 break;
3826
3827 default:
3828 rc = -EINVAL;
3829 DP(NETIF_MSG_LINK, "bnx2x_set_led: Invalid led mode %d\n",
3830 mode);
3831 break;
3832 }
3833 return rc;
3834
3835}
3836
3837u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars)
3838{
3839 struct bnx2x *bp = params->bp;
3840 u16 gp_status = 0;
3841
3842 CL45_RD_OVER_CL22(bp, params->port,
3843 params->phy_addr,
3844 MDIO_REG_BANK_GP_STATUS,
3845 MDIO_GP_STATUS_TOP_AN_STATUS1,
3846 &gp_status);
3847 /* link is up only if both local phy and external phy are up */
3848 if ((gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) &&
3849 bnx2x_ext_phy_is_link_up(params, vars))
3850 return 0;
3851
3852 return -ESRCH;
3853}
3854
3855static u8 bnx2x_link_initialize(struct link_params *params,
3856 struct link_vars *vars)
3857{
3858 struct bnx2x *bp = params->bp;
3859 u8 port = params->port;
3860 u8 rc = 0;
57963ed9
YR
3861 u8 non_ext_phy;
3862 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
ea4e040a
YR
3863 /* Activate the external PHY */
3864 bnx2x_ext_phy_reset(params, vars);
3865
3866 bnx2x_set_aer_mmd(params, vars);
3867
3868 if (vars->phy_flags & PHY_XGXS_FLAG)
3869 bnx2x_set_master_ln(params);
3870
3871 rc = bnx2x_reset_unicore(params);
3872 /* reset the SerDes and wait for reset bit return low */
3873 if (rc != 0)
3874 return rc;
3875
3876 bnx2x_set_aer_mmd(params, vars);
3877
3878 /* setting the masterLn_def again after the reset */
3879 if (vars->phy_flags & PHY_XGXS_FLAG) {
3880 bnx2x_set_master_ln(params);
3881 bnx2x_set_swap_lanes(params);
3882 }
3883
ea4e040a
YR
3884 if (vars->phy_flags & PHY_XGXS_FLAG) {
3885 if (params->req_line_speed &&
3886 ((params->req_line_speed == SPEED_100) ||
3887 (params->req_line_speed == SPEED_10))) {
3888 vars->phy_flags |= PHY_SGMII_FLAG;
3889 } else {
3890 vars->phy_flags &= ~PHY_SGMII_FLAG;
3891 }
3892 }
57963ed9
YR
3893 /* In case of external phy existance, the line speed would be the
3894 line speed linked up by the external phy. In case it is direct only,
3895 then the line_speed during initialization will be equal to the
3896 req_line_speed*/
3897 vars->line_speed = params->req_line_speed;
ea4e040a 3898
8c99e7b0 3899 bnx2x_calc_ieee_aneg_adv(params, &vars->ieee_fc);
ea4e040a 3900
57963ed9
YR
3901 /* init ext phy and enable link state int */
3902 non_ext_phy = ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
3903 (params->loopback_mode == LOOPBACK_XGXS_10) ||
3904 (params->loopback_mode == LOOPBACK_EXT_PHY));
3905
3906 if (non_ext_phy ||
3907 (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705)) {
3908 if (params->req_line_speed == SPEED_AUTO_NEG)
3909 bnx2x_set_parallel_detection(params, vars->phy_flags);
3910 bnx2x_init_internal_phy(params, vars);
ea4e040a
YR
3911 }
3912
57963ed9
YR
3913 if (!non_ext_phy)
3914 rc |= bnx2x_ext_phy_init(params, vars);
ea4e040a
YR
3915
3916 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
57963ed9
YR
3917 (NIG_STATUS_XGXS0_LINK10G |
3918 NIG_STATUS_XGXS0_LINK_STATUS |
3919 NIG_STATUS_SERDES0_LINK_STATUS));
ea4e040a
YR
3920
3921 return rc;
3922
3923}
3924
3925
3926u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
3927{
3928 struct bnx2x *bp = params->bp;
3929
3930 u32 val;
3196a88a 3931 DP(NETIF_MSG_LINK, "Phy Initialization started \n");
ea4e040a
YR
3932 DP(NETIF_MSG_LINK, "req_speed = %d, req_flowctrl=%d\n",
3933 params->req_line_speed, params->req_flow_ctrl);
3934 vars->link_status = 0;
57963ed9
YR
3935 vars->phy_link_up = 0;
3936 vars->link_up = 0;
3937 vars->line_speed = 0;
3938 vars->duplex = DUPLEX_FULL;
c0700f90 3939 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
57963ed9
YR
3940 vars->mac_type = MAC_TYPE_NONE;
3941
ea4e040a
YR
3942 if (params->switch_cfg == SWITCH_CFG_1G)
3943 vars->phy_flags = PHY_SERDES_FLAG;
3944 else
3945 vars->phy_flags = PHY_XGXS_FLAG;
3946
3196a88a 3947
ea4e040a
YR
3948 /* disable attentions */
3949 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
3950 (NIG_MASK_XGXS0_LINK_STATUS |
3951 NIG_MASK_XGXS0_LINK10G |
3952 NIG_MASK_SERDES0_LINK_STATUS |
3953 NIG_MASK_MI_INT));
3954
3955 bnx2x_emac_init(params, vars);
3956
3957 if (CHIP_REV_IS_FPGA(bp)) {
3958 vars->link_up = 1;
3959 vars->line_speed = SPEED_10000;
3960 vars->duplex = DUPLEX_FULL;
c0700f90 3961 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
ea4e040a 3962 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
34f80b04
EG
3963 /* enable on E1.5 FPGA */
3964 if (CHIP_IS_E1H(bp)) {
3965 vars->flow_ctrl |=
c0700f90 3966 (BNX2X_FLOW_CTRL_TX | BNX2X_FLOW_CTRL_RX);
34f80b04
EG
3967 vars->link_status |=
3968 (LINK_STATUS_TX_FLOW_CONTROL_ENABLED |
3969 LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
3970 }
ea4e040a
YR
3971
3972 bnx2x_emac_enable(params, vars, 0);
3973 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
3974 /* disable drain */
3975 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
3976 + params->port*4, 0);
3977
3978 /* update shared memory */
3979 bnx2x_update_mng(params, vars->link_status);
3980
3981 return 0;
3982
3983 } else
3984 if (CHIP_REV_IS_EMUL(bp)) {
3985
3986 vars->link_up = 1;
3987 vars->line_speed = SPEED_10000;
3988 vars->duplex = DUPLEX_FULL;
c0700f90 3989 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
ea4e040a
YR
3990 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
3991
3992 bnx2x_bmac_enable(params, vars, 0);
3993
3994 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
3995 /* Disable drain */
3996 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
3997 + params->port*4, 0);
3998
3999 /* update shared memory */
4000 bnx2x_update_mng(params, vars->link_status);
4001
4002 return 0;
4003
4004 } else
4005 if (params->loopback_mode == LOOPBACK_BMAC) {
4006 vars->link_up = 1;
4007 vars->line_speed = SPEED_10000;
4008 vars->duplex = DUPLEX_FULL;
c0700f90 4009 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
ea4e040a
YR
4010 vars->mac_type = MAC_TYPE_BMAC;
4011
4012 vars->phy_flags = PHY_XGXS_FLAG;
4013
4014 bnx2x_phy_deassert(params, vars->phy_flags);
4015 /* set bmac loopback */
4016 bnx2x_bmac_enable(params, vars, 1);
4017
4018 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
4019 params->port*4, 0);
4020 } else if (params->loopback_mode == LOOPBACK_EMAC) {
4021 vars->link_up = 1;
4022 vars->line_speed = SPEED_1000;
4023 vars->duplex = DUPLEX_FULL;
c0700f90 4024 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
ea4e040a
YR
4025 vars->mac_type = MAC_TYPE_EMAC;
4026
4027 vars->phy_flags = PHY_XGXS_FLAG;
4028
4029 bnx2x_phy_deassert(params, vars->phy_flags);
4030 /* set bmac loopback */
4031 bnx2x_emac_enable(params, vars, 1);
4032 bnx2x_emac_program(params, vars->line_speed,
4033 vars->duplex);
4034 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
4035 params->port*4, 0);
4036 } else if ((params->loopback_mode == LOOPBACK_XGXS_10) ||
4037 (params->loopback_mode == LOOPBACK_EXT_PHY)) {
4038 vars->link_up = 1;
4039 vars->line_speed = SPEED_10000;
4040 vars->duplex = DUPLEX_FULL;
c0700f90 4041 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
ea4e040a
YR
4042
4043 vars->phy_flags = PHY_XGXS_FLAG;
4044
4045 val = REG_RD(bp,
4046 NIG_REG_XGXS0_CTRL_PHY_ADDR+
4047 params->port*0x18);
4048 params->phy_addr = (u8)val;
4049
4050 bnx2x_phy_deassert(params, vars->phy_flags);
4051 bnx2x_link_initialize(params, vars);
4052
4053 vars->mac_type = MAC_TYPE_BMAC;
4054
4055 bnx2x_bmac_enable(params, vars, 0);
4056
4057 if (params->loopback_mode == LOOPBACK_XGXS_10) {
4058 /* set 10G XGXS loopback */
4059 bnx2x_set_xgxs_loopback(params, vars, 1);
4060 } else {
4061 /* set external phy loopback */
4062 bnx2x_ext_phy_loopback(params);
4063 }
4064 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
4065 params->port*4, 0);
4066 } else
4067 /* No loopback */
4068 {
4069
4070 bnx2x_phy_deassert(params, vars->phy_flags);
4071 switch (params->switch_cfg) {
4072 case SWITCH_CFG_1G:
4073 vars->phy_flags |= PHY_SERDES_FLAG;
4074 if ((params->ext_phy_config &
4075 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK) ==
4076 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482) {
4077 vars->phy_flags |=
4078 PHY_SGMII_FLAG;
4079 }
4080
4081 val = REG_RD(bp,
4082 NIG_REG_SERDES0_CTRL_PHY_ADDR+
4083 params->port*0x10);
4084
4085 params->phy_addr = (u8)val;
4086
4087 break;
4088 case SWITCH_CFG_10G:
4089 vars->phy_flags |= PHY_XGXS_FLAG;
4090 val = REG_RD(bp,
4091 NIG_REG_XGXS0_CTRL_PHY_ADDR+
4092 params->port*0x18);
4093 params->phy_addr = (u8)val;
4094
4095 break;
4096 default:
4097 DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
4098 return -EINVAL;
4099 break;
4100 }
4101
4102 bnx2x_link_initialize(params, vars);
57963ed9 4103 msleep(30);
ea4e040a
YR
4104 bnx2x_link_int_enable(params);
4105 }
4106 return 0;
4107}
4108
4109u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars)
4110{
4111
4112 struct bnx2x *bp = params->bp;
4113 u32 ext_phy_config = params->ext_phy_config;
4114 u16 hw_led_mode = params->hw_led_mode;
4115 u32 chip_id = params->chip_id;
4116 u8 port = params->port;
4117 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
4118 /* disable attentions */
4119
4120 vars->link_status = 0;
4121 bnx2x_update_mng(params, vars->link_status);
4122 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
4123 (NIG_MASK_XGXS0_LINK_STATUS |
4124 NIG_MASK_XGXS0_LINK10G |
4125 NIG_MASK_SERDES0_LINK_STATUS |
4126 NIG_MASK_MI_INT));
4127
4128 /* activate nig drain */
4129 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
4130
4131 /* disable nig egress interface */
4132 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
4133 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
4134
4135 /* Stop BigMac rx */
4136 bnx2x_bmac_rx_disable(bp, port);
4137
4138 /* disable emac */
4139 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
4140
4141 msleep(10);
4142 /* The PHY reset is controled by GPIO 1
4143 * Hold it as vars low
4144 */
4145 /* clear link led */
4146 bnx2x_set_led(bp, port, LED_MODE_OFF, 0, hw_led_mode, chip_id);
4147 if (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
4148 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
4149 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
4150 /* HW reset */
4151
4152 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
17de50b7
EG
4153 MISC_REGISTERS_GPIO_OUTPUT_LOW,
4154 port);
ea4e040a
YR
4155
4156 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
17de50b7
EG
4157 MISC_REGISTERS_GPIO_OUTPUT_LOW,
4158 port);
ea4e040a
YR
4159
4160 DP(NETIF_MSG_LINK, "reset external PHY\n");
57963ed9
YR
4161 } else if (ext_phy_type ==
4162 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
4163 DP(NETIF_MSG_LINK, "Setting 8073 port %d into "
ea4e040a
YR
4164 "low power mode\n",
4165 port);
4166 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
17de50b7
EG
4167 MISC_REGISTERS_GPIO_OUTPUT_LOW,
4168 port);
ea4e040a
YR
4169 }
4170 }
4171 /* reset the SerDes/XGXS */
4172 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
4173 (0x1ff << (port*16)));
4174
4175 /* reset BigMac */
4176 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
4177 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
4178
4179 /* disable nig ingress interface */
4180 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
4181 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
4182 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
4183 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
4184 vars->link_up = 0;
4185 return 0;
4186}
4187
57963ed9
YR
4188static u8 bnx2x_update_link_down(struct link_params *params,
4189 struct link_vars *vars)
4190{
4191 struct bnx2x *bp = params->bp;
4192 u8 port = params->port;
4193 DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
4194 bnx2x_set_led(bp, port, LED_MODE_OFF,
4195 0, params->hw_led_mode,
4196 params->chip_id);
4197
4198 /* indicate no mac active */
4199 vars->mac_type = MAC_TYPE_NONE;
4200
4201 /* update shared memory */
4202 vars->link_status = 0;
4203 vars->line_speed = 0;
4204 bnx2x_update_mng(params, vars->link_status);
4205
4206 /* activate nig drain */
4207 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
4208
6c55c3cd
EG
4209 /* disable emac */
4210 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
4211
4212 msleep(10);
4213
57963ed9
YR
4214 /* reset BigMac */
4215 bnx2x_bmac_rx_disable(bp, params->port);
4216 REG_WR(bp, GRCBASE_MISC +
4217 MISC_REGISTERS_RESET_REG_2_CLEAR,
4218 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
4219 return 0;
4220}
4221
4222static u8 bnx2x_update_link_up(struct link_params *params,
4223 struct link_vars *vars,
4224 u8 link_10g, u32 gp_status)
4225{
4226 struct bnx2x *bp = params->bp;
4227 u8 port = params->port;
4228 u8 rc = 0;
4229 vars->link_status |= LINK_STATUS_LINK_UP;
4230 if (link_10g) {
4231 bnx2x_bmac_enable(params, vars, 0);
4232 bnx2x_set_led(bp, port, LED_MODE_OPER,
4233 SPEED_10000, params->hw_led_mode,
4234 params->chip_id);
4235
4236 } else {
4237 bnx2x_emac_enable(params, vars, 0);
4238 rc = bnx2x_emac_program(params, vars->line_speed,
4239 vars->duplex);
4240
4241 /* AN complete? */
4242 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
4243 if (!(vars->phy_flags &
4244 PHY_SGMII_FLAG))
4245 bnx2x_set_sgmii_tx_driver(params);
4246 }
4247 }
4248
4249 /* PBF - link up */
4250 rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
4251 vars->line_speed);
4252
4253 /* disable drain */
4254 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
4255
4256 /* update shared memory */
4257 bnx2x_update_mng(params, vars->link_status);
6c55c3cd 4258 msleep(20);
57963ed9
YR
4259 return rc;
4260}
ea4e040a
YR
4261/* This function should called upon link interrupt */
4262/* In case vars->link_up, driver needs to
4263 1. Update the pbf
4264 2. Disable drain
4265 3. Update the shared memory
4266 4. Indicate link up
4267 5. Set LEDs
4268 Otherwise,
4269 1. Update shared memory
4270 2. Reset BigMac
4271 3. Report link down
4272 4. Unset LEDs
4273*/
4274u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
4275{
4276 struct bnx2x *bp = params->bp;
4277 u8 port = params->port;
ea4e040a 4278 u16 gp_status;
57963ed9
YR
4279 u8 link_10g;
4280 u8 ext_phy_link_up, rc = 0;
4281 u32 ext_phy_type;
ea4e040a
YR
4282
4283 DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
4284 port,
4285 (vars->phy_flags & PHY_XGXS_FLAG),
4286 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
4287
4288 DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
4289 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
4290 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
4291 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
4292
4293 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
4294 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
4295 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
4296
6c55c3cd
EG
4297 /* disable emac */
4298 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
4299
57963ed9 4300 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
ea4e040a 4301
57963ed9
YR
4302 /* Check external link change only for non-direct */
4303 ext_phy_link_up = bnx2x_ext_phy_is_link_up(params, vars);
4304
4305 /* Read gp_status */
4306 CL45_RD_OVER_CL22(bp, port, params->phy_addr,
4307 MDIO_REG_BANK_GP_STATUS,
4308 MDIO_GP_STATUS_TOP_AN_STATUS1,
4309 &gp_status);
ea4e040a
YR
4310
4311 rc = bnx2x_link_settings_status(params, vars, gp_status);
4312 if (rc != 0)
4313 return rc;
4314
4315 /* anything 10 and over uses the bmac */
4316 link_10g = ((vars->line_speed == SPEED_10000) ||
4317 (vars->line_speed == SPEED_12000) ||
4318 (vars->line_speed == SPEED_12500) ||
4319 (vars->line_speed == SPEED_13000) ||
4320 (vars->line_speed == SPEED_15000) ||
4321 (vars->line_speed == SPEED_16000));
4322
4323 bnx2x_link_int_ack(params, vars, link_10g);
4324
57963ed9
YR
4325 /* In case external phy link is up, and internal link is down
4326 ( not initialized yet probably after link initialization, it needs
4327 to be initialized.
4328 Note that after link down-up as result of cable plug,
4329 the xgxs link would probably become up again without the need to
4330 initialize it*/
ea4e040a 4331
57963ed9
YR
4332 if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
4333 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) &&
4334 (ext_phy_link_up && !vars->phy_link_up))
4335 bnx2x_init_internal_phy(params, vars);
ea4e040a 4336
57963ed9
YR
4337 /* link is up only if both local phy and external phy are up */
4338 vars->link_up = (ext_phy_link_up && vars->phy_link_up);
ea4e040a 4339
57963ed9
YR
4340 if (vars->link_up)
4341 rc = bnx2x_update_link_up(params, vars, link_10g, gp_status);
4342 else
4343 rc = bnx2x_update_link_down(params, vars);
ea4e040a
YR
4344
4345 return rc;
4346}
4347
6bbca910
YR
4348static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
4349{
4350 u8 ext_phy_addr[PORT_MAX];
4351 u16 val;
4352 s8 port;
4353
4354 /* PART1 - Reset both phys */
4355 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4356 /* Extract the ext phy address for the port */
4357 u32 ext_phy_config = REG_RD(bp, shmem_base +
4358 offsetof(struct shmem_region,
4359 dev_info.port_hw_config[port].external_phy_config));
4360
4361 /* disable attentions */
4362 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
4363 (NIG_MASK_XGXS0_LINK_STATUS |
4364 NIG_MASK_XGXS0_LINK10G |
4365 NIG_MASK_SERDES0_LINK_STATUS |
4366 NIG_MASK_MI_INT));
4367
4368 ext_phy_addr[port] =
4369 ((ext_phy_config &
4370 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
4371 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
4372
4373 /* Need to take the phy out of low power mode in order
4374 to write to access its registers */
4375 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4376 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
4377
4378 /* Reset the phy */
4379 bnx2x_cl45_write(bp, port,
4380 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4381 ext_phy_addr[port],
4382 MDIO_PMA_DEVAD,
4383 MDIO_PMA_REG_CTRL,
4384 1<<15);
4385 }
4386
4387 /* Add delay of 150ms after reset */
4388 msleep(150);
4389
4390 /* PART2 - Download firmware to both phys */
4391 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4392 u16 fw_ver1;
4393
4394 bnx2x_bcm8073_external_rom_boot(bp, port,
4395 ext_phy_addr[port]);
4396
4397 bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4398 ext_phy_addr[port],
4399 MDIO_PMA_DEVAD,
4400 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
4401 if (fw_ver1 == 0) {
4402 DP(NETIF_MSG_LINK,
4403 "bnx2x_8073_common_init_phy port %x "
4404 "fw Download failed\n", port);
4405 return -EINVAL;
4406 }
4407
4408 /* Only set bit 10 = 1 (Tx power down) */
4409 bnx2x_cl45_read(bp, port,
4410 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4411 ext_phy_addr[port],
4412 MDIO_PMA_DEVAD,
4413 MDIO_PMA_REG_TX_POWER_DOWN, &val);
4414
4415 /* Phase1 of TX_POWER_DOWN reset */
4416 bnx2x_cl45_write(bp, port,
4417 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4418 ext_phy_addr[port],
4419 MDIO_PMA_DEVAD,
4420 MDIO_PMA_REG_TX_POWER_DOWN,
4421 (val | 1<<10));
4422 }
4423
4424 /* Toggle Transmitter: Power down and then up with 600ms
4425 delay between */
4426 msleep(600);
4427
4428 /* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low */
4429 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4430 /* Phase2 of POWER_DOWN_RESET*/
4431 /* Release bit 10 (Release Tx power down) */
4432 bnx2x_cl45_read(bp, port,
4433 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4434 ext_phy_addr[port],
4435 MDIO_PMA_DEVAD,
4436 MDIO_PMA_REG_TX_POWER_DOWN, &val);
4437
4438 bnx2x_cl45_write(bp, port,
4439 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4440 ext_phy_addr[port],
4441 MDIO_PMA_DEVAD,
4442 MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
4443 msleep(15);
4444
4445 /* Read modify write the SPI-ROM version select register */
4446 bnx2x_cl45_read(bp, port,
4447 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4448 ext_phy_addr[port],
4449 MDIO_PMA_DEVAD,
4450 MDIO_PMA_REG_EDC_FFE_MAIN, &val);
4451 bnx2x_cl45_write(bp, port,
4452 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
4453 ext_phy_addr[port],
4454 MDIO_PMA_DEVAD,
4455 MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
4456
4457 /* set GPIO2 back to LOW */
4458 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4459 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
4460 }
4461 return 0;
4462
4463}
4464
4465u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base)
4466{
4467 u8 rc = 0;
4468 u32 ext_phy_type;
4469
4470 DP(NETIF_MSG_LINK, "bnx2x_common_init_phy\n");
4471
4472 /* Read the ext_phy_type for arbitrary port(0) */
4473 ext_phy_type = XGXS_EXT_PHY_TYPE(
4474 REG_RD(bp, shmem_base +
4475 offsetof(struct shmem_region,
4476 dev_info.port_hw_config[0].external_phy_config)));
4477
4478 switch (ext_phy_type) {
4479 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
4480 {
4481 rc = bnx2x_8073_common_init_phy(bp, shmem_base);
4482 break;
4483 }
4484 default:
4485 DP(NETIF_MSG_LINK,
4486 "bnx2x_common_init_phy: ext_phy 0x%x not required\n",
4487 ext_phy_type);
4488 break;
4489 }
4490
4491 return rc;
4492}
4493
4494
4495
ea4e040a
YR
4496static void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
4497{
4498 u16 val, cnt;
4499
4500 bnx2x_cl45_read(bp, port,
4501 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4502 phy_addr,
4503 MDIO_PMA_DEVAD,
4504 MDIO_PMA_REG_7101_RESET, &val);
4505
4506 for (cnt = 0; cnt < 10; cnt++) {
4507 msleep(50);
4508 /* Writes a self-clearing reset */
4509 bnx2x_cl45_write(bp, port,
4510 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4511 phy_addr,
4512 MDIO_PMA_DEVAD,
4513 MDIO_PMA_REG_7101_RESET,
4514 (val | (1<<15)));
4515 /* Wait for clear */
4516 bnx2x_cl45_read(bp, port,
4517 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4518 phy_addr,
4519 MDIO_PMA_DEVAD,
4520 MDIO_PMA_REG_7101_RESET, &val);
4521
4522 if ((val & (1<<15)) == 0)
4523 break;
4524 }
4525}
4526#define RESERVED_SIZE 256
4527/* max application is 160K bytes - data at end of RAM */
6378c025 4528#define MAX_APP_SIZE (160*1024 - RESERVED_SIZE)
ea4e040a
YR
4529
4530/* Header is 14 bytes */
4531#define HEADER_SIZE 14
4532#define DATA_OFFSET HEADER_SIZE
4533
4534#define SPI_START_TRANSFER(bp, port, ext_phy_addr) \
4535 bnx2x_cl45_write(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101, \
4536 ext_phy_addr, \
4537 MDIO_PCS_DEVAD, \
4538 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 1)
4539
4540/* Programs an image to DSP's flash via the SPI port*/
4541static u8 bnx2x_sfx7101_flash_download(struct bnx2x *bp, u8 port,
4542 u8 ext_phy_addr,
4543 char data[], u32 size)
4544{
4545 const u16 num_trans = size/4; /* 4 bytes can be sent at a time */
4546 /* Doesn't include last trans!*/
4547 const u16 last_trans_size = size%4; /* Num bytes on last trans */
4548 u16 trans_cnt, byte_cnt;
4549 u32 data_index;
4550 u16 tmp;
4551 u16 code_started = 0;
4552 u16 image_revision1, image_revision2;
4553 u16 cnt;
4554
4555 DP(NETIF_MSG_LINK, "bnx2x_sfx7101_flash_download file_size=%d\n", size);
4556 /* Going to flash*/
4557 if ((size-HEADER_SIZE) > MAX_APP_SIZE) {
4558 /* This very often will be the case, because the image is built
4559 with 160Kbytes size whereas the total image size must actually
4560 be 160Kbytes-RESERVED_SIZE */
4561 DP(NETIF_MSG_LINK, "Warning, file size was %d bytes "
4562 "truncated to %d bytes\n", size, MAX_APP_SIZE);
4563 size = MAX_APP_SIZE+HEADER_SIZE;
4564 }
4565 DP(NETIF_MSG_LINK, "File version is %c%c\n", data[0x14e], data[0x14f]);
3196a88a 4566 DP(NETIF_MSG_LINK, " %c%c\n", data[0x150], data[0x151]);
ea4e040a
YR
4567 /* Put the DSP in download mode by setting FLASH_CFG[2] to 1
4568 and issuing a reset.*/
4569
4570 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
17de50b7 4571 MISC_REGISTERS_GPIO_HIGH, port);
ea4e040a
YR
4572
4573 bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
4574
4575 /* wait 0.5 sec */
4576 for (cnt = 0; cnt < 100; cnt++)
4577 msleep(5);
4578
4579 /* Make sure we can access the DSP
4580 And it's in the correct mode (waiting for download) */
4581
4582 bnx2x_cl45_read(bp, port,
4583 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4584 ext_phy_addr,
4585 MDIO_PCS_DEVAD,
4586 MDIO_PCS_REG_7101_DSP_ACCESS, &tmp);
4587
4588 if (tmp != 0x000A) {
4589 DP(NETIF_MSG_LINK, "DSP is not in waiting on download mode. "
4590 "Expected 0x000A, read 0x%04X\n", tmp);
4591 DP(NETIF_MSG_LINK, "Download failed\n");
4592 return -EINVAL;
4593 }
4594
4595 /* Mux the SPI interface away from the internal processor */
4596 bnx2x_cl45_write(bp, port,
4597 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4598 ext_phy_addr,
4599 MDIO_PCS_DEVAD,
4600 MDIO_PCS_REG_7101_SPI_MUX, 1);
4601
4602 /* Reset the SPI port */
4603 bnx2x_cl45_write(bp, port,
4604 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4605 ext_phy_addr,
4606 MDIO_PCS_DEVAD,
4607 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
4608 bnx2x_cl45_write(bp, port,
4609 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4610 ext_phy_addr,
4611 MDIO_PCS_DEVAD,
4612 MDIO_PCS_REG_7101_SPI_CTRL_ADDR,
4613 (1<<MDIO_PCS_REG_7101_SPI_RESET_BIT));
4614 bnx2x_cl45_write(bp, port,
4615 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4616 ext_phy_addr,
4617 MDIO_PCS_DEVAD,
4618 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
4619
4620 /* Erase the flash */
4621 bnx2x_cl45_write(bp, port,
4622 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4623 ext_phy_addr,
4624 MDIO_PCS_DEVAD,
4625 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4626 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4627
4628 bnx2x_cl45_write(bp, port,
4629 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4630 ext_phy_addr,
4631 MDIO_PCS_DEVAD,
4632 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4633 1);
4634
4635 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4636 bnx2x_cl45_write(bp, port,
4637 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4638 ext_phy_addr,
4639 MDIO_PCS_DEVAD,
4640 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4641 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_BULK_ERASE_CMD);
4642
4643 bnx2x_cl45_write(bp, port,
4644 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4645 ext_phy_addr,
4646 MDIO_PCS_DEVAD,
4647 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4648 1);
4649 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4650
4651 /* Wait 10 seconds, the maximum time for the erase to complete */
4652 DP(NETIF_MSG_LINK, "Erasing flash, this takes 10 seconds...\n");
4653 for (cnt = 0; cnt < 1000; cnt++)
4654 msleep(10);
4655
4656 DP(NETIF_MSG_LINK, "Downloading flash, please wait...\n");
4657 data_index = 0;
4658 for (trans_cnt = 0; trans_cnt < num_trans; trans_cnt++) {
4659 bnx2x_cl45_write(bp, port,
4660 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4661 ext_phy_addr,
4662 MDIO_PCS_DEVAD,
4663 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4664 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4665
4666 bnx2x_cl45_write(bp, port,
4667 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4668 ext_phy_addr,
4669 MDIO_PCS_DEVAD,
4670 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4671 1);
4672 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4673
4674 bnx2x_cl45_write(bp, port,
4675 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4676 ext_phy_addr,
4677 MDIO_PCS_DEVAD,
4678 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4679 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
4680
4681 /* Bits 23-16 of address */
4682 bnx2x_cl45_write(bp, port,
4683 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4684 ext_phy_addr,
4685 MDIO_PCS_DEVAD,
4686 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4687 (data_index>>16));
4688 /* Bits 15-8 of address */
4689 bnx2x_cl45_write(bp, port,
4690 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4691 ext_phy_addr,
4692 MDIO_PCS_DEVAD,
4693 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4694 (data_index>>8));
4695
4696 /* Bits 7-0 of address */
4697 bnx2x_cl45_write(bp, port,
4698 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4699 ext_phy_addr,
4700 MDIO_PCS_DEVAD,
4701 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4702 ((u16)data_index));
4703
4704 byte_cnt = 0;
4705 while (byte_cnt < 4 && data_index < size) {
4706 bnx2x_cl45_write(bp, port,
4707 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4708 ext_phy_addr,
4709 MDIO_PCS_DEVAD,
4710 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4711 data[data_index++]);
4712 byte_cnt++;
4713 }
4714
4715 bnx2x_cl45_write(bp, port,
4716 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4717 ext_phy_addr,
4718 MDIO_PCS_DEVAD,
4719 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4720 byte_cnt+4);
4721
4722 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4723 msleep(5); /* Wait 5 ms minimum between transs */
4724
4725 /* Let the user know something's going on.*/
4726 /* a pacifier ever 4K */
4727 if ((data_index % 1023) == 0)
4728 DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
4729 }
4730
4731 DP(NETIF_MSG_LINK, "\n");
4732 /* Transfer the last block if there is data remaining */
4733 if (last_trans_size) {
4734 bnx2x_cl45_write(bp, port,
4735 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4736 ext_phy_addr,
4737 MDIO_PCS_DEVAD,
4738 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4739 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4740
4741 bnx2x_cl45_write(bp, port,
4742 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4743 ext_phy_addr,
4744 MDIO_PCS_DEVAD,
4745 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4746 1);
4747
4748 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4749
4750 bnx2x_cl45_write(bp, port,
4751 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4752 ext_phy_addr,
4753 MDIO_PCS_DEVAD,
4754 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4755 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
4756
4757 /* Bits 23-16 of address */
4758 bnx2x_cl45_write(bp, port,
4759 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4760 ext_phy_addr,
4761 MDIO_PCS_DEVAD,
4762 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4763 (data_index>>16));
4764 /* Bits 15-8 of address */
4765 bnx2x_cl45_write(bp, port,
4766 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4767 ext_phy_addr,
4768 MDIO_PCS_DEVAD,
4769 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4770 (data_index>>8));
4771
4772 /* Bits 7-0 of address */
4773 bnx2x_cl45_write(bp, port,
4774 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4775 ext_phy_addr,
4776 MDIO_PCS_DEVAD,
4777 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4778 ((u16)data_index));
4779
4780 byte_cnt = 0;
4781 while (byte_cnt < last_trans_size && data_index < size) {
4782 /* Bits 7-0 of address */
4783 bnx2x_cl45_write(bp, port,
4784 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4785 ext_phy_addr,
4786 MDIO_PCS_DEVAD,
4787 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4788 data[data_index++]);
4789 byte_cnt++;
4790 }
4791
4792 bnx2x_cl45_write(bp, port,
4793 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4794 ext_phy_addr,
4795 MDIO_PCS_DEVAD,
4796 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4797 byte_cnt+4);
4798
4799 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4800 }
4801
4802 /* DSP Remove Download Mode */
17de50b7
EG
4803 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
4804 MISC_REGISTERS_GPIO_LOW, port);
ea4e040a
YR
4805
4806 bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
4807
4808 /* wait 0.5 sec to allow it to run */
4809 for (cnt = 0; cnt < 100; cnt++)
4810 msleep(5);
4811
17de50b7 4812 bnx2x_hw_reset(bp, port);
ea4e040a
YR
4813
4814 for (cnt = 0; cnt < 100; cnt++)
4815 msleep(5);
4816
4817 /* Check that the code is started. In case the download
4818 checksum failed, the code won't be started. */
4819 bnx2x_cl45_read(bp, port,
4820 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4821 ext_phy_addr,
4822 MDIO_PCS_DEVAD,
4823 MDIO_PCS_REG_7101_DSP_ACCESS,
4824 &tmp);
4825
4826 code_started = (tmp & (1<<4));
4827 if (!code_started) {
4828 DP(NETIF_MSG_LINK, "Download failed. Please check file.\n");
4829 return -EINVAL;
4830 }
4831
4832 /* Verify that the file revision is now equal to the image
4833 revision within the DSP */
4834 bnx2x_cl45_read(bp, port,
4835 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4836 ext_phy_addr,
4837 MDIO_PMA_DEVAD,
4838 MDIO_PMA_REG_7101_VER1,
4839 &image_revision1);
4840
4841 bnx2x_cl45_read(bp, port,
4842 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4843 ext_phy_addr,
4844 MDIO_PMA_DEVAD,
4845 MDIO_PMA_REG_7101_VER2,
4846 &image_revision2);
4847
3196a88a 4848 if (data[0x14e] != (image_revision2&0xFF) ||
ea4e040a
YR
4849 data[0x14f] != ((image_revision2&0xFF00)>>8) ||
4850 data[0x150] != (image_revision1&0xFF) ||
4851 data[0x151] != ((image_revision1&0xFF00)>>8)) {
4852 DP(NETIF_MSG_LINK, "Download failed.\n");
4853 return -EINVAL;
4854 }
4855 DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
4856 return 0;
4857}
4858
4859u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config,
4860 u8 driver_loaded, char data[], u32 size)
4861{
4862 u8 rc = 0;
4863 u32 ext_phy_type;
4864 u8 ext_phy_addr;
4865 ext_phy_addr = ((ext_phy_config &
4866 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
4867 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
4868
4869 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
4870
4871 switch (ext_phy_type) {
4872 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
4873 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
4874 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
4875 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
4876 DP(NETIF_MSG_LINK,
4877 "Flash download not supported for this ext phy\n");
4878 rc = -EINVAL;
4879 break;
4880 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
4881 /* Take ext phy out of reset */
4882 if (!driver_loaded)
57963ed9 4883 bnx2x_turn_on_ef(bp, port, ext_phy_addr, ext_phy_type);
ea4e040a
YR
4884 rc = bnx2x_sfx7101_flash_download(bp, port, ext_phy_addr,
4885 data, size);
4886 if (!driver_loaded)
17de50b7 4887 bnx2x_turn_off_sf(bp, port);
ea4e040a
YR
4888 break;
4889 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
4890 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
4891 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
4892 default:
4893 DP(NETIF_MSG_LINK, "Invalid ext phy type\n");
4894 rc = -EINVAL;
4895 break;
4896 }
4897 return rc;
4898}
4899