blob: 3b63c8ce952ab5141cce185c611b4d4147610aa1 [file] [log] [blame]
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07001/* 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
Yaniv Rosner57963ed2008-08-13 15:55:28 -07001693 if ((params->req_line_speed == SPEED_AUTO_NEG) &&
1694 ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1695 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
1696 (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1697 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705))) {
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07001698 vars->autoneg = AUTO_NEG_ENABLED;
1699
1700 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
1701 vars->autoneg |= AUTO_NEG_COMPLETE;
1702 vars->link_status |=
1703 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
1704 }
1705
1706 vars->autoneg |= AUTO_NEG_PARALLEL_DETECTION_USED;
1707 vars->link_status |=
1708 LINK_STATUS_PARALLEL_DETECTION_USED;
1709
1710 }
1711 if (vars->flow_ctrl & FLOW_CTRL_TX)
1712 vars->link_status |=
1713 LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
1714
1715 if (vars->flow_ctrl & FLOW_CTRL_RX)
1716 vars->link_status |=
1717 LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
1718
1719 } else { /* link_down */
1720 DP(NETIF_MSG_LINK, "phy link down\n");
1721
1722 vars->phy_link_up = 0;
Yaniv Rosner57963ed2008-08-13 15:55:28 -07001723
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07001724 vars->duplex = DUPLEX_FULL;
1725 vars->flow_ctrl = FLOW_CTRL_NONE;
1726 vars->autoneg = AUTO_NEG_DISABLED;
1727 vars->mac_type = MAC_TYPE_NONE;
1728 }
1729
1730 DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x \n",
1731 gp_status, vars->phy_link_up, vars->line_speed);
1732 DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x"
1733 " autoneg 0x%x\n",
1734 vars->duplex,
1735 vars->flow_ctrl, vars->autoneg);
1736 DP(NETIF_MSG_LINK, "link_status 0x%x\n", vars->link_status);
1737
1738 return rc;
1739}
1740
1741static void bnx2x_set_sgmii_tx_driver(struct link_params *params)
1742{
1743 struct bnx2x *bp = params->bp;
1744 u16 lp_up2;
1745 u16 tx_driver;
1746
1747 /* read precomp */
1748
1749 CL45_RD_OVER_CL22(bp, params->port,
1750 params->phy_addr,
1751 MDIO_REG_BANK_OVER_1G,
1752 MDIO_OVER_1G_LP_UP2, &lp_up2);
1753
1754 CL45_RD_OVER_CL22(bp, params->port,
1755 params->phy_addr,
1756 MDIO_REG_BANK_TX0,
1757 MDIO_TX0_TX_DRIVER, &tx_driver);
1758
1759 /* bits [10:7] at lp_up2, positioned at [15:12] */
1760 lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >>
1761 MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT) <<
1762 MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT);
1763
1764 if ((lp_up2 != 0) &&
1765 (lp_up2 != (tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK))) {
1766 /* replace tx_driver bits [15:12] */
1767 tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
1768 tx_driver |= lp_up2;
1769 CL45_WR_OVER_CL22(bp, params->port,
1770 params->phy_addr,
1771 MDIO_REG_BANK_TX0,
1772 MDIO_TX0_TX_DRIVER, tx_driver);
1773 }
1774}
1775
1776static u8 bnx2x_emac_program(struct link_params *params,
1777 u32 line_speed, u32 duplex)
1778{
1779 struct bnx2x *bp = params->bp;
1780 u8 port = params->port;
1781 u16 mode = 0;
1782
1783 DP(NETIF_MSG_LINK, "setting link speed & duplex\n");
1784 bnx2x_bits_dis(bp, GRCBASE_EMAC0 + port*0x400 +
1785 EMAC_REG_EMAC_MODE,
1786 (EMAC_MODE_25G_MODE |
1787 EMAC_MODE_PORT_MII_10M |
1788 EMAC_MODE_HALF_DUPLEX));
1789 switch (line_speed) {
1790 case SPEED_10:
1791 mode |= EMAC_MODE_PORT_MII_10M;
1792 break;
1793
1794 case SPEED_100:
1795 mode |= EMAC_MODE_PORT_MII;
1796 break;
1797
1798 case SPEED_1000:
1799 mode |= EMAC_MODE_PORT_GMII;
1800 break;
1801
1802 case SPEED_2500:
1803 mode |= (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_GMII);
1804 break;
1805
1806 default:
1807 /* 10G not valid for EMAC */
1808 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n", line_speed);
1809 return -EINVAL;
1810 }
1811
1812 if (duplex == DUPLEX_HALF)
1813 mode |= EMAC_MODE_HALF_DUPLEX;
1814 bnx2x_bits_en(bp,
1815 GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
1816 mode);
1817
1818 bnx2x_set_led(bp, params->port, LED_MODE_OPER,
1819 line_speed, params->hw_led_mode, params->chip_id);
1820 return 0;
1821}
1822
1823/*****************************************************************************/
1824/* External Phy section */
1825/*****************************************************************************/
1826static void bnx2x_hw_reset(struct bnx2x *bp)
1827{
1828 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1829 MISC_REGISTERS_GPIO_OUTPUT_LOW);
1830 msleep(1);
1831 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1832 MISC_REGISTERS_GPIO_OUTPUT_HIGH);
1833}
1834
1835static void bnx2x_ext_phy_reset(struct link_params *params,
1836 struct link_vars *vars)
1837{
1838 struct bnx2x *bp = params->bp;
1839 u32 ext_phy_type;
1840 u8 ext_phy_addr = ((params->ext_phy_config &
1841 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1842 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1843 DP(NETIF_MSG_LINK, "Port %x: bnx2x_ext_phy_reset\n", params->port);
1844 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1845 /* The PHY reset is controled by GPIO 1
1846 * Give it 1ms of reset pulse
1847 */
1848 if (vars->phy_flags & PHY_XGXS_FLAG) {
1849
1850 switch (ext_phy_type) {
1851 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
1852 DP(NETIF_MSG_LINK, "XGXS Direct\n");
1853 break;
1854
1855 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
1856 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
1857 DP(NETIF_MSG_LINK, "XGXS 8705/8706\n");
1858
1859 /* Restore normal power mode*/
1860 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1861 MISC_REGISTERS_GPIO_OUTPUT_HIGH);
1862
1863 /* HW reset */
1864 bnx2x_hw_reset(bp);
1865
1866 bnx2x_cl45_write(bp, params->port,
1867 ext_phy_type,
1868 ext_phy_addr,
1869 MDIO_PMA_DEVAD,
1870 MDIO_PMA_REG_CTRL, 0xa040);
1871 break;
1872 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
1873 /* Unset Low Power Mode and SW reset */
1874 /* Restore normal power mode*/
1875 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1876 MISC_REGISTERS_GPIO_OUTPUT_HIGH);
1877
1878 DP(NETIF_MSG_LINK, "XGXS 8072\n");
1879 bnx2x_cl45_write(bp, params->port,
1880 ext_phy_type,
1881 ext_phy_addr,
1882 MDIO_PMA_DEVAD,
1883 MDIO_PMA_REG_CTRL,
1884 1<<15);
1885 break;
1886 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
1887 {
1888 u16 emac_base;
1889 emac_base = (params->port) ? GRCBASE_EMAC0 :
1890 GRCBASE_EMAC1;
1891
1892 /* Restore normal power mode*/
1893 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1894 MISC_REGISTERS_GPIO_OUTPUT_HIGH);
1895
1896 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
1897 MISC_REGISTERS_GPIO_OUTPUT_HIGH);
1898
1899 DP(NETIF_MSG_LINK, "XGXS 8073\n");
1900 bnx2x_cl45_write(bp,
1901 params->port,
1902 ext_phy_type,
1903 ext_phy_addr,
1904 MDIO_PMA_DEVAD,
1905 MDIO_PMA_REG_CTRL,
1906 1<<15);
1907 }
1908 break;
1909
1910 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
1911 DP(NETIF_MSG_LINK, "XGXS SFX7101\n");
1912
1913 /* Restore normal power mode*/
1914 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
1915 MISC_REGISTERS_GPIO_OUTPUT_HIGH);
1916
1917 /* HW reset */
1918 bnx2x_hw_reset(bp);
1919
1920 break;
1921
1922 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
1923 DP(NETIF_MSG_LINK, "XGXS PHY Failure detected\n");
1924 break;
1925
1926 default:
1927 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
1928 params->ext_phy_config);
1929 break;
1930 }
1931
1932 } else { /* SerDes */
1933 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
1934 switch (ext_phy_type) {
1935 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
1936 DP(NETIF_MSG_LINK, "SerDes Direct\n");
1937 break;
1938
1939 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
1940 DP(NETIF_MSG_LINK, "SerDes 5482\n");
1941 bnx2x_hw_reset(bp);
1942 break;
1943
1944 default:
1945 DP(NETIF_MSG_LINK,
1946 "BAD SerDes ext_phy_config 0x%x\n",
1947 params->ext_phy_config);
1948 break;
1949 }
1950 }
1951}
1952
1953static void bnx2x_bcm8072_external_rom_boot(struct link_params *params)
1954{
1955 struct bnx2x *bp = params->bp;
1956 u8 port = params->port;
1957 u8 ext_phy_addr = ((params->ext_phy_config &
1958 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
1959 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
1960 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1961 u16 fw_ver1, fw_ver2;
1962
1963 /* Need to wait 200ms after reset */
1964 msleep(200);
1965 /* Boot port from external ROM
1966 * Set ser_boot_ctl bit in the MISC_CTRL1 register
1967 */
1968 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1969 MDIO_PMA_DEVAD,
1970 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
1971
1972 /* Reset internal microprocessor */
1973 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1974 MDIO_PMA_DEVAD,
1975 MDIO_PMA_REG_GEN_CTRL,
1976 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
1977 /* set micro reset = 0 */
1978 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1979 MDIO_PMA_DEVAD,
1980 MDIO_PMA_REG_GEN_CTRL,
1981 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
1982 /* Reset internal microprocessor */
1983 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1984 MDIO_PMA_DEVAD,
1985 MDIO_PMA_REG_GEN_CTRL,
1986 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
1987 /* wait for 100ms for code download via SPI port */
1988 msleep(100);
1989
1990 /* Clear ser_boot_ctl bit */
1991 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
1992 MDIO_PMA_DEVAD,
1993 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
1994 /* Wait 100ms */
1995 msleep(100);
1996
1997 /* Print the PHY FW version */
1998 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
1999 MDIO_PMA_DEVAD,
2000 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
2001 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2002 MDIO_PMA_DEVAD,
2003 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
2004 DP(NETIF_MSG_LINK, "8072 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
2005}
2006
2007static u8 bnx2x_8073_is_snr_needed(struct link_params *params)
2008{
2009 /* This is only required for 8073A1, version 102 only */
2010
2011 struct bnx2x *bp = params->bp;
2012 u8 ext_phy_addr = ((params->ext_phy_config &
2013 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2014 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2015 u16 val;
2016
2017 /* Read 8073 HW revision*/
2018 bnx2x_cl45_read(bp, params->port,
2019 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2020 ext_phy_addr,
2021 MDIO_PMA_DEVAD,
2022 0xc801, &val);
2023
2024 if (val != 1) {
2025 /* No need to workaround in 8073 A1 */
2026 return 0;
2027 }
2028
2029 bnx2x_cl45_read(bp, params->port,
2030 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2031 ext_phy_addr,
2032 MDIO_PMA_DEVAD,
2033 MDIO_PMA_REG_ROM_VER2, &val);
2034
2035 /* SNR should be applied only for version 0x102 */
2036 if (val != 0x102)
2037 return 0;
2038
2039 return 1;
2040}
2041
2042static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
2043{
2044 struct bnx2x *bp = params->bp;
2045 u8 ext_phy_addr = ((params->ext_phy_config &
2046 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2047 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2048 u16 val, cnt, cnt1 ;
2049
2050 bnx2x_cl45_read(bp, params->port,
2051 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2052 ext_phy_addr,
2053 MDIO_PMA_DEVAD,
2054 0xc801, &val);
2055
2056 if (val > 0) {
2057 /* No need to workaround in 8073 A1 */
2058 return 0;
2059 }
2060 /* XAUI workaround in 8073 A0: */
2061
2062 /* After loading the boot ROM and restarting Autoneg,
2063 poll Dev1, Reg $C820: */
2064
2065 for (cnt = 0; cnt < 1000; cnt++) {
2066 bnx2x_cl45_read(bp, params->port,
2067 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2068 ext_phy_addr,
2069 MDIO_PMA_DEVAD,
2070 0xc820, &val);
2071 /* If bit [14] = 0 or bit [13] = 0, continue on with
2072 system initialization (XAUI work-around not required,
2073 as these bits indicate 2.5G or 1G link up). */
2074 if (!(val & (1<<14)) || !(val & (1<<13))) {
2075 DP(NETIF_MSG_LINK, "XAUI work-around not required\n");
2076 return 0;
2077 } else if (!(val & (1<<15))) {
2078 DP(NETIF_MSG_LINK, "clc bit 15 went off\n");
2079 /* If bit 15 is 0, then poll Dev1, Reg $C841 until
2080 it's MSB (bit 15) goes to 1 (indicating that the
2081 XAUI workaround has completed),
2082 then continue on with system initialization.*/
2083 for (cnt1 = 0; cnt1 < 1000; cnt1++) {
2084 bnx2x_cl45_read(bp, params->port,
2085 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2086 ext_phy_addr,
2087 MDIO_PMA_DEVAD,
2088 0xc841, &val);
2089 if (val & (1<<15)) {
2090 DP(NETIF_MSG_LINK,
2091 "XAUI workaround has completed\n");
2092 return 0;
2093 }
2094 msleep(3);
2095 }
2096 break;
2097 }
2098 msleep(3);
2099 }
2100 DP(NETIF_MSG_LINK, "Warning: XAUI work-around timeout !!!\n");
2101 return -EINVAL;
2102
2103}
2104
2105static void bnx2x_bcm8073_external_rom_boot(struct link_params *params)
2106{
2107 struct bnx2x *bp = params->bp;
2108 u8 port = params->port;
2109 u8 ext_phy_addr = ((params->ext_phy_config &
2110 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2111 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2112 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2113 u16 fw_ver1, fw_ver2, val;
2114 /* Need to wait 100ms after reset */
2115 msleep(100);
2116 /* Boot port from external ROM */
2117 /* EDC grst */
2118 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2119 MDIO_PMA_DEVAD,
2120 MDIO_PMA_REG_GEN_CTRL,
2121 0x0001);
2122
2123 /* ucode reboot and rst */
2124 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2125 MDIO_PMA_DEVAD,
2126 MDIO_PMA_REG_GEN_CTRL,
2127 0x008c);
2128
2129 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2130 MDIO_PMA_DEVAD,
2131 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
2132
2133 /* Reset internal microprocessor */
2134 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2135 MDIO_PMA_DEVAD,
2136 MDIO_PMA_REG_GEN_CTRL,
2137 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
2138
2139 /* Release srst bit */
2140 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2141 MDIO_PMA_DEVAD,
2142 MDIO_PMA_REG_GEN_CTRL,
2143 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2144
2145 /* wait for 100ms for code download via SPI port */
2146 msleep(100);
2147
2148 /* Clear ser_boot_ctl bit */
2149 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2150 MDIO_PMA_DEVAD,
2151 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2152
2153 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2154 MDIO_PMA_DEVAD,
2155 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
2156 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2157 MDIO_PMA_DEVAD,
2158 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
2159 DP(NETIF_MSG_LINK, "8073 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
2160
2161 /* Only set bit 10 = 1 (Tx power down) */
2162 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2163 MDIO_PMA_DEVAD,
2164 MDIO_PMA_REG_TX_POWER_DOWN, &val);
2165
2166 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2167 MDIO_PMA_DEVAD,
2168 MDIO_PMA_REG_TX_POWER_DOWN, (val | 1<<10));
2169
2170 msleep(600);
2171 /* Release bit 10 (Release Tx power down) */
2172 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2173 MDIO_PMA_DEVAD,
2174 MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
2175
2176}
2177
2178static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
2179{
2180 struct bnx2x *bp = params->bp;
2181 u8 port = params->port;
2182 u16 val;
2183 u8 ext_phy_addr = ((params->ext_phy_config &
2184 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2185 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2186 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2187
2188 bnx2x_cl45_read(bp, params->port,
2189 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2190 ext_phy_addr,
2191 MDIO_PMA_DEVAD,
2192 0xc801, &val);
2193
2194 if (val == 0) {
2195 /* Mustn't set low power mode in 8073 A0 */
2196 return;
2197 }
2198
2199 /* Disable PLL sequencer (use read-modify-write to clear bit 13) */
2200 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2201 MDIO_XS_DEVAD,
2202 MDIO_XS_PLL_SEQUENCER, &val);
2203 val &= ~(1<<13);
2204 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2205 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
2206
2207 /* PLL controls */
2208 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2209 MDIO_XS_DEVAD, 0x805E, 0x1077);
2210 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2211 MDIO_XS_DEVAD, 0x805D, 0x0000);
2212 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2213 MDIO_XS_DEVAD, 0x805C, 0x030B);
2214 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2215 MDIO_XS_DEVAD, 0x805B, 0x1240);
2216 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2217 MDIO_XS_DEVAD, 0x805A, 0x2490);
2218
2219 /* Tx Controls */
2220 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2221 MDIO_XS_DEVAD, 0x80A7, 0x0C74);
2222 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2223 MDIO_XS_DEVAD, 0x80A6, 0x9041);
2224 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2225 MDIO_XS_DEVAD, 0x80A5, 0x4640);
2226
2227 /* Rx Controls */
2228 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2229 MDIO_XS_DEVAD, 0x80FE, 0x01C4);
2230 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2231 MDIO_XS_DEVAD, 0x80FD, 0x9249);
2232 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2233 MDIO_XS_DEVAD, 0x80FC, 0x2015);
2234
2235 /* Enable PLL sequencer (use read-modify-write to set bit 13) */
2236 bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
2237 MDIO_XS_DEVAD,
2238 MDIO_XS_PLL_SEQUENCER, &val);
2239 val |= (1<<13);
2240 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2241 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
2242}
2243static void bnx2x_bcm807x_force_10G(struct link_params *params)
2244{
2245 struct bnx2x *bp = params->bp;
2246 u8 port = params->port;
2247 u8 ext_phy_addr = ((params->ext_phy_config &
2248 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2249 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2250 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2251
2252 /* Force KR or KX */
2253 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2254 MDIO_PMA_DEVAD,
2255 MDIO_PMA_REG_CTRL,
2256 0x2040);
2257 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2258 MDIO_PMA_DEVAD,
2259 MDIO_PMA_REG_10G_CTRL2,
2260 0x000b);
2261 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2262 MDIO_PMA_DEVAD,
2263 MDIO_PMA_REG_BCM_CTRL,
2264 0x0000);
2265 bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
2266 MDIO_AN_DEVAD,
2267 MDIO_AN_REG_CTRL,
2268 0x0000);
2269}
2270
2271static void bnx2x_ext_phy_set_pause(struct link_params *params,
2272 struct link_vars *vars)
2273{
2274 struct bnx2x *bp = params->bp;
2275 u16 val;
2276 u8 ext_phy_addr = ((params->ext_phy_config &
2277 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2278 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2279 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2280
2281 /* read modify write pause advertizing */
2282 bnx2x_cl45_read(bp, params->port,
2283 ext_phy_type,
2284 ext_phy_addr,
2285 MDIO_AN_DEVAD,
2286 MDIO_AN_REG_ADV_PAUSE, &val);
2287
2288 val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
2289 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
2290
2291 if (vars->ieee_fc &
2292 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
2293 val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
2294 }
2295 if (vars->ieee_fc &
2296 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
2297 val |=
2298 MDIO_AN_REG_ADV_PAUSE_PAUSE;
2299 }
2300 DP(NETIF_MSG_LINK,
2301 "Ext phy AN advertize 0x%x\n", val);
2302 bnx2x_cl45_write(bp, params->port,
2303 ext_phy_type,
2304 ext_phy_addr,
2305 MDIO_AN_DEVAD,
2306 MDIO_AN_REG_ADV_PAUSE, val);
2307}
2308
Yaniv Rosner57963ed2008-08-13 15:55:28 -07002309
2310static void bnx2x_init_internal_phy(struct link_params *params,
2311 struct link_vars *vars)
2312{
2313 struct bnx2x *bp = params->bp;
2314 u8 port = params->port;
2315 if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
2316 u16 bank, rx_eq;
2317
2318 rx_eq = ((params->serdes_config &
2319 PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK) >>
2320 PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT);
2321
2322 DP(NETIF_MSG_LINK, "setting rx eq to 0x%x\n", rx_eq);
2323 for (bank = MDIO_REG_BANK_RX0; bank <= MDIO_REG_BANK_RX_ALL;
2324 bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0)) {
2325 CL45_WR_OVER_CL22(bp, port,
2326 params->phy_addr,
2327 bank ,
2328 MDIO_RX0_RX_EQ_BOOST,
2329 ((rx_eq &
2330 MDIO_RX0_RX_EQ_BOOST_EQUALIZER_CTRL_MASK) |
2331 MDIO_RX0_RX_EQ_BOOST_OFFSET_CTRL));
2332 }
2333
2334 /* forced speed requested? */
2335 if (vars->line_speed != SPEED_AUTO_NEG) {
2336 DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
2337
2338 /* disable autoneg */
2339 bnx2x_set_autoneg(params, vars);
2340
2341 /* program speed and duplex */
2342 bnx2x_program_serdes(params);
2343
2344 } else { /* AN_mode */
2345 DP(NETIF_MSG_LINK, "not SGMII, AN\n");
2346
2347 /* AN enabled */
2348 bnx2x_set_brcm_cl37_advertisment(params);
2349
2350 /* program duplex & pause advertisement (for aneg) */
2351 bnx2x_set_ieee_aneg_advertisment(params,
2352 &vars->ieee_fc);
2353
2354 /* enable autoneg */
2355 bnx2x_set_autoneg(params, vars);
2356
2357 /* enable and restart AN */
2358 bnx2x_restart_autoneg(params);
2359 }
2360
2361 } else { /* SGMII mode */
2362 DP(NETIF_MSG_LINK, "SGMII\n");
2363
2364 bnx2x_initialize_sgmii_process(params);
2365 }
2366}
2367
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07002368static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
2369{
2370 struct bnx2x *bp = params->bp;
2371 u32 ext_phy_type;
2372 u8 ext_phy_addr;
2373 u16 cnt;
2374 u16 ctrl = 0;
2375 u16 val = 0;
2376 u8 rc = 0;
2377 if (vars->phy_flags & PHY_XGXS_FLAG) {
2378 ext_phy_addr = ((params->ext_phy_config &
2379 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2380 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2381
2382 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2383 /* Make sure that the soft reset is off (expect for the 8072:
2384 * due to the lock, it will be done inside the specific
2385 * handling)
2386 */
2387 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
2388 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
2389 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) &&
2390 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
2391 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
2392 /* Wait for soft reset to get cleared upto 1 sec */
2393 for (cnt = 0; cnt < 1000; cnt++) {
2394 bnx2x_cl45_read(bp, params->port,
2395 ext_phy_type,
2396 ext_phy_addr,
2397 MDIO_PMA_DEVAD,
2398 MDIO_PMA_REG_CTRL, &ctrl);
2399 if (!(ctrl & (1<<15)))
2400 break;
2401 msleep(1);
2402 }
2403 DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n",
2404 ctrl, cnt);
2405 }
2406
2407 switch (ext_phy_type) {
2408 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07002409 break;
2410
2411 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2412 DP(NETIF_MSG_LINK, "XGXS 8705\n");
2413
2414 bnx2x_cl45_write(bp, params->port,
2415 ext_phy_type,
2416 ext_phy_addr,
2417 MDIO_PMA_DEVAD,
2418 MDIO_PMA_REG_MISC_CTRL,
2419 0x8288);
2420 bnx2x_cl45_write(bp, params->port,
2421 ext_phy_type,
2422 ext_phy_addr,
2423 MDIO_PMA_DEVAD,
2424 MDIO_PMA_REG_PHY_IDENTIFIER,
2425 0x7fbf);
2426 bnx2x_cl45_write(bp, params->port,
2427 ext_phy_type,
2428 ext_phy_addr,
2429 MDIO_PMA_DEVAD,
2430 MDIO_PMA_REG_CMU_PLL_BYPASS,
2431 0x0100);
2432 bnx2x_cl45_write(bp, params->port,
2433 ext_phy_type,
2434 ext_phy_addr,
2435 MDIO_WIS_DEVAD,
2436 MDIO_WIS_REG_LASI_CNTL, 0x1);
2437 break;
2438
2439 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2440 DP(NETIF_MSG_LINK, "XGXS 8706\n");
2441
2442 msleep(10);
2443 /* Force speed */
2444 /* First enable LASI */
2445 bnx2x_cl45_write(bp, params->port,
2446 ext_phy_type,
2447 ext_phy_addr,
2448 MDIO_PMA_DEVAD,
2449 MDIO_PMA_REG_RX_ALARM_CTRL,
2450 0x0400);
2451 bnx2x_cl45_write(bp, params->port,
2452 ext_phy_type,
2453 ext_phy_addr,
2454 MDIO_PMA_DEVAD,
2455 MDIO_PMA_REG_LASI_CTRL, 0x0004);
2456
2457 if (params->req_line_speed == SPEED_10000) {
2458 DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n");
2459
2460 bnx2x_cl45_write(bp, params->port,
2461 ext_phy_type,
2462 ext_phy_addr,
2463 MDIO_PMA_DEVAD,
2464 MDIO_PMA_REG_DIGITAL_CTRL,
2465 0x400);
2466 } else {
2467 /* Force 1Gbps using autoneg with 1G
2468 advertisment */
2469
2470 /* Allow CL37 through CL73 */
2471 DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
2472 bnx2x_cl45_write(bp, params->port,
2473 ext_phy_type,
2474 ext_phy_addr,
2475 MDIO_AN_DEVAD,
2476 MDIO_AN_REG_CL37_CL73,
2477 0x040c);
2478
2479 /* Enable Full-Duplex advertisment on CL37 */
2480 bnx2x_cl45_write(bp, params->port,
2481 ext_phy_type,
2482 ext_phy_addr,
2483 MDIO_AN_DEVAD,
2484 MDIO_AN_REG_CL37_FD,
2485 0x0020);
2486 /* Enable CL37 AN */
2487 bnx2x_cl45_write(bp, params->port,
2488 ext_phy_type,
2489 ext_phy_addr,
2490 MDIO_AN_DEVAD,
2491 MDIO_AN_REG_CL37_AN,
2492 0x1000);
2493 /* 1G support */
2494 bnx2x_cl45_write(bp, params->port,
2495 ext_phy_type,
2496 ext_phy_addr,
2497 MDIO_AN_DEVAD,
2498 MDIO_AN_REG_ADV, (1<<5));
2499
2500 /* Enable clause 73 AN */
2501 bnx2x_cl45_write(bp, params->port,
2502 ext_phy_type,
2503 ext_phy_addr,
2504 MDIO_AN_DEVAD,
2505 MDIO_AN_REG_CTRL,
2506 0x1200);
2507
2508 }
2509
2510 break;
2511
2512 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2513 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2514 {
2515 u16 tmp1;
2516 u16 rx_alarm_ctrl_val;
2517 u16 lasi_ctrl_val;
2518 if (ext_phy_type ==
2519 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
2520 rx_alarm_ctrl_val = 0x400;
2521 lasi_ctrl_val = 0x0004;
2522 } else {
2523 /* In 8073, port1 is directed through emac0 and
2524 * port0 is directed through emac1
2525 */
2526 rx_alarm_ctrl_val = (1<<2);
2527 /*lasi_ctrl_val = 0x0005;*/
2528 lasi_ctrl_val = 0x0004;
2529 }
2530
2531 /* Wait for soft reset to get cleared upto 1 sec */
2532 for (cnt = 0; cnt < 1000; cnt++) {
2533 bnx2x_cl45_read(bp, params->port,
2534 ext_phy_type,
2535 ext_phy_addr,
2536 MDIO_PMA_DEVAD,
2537 MDIO_PMA_REG_CTRL,
2538 &ctrl);
2539 if (!(ctrl & (1<<15)))
2540 break;
2541 msleep(1);
2542 }
2543 DP(NETIF_MSG_LINK,
2544 "807x control reg 0x%x (after %d ms)\n",
2545 ctrl, cnt);
2546
2547 if (ext_phy_type ==
2548 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072){
2549 bnx2x_bcm8072_external_rom_boot(params);
2550 } else {
2551 bnx2x_bcm8073_external_rom_boot(params);
2552 /* In case of 8073 with long xaui lines,
2553 don't set the 8073 xaui low power*/
2554 bnx2x_bcm8073_set_xaui_low_power_mode(params);
2555 }
2556
2557 /* enable LASI */
2558 bnx2x_cl45_write(bp, params->port,
2559 ext_phy_type,
2560 ext_phy_addr,
2561 MDIO_PMA_DEVAD,
2562 MDIO_PMA_REG_RX_ALARM_CTRL,
2563 rx_alarm_ctrl_val);
2564
2565 bnx2x_cl45_write(bp, params->port,
2566 ext_phy_type,
2567 ext_phy_addr,
2568 MDIO_PMA_DEVAD,
2569 MDIO_PMA_REG_LASI_CTRL,
2570 lasi_ctrl_val);
2571
2572 bnx2x_cl45_read(bp, params->port,
2573 ext_phy_type,
2574 ext_phy_addr,
2575 MDIO_PMA_DEVAD,
2576 MDIO_PMA_REG_RX_ALARM, &tmp1);
2577
2578 DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1):"
2579 "0x%x\n", tmp1);
2580
2581 /* If this is forced speed, set to KR or KX
2582 * (all other are not supported)
2583 */
2584 if (!(params->req_line_speed == SPEED_AUTO_NEG)) {
2585 if (params->req_line_speed == SPEED_10000) {
2586 bnx2x_bcm807x_force_10G(params);
2587 DP(NETIF_MSG_LINK,
2588 "Forced speed 10G on 807X\n");
2589 break;
2590 } else if (params->req_line_speed ==
2591 SPEED_2500) {
2592 val = (1<<5);
2593 /* Note that 2.5G works only
2594 when used with 1G advertisment */
2595 } else
2596 val = (1<<5);
2597 } else {
2598
2599 val = 0;
2600 if (params->speed_cap_mask &
2601 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
2602 val |= (1<<7);
2603
2604 if (params->speed_cap_mask &
2605 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
2606 val |= (1<<5);
2607 DP(NETIF_MSG_LINK, "807x autoneg val = 0x%x\n", val);
2608 /*val = ((1<<5)|(1<<7));*/
2609 }
2610
2611 bnx2x_cl45_write(bp, params->port,
2612 ext_phy_type,
2613 ext_phy_addr,
2614 MDIO_AN_DEVAD,
2615 MDIO_AN_REG_ADV, val);
2616
2617 if (ext_phy_type ==
2618 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
2619 /* Disable 2.5Ghz */
2620 bnx2x_cl45_read(bp, params->port,
2621 ext_phy_type,
2622 ext_phy_addr,
2623 MDIO_AN_DEVAD,
2624 0x8329, &tmp1);
2625/* SUPPORT_SPEED_CAPABILITY
2626 (Due to the nature of the link order, its not
2627 possible to enable 2.5G within the autoneg
2628 capabilities)
2629 if (params->speed_cap_mask &
2630 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
2631*/
2632 if (params->req_line_speed == SPEED_2500) {
2633 u16 phy_ver;
2634 /* Allow 2.5G for A1 and above */
2635 bnx2x_cl45_read(bp, params->port,
2636 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2637 ext_phy_addr,
2638 MDIO_PMA_DEVAD,
2639 0xc801, &phy_ver);
2640
2641 if (phy_ver > 0)
2642 tmp1 |= 1;
2643 else
2644 tmp1 &= 0xfffe;
2645 }
2646 else
2647 tmp1 &= 0xfffe;
2648
2649 bnx2x_cl45_write(bp, params->port,
2650 ext_phy_type,
2651 ext_phy_addr,
2652 MDIO_AN_DEVAD,
2653 0x8329, tmp1);
2654 }
2655 /* Add support for CL37 (passive mode) I */
2656 bnx2x_cl45_write(bp, params->port,
2657 ext_phy_type,
2658 ext_phy_addr,
2659 MDIO_AN_DEVAD,
2660 MDIO_AN_REG_CL37_CL73, 0x040c);
2661 /* Add support for CL37 (passive mode) II */
2662 bnx2x_cl45_write(bp, params->port,
2663 ext_phy_type,
2664 ext_phy_addr,
2665 MDIO_AN_DEVAD,
2666 MDIO_AN_REG_CL37_FD, 0x20);
2667 /* Add support for CL37 (passive mode) III */
2668 bnx2x_cl45_write(bp, params->port,
2669 ext_phy_type,
2670 ext_phy_addr,
2671 MDIO_AN_DEVAD,
2672 MDIO_AN_REG_CL37_AN, 0x1000);
2673 /* Restart autoneg */
2674 msleep(500);
2675
2676 if (ext_phy_type ==
2677 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
2678
2679 /* The SNR will improve about 2db by changing the
2680 BW and FEE main tap. Rest commands are executed
2681 after link is up*/
2682 /* Change FFE main cursor to 5 in EDC register */
2683 if (bnx2x_8073_is_snr_needed(params))
2684 bnx2x_cl45_write(bp, params->port,
2685 ext_phy_type,
2686 ext_phy_addr,
2687 MDIO_PMA_DEVAD,
2688 MDIO_PMA_REG_EDC_FFE_MAIN,
2689 0xFB0C);
2690
2691 /* Enable FEC (Forware Error Correction)
2692 Request in the AN */
2693 bnx2x_cl45_read(bp, params->port,
2694 ext_phy_type,
2695 ext_phy_addr,
2696 MDIO_AN_DEVAD,
2697 MDIO_AN_REG_ADV2, &tmp1);
2698
2699 tmp1 |= (1<<15);
2700
2701 bnx2x_cl45_write(bp, params->port,
2702 ext_phy_type,
2703 ext_phy_addr,
2704 MDIO_AN_DEVAD,
2705 MDIO_AN_REG_ADV2, tmp1);
2706 }
2707
2708 bnx2x_ext_phy_set_pause(params, vars);
2709
2710 bnx2x_cl45_write(bp, params->port,
2711 ext_phy_type,
2712 ext_phy_addr,
2713 MDIO_AN_DEVAD,
2714 MDIO_AN_REG_CTRL, 0x1200);
2715 DP(NETIF_MSG_LINK, "807x Autoneg Restart: "
2716 "Advertise 1G=%x, 10G=%x\n",
2717 ((val & (1<<5)) > 0),
2718 ((val & (1<<7)) > 0));
2719 break;
2720 }
2721 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
2722 DP(NETIF_MSG_LINK,
2723 "Setting the SFX7101 LASI indication\n");
2724
2725 bnx2x_cl45_write(bp, params->port,
2726 ext_phy_type,
2727 ext_phy_addr,
2728 MDIO_PMA_DEVAD,
2729 MDIO_PMA_REG_LASI_CTRL, 0x1);
2730 DP(NETIF_MSG_LINK,
2731 "Setting the SFX7101 LED to blink on traffic\n");
2732 bnx2x_cl45_write(bp, params->port,
2733 ext_phy_type,
2734 ext_phy_addr,
2735 MDIO_PMA_DEVAD,
2736 MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
2737
2738 bnx2x_ext_phy_set_pause(params, vars);
2739 /* Restart autoneg */
2740 bnx2x_cl45_read(bp, params->port,
2741 ext_phy_type,
2742 ext_phy_addr,
2743 MDIO_AN_DEVAD,
2744 MDIO_AN_REG_CTRL, &val);
2745 val |= 0x200;
2746 bnx2x_cl45_write(bp, params->port,
2747 ext_phy_type,
2748 ext_phy_addr,
2749 MDIO_AN_DEVAD,
2750 MDIO_AN_REG_CTRL, val);
2751 break;
2752 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
2753 DP(NETIF_MSG_LINK,
2754 "XGXS PHY Failure detected 0x%x\n",
2755 params->ext_phy_config);
2756 rc = -EINVAL;
2757 break;
2758 default:
2759 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
2760 params->ext_phy_config);
2761 rc = -EINVAL;
2762 break;
2763 }
2764
2765 } else { /* SerDes */
Yaniv Rosner57963ed2008-08-13 15:55:28 -07002766
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07002767 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
2768 switch (ext_phy_type) {
2769 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
2770 DP(NETIF_MSG_LINK, "SerDes Direct\n");
2771 break;
2772
2773 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
2774 DP(NETIF_MSG_LINK, "SerDes 5482\n");
2775 break;
2776
2777 default:
2778 DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
2779 params->ext_phy_config);
2780 break;
2781 }
2782 }
2783 return rc;
2784}
2785
2786
2787static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
2788 struct link_vars *vars)
2789{
2790 struct bnx2x *bp = params->bp;
2791 u32 ext_phy_type;
2792 u8 ext_phy_addr;
2793 u16 val1 = 0, val2;
2794 u16 rx_sd, pcs_status;
2795 u8 ext_phy_link_up = 0;
2796 u8 port = params->port;
2797 if (vars->phy_flags & PHY_XGXS_FLAG) {
2798 ext_phy_addr = ((params->ext_phy_config &
2799 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
2800 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
2801
2802 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2803 switch (ext_phy_type) {
2804 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
2805 DP(NETIF_MSG_LINK, "XGXS Direct\n");
2806 ext_phy_link_up = 1;
2807 break;
2808
2809 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2810 DP(NETIF_MSG_LINK, "XGXS 8705\n");
2811 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2812 ext_phy_addr,
2813 MDIO_WIS_DEVAD,
2814 MDIO_WIS_REG_LASI_STATUS, &val1);
2815 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
2816
2817 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2818 ext_phy_addr,
2819 MDIO_WIS_DEVAD,
2820 MDIO_WIS_REG_LASI_STATUS, &val1);
2821 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
2822
2823 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2824 ext_phy_addr,
2825 MDIO_PMA_DEVAD,
2826 MDIO_PMA_REG_RX_SD, &rx_sd);
2827 DP(NETIF_MSG_LINK, "8705 rx_sd 0x%x\n", rx_sd);
2828 ext_phy_link_up = (rx_sd & 0x1);
2829 break;
2830
2831 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2832 DP(NETIF_MSG_LINK, "XGXS 8706\n");
2833 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2834 ext_phy_addr,
2835 MDIO_PMA_DEVAD,
2836 MDIO_PMA_REG_LASI_STATUS, &val1);
2837 DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
2838
2839 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2840 ext_phy_addr,
2841 MDIO_PMA_DEVAD,
2842 MDIO_PMA_REG_LASI_STATUS, &val1);
2843 DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1);
2844
2845 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2846 ext_phy_addr,
2847 MDIO_PMA_DEVAD,
2848 MDIO_PMA_REG_RX_SD, &rx_sd);
2849 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2850 ext_phy_addr,
2851 MDIO_PCS_DEVAD,
2852 MDIO_PCS_REG_STATUS, &pcs_status);
2853
2854 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2855 ext_phy_addr,
2856 MDIO_AN_DEVAD,
2857 MDIO_AN_REG_LINK_STATUS, &val2);
2858 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2859 ext_phy_addr,
2860 MDIO_AN_DEVAD,
2861 MDIO_AN_REG_LINK_STATUS, &val2);
2862
2863 DP(NETIF_MSG_LINK, "8706 rx_sd 0x%x"
2864 " pcs_status 0x%x 1Gbps link_status 0x%x\n",
2865 rx_sd, pcs_status, val2);
2866 /* link is up if both bit 0 of pmd_rx_sd and
2867 * bit 0 of pcs_status are set, or if the autoneg bit
2868 1 is set
2869 */
2870 ext_phy_link_up = ((rx_sd & pcs_status & 0x1) ||
2871 (val2 & (1<<1)));
Yaniv Rosner57963ed2008-08-13 15:55:28 -07002872 if (ext_phy_link_up) {
2873 if (val2 & (1<<1))
2874 vars->line_speed = SPEED_1000;
2875 else
2876 vars->line_speed = SPEED_10000;
2877 }
2878
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07002879 /* clear LASI indication*/
2880 bnx2x_cl45_read(bp, params->port, ext_phy_type,
2881 ext_phy_addr,
2882 MDIO_PMA_DEVAD,
2883 MDIO_PMA_REG_RX_ALARM, &val2);
2884 break;
2885
2886 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2887 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2888 {
2889 if (ext_phy_type ==
2890 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
2891 bnx2x_cl45_read(bp, params->port,
2892 ext_phy_type,
2893 ext_phy_addr,
2894 MDIO_PCS_DEVAD,
2895 MDIO_PCS_REG_LASI_STATUS, &val1);
2896 bnx2x_cl45_read(bp, params->port,
2897 ext_phy_type,
2898 ext_phy_addr,
2899 MDIO_PCS_DEVAD,
2900 MDIO_PCS_REG_LASI_STATUS, &val2);
2901 DP(NETIF_MSG_LINK,
2902 "870x LASI status 0x%x->0x%x\n",
2903 val1, val2);
2904
2905 } else {
2906 /* In 8073, port1 is directed through emac0 and
2907 * port0 is directed through emac1
2908 */
2909 bnx2x_cl45_read(bp, params->port,
2910 ext_phy_type,
2911 ext_phy_addr,
2912 MDIO_PMA_DEVAD,
2913 MDIO_PMA_REG_LASI_STATUS, &val1);
2914
2915 bnx2x_cl45_read(bp, params->port,
2916 ext_phy_type,
2917 ext_phy_addr,
2918 MDIO_PMA_DEVAD,
2919 MDIO_PMA_REG_LASI_STATUS, &val2);
2920 DP(NETIF_MSG_LINK,
2921 "8703 LASI status 0x%x->0x%x\n",
2922 val1, val2);
2923 }
2924
2925 /* clear the interrupt LASI status register */
2926 bnx2x_cl45_read(bp, params->port,
2927 ext_phy_type,
2928 ext_phy_addr,
2929 MDIO_PCS_DEVAD,
2930 MDIO_PCS_REG_STATUS, &val2);
2931 bnx2x_cl45_read(bp, params->port,
2932 ext_phy_type,
2933 ext_phy_addr,
2934 MDIO_PCS_DEVAD,
2935 MDIO_PCS_REG_STATUS, &val1);
2936 DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n",
2937 val2, val1);
2938 /* Check the LASI */
2939 bnx2x_cl45_read(bp, params->port,
2940 ext_phy_type,
2941 ext_phy_addr,
2942 MDIO_PMA_DEVAD,
2943 MDIO_PMA_REG_RX_ALARM, &val2);
2944 bnx2x_cl45_read(bp, params->port,
2945 ext_phy_type,
2946 ext_phy_addr,
2947 MDIO_PMA_DEVAD,
2948 MDIO_PMA_REG_RX_ALARM,
2949 &val1);
2950 DP(NETIF_MSG_LINK, "KR 0x9003 0x%x->0x%x\n",
2951 val2, val1);
2952 /* Check the link status */
2953 bnx2x_cl45_read(bp, params->port,
2954 ext_phy_type,
2955 ext_phy_addr,
2956 MDIO_PCS_DEVAD,
2957 MDIO_PCS_REG_STATUS, &val2);
2958 DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
2959
2960 bnx2x_cl45_read(bp, params->port,
2961 ext_phy_type,
2962 ext_phy_addr,
2963 MDIO_PMA_DEVAD,
2964 MDIO_PMA_REG_STATUS, &val2);
2965 bnx2x_cl45_read(bp, params->port,
2966 ext_phy_type,
2967 ext_phy_addr,
2968 MDIO_PMA_DEVAD,
2969 MDIO_PMA_REG_STATUS, &val1);
2970 ext_phy_link_up = ((val1 & 4) == 4);
2971 DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
2972 if (ext_phy_type ==
2973 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
2974 u16 an1000_status = 0;
2975 if (ext_phy_link_up &&
2976 (
2977 (params->req_line_speed != SPEED_10000)
2978 )) {
2979 if (bnx2x_bcm8073_xaui_wa(params)
2980 != 0) {
2981 ext_phy_link_up = 0;
2982 break;
2983 }
2984 bnx2x_cl45_read(bp, params->port,
2985 ext_phy_type,
2986 ext_phy_addr,
2987 MDIO_XS_DEVAD,
2988 0x8304,
2989 &an1000_status);
2990 bnx2x_cl45_read(bp, params->port,
2991 ext_phy_type,
2992 ext_phy_addr,
2993 MDIO_XS_DEVAD,
2994 0x8304,
2995 &an1000_status);
2996 }
2997 /* Check the link status on 1.1.2 */
2998 bnx2x_cl45_read(bp, params->port,
2999 ext_phy_type,
3000 ext_phy_addr,
3001 MDIO_PMA_DEVAD,
3002 MDIO_PMA_REG_STATUS, &val2);
3003 bnx2x_cl45_read(bp, params->port,
3004 ext_phy_type,
3005 ext_phy_addr,
3006 MDIO_PMA_DEVAD,
3007 MDIO_PMA_REG_STATUS, &val1);
3008 DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x,"
3009 "an_link_status=0x%x\n",
3010 val2, val1, an1000_status);
3011
3012 ext_phy_link_up = (((val1 & 4) == 4) ||
3013 (an1000_status & (1<<1)));
3014 if (ext_phy_link_up &&
3015 bnx2x_8073_is_snr_needed(params)) {
3016 /* The SNR will improve about 2dbby
3017 changing the BW and FEE main tap.*/
3018
3019 /* The 1st write to change FFE main
3020 tap is set before restart AN */
3021 /* Change PLL Bandwidth in EDC
3022 register */
3023 bnx2x_cl45_write(bp, port, ext_phy_type,
3024 ext_phy_addr,
3025 MDIO_PMA_DEVAD,
3026 MDIO_PMA_REG_PLL_BANDWIDTH,
3027 0x26BC);
3028
3029 /* Change CDR Bandwidth in EDC
3030 register */
3031 bnx2x_cl45_write(bp, port, ext_phy_type,
3032 ext_phy_addr,
3033 MDIO_PMA_DEVAD,
3034 MDIO_PMA_REG_CDR_BANDWIDTH,
3035 0x0333);
3036
3037 }
3038 }
3039 break;
3040 }
3041 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3042 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3043 ext_phy_addr,
3044 MDIO_PMA_DEVAD,
3045 MDIO_PMA_REG_LASI_STATUS, &val2);
3046 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3047 ext_phy_addr,
3048 MDIO_PMA_DEVAD,
3049 MDIO_PMA_REG_LASI_STATUS, &val1);
3050 DP(NETIF_MSG_LINK,
3051 "10G-base-T LASI status 0x%x->0x%x\n",
3052 val2, val1);
3053 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3054 ext_phy_addr,
3055 MDIO_PMA_DEVAD,
3056 MDIO_PMA_REG_STATUS, &val2);
3057 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3058 ext_phy_addr,
3059 MDIO_PMA_DEVAD,
3060 MDIO_PMA_REG_STATUS, &val1);
3061 DP(NETIF_MSG_LINK,
3062 "10G-base-T PMA status 0x%x->0x%x\n",
3063 val2, val1);
3064 ext_phy_link_up = ((val1 & 4) == 4);
3065 /* if link is up
3066 * print the AN outcome of the SFX7101 PHY
3067 */
3068 if (ext_phy_link_up) {
3069 bnx2x_cl45_read(bp, params->port,
3070 ext_phy_type,
3071 ext_phy_addr,
3072 MDIO_AN_DEVAD,
3073 MDIO_AN_REG_MASTER_STATUS,
3074 &val2);
Yaniv Rosner57963ed2008-08-13 15:55:28 -07003075 vars->line_speed = SPEED_10000;
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003076 DP(NETIF_MSG_LINK,
3077 "SFX7101 AN status 0x%x->Master=%x\n",
3078 val2,
3079 (val2 & (1<<14)));
3080 }
3081 break;
3082
3083 default:
3084 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
3085 params->ext_phy_config);
3086 ext_phy_link_up = 0;
3087 break;
3088 }
3089
3090 } else { /* SerDes */
3091 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3092 switch (ext_phy_type) {
3093 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
3094 DP(NETIF_MSG_LINK, "SerDes Direct\n");
3095 ext_phy_link_up = 1;
3096 break;
3097
3098 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
3099 DP(NETIF_MSG_LINK, "SerDes 5482\n");
3100 ext_phy_link_up = 1;
3101 break;
3102
3103 default:
3104 DP(NETIF_MSG_LINK,
3105 "BAD SerDes ext_phy_config 0x%x\n",
3106 params->ext_phy_config);
3107 ext_phy_link_up = 0;
3108 break;
3109 }
3110 }
3111
3112 return ext_phy_link_up;
3113}
3114
3115static void bnx2x_link_int_enable(struct link_params *params)
3116{
3117 u8 port = params->port;
3118 u32 ext_phy_type;
3119 u32 mask;
3120 struct bnx2x *bp = params->bp;
3121 /* setting the status to report on link up
3122 for either XGXS or SerDes */
3123
3124 if (params->switch_cfg == SWITCH_CFG_10G) {
3125 mask = (NIG_MASK_XGXS0_LINK10G |
3126 NIG_MASK_XGXS0_LINK_STATUS);
3127 DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
3128 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3129 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
3130 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
3131 (ext_phy_type !=
3132 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) {
3133 mask |= NIG_MASK_MI_INT;
3134 DP(NETIF_MSG_LINK, "enabled external phy int\n");
3135 }
3136
3137 } else { /* SerDes */
3138 mask = NIG_MASK_SERDES0_LINK_STATUS;
3139 DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n");
3140 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3141 if ((ext_phy_type !=
3142 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
3143 (ext_phy_type !=
3144 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN)) {
3145 mask |= NIG_MASK_MI_INT;
3146 DP(NETIF_MSG_LINK, "enabled external phy int\n");
3147 }
3148 }
3149 bnx2x_bits_en(bp,
3150 NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
3151 mask);
3152 DP(NETIF_MSG_LINK, "port %x, is_xgxs=%x, int_status 0x%x\n", port,
3153 (params->switch_cfg == SWITCH_CFG_10G),
3154 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
3155
3156 DP(NETIF_MSG_LINK, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n",
3157 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
3158 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
3159 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS+port*0x3c));
3160 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
3161 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
3162 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
3163}
3164
3165
3166/*
3167 * link management
3168 */
3169static void bnx2x_link_int_ack(struct link_params *params,
3170 struct link_vars *vars, u16 is_10g)
3171{
3172 struct bnx2x *bp = params->bp;
3173 u8 port = params->port;
3174
3175 /* first reset all status
3176 * we assume only one line will be change at a time */
3177 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3178 (NIG_STATUS_XGXS0_LINK10G |
3179 NIG_STATUS_XGXS0_LINK_STATUS |
3180 NIG_STATUS_SERDES0_LINK_STATUS));
3181 if (vars->phy_link_up) {
3182 if (is_10g) {
3183 /* Disable the 10G link interrupt
3184 * by writing 1 to the status register
3185 */
3186 DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
3187 bnx2x_bits_en(bp,
3188 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3189 NIG_STATUS_XGXS0_LINK10G);
3190
3191 } else if (params->switch_cfg == SWITCH_CFG_10G) {
3192 /* Disable the link interrupt
3193 * by writing 1 to the relevant lane
3194 * in the status register
3195 */
3196 u32 ser_lane = ((params->lane_config &
3197 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
3198 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
3199
3200 DP(NETIF_MSG_LINK, "1G XGXS phy link up\n");
3201 bnx2x_bits_en(bp,
3202 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3203 ((1 << ser_lane) <<
3204 NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
3205
3206 } else { /* SerDes */
3207 DP(NETIF_MSG_LINK, "SerDes phy link up\n");
3208 /* Disable the link interrupt
3209 * by writing 1 to the status register
3210 */
3211 bnx2x_bits_en(bp,
3212 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
3213 NIG_STATUS_SERDES0_LINK_STATUS);
3214 }
3215
3216 } else { /* link_down */
3217 }
3218}
3219
3220static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len)
3221{
3222 u8 *str_ptr = str;
3223 u32 mask = 0xf0000000;
3224 u8 shift = 8*4;
3225 u8 digit;
3226 if (len < 10) {
3227 /* Need more then 10chars for this format */
3228 *str_ptr = '\0';
3229 return -EINVAL;
3230 }
3231 while (shift > 0) {
3232
3233 shift -= 4;
3234 digit = ((num & mask) >> shift);
3235 if (digit < 0xa)
3236 *str_ptr = digit + '0';
3237 else
3238 *str_ptr = digit - 0xa + 'a';
3239 str_ptr++;
3240 mask = mask >> 4;
3241 if (shift == 4*4) {
3242 *str_ptr = ':';
3243 str_ptr++;
3244 }
3245 }
3246 *str_ptr = '\0';
3247 return 0;
3248}
3249
3250
Yaniv Rosner57963ed2008-08-13 15:55:28 -07003251static void bnx2x_turn_on_ef(struct bnx2x *bp, u8 port, u8 ext_phy_addr,
3252 u32 ext_phy_type)
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003253{
3254 u32 cnt = 0;
3255 u16 ctrl = 0;
3256 /* Enable EMAC0 in to enable MDIO */
3257 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
3258 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
3259 msleep(5);
3260
3261 /* take ext phy out of reset */
3262 bnx2x_set_gpio(bp,
3263 MISC_REGISTERS_GPIO_2,
3264 MISC_REGISTERS_GPIO_HIGH);
3265
3266 bnx2x_set_gpio(bp,
3267 MISC_REGISTERS_GPIO_1,
3268 MISC_REGISTERS_GPIO_HIGH);
3269
3270 /* wait for 5ms */
3271 msleep(5);
3272
3273 for (cnt = 0; cnt < 1000; cnt++) {
3274 msleep(1);
3275 bnx2x_cl45_read(bp, port,
Yaniv Rosner57963ed2008-08-13 15:55:28 -07003276 ext_phy_type,
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003277 ext_phy_addr,
3278 MDIO_PMA_DEVAD,
3279 MDIO_PMA_REG_CTRL,
3280 &ctrl);
3281 if (!(ctrl & (1<<15))) {
3282 DP(NETIF_MSG_LINK, "Reset completed\n\n");
3283 break;
3284 }
3285 }
3286}
3287
3288static void bnx2x_turn_off_sf(struct bnx2x *bp)
3289{
3290 /* put sf to reset */
3291 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_LOW);
3292 bnx2x_set_gpio(bp,
3293 MISC_REGISTERS_GPIO_2,
3294 MISC_REGISTERS_GPIO_LOW);
3295}
3296
3297u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
3298 u8 *version, u16 len)
3299{
3300 struct bnx2x *bp = params->bp;
3301 u32 ext_phy_type = 0;
3302 u16 val = 0;
3303 u8 ext_phy_addr = 0 ;
3304 u8 status = 0 ;
3305 u32 ver_num;
3306
3307 if (version == NULL || params == NULL)
3308 return -EINVAL;
3309
3310 /* reset the returned value to zero */
3311 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3312 ext_phy_addr = ((params->ext_phy_config &
3313 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
3314 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
3315
3316 switch (ext_phy_type) {
3317 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3318
3319 if (len < 5)
3320 return -EINVAL;
3321
3322 /* Take ext phy out of reset */
3323 if (!driver_loaded)
Yaniv Rosner57963ed2008-08-13 15:55:28 -07003324 bnx2x_turn_on_ef(bp, params->port, ext_phy_addr,
3325 ext_phy_type);
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003326
3327 /* wait for 1ms */
3328 msleep(1);
3329
3330 bnx2x_cl45_read(bp, params->port,
3331 ext_phy_type,
3332 ext_phy_addr,
3333 MDIO_PMA_DEVAD,
3334 MDIO_PMA_REG_7101_VER1, &val);
3335 version[2] = (val & 0xFF);
3336 version[3] = ((val & 0xFF00)>>8);
3337
3338 bnx2x_cl45_read(bp, params->port,
3339 ext_phy_type,
3340 ext_phy_addr,
3341 MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2,
3342 &val);
3343 version[0] = (val & 0xFF);
3344 version[1] = ((val & 0xFF00)>>8);
3345 version[4] = '\0';
3346
3347 if (!driver_loaded)
3348 bnx2x_turn_off_sf(bp);
3349 break;
3350 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
3351 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
3352 {
Yaniv Rosner57963ed2008-08-13 15:55:28 -07003353 /* Take ext phy out of reset */
3354 if (!driver_loaded)
3355 bnx2x_turn_on_ef(bp, params->port, ext_phy_addr,
3356 ext_phy_type);
3357
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003358 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3359 ext_phy_addr,
3360 MDIO_PMA_DEVAD,
3361 MDIO_PMA_REG_ROM_VER1, &val);
3362 ver_num = val<<16;
3363 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3364 ext_phy_addr,
3365 MDIO_PMA_DEVAD,
3366 MDIO_PMA_REG_ROM_VER2, &val);
3367 ver_num |= val;
3368 status = bnx2x_format_ver(ver_num, version, len);
3369 break;
3370 }
3371 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
3372 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
3373
3374 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3375 ext_phy_addr,
3376 MDIO_PMA_DEVAD,
3377 MDIO_PMA_REG_ROM_VER1, &val);
3378 ver_num = val<<16;
3379 bnx2x_cl45_read(bp, params->port, ext_phy_type,
3380 ext_phy_addr,
3381 MDIO_PMA_DEVAD,
3382 MDIO_PMA_REG_ROM_VER2, &val);
3383 ver_num |= val;
3384 status = bnx2x_format_ver(ver_num, version, len);
3385 break;
3386
3387 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3388 break;
3389
3390 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
3391 DP(NETIF_MSG_LINK, "bnx2x_get_ext_phy_fw_version:"
3392 " type is FAILURE!\n");
3393 status = -EINVAL;
3394 break;
3395
3396 default:
3397 break;
3398 }
3399 return status;
3400}
3401
3402static void bnx2x_set_xgxs_loopback(struct link_params *params,
3403 struct link_vars *vars,
3404 u8 is_10g)
3405{
3406 u8 port = params->port;
3407 struct bnx2x *bp = params->bp;
3408
3409 if (is_10g) {
3410 u32 md_devad;
3411
3412 DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
3413
3414 /* change the uni_phy_addr in the nig */
3415 md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
3416 port*0x18));
3417
3418 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
3419
3420 bnx2x_cl45_write(bp, port, 0,
3421 params->phy_addr,
3422 5,
3423 (MDIO_REG_BANK_AER_BLOCK +
3424 (MDIO_AER_BLOCK_AER_REG & 0xf)),
3425 0x2800);
3426
3427 bnx2x_cl45_write(bp, port, 0,
3428 params->phy_addr,
3429 5,
3430 (MDIO_REG_BANK_CL73_IEEEB0 +
3431 (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
3432 0x6041);
3433
3434 /* set aer mmd back */
3435 bnx2x_set_aer_mmd(params, vars);
3436
3437 /* and md_devad */
3438 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
3439 md_devad);
3440
3441 } else {
3442 u16 mii_control;
3443
3444 DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
3445
3446 CL45_RD_OVER_CL22(bp, port,
3447 params->phy_addr,
3448 MDIO_REG_BANK_COMBO_IEEE0,
3449 MDIO_COMBO_IEEE0_MII_CONTROL,
3450 &mii_control);
3451
3452 CL45_WR_OVER_CL22(bp, port,
3453 params->phy_addr,
3454 MDIO_REG_BANK_COMBO_IEEE0,
3455 MDIO_COMBO_IEEE0_MII_CONTROL,
3456 (mii_control |
3457 MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK));
3458 }
3459}
3460
3461
3462static void bnx2x_ext_phy_loopback(struct link_params *params)
3463{
3464 struct bnx2x *bp = params->bp;
3465 u8 ext_phy_addr;
3466 u32 ext_phy_type;
3467
3468 if (params->switch_cfg == SWITCH_CFG_10G) {
3469 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3470 /* CL37 Autoneg Enabled */
3471 ext_phy_addr = ((params->ext_phy_config &
3472 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
3473 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
3474 switch (ext_phy_type) {
3475 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3476 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
3477 DP(NETIF_MSG_LINK,
3478 "ext_phy_loopback: We should not get here\n");
3479 break;
3480 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
3481 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8705\n");
3482 break;
3483 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
3484 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8706\n");
3485 break;
3486 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3487 /* SFX7101_XGXS_TEST1 */
3488 bnx2x_cl45_write(bp, params->port, ext_phy_type,
3489 ext_phy_addr,
3490 MDIO_XS_DEVAD,
3491 MDIO_XS_SFX7101_XGXS_TEST1,
3492 0x100);
3493 DP(NETIF_MSG_LINK,
3494 "ext_phy_loopback: set ext phy loopback\n");
3495 break;
3496 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
3497
3498 break;
3499 } /* switch external PHY type */
3500 } else {
3501 /* serdes */
3502 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
3503 ext_phy_addr = (params->ext_phy_config &
3504 PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK)
3505 >> PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT;
3506 }
3507}
3508
3509
3510/*
3511 *------------------------------------------------------------------------
3512 * bnx2x_override_led_value -
3513 *
3514 * Override the led value of the requsted led
3515 *
3516 *------------------------------------------------------------------------
3517 */
3518u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port,
3519 u32 led_idx, u32 value)
3520{
3521 u32 reg_val;
3522
3523 /* If port 0 then use EMAC0, else use EMAC1*/
3524 u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
3525
3526 DP(NETIF_MSG_LINK,
3527 "bnx2x_override_led_value() port %x led_idx %d value %d\n",
3528 port, led_idx, value);
3529
3530 switch (led_idx) {
3531 case 0: /* 10MB led */
3532 /* Read the current value of the LED register in
3533 the EMAC block */
3534 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3535 /* Set the OVERRIDE bit to 1 */
3536 reg_val |= EMAC_LED_OVERRIDE;
3537 /* If value is 1, set the 10M_OVERRIDE bit,
3538 otherwise reset it.*/
3539 reg_val = (value == 1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) :
3540 (reg_val & ~EMAC_LED_10MB_OVERRIDE);
3541 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3542 break;
3543 case 1: /*100MB led */
3544 /*Read the current value of the LED register in
3545 the EMAC block */
3546 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3547 /* Set the OVERRIDE bit to 1 */
3548 reg_val |= EMAC_LED_OVERRIDE;
3549 /* If value is 1, set the 100M_OVERRIDE bit,
3550 otherwise reset it.*/
3551 reg_val = (value == 1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) :
3552 (reg_val & ~EMAC_LED_100MB_OVERRIDE);
3553 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3554 break;
3555 case 2: /* 1000MB led */
3556 /* Read the current value of the LED register in the
3557 EMAC block */
3558 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3559 /* Set the OVERRIDE bit to 1 */
3560 reg_val |= EMAC_LED_OVERRIDE;
3561 /* If value is 1, set the 1000M_OVERRIDE bit, otherwise
3562 reset it. */
3563 reg_val = (value == 1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) :
3564 (reg_val & ~EMAC_LED_1000MB_OVERRIDE);
3565 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3566 break;
3567 case 3: /* 2500MB led */
3568 /* Read the current value of the LED register in the
3569 EMAC block*/
3570 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
3571 /* Set the OVERRIDE bit to 1 */
3572 reg_val |= EMAC_LED_OVERRIDE;
3573 /* If value is 1, set the 2500M_OVERRIDE bit, otherwise
3574 reset it.*/
3575 reg_val = (value == 1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) :
3576 (reg_val & ~EMAC_LED_2500MB_OVERRIDE);
3577 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3578 break;
3579 case 4: /*10G led */
3580 if (port == 0) {
3581 REG_WR(bp, NIG_REG_LED_10G_P0,
3582 value);
3583 } else {
3584 REG_WR(bp, NIG_REG_LED_10G_P1,
3585 value);
3586 }
3587 break;
3588 case 5: /* TRAFFIC led */
3589 /* Find if the traffic control is via BMAC or EMAC */
3590 if (port == 0)
3591 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC0_EN);
3592 else
3593 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC1_EN);
3594
3595 /* Override the traffic led in the EMAC:*/
3596 if (reg_val == 1) {
3597 /* Read the current value of the LED register in
3598 the EMAC block */
3599 reg_val = REG_RD(bp, emac_base +
3600 EMAC_REG_EMAC_LED);
3601 /* Set the TRAFFIC_OVERRIDE bit to 1 */
3602 reg_val |= EMAC_LED_OVERRIDE;
3603 /* If value is 1, set the TRAFFIC bit, otherwise
3604 reset it.*/
3605 reg_val = (value == 1) ? (reg_val | EMAC_LED_TRAFFIC) :
3606 (reg_val & ~EMAC_LED_TRAFFIC);
3607 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
3608 } else { /* Override the traffic led in the BMAC: */
3609 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
3610 + port*4, 1);
3611 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port*4,
3612 value);
3613 }
3614 break;
3615 default:
3616 DP(NETIF_MSG_LINK,
3617 "bnx2x_override_led_value() unknown led index %d "
3618 "(should be 0-5)\n", led_idx);
3619 return -EINVAL;
3620 }
3621
3622 return 0;
3623}
3624
3625
3626u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
3627 u16 hw_led_mode, u32 chip_id)
3628{
3629 u8 rc = 0;
3630 DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
3631 DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
3632 speed, hw_led_mode);
3633 switch (mode) {
3634 case LED_MODE_OFF:
3635 REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0);
3636 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
3637 SHARED_HW_CFG_LED_MAC1);
3638 break;
3639
3640 case LED_MODE_OPER:
3641 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode);
3642 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
3643 port*4, 0);
3644 /* Set blinking rate to ~15.9Hz */
3645 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
3646 LED_BLINK_RATE_VAL);
3647 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
3648 port*4, 1);
Eilon Greenstein34f80b02008-06-23 20:33:01 -07003649 if (!CHIP_IS_E1H(bp) &&
3650 ((speed == SPEED_2500) ||
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003651 (speed == SPEED_1000) ||
3652 (speed == SPEED_100) ||
3653 (speed == SPEED_10))) {
3654 /* On Everest 1 Ax chip versions for speeds less than
3655 10G LED scheme is different */
3656 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
3657 + port*4, 1);
3658 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
3659 port*4, 0);
3660 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
3661 port*4, 1);
3662 }
3663 break;
3664
3665 default:
3666 rc = -EINVAL;
3667 DP(NETIF_MSG_LINK, "bnx2x_set_led: Invalid led mode %d\n",
3668 mode);
3669 break;
3670 }
3671 return rc;
3672
3673}
3674
3675u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars)
3676{
3677 struct bnx2x *bp = params->bp;
3678 u16 gp_status = 0;
3679
3680 CL45_RD_OVER_CL22(bp, params->port,
3681 params->phy_addr,
3682 MDIO_REG_BANK_GP_STATUS,
3683 MDIO_GP_STATUS_TOP_AN_STATUS1,
3684 &gp_status);
3685 /* link is up only if both local phy and external phy are up */
3686 if ((gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) &&
3687 bnx2x_ext_phy_is_link_up(params, vars))
3688 return 0;
3689
3690 return -ESRCH;
3691}
3692
3693static u8 bnx2x_link_initialize(struct link_params *params,
3694 struct link_vars *vars)
3695{
3696 struct bnx2x *bp = params->bp;
3697 u8 port = params->port;
3698 u8 rc = 0;
Yaniv Rosner57963ed2008-08-13 15:55:28 -07003699 u8 non_ext_phy;
3700 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003701 /* Activate the external PHY */
3702 bnx2x_ext_phy_reset(params, vars);
3703
3704 bnx2x_set_aer_mmd(params, vars);
3705
3706 if (vars->phy_flags & PHY_XGXS_FLAG)
3707 bnx2x_set_master_ln(params);
3708
3709 rc = bnx2x_reset_unicore(params);
3710 /* reset the SerDes and wait for reset bit return low */
3711 if (rc != 0)
3712 return rc;
3713
3714 bnx2x_set_aer_mmd(params, vars);
3715
3716 /* setting the masterLn_def again after the reset */
3717 if (vars->phy_flags & PHY_XGXS_FLAG) {
3718 bnx2x_set_master_ln(params);
3719 bnx2x_set_swap_lanes(params);
3720 }
3721
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003722 if (vars->phy_flags & PHY_XGXS_FLAG) {
3723 if (params->req_line_speed &&
3724 ((params->req_line_speed == SPEED_100) ||
3725 (params->req_line_speed == SPEED_10))) {
3726 vars->phy_flags |= PHY_SGMII_FLAG;
3727 } else {
3728 vars->phy_flags &= ~PHY_SGMII_FLAG;
3729 }
3730 }
Yaniv Rosner57963ed2008-08-13 15:55:28 -07003731 /* In case of external phy existance, the line speed would be the
3732 line speed linked up by the external phy. In case it is direct only,
3733 then the line_speed during initialization will be equal to the
3734 req_line_speed*/
3735 vars->line_speed = params->req_line_speed;
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003736
Yaniv Rosner57963ed2008-08-13 15:55:28 -07003737 bnx2x_set_ieee_aneg_advertisment(params, &vars->ieee_fc);
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003738
3739 /* init ext phy and enable link state int */
Yaniv Rosner57963ed2008-08-13 15:55:28 -07003740 non_ext_phy = ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
3741 (params->loopback_mode == LOOPBACK_XGXS_10) ||
3742 (params->loopback_mode == LOOPBACK_EXT_PHY));
3743
3744 if (non_ext_phy ||
3745 (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705)) {
3746 if (params->req_line_speed == SPEED_AUTO_NEG)
3747 bnx2x_set_parallel_detection(params, vars->phy_flags);
3748 bnx2x_init_internal_phy(params, vars);
3749 }
3750
3751 if (!non_ext_phy)
3752 rc |= bnx2x_ext_phy_init(params, vars);
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003753
3754 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
Yaniv Rosner57963ed2008-08-13 15:55:28 -07003755 (NIG_STATUS_XGXS0_LINK10G |
3756 NIG_STATUS_XGXS0_LINK_STATUS |
3757 NIG_STATUS_SERDES0_LINK_STATUS));
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003758
3759 return rc;
3760
3761}
3762
3763
3764u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
3765{
3766 struct bnx2x *bp = params->bp;
3767
3768 u32 val;
3769 DP(NETIF_MSG_LINK, "Phy Initialization started\n");
3770 DP(NETIF_MSG_LINK, "req_speed = %d, req_flowctrl=%d\n",
3771 params->req_line_speed, params->req_flow_ctrl);
3772 vars->link_status = 0;
Yaniv Rosner57963ed2008-08-13 15:55:28 -07003773 vars->phy_link_up = 0;
3774 vars->link_up = 0;
3775 vars->line_speed = 0;
3776 vars->duplex = DUPLEX_FULL;
3777 vars->flow_ctrl = FLOW_CTRL_NONE;
3778 vars->mac_type = MAC_TYPE_NONE;
3779
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003780 if (params->switch_cfg == SWITCH_CFG_1G)
3781 vars->phy_flags = PHY_SERDES_FLAG;
3782 else
3783 vars->phy_flags = PHY_XGXS_FLAG;
3784
3785 /* disable attentions */
3786 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
3787 (NIG_MASK_XGXS0_LINK_STATUS |
3788 NIG_MASK_XGXS0_LINK10G |
3789 NIG_MASK_SERDES0_LINK_STATUS |
3790 NIG_MASK_MI_INT));
3791
3792 bnx2x_emac_init(params, vars);
3793
3794 if (CHIP_REV_IS_FPGA(bp)) {
3795 vars->link_up = 1;
3796 vars->line_speed = SPEED_10000;
3797 vars->duplex = DUPLEX_FULL;
3798 vars->flow_ctrl = FLOW_CTRL_NONE;
3799 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
Eilon Greenstein34f80b02008-06-23 20:33:01 -07003800 /* enable on E1.5 FPGA */
3801 if (CHIP_IS_E1H(bp)) {
3802 vars->flow_ctrl |=
3803 (FLOW_CTRL_TX | FLOW_CTRL_RX);
3804 vars->link_status |=
3805 (LINK_STATUS_TX_FLOW_CONTROL_ENABLED |
3806 LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
3807 }
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003808
3809 bnx2x_emac_enable(params, vars, 0);
3810 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
3811 /* disable drain */
3812 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
3813 + params->port*4, 0);
3814
3815 /* update shared memory */
3816 bnx2x_update_mng(params, vars->link_status);
3817
3818 return 0;
3819
3820 } else
3821 if (CHIP_REV_IS_EMUL(bp)) {
3822
3823 vars->link_up = 1;
3824 vars->line_speed = SPEED_10000;
3825 vars->duplex = DUPLEX_FULL;
3826 vars->flow_ctrl = FLOW_CTRL_NONE;
3827 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
3828
3829 bnx2x_bmac_enable(params, vars, 0);
3830
3831 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
3832 /* Disable drain */
3833 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
3834 + params->port*4, 0);
3835
3836 /* update shared memory */
3837 bnx2x_update_mng(params, vars->link_status);
3838
3839 return 0;
3840
3841 } else
3842 if (params->loopback_mode == LOOPBACK_BMAC) {
3843 vars->link_up = 1;
3844 vars->line_speed = SPEED_10000;
3845 vars->duplex = DUPLEX_FULL;
3846 vars->flow_ctrl = FLOW_CTRL_NONE;
3847 vars->mac_type = MAC_TYPE_BMAC;
3848
3849 vars->phy_flags = PHY_XGXS_FLAG;
3850
3851 bnx2x_phy_deassert(params, vars->phy_flags);
3852 /* set bmac loopback */
3853 bnx2x_bmac_enable(params, vars, 1);
3854
3855 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
3856 params->port*4, 0);
3857 } else if (params->loopback_mode == LOOPBACK_EMAC) {
3858 vars->link_up = 1;
3859 vars->line_speed = SPEED_1000;
3860 vars->duplex = DUPLEX_FULL;
3861 vars->flow_ctrl = FLOW_CTRL_NONE;
3862 vars->mac_type = MAC_TYPE_EMAC;
3863
3864 vars->phy_flags = PHY_XGXS_FLAG;
3865
3866 bnx2x_phy_deassert(params, vars->phy_flags);
3867 /* set bmac loopback */
3868 bnx2x_emac_enable(params, vars, 1);
3869 bnx2x_emac_program(params, vars->line_speed,
3870 vars->duplex);
3871 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
3872 params->port*4, 0);
3873 } else if ((params->loopback_mode == LOOPBACK_XGXS_10) ||
3874 (params->loopback_mode == LOOPBACK_EXT_PHY)) {
3875 vars->link_up = 1;
3876 vars->line_speed = SPEED_10000;
3877 vars->duplex = DUPLEX_FULL;
3878 vars->flow_ctrl = FLOW_CTRL_NONE;
3879
3880 vars->phy_flags = PHY_XGXS_FLAG;
3881
3882 val = REG_RD(bp,
3883 NIG_REG_XGXS0_CTRL_PHY_ADDR+
3884 params->port*0x18);
3885 params->phy_addr = (u8)val;
3886
3887 bnx2x_phy_deassert(params, vars->phy_flags);
3888 bnx2x_link_initialize(params, vars);
3889
3890 vars->mac_type = MAC_TYPE_BMAC;
3891
3892 bnx2x_bmac_enable(params, vars, 0);
3893
3894 if (params->loopback_mode == LOOPBACK_XGXS_10) {
3895 /* set 10G XGXS loopback */
3896 bnx2x_set_xgxs_loopback(params, vars, 1);
3897 } else {
3898 /* set external phy loopback */
3899 bnx2x_ext_phy_loopback(params);
3900 }
3901 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
3902 params->port*4, 0);
3903 } else
3904 /* No loopback */
3905 {
3906
3907 bnx2x_phy_deassert(params, vars->phy_flags);
3908 switch (params->switch_cfg) {
3909 case SWITCH_CFG_1G:
3910 vars->phy_flags |= PHY_SERDES_FLAG;
3911 if ((params->ext_phy_config &
3912 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK) ==
3913 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482) {
3914 vars->phy_flags |=
3915 PHY_SGMII_FLAG;
3916 }
3917
3918 val = REG_RD(bp,
3919 NIG_REG_SERDES0_CTRL_PHY_ADDR+
3920 params->port*0x10);
3921
3922 params->phy_addr = (u8)val;
3923
3924 break;
3925 case SWITCH_CFG_10G:
3926 vars->phy_flags |= PHY_XGXS_FLAG;
3927 val = REG_RD(bp,
3928 NIG_REG_XGXS0_CTRL_PHY_ADDR+
3929 params->port*0x18);
3930 params->phy_addr = (u8)val;
3931
3932 break;
3933 default:
3934 DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
3935 return -EINVAL;
3936 break;
3937 }
3938
3939 bnx2x_link_initialize(params, vars);
Yaniv Rosner57963ed2008-08-13 15:55:28 -07003940 msleep(30);
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003941 bnx2x_link_int_enable(params);
3942 }
3943 return 0;
3944}
3945
3946u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars)
3947{
3948
3949 struct bnx2x *bp = params->bp;
3950 u32 ext_phy_config = params->ext_phy_config;
3951 u16 hw_led_mode = params->hw_led_mode;
3952 u32 chip_id = params->chip_id;
3953 u8 port = params->port;
3954 u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
3955 /* disable attentions */
3956
3957 vars->link_status = 0;
3958 bnx2x_update_mng(params, vars->link_status);
3959 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
3960 (NIG_MASK_XGXS0_LINK_STATUS |
3961 NIG_MASK_XGXS0_LINK10G |
3962 NIG_MASK_SERDES0_LINK_STATUS |
3963 NIG_MASK_MI_INT));
3964
3965 /* activate nig drain */
3966 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
3967
3968 /* disable nig egress interface */
3969 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
3970 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
3971
3972 /* Stop BigMac rx */
3973 bnx2x_bmac_rx_disable(bp, port);
3974
3975 /* disable emac */
3976 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
3977
3978 msleep(10);
3979 /* The PHY reset is controled by GPIO 1
3980 * Hold it as vars low
3981 */
3982 /* clear link led */
3983 bnx2x_set_led(bp, port, LED_MODE_OFF, 0, hw_led_mode, chip_id);
3984 if (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
3985 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
3986 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
3987 /* HW reset */
3988
3989 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
3990 MISC_REGISTERS_GPIO_OUTPUT_LOW);
3991
3992 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
3993 MISC_REGISTERS_GPIO_OUTPUT_LOW);
3994
3995 DP(NETIF_MSG_LINK, "reset external PHY\n");
Yaniv Rosner57963ed2008-08-13 15:55:28 -07003996 } else if (ext_phy_type ==
3997 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
3998 DP(NETIF_MSG_LINK, "Setting 8073 port %d into "
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07003999 "low power mode\n",
4000 port);
4001 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4002 MISC_REGISTERS_GPIO_OUTPUT_LOW);
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07004003 }
4004 }
4005 /* reset the SerDes/XGXS */
4006 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
4007 (0x1ff << (port*16)));
4008
4009 /* reset BigMac */
4010 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
4011 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
4012
4013 /* disable nig ingress interface */
4014 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
4015 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
4016 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
4017 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
4018 vars->link_up = 0;
4019 return 0;
4020}
4021
Yaniv Rosner57963ed2008-08-13 15:55:28 -07004022static u8 bnx2x_update_link_down(struct link_params *params,
4023 struct link_vars *vars)
4024{
4025 struct bnx2x *bp = params->bp;
4026 u8 port = params->port;
4027 DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
4028 bnx2x_set_led(bp, port, LED_MODE_OFF,
4029 0, params->hw_led_mode,
4030 params->chip_id);
4031
4032 /* indicate no mac active */
4033 vars->mac_type = MAC_TYPE_NONE;
4034
4035 /* update shared memory */
4036 vars->link_status = 0;
4037 vars->line_speed = 0;
4038 bnx2x_update_mng(params, vars->link_status);
4039
4040 /* activate nig drain */
4041 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
4042
4043 /* reset BigMac */
4044 bnx2x_bmac_rx_disable(bp, params->port);
4045 REG_WR(bp, GRCBASE_MISC +
4046 MISC_REGISTERS_RESET_REG_2_CLEAR,
4047 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
4048 return 0;
4049}
4050
4051static u8 bnx2x_update_link_up(struct link_params *params,
4052 struct link_vars *vars,
4053 u8 link_10g, u32 gp_status)
4054{
4055 struct bnx2x *bp = params->bp;
4056 u8 port = params->port;
4057 u8 rc = 0;
4058 vars->link_status |= LINK_STATUS_LINK_UP;
4059 if (link_10g) {
4060 bnx2x_bmac_enable(params, vars, 0);
4061 bnx2x_set_led(bp, port, LED_MODE_OPER,
4062 SPEED_10000, params->hw_led_mode,
4063 params->chip_id);
4064
4065 } else {
4066 bnx2x_emac_enable(params, vars, 0);
4067 rc = bnx2x_emac_program(params, vars->line_speed,
4068 vars->duplex);
4069
4070 /* AN complete? */
4071 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
4072 if (!(vars->phy_flags &
4073 PHY_SGMII_FLAG))
4074 bnx2x_set_sgmii_tx_driver(params);
4075 }
4076 }
4077
4078 /* PBF - link up */
4079 rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
4080 vars->line_speed);
4081
4082 /* disable drain */
4083 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
4084
4085 /* update shared memory */
4086 bnx2x_update_mng(params, vars->link_status);
4087 return rc;
4088}
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07004089/* This function should called upon link interrupt */
4090/* In case vars->link_up, driver needs to
4091 1. Update the pbf
4092 2. Disable drain
4093 3. Update the shared memory
4094 4. Indicate link up
4095 5. Set LEDs
4096 Otherwise,
4097 1. Update shared memory
4098 2. Reset BigMac
4099 3. Report link down
4100 4. Unset LEDs
4101*/
4102u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
4103{
4104 struct bnx2x *bp = params->bp;
4105 u8 port = params->port;
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07004106 u16 gp_status;
Yaniv Rosner57963ed2008-08-13 15:55:28 -07004107 u8 link_10g;
4108 u8 ext_phy_link_up, rc = 0;
4109 u32 ext_phy_type;
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07004110
4111 DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
4112 port,
4113 (vars->phy_flags & PHY_XGXS_FLAG),
4114 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
4115
4116 DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
4117 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
4118 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
4119 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
4120
4121 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
4122 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
4123 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
4124
Yaniv Rosner57963ed2008-08-13 15:55:28 -07004125 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07004126
Yaniv Rosner57963ed2008-08-13 15:55:28 -07004127 /* Check external link change only for non-direct */
4128 ext_phy_link_up = bnx2x_ext_phy_is_link_up(params, vars);
4129
4130 /* Read gp_status */
4131 CL45_RD_OVER_CL22(bp, port, params->phy_addr,
4132 MDIO_REG_BANK_GP_STATUS,
4133 MDIO_GP_STATUS_TOP_AN_STATUS1,
4134 &gp_status);
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07004135
4136 rc = bnx2x_link_settings_status(params, vars, gp_status);
4137 if (rc != 0)
4138 return rc;
4139
4140 /* anything 10 and over uses the bmac */
4141 link_10g = ((vars->line_speed == SPEED_10000) ||
4142 (vars->line_speed == SPEED_12000) ||
4143 (vars->line_speed == SPEED_12500) ||
4144 (vars->line_speed == SPEED_13000) ||
4145 (vars->line_speed == SPEED_15000) ||
4146 (vars->line_speed == SPEED_16000));
4147
4148 bnx2x_link_int_ack(params, vars, link_10g);
4149
Yaniv Rosner57963ed2008-08-13 15:55:28 -07004150 /* In case external phy link is up, and internal link is down
4151 ( not initialized yet probably after link initialization, it needs
4152 to be initialized.
4153 Note that after link down-up as result of cable plug,
4154 the xgxs link would probably become up again without the need to
4155 initialize it*/
4156
4157 if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
4158 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) &&
4159 (ext_phy_link_up && !vars->phy_link_up))
4160 bnx2x_init_internal_phy(params, vars);
4161
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07004162 /* link is up only if both local phy and external phy are up */
Yaniv Rosner57963ed2008-08-13 15:55:28 -07004163 vars->link_up = (ext_phy_link_up && vars->phy_link_up);
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07004164
Yaniv Rosner57963ed2008-08-13 15:55:28 -07004165 if (vars->link_up)
4166 rc = bnx2x_update_link_up(params, vars, link_10g, gp_status);
4167 else
4168 rc = bnx2x_update_link_down(params, vars);
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07004169
4170 return rc;
4171}
4172
4173static void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
4174{
4175 u16 val, cnt;
4176
4177 bnx2x_cl45_read(bp, port,
4178 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4179 phy_addr,
4180 MDIO_PMA_DEVAD,
4181 MDIO_PMA_REG_7101_RESET, &val);
4182
4183 for (cnt = 0; cnt < 10; cnt++) {
4184 msleep(50);
4185 /* Writes a self-clearing reset */
4186 bnx2x_cl45_write(bp, port,
4187 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4188 phy_addr,
4189 MDIO_PMA_DEVAD,
4190 MDIO_PMA_REG_7101_RESET,
4191 (val | (1<<15)));
4192 /* Wait for clear */
4193 bnx2x_cl45_read(bp, port,
4194 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4195 phy_addr,
4196 MDIO_PMA_DEVAD,
4197 MDIO_PMA_REG_7101_RESET, &val);
4198
4199 if ((val & (1<<15)) == 0)
4200 break;
4201 }
4202}
4203#define RESERVED_SIZE 256
4204/* max application is 160K bytes - data at end of RAM */
4205#define MAX_APP_SIZE 160*1024 - RESERVED_SIZE
4206
4207/* Header is 14 bytes */
4208#define HEADER_SIZE 14
4209#define DATA_OFFSET HEADER_SIZE
4210
4211#define SPI_START_TRANSFER(bp, port, ext_phy_addr) \
4212 bnx2x_cl45_write(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101, \
4213 ext_phy_addr, \
4214 MDIO_PCS_DEVAD, \
4215 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 1)
4216
4217/* Programs an image to DSP's flash via the SPI port*/
4218static u8 bnx2x_sfx7101_flash_download(struct bnx2x *bp, u8 port,
4219 u8 ext_phy_addr,
4220 char data[], u32 size)
4221{
4222 const u16 num_trans = size/4; /* 4 bytes can be sent at a time */
4223 /* Doesn't include last trans!*/
4224 const u16 last_trans_size = size%4; /* Num bytes on last trans */
4225 u16 trans_cnt, byte_cnt;
4226 u32 data_index;
4227 u16 tmp;
4228 u16 code_started = 0;
4229 u16 image_revision1, image_revision2;
4230 u16 cnt;
4231
4232 DP(NETIF_MSG_LINK, "bnx2x_sfx7101_flash_download file_size=%d\n", size);
4233 /* Going to flash*/
4234 if ((size-HEADER_SIZE) > MAX_APP_SIZE) {
4235 /* This very often will be the case, because the image is built
4236 with 160Kbytes size whereas the total image size must actually
4237 be 160Kbytes-RESERVED_SIZE */
4238 DP(NETIF_MSG_LINK, "Warning, file size was %d bytes "
4239 "truncated to %d bytes\n", size, MAX_APP_SIZE);
4240 size = MAX_APP_SIZE+HEADER_SIZE;
4241 }
4242 DP(NETIF_MSG_LINK, "File version is %c%c\n", data[0x14e], data[0x14f]);
4243 DP(NETIF_MSG_LINK, " %c%c\n", data[0x150], data[0x151]);
4244 /* Put the DSP in download mode by setting FLASH_CFG[2] to 1
4245 and issuing a reset.*/
4246
4247 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
4248 MISC_REGISTERS_GPIO_HIGH);
4249
4250 bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
4251
4252 /* wait 0.5 sec */
4253 for (cnt = 0; cnt < 100; cnt++)
4254 msleep(5);
4255
4256 /* Make sure we can access the DSP
4257 And it's in the correct mode (waiting for download) */
4258
4259 bnx2x_cl45_read(bp, port,
4260 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4261 ext_phy_addr,
4262 MDIO_PCS_DEVAD,
4263 MDIO_PCS_REG_7101_DSP_ACCESS, &tmp);
4264
4265 if (tmp != 0x000A) {
4266 DP(NETIF_MSG_LINK, "DSP is not in waiting on download mode. "
4267 "Expected 0x000A, read 0x%04X\n", tmp);
4268 DP(NETIF_MSG_LINK, "Download failed\n");
4269 return -EINVAL;
4270 }
4271
4272 /* Mux the SPI interface away from the internal processor */
4273 bnx2x_cl45_write(bp, port,
4274 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4275 ext_phy_addr,
4276 MDIO_PCS_DEVAD,
4277 MDIO_PCS_REG_7101_SPI_MUX, 1);
4278
4279 /* Reset the SPI port */
4280 bnx2x_cl45_write(bp, port,
4281 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4282 ext_phy_addr,
4283 MDIO_PCS_DEVAD,
4284 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
4285 bnx2x_cl45_write(bp, port,
4286 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4287 ext_phy_addr,
4288 MDIO_PCS_DEVAD,
4289 MDIO_PCS_REG_7101_SPI_CTRL_ADDR,
4290 (1<<MDIO_PCS_REG_7101_SPI_RESET_BIT));
4291 bnx2x_cl45_write(bp, port,
4292 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4293 ext_phy_addr,
4294 MDIO_PCS_DEVAD,
4295 MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
4296
4297 /* Erase the flash */
4298 bnx2x_cl45_write(bp, port,
4299 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4300 ext_phy_addr,
4301 MDIO_PCS_DEVAD,
4302 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4303 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4304
4305 bnx2x_cl45_write(bp, port,
4306 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4307 ext_phy_addr,
4308 MDIO_PCS_DEVAD,
4309 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4310 1);
4311
4312 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4313 bnx2x_cl45_write(bp, port,
4314 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4315 ext_phy_addr,
4316 MDIO_PCS_DEVAD,
4317 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4318 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_BULK_ERASE_CMD);
4319
4320 bnx2x_cl45_write(bp, port,
4321 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4322 ext_phy_addr,
4323 MDIO_PCS_DEVAD,
4324 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4325 1);
4326 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4327
4328 /* Wait 10 seconds, the maximum time for the erase to complete */
4329 DP(NETIF_MSG_LINK, "Erasing flash, this takes 10 seconds...\n");
4330 for (cnt = 0; cnt < 1000; cnt++)
4331 msleep(10);
4332
4333 DP(NETIF_MSG_LINK, "Downloading flash, please wait...\n");
4334 data_index = 0;
4335 for (trans_cnt = 0; trans_cnt < num_trans; trans_cnt++) {
4336 bnx2x_cl45_write(bp, port,
4337 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4338 ext_phy_addr,
4339 MDIO_PCS_DEVAD,
4340 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4341 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4342
4343 bnx2x_cl45_write(bp, port,
4344 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4345 ext_phy_addr,
4346 MDIO_PCS_DEVAD,
4347 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4348 1);
4349 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4350
4351 bnx2x_cl45_write(bp, port,
4352 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4353 ext_phy_addr,
4354 MDIO_PCS_DEVAD,
4355 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4356 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
4357
4358 /* Bits 23-16 of address */
4359 bnx2x_cl45_write(bp, port,
4360 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4361 ext_phy_addr,
4362 MDIO_PCS_DEVAD,
4363 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4364 (data_index>>16));
4365 /* Bits 15-8 of address */
4366 bnx2x_cl45_write(bp, port,
4367 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4368 ext_phy_addr,
4369 MDIO_PCS_DEVAD,
4370 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4371 (data_index>>8));
4372
4373 /* Bits 7-0 of address */
4374 bnx2x_cl45_write(bp, port,
4375 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4376 ext_phy_addr,
4377 MDIO_PCS_DEVAD,
4378 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4379 ((u16)data_index));
4380
4381 byte_cnt = 0;
4382 while (byte_cnt < 4 && data_index < size) {
4383 bnx2x_cl45_write(bp, port,
4384 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4385 ext_phy_addr,
4386 MDIO_PCS_DEVAD,
4387 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4388 data[data_index++]);
4389 byte_cnt++;
4390 }
4391
4392 bnx2x_cl45_write(bp, port,
4393 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4394 ext_phy_addr,
4395 MDIO_PCS_DEVAD,
4396 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4397 byte_cnt+4);
4398
4399 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4400 msleep(5); /* Wait 5 ms minimum between transs */
4401
4402 /* Let the user know something's going on.*/
4403 /* a pacifier ever 4K */
4404 if ((data_index % 1023) == 0)
4405 DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
4406 }
4407
4408 DP(NETIF_MSG_LINK, "\n");
4409 /* Transfer the last block if there is data remaining */
4410 if (last_trans_size) {
4411 bnx2x_cl45_write(bp, port,
4412 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4413 ext_phy_addr,
4414 MDIO_PCS_DEVAD,
4415 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4416 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
4417
4418 bnx2x_cl45_write(bp, port,
4419 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4420 ext_phy_addr,
4421 MDIO_PCS_DEVAD,
4422 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4423 1);
4424
4425 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4426
4427 bnx2x_cl45_write(bp, port,
4428 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4429 ext_phy_addr,
4430 MDIO_PCS_DEVAD,
4431 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4432 MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
4433
4434 /* Bits 23-16 of address */
4435 bnx2x_cl45_write(bp, port,
4436 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4437 ext_phy_addr,
4438 MDIO_PCS_DEVAD,
4439 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4440 (data_index>>16));
4441 /* Bits 15-8 of address */
4442 bnx2x_cl45_write(bp, port,
4443 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4444 ext_phy_addr,
4445 MDIO_PCS_DEVAD,
4446 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4447 (data_index>>8));
4448
4449 /* Bits 7-0 of address */
4450 bnx2x_cl45_write(bp, port,
4451 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4452 ext_phy_addr,
4453 MDIO_PCS_DEVAD,
4454 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4455 ((u16)data_index));
4456
4457 byte_cnt = 0;
4458 while (byte_cnt < last_trans_size && data_index < size) {
4459 /* Bits 7-0 of address */
4460 bnx2x_cl45_write(bp, port,
4461 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4462 ext_phy_addr,
4463 MDIO_PCS_DEVAD,
4464 MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
4465 data[data_index++]);
4466 byte_cnt++;
4467 }
4468
4469 bnx2x_cl45_write(bp, port,
4470 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4471 ext_phy_addr,
4472 MDIO_PCS_DEVAD,
4473 MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
4474 byte_cnt+4);
4475
4476 SPI_START_TRANSFER(bp, port, ext_phy_addr);
4477 }
4478
4479 /* DSP Remove Download Mode */
4480 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, MISC_REGISTERS_GPIO_LOW);
4481
4482 bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
4483
4484 /* wait 0.5 sec to allow it to run */
4485 for (cnt = 0; cnt < 100; cnt++)
4486 msleep(5);
4487
4488 bnx2x_hw_reset(bp);
4489
4490 for (cnt = 0; cnt < 100; cnt++)
4491 msleep(5);
4492
4493 /* Check that the code is started. In case the download
4494 checksum failed, the code won't be started. */
4495 bnx2x_cl45_read(bp, port,
4496 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4497 ext_phy_addr,
4498 MDIO_PCS_DEVAD,
4499 MDIO_PCS_REG_7101_DSP_ACCESS,
4500 &tmp);
4501
4502 code_started = (tmp & (1<<4));
4503 if (!code_started) {
4504 DP(NETIF_MSG_LINK, "Download failed. Please check file.\n");
4505 return -EINVAL;
4506 }
4507
4508 /* Verify that the file revision is now equal to the image
4509 revision within the DSP */
4510 bnx2x_cl45_read(bp, port,
4511 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4512 ext_phy_addr,
4513 MDIO_PMA_DEVAD,
4514 MDIO_PMA_REG_7101_VER1,
4515 &image_revision1);
4516
4517 bnx2x_cl45_read(bp, port,
4518 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
4519 ext_phy_addr,
4520 MDIO_PMA_DEVAD,
4521 MDIO_PMA_REG_7101_VER2,
4522 &image_revision2);
4523
4524 if (data[0x14e] != (image_revision2&0xFF) ||
4525 data[0x14f] != ((image_revision2&0xFF00)>>8) ||
4526 data[0x150] != (image_revision1&0xFF) ||
4527 data[0x151] != ((image_revision1&0xFF00)>>8)) {
4528 DP(NETIF_MSG_LINK, "Download failed.\n");
4529 return -EINVAL;
4530 }
4531 DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
4532 return 0;
4533}
4534
4535u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config,
4536 u8 driver_loaded, char data[], u32 size)
4537{
4538 u8 rc = 0;
4539 u32 ext_phy_type;
4540 u8 ext_phy_addr;
4541 ext_phy_addr = ((ext_phy_config &
4542 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
4543 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
4544
4545 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
4546
4547 switch (ext_phy_type) {
4548 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
4549 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
4550 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
4551 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
4552 DP(NETIF_MSG_LINK,
4553 "Flash download not supported for this ext phy\n");
4554 rc = -EINVAL;
4555 break;
4556 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
4557 /* Take ext phy out of reset */
4558 if (!driver_loaded)
Yaniv Rosner57963ed2008-08-13 15:55:28 -07004559 bnx2x_turn_on_ef(bp, port, ext_phy_addr, ext_phy_type);
Yaniv Rosnerea4e0402008-06-23 20:27:26 -07004560 rc = bnx2x_sfx7101_flash_download(bp, port, ext_phy_addr,
4561 data, size);
4562 if (!driver_loaded)
4563 bnx2x_turn_off_sf(bp);
4564 break;
4565 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
4566 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
4567 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
4568 default:
4569 DP(NETIF_MSG_LINK, "Invalid ext phy type\n");
4570 rc = -EINVAL;
4571 break;
4572 }
4573 return rc;
4574}
4575