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