]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/net/bnx2x/bnx2x_link.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[net-next-2.6.git] / drivers / net / bnx2x / bnx2x_link.c
CommitLineData
d05c26ce 1/* Copyright 2008-2009 Broadcom Corporation
ea4e040a
YR
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
7995c64e
JP
17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
ea4e040a
YR
19#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/pci.h>
22#include <linux/netdevice.h>
23#include <linux/delay.h>
24#include <linux/ethtool.h>
25#include <linux/mutex.h>
ea4e040a 26
ea4e040a
YR
27#include "bnx2x.h"
28
29/********************************************************/
3196a88a 30#define ETH_HLEN 14
ea4e040a
YR
31#define ETH_OVREHEAD (ETH_HLEN + 8)/* 8 for CRC + VLAN*/
32#define ETH_MIN_PACKET_SIZE 60
33#define ETH_MAX_PACKET_SIZE 1500
34#define ETH_MAX_JUMBO_PACKET_SIZE 9600
35#define MDIO_ACCESS_TIMEOUT 1000
36#define BMAC_CONTROL_RX_ENABLE 2
ea4e040a
YR
37
38/***********************************************************/
3196a88a 39/* Shortcut definitions */
ea4e040a
YR
40/***********************************************************/
41
2f904460
EG
42#define NIG_LATCH_BC_ENABLE_MI_INT 0
43
44#define NIG_STATUS_EMAC0_MI_INT \
45 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_INT
ea4e040a
YR
46#define NIG_STATUS_XGXS0_LINK10G \
47 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G
48#define NIG_STATUS_XGXS0_LINK_STATUS \
49 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS
50#define NIG_STATUS_XGXS0_LINK_STATUS_SIZE \
51 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE
52#define NIG_STATUS_SERDES0_LINK_STATUS \
53 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS
54#define NIG_MASK_MI_INT \
55 NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT
56#define NIG_MASK_XGXS0_LINK10G \
57 NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G
58#define NIG_MASK_XGXS0_LINK_STATUS \
59 NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK_STATUS
60#define NIG_MASK_SERDES0_LINK_STATUS \
61 NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS
62
63#define MDIO_AN_CL73_OR_37_COMPLETE \
64 (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | \
65 MDIO_GP_STATUS_TOP_AN_STATUS1_CL37_AUTONEG_COMPLETE)
66
67#define XGXS_RESET_BITS \
68 (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW | \
69 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_IDDQ | \
70 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN | \
71 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN_SD | \
72 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB)
73
74#define SERDES_RESET_BITS \
75 (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_RSTB_HW | \
76 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ | \
77 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN | \
78 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN_SD)
79
80#define AUTONEG_CL37 SHARED_HW_CFG_AN_ENABLE_CL37
81#define AUTONEG_CL73 SHARED_HW_CFG_AN_ENABLE_CL73
3196a88a
EG
82#define AUTONEG_BAM SHARED_HW_CFG_AN_ENABLE_BAM
83#define AUTONEG_PARALLEL \
ea4e040a 84 SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
3196a88a 85#define AUTONEG_SGMII_FIBER_AUTODET \
ea4e040a 86 SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT
3196a88a 87#define AUTONEG_REMOTE_PHY SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY
ea4e040a
YR
88
89#define GP_STATUS_PAUSE_RSOLUTION_TXSIDE \
90 MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE
91#define GP_STATUS_PAUSE_RSOLUTION_RXSIDE \
92 MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_RXSIDE
93#define GP_STATUS_SPEED_MASK \
94 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_MASK
95#define GP_STATUS_10M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10M
96#define GP_STATUS_100M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_100M
97#define GP_STATUS_1G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G
98#define GP_STATUS_2_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_2_5G
99#define GP_STATUS_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_5G
100#define GP_STATUS_6G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_6G
101#define GP_STATUS_10G_HIG \
102 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG
103#define GP_STATUS_10G_CX4 \
104 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4
105#define GP_STATUS_12G_HIG \
106 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12G_HIG
107#define GP_STATUS_12_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12_5G
108#define GP_STATUS_13G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_13G
109#define GP_STATUS_15G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_15G
110#define GP_STATUS_16G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G
111#define GP_STATUS_1G_KX MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX
112#define GP_STATUS_10G_KX4 \
113 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
114
115#define LINK_10THD LINK_STATUS_SPEED_AND_DUPLEX_10THD
116#define LINK_10TFD LINK_STATUS_SPEED_AND_DUPLEX_10TFD
117#define LINK_100TXHD LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
118#define LINK_100T4 LINK_STATUS_SPEED_AND_DUPLEX_100T4
119#define LINK_100TXFD LINK_STATUS_SPEED_AND_DUPLEX_100TXFD
120#define LINK_1000THD LINK_STATUS_SPEED_AND_DUPLEX_1000THD
121#define LINK_1000TFD LINK_STATUS_SPEED_AND_DUPLEX_1000TFD
122#define LINK_1000XFD LINK_STATUS_SPEED_AND_DUPLEX_1000XFD
123#define LINK_2500THD LINK_STATUS_SPEED_AND_DUPLEX_2500THD
124#define LINK_2500TFD LINK_STATUS_SPEED_AND_DUPLEX_2500TFD
125#define LINK_2500XFD LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
126#define LINK_10GTFD LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
127#define LINK_10GXFD LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
128#define LINK_12GTFD LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
129#define LINK_12GXFD LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
130#define LINK_12_5GTFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD
131#define LINK_12_5GXFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD
132#define LINK_13GTFD LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
133#define LINK_13GXFD LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
134#define LINK_15GTFD LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
135#define LINK_15GXFD LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
136#define LINK_16GTFD LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
137#define LINK_16GXFD LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
138
139#define PHY_XGXS_FLAG 0x1
140#define PHY_SGMII_FLAG 0x2
141#define PHY_SERDES_FLAG 0x4
142
589abe3a
EG
143/* */
144#define SFP_EEPROM_CON_TYPE_ADDR 0x2
145 #define SFP_EEPROM_CON_TYPE_VAL_LC 0x7
146 #define SFP_EEPROM_CON_TYPE_VAL_COPPER 0x21
147
4d295db0
EG
148
149#define SFP_EEPROM_COMP_CODE_ADDR 0x3
150 #define SFP_EEPROM_COMP_CODE_SR_MASK (1<<4)
151 #define SFP_EEPROM_COMP_CODE_LR_MASK (1<<5)
152 #define SFP_EEPROM_COMP_CODE_LRM_MASK (1<<6)
153
589abe3a
EG
154#define SFP_EEPROM_FC_TX_TECH_ADDR 0x8
155 #define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE 0x4
156 #define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE 0x8
4d295db0 157
589abe3a
EG
158#define SFP_EEPROM_OPTIONS_ADDR 0x40
159 #define SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK 0x1
160#define SFP_EEPROM_OPTIONS_SIZE 2
161
4d295db0
EG
162#define EDC_MODE_LINEAR 0x0022
163#define EDC_MODE_LIMITING 0x0044
164#define EDC_MODE_PASSIVE_DAC 0x0055
165
166
589abe3a 167
ea4e040a
YR
168/**********************************************************/
169/* INTERFACE */
170/**********************************************************/
e10bc84d
YR
171
172#define CL45_WR_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
173 bnx2x_cl45_write(_bp, _phy, \
7aa0711f 174 (_phy)->def_md_devad, \
ea4e040a
YR
175 (_bank + (_addr & 0xf)), \
176 _val)
177
e10bc84d
YR
178#define CL45_RD_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
179 bnx2x_cl45_read(_bp, _phy, \
7aa0711f 180 (_phy)->def_md_devad, \
ea4e040a
YR
181 (_bank + (_addr & 0xf)), \
182 _val)
183
ea4e040a
YR
184static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
185{
186 u32 val = REG_RD(bp, reg);
187
188 val |= bits;
189 REG_WR(bp, reg, val);
190 return val;
191}
192
193static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits)
194{
195 u32 val = REG_RD(bp, reg);
196
197 val &= ~bits;
198 REG_WR(bp, reg, val);
199 return val;
200}
201
202static void bnx2x_emac_init(struct link_params *params,
203 struct link_vars *vars)
204{
205 /* reset and unreset the emac core */
206 struct bnx2x *bp = params->bp;
207 u8 port = params->port;
208 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
209 u32 val;
210 u16 timeout;
211
212 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
213 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
214 udelay(5);
215 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
216 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
217
218 /* init emac - use read-modify-write */
219 /* self clear reset */
220 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
3196a88a 221 EMAC_WR(bp, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET));
ea4e040a
YR
222
223 timeout = 200;
3196a88a 224 do {
ea4e040a
YR
225 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
226 DP(NETIF_MSG_LINK, "EMAC reset reg is %u\n", val);
227 if (!timeout) {
228 DP(NETIF_MSG_LINK, "EMAC timeout!\n");
229 return;
230 }
231 timeout--;
3196a88a 232 } while (val & EMAC_MODE_RESET);
ea4e040a
YR
233
234 /* Set mac address */
235 val = ((params->mac_addr[0] << 8) |
236 params->mac_addr[1]);
3196a88a 237 EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH, val);
ea4e040a
YR
238
239 val = ((params->mac_addr[2] << 24) |
240 (params->mac_addr[3] << 16) |
241 (params->mac_addr[4] << 8) |
242 params->mac_addr[5]);
3196a88a 243 EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + 4, val);
ea4e040a
YR
244}
245
246static u8 bnx2x_emac_enable(struct link_params *params,
247 struct link_vars *vars, u8 lb)
248{
249 struct bnx2x *bp = params->bp;
250 u8 port = params->port;
251 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
252 u32 val;
253
254 DP(NETIF_MSG_LINK, "enabling EMAC\n");
255
256 /* enable emac and not bmac */
257 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
258
259 /* for paladium */
260 if (CHIP_REV_IS_EMUL(bp)) {
261 /* Use lane 1 (of lanes 0-3) */
262 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
263 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
264 port*4, 1);
265 }
266 /* for fpga */
267 else
268
269 if (CHIP_REV_IS_FPGA(bp)) {
270 /* Use lane 1 (of lanes 0-3) */
271 DP(NETIF_MSG_LINK, "bnx2x_emac_enable: Setting FPGA\n");
272
273 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
274 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4,
275 0);
276 } else
277 /* ASIC */
278 if (vars->phy_flags & PHY_XGXS_FLAG) {
279 u32 ser_lane = ((params->lane_config &
280 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
281 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
282
283 DP(NETIF_MSG_LINK, "XGXS\n");
284 /* select the master lanes (out of 0-3) */
285 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 +
286 port*4, ser_lane);
287 /* select XGXS */
288 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
289 port*4, 1);
290
291 } else { /* SerDes */
292 DP(NETIF_MSG_LINK, "SerDes\n");
293 /* select SerDes */
294 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
295 port*4, 0);
296 }
297
811a2f2d
EG
298 bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
299 EMAC_RX_MODE_RESET);
300 bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
301 EMAC_TX_MODE_RESET);
ea4e040a
YR
302
303 if (CHIP_REV_IS_SLOW(bp)) {
304 /* config GMII mode */
305 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
3196a88a 306 EMAC_WR(bp, EMAC_REG_EMAC_MODE,
ea4e040a
YR
307 (val | EMAC_MODE_PORT_GMII));
308 } else { /* ASIC */
309 /* pause enable/disable */
310 bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
311 EMAC_RX_MODE_FLOW_EN);
c0700f90 312 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
ea4e040a
YR
313 bnx2x_bits_en(bp, emac_base +
314 EMAC_REG_EMAC_RX_MODE,
315 EMAC_RX_MODE_FLOW_EN);
316
317 bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
8c99e7b0
YR
318 (EMAC_TX_MODE_EXT_PAUSE_EN |
319 EMAC_TX_MODE_FLOW_EN));
c0700f90 320 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
ea4e040a
YR
321 bnx2x_bits_en(bp, emac_base +
322 EMAC_REG_EMAC_TX_MODE,
8c99e7b0
YR
323 (EMAC_TX_MODE_EXT_PAUSE_EN |
324 EMAC_TX_MODE_FLOW_EN));
ea4e040a
YR
325 }
326
327 /* KEEP_VLAN_TAG, promiscuous */
328 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
329 val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
3196a88a 330 EMAC_WR(bp, EMAC_REG_EMAC_RX_MODE, val);
ea4e040a
YR
331
332 /* Set Loopback */
333 val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
334 if (lb)
335 val |= 0x810;
336 else
337 val &= ~0x810;
3196a88a 338 EMAC_WR(bp, EMAC_REG_EMAC_MODE, val);
ea4e040a 339
6c55c3cd
EG
340 /* enable emac */
341 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1);
342
ea4e040a 343 /* enable emac for jumbo packets */
3196a88a 344 EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE,
ea4e040a
YR
345 (EMAC_RX_MTU_SIZE_JUMBO_ENA |
346 (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD)));
347
348 /* strip CRC */
349 REG_WR(bp, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1);
350
351 /* disable the NIG in/out to the bmac */
352 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x0);
353 REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, 0x0);
354 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x0);
355
356 /* enable the NIG in/out to the emac */
357 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x1);
358 val = 0;
c0700f90 359 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
ea4e040a
YR
360 val = 1;
361
362 REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
363 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x1);
364
365 if (CHIP_REV_IS_EMUL(bp)) {
366 /* take the BigMac out of reset */
367 REG_WR(bp,
368 GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
369 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
370
371 /* enable access for bmac registers */
372 REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
6f65497b
EG
373 } else
374 REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x0);
ea4e040a
YR
375
376 vars->mac_type = MAC_TYPE_EMAC;
377 return 0;
378}
379
380
381
382static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
383 u8 is_lb)
384{
385 struct bnx2x *bp = params->bp;
386 u8 port = params->port;
387 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
388 NIG_REG_INGRESS_BMAC0_MEM;
389 u32 wb_data[2];
390 u32 val;
391
392 DP(NETIF_MSG_LINK, "Enabling BigMAC\n");
393 /* reset and unreset the BigMac */
394 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
395 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
396 msleep(1);
397
398 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
399 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
400
401 /* enable access for bmac registers */
402 REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
403
404 /* XGXS control */
405 wb_data[0] = 0x3c;
406 wb_data[1] = 0;
407 REG_WR_DMAE(bp, bmac_addr +
408 BIGMAC_REGISTER_BMAC_XGXS_CONTROL,
409 wb_data, 2);
410
411 /* tx MAC SA */
412 wb_data[0] = ((params->mac_addr[2] << 24) |
413 (params->mac_addr[3] << 16) |
414 (params->mac_addr[4] << 8) |
415 params->mac_addr[5]);
416 wb_data[1] = ((params->mac_addr[0] << 8) |
417 params->mac_addr[1]);
418 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR,
419 wb_data, 2);
420
421 /* tx control */
422 val = 0xc0;
c0700f90 423 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
ea4e040a
YR
424 val |= 0x800000;
425 wb_data[0] = val;
426 wb_data[1] = 0;
427 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_CONTROL,
428 wb_data, 2);
429
430 /* mac control */
431 val = 0x3;
432 if (is_lb) {
433 val |= 0x4;
434 DP(NETIF_MSG_LINK, "enable bmac loopback\n");
435 }
436 wb_data[0] = val;
437 wb_data[1] = 0;
438 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
439 wb_data, 2);
440
ea4e040a
YR
441 /* set rx mtu */
442 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
443 wb_data[1] = 0;
444 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE,
445 wb_data, 2);
446
447 /* rx control set to don't strip crc */
448 val = 0x14;
c0700f90 449 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
ea4e040a
YR
450 val |= 0x20;
451 wb_data[0] = val;
452 wb_data[1] = 0;
453 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_CONTROL,
454 wb_data, 2);
455
456 /* set tx mtu */
457 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
458 wb_data[1] = 0;
459 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE,
460 wb_data, 2);
461
462 /* set cnt max size */
463 wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
464 wb_data[1] = 0;
465 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE,
466 wb_data, 2);
467
468 /* configure safc */
469 wb_data[0] = 0x1000200;
470 wb_data[1] = 0;
471 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
472 wb_data, 2);
473 /* fix for emulation */
474 if (CHIP_REV_IS_EMUL(bp)) {
475 wb_data[0] = 0xf000;
476 wb_data[1] = 0;
477 REG_WR_DMAE(bp,
478 bmac_addr + BIGMAC_REGISTER_TX_PAUSE_THRESHOLD,
479 wb_data, 2);
480 }
481
482 REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
483 REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
484 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
485 val = 0;
c0700f90 486 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
ea4e040a
YR
487 val = 1;
488 REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
489 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
490 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x0);
491 REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, 0x0);
492 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x1);
493 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);
494
495 vars->mac_type = MAC_TYPE_BMAC;
496 return 0;
497}
498
ea4e040a
YR
499
500static void bnx2x_update_mng(struct link_params *params, u32 link_status)
501{
502 struct bnx2x *bp = params->bp;
ab6ad5a4 503
ea4e040a
YR
504 REG_WR(bp, params->shmem_base +
505 offsetof(struct shmem_region,
506 port_mb[params->port].link_status),
507 link_status);
508}
509
510static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
511{
512 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
513 NIG_REG_INGRESS_BMAC0_MEM;
514 u32 wb_data[2];
3196a88a 515 u32 nig_bmac_enable = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4);
ea4e040a
YR
516
517 /* Only if the bmac is out of reset */
518 if (REG_RD(bp, MISC_REG_RESET_REG_2) &
519 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) &&
520 nig_bmac_enable) {
521
522 /* Clear Rx Enable bit in BMAC_CONTROL register */
523 REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
524 wb_data, 2);
525 wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
526 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
527 wb_data, 2);
528
529 msleep(1);
530 }
531}
532
533static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
534 u32 line_speed)
535{
536 struct bnx2x *bp = params->bp;
537 u8 port = params->port;
538 u32 init_crd, crd;
539 u32 count = 1000;
ea4e040a
YR
540
541 /* disable port */
542 REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1);
543
544 /* wait for init credit */
545 init_crd = REG_RD(bp, PBF_REG_P0_INIT_CRD + port*4);
546 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
547 DP(NETIF_MSG_LINK, "init_crd 0x%x crd 0x%x\n", init_crd, crd);
548
549 while ((init_crd != crd) && count) {
550 msleep(5);
551
552 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
553 count--;
554 }
555 crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
556 if (init_crd != crd) {
557 DP(NETIF_MSG_LINK, "BUG! init_crd 0x%x != crd 0x%x\n",
558 init_crd, crd);
559 return -EINVAL;
560 }
561
c0700f90 562 if (flow_ctrl & BNX2X_FLOW_CTRL_RX ||
8c99e7b0
YR
563 line_speed == SPEED_10 ||
564 line_speed == SPEED_100 ||
565 line_speed == SPEED_1000 ||
566 line_speed == SPEED_2500) {
567 REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 1);
ea4e040a
YR
568 /* update threshold */
569 REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, 0);
570 /* update init credit */
8c99e7b0 571 init_crd = 778; /* (800-18-4) */
ea4e040a
YR
572
573 } else {
574 u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
575 ETH_OVREHEAD)/16;
8c99e7b0 576 REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
ea4e040a
YR
577 /* update threshold */
578 REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh);
579 /* update init credit */
580 switch (line_speed) {
ea4e040a
YR
581 case SPEED_10000:
582 init_crd = thresh + 553 - 22;
583 break;
584
585 case SPEED_12000:
586 init_crd = thresh + 664 - 22;
587 break;
588
589 case SPEED_13000:
590 init_crd = thresh + 742 - 22;
591 break;
592
593 case SPEED_16000:
594 init_crd = thresh + 778 - 22;
595 break;
596 default:
597 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
598 line_speed);
599 return -EINVAL;
ea4e040a
YR
600 }
601 }
602 REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, init_crd);
603 DP(NETIF_MSG_LINK, "PBF updated to speed %d credit %d\n",
604 line_speed, init_crd);
605
606 /* probe the credit changes */
607 REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x1);
608 msleep(5);
609 REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x0);
610
611 /* enable port */
612 REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x0);
613 return 0;
614}
615
c18aa15d
YR
616static u32 bnx2x_get_emac_base(struct bnx2x *bp,
617 u32 mdc_mdio_access, u8 port)
ea4e040a 618{
c18aa15d
YR
619 u32 emac_base = 0;
620 switch (mdc_mdio_access) {
621 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE:
622 break;
623 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0:
624 if (REG_RD(bp, NIG_REG_PORT_SWAP))
625 emac_base = GRCBASE_EMAC1;
626 else
627 emac_base = GRCBASE_EMAC0;
628 break;
629 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1:
589abe3a
EG
630 if (REG_RD(bp, NIG_REG_PORT_SWAP))
631 emac_base = GRCBASE_EMAC0;
632 else
633 emac_base = GRCBASE_EMAC1;
ea4e040a 634 break;
c18aa15d
YR
635 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH:
636 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
637 break;
638 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED:
6378c025 639 emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
ea4e040a
YR
640 break;
641 default:
ea4e040a
YR
642 break;
643 }
644 return emac_base;
645
646}
647
e10bc84d
YR
648u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
649 u8 devad, u16 reg, u16 val)
ea4e040a
YR
650{
651 u32 tmp, saved_mode;
652 u8 i, rc = 0;
ea4e040a
YR
653
654 /* set clause 45 mode, slow down the MDIO clock to 2.5MHz
655 * (a value of 49==0x31) and make sure that the AUTO poll is off
656 */
589abe3a 657
e10bc84d 658 saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
ea4e040a
YR
659 tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
660 EMAC_MDIO_MODE_CLOCK_CNT);
661 tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
662 (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
e10bc84d
YR
663 REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
664 REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
ea4e040a
YR
665 udelay(40);
666
667 /* address */
668
e10bc84d 669 tmp = ((phy->addr << 21) | (devad << 16) | reg |
ea4e040a
YR
670 EMAC_MDIO_COMM_COMMAND_ADDRESS |
671 EMAC_MDIO_COMM_START_BUSY);
e10bc84d 672 REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
ea4e040a
YR
673
674 for (i = 0; i < 50; i++) {
675 udelay(10);
676
e10bc84d
YR
677 tmp = REG_RD(bp, phy->mdio_ctrl +
678 EMAC_REG_EMAC_MDIO_COMM);
ea4e040a
YR
679 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
680 udelay(5);
681 break;
682 }
683 }
684 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
685 DP(NETIF_MSG_LINK, "write phy register failed\n");
686 rc = -EFAULT;
687 } else {
688 /* data */
e10bc84d 689 tmp = ((phy->addr << 21) | (devad << 16) | val |
ea4e040a
YR
690 EMAC_MDIO_COMM_COMMAND_WRITE_45 |
691 EMAC_MDIO_COMM_START_BUSY);
e10bc84d 692 REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
ea4e040a
YR
693
694 for (i = 0; i < 50; i++) {
695 udelay(10);
696
e10bc84d 697 tmp = REG_RD(bp, phy->mdio_ctrl +
ea4e040a
YR
698 EMAC_REG_EMAC_MDIO_COMM);
699 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
700 udelay(5);
701 break;
702 }
703 }
704 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
705 DP(NETIF_MSG_LINK, "write phy register failed\n");
706 rc = -EFAULT;
707 }
708 }
709
710 /* Restore the saved mode */
e10bc84d 711 REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
ea4e040a
YR
712
713 return rc;
714}
715
e10bc84d
YR
716u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
717 u8 devad, u16 reg, u16 *ret_val)
ea4e040a
YR
718{
719 u32 val, saved_mode;
720 u16 i;
721 u8 rc = 0;
722
ea4e040a
YR
723 /* set clause 45 mode, slow down the MDIO clock to 2.5MHz
724 * (a value of 49==0x31) and make sure that the AUTO poll is off
725 */
589abe3a 726
e10bc84d
YR
727 saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
728 val = saved_mode & ~((EMAC_MDIO_MODE_AUTO_POLL |
ea4e040a
YR
729 EMAC_MDIO_MODE_CLOCK_CNT));
730 val |= (EMAC_MDIO_MODE_CLAUSE_45 |
ab6ad5a4 731 (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
e10bc84d
YR
732 REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
733 REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
ea4e040a
YR
734 udelay(40);
735
736 /* address */
e10bc84d 737 val = ((phy->addr << 21) | (devad << 16) | reg |
ea4e040a
YR
738 EMAC_MDIO_COMM_COMMAND_ADDRESS |
739 EMAC_MDIO_COMM_START_BUSY);
e10bc84d 740 REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
ea4e040a
YR
741
742 for (i = 0; i < 50; i++) {
743 udelay(10);
744
e10bc84d 745 val = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
ea4e040a
YR
746 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
747 udelay(5);
748 break;
749 }
750 }
751 if (val & EMAC_MDIO_COMM_START_BUSY) {
752 DP(NETIF_MSG_LINK, "read phy register failed\n");
753
754 *ret_val = 0;
755 rc = -EFAULT;
756
757 } else {
758 /* data */
e10bc84d 759 val = ((phy->addr << 21) | (devad << 16) |
ea4e040a
YR
760 EMAC_MDIO_COMM_COMMAND_READ_45 |
761 EMAC_MDIO_COMM_START_BUSY);
e10bc84d 762 REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
ea4e040a
YR
763
764 for (i = 0; i < 50; i++) {
765 udelay(10);
766
e10bc84d 767 val = REG_RD(bp, phy->mdio_ctrl +
ea4e040a
YR
768 EMAC_REG_EMAC_MDIO_COMM);
769 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
770 *ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
771 break;
772 }
773 }
774 if (val & EMAC_MDIO_COMM_START_BUSY) {
775 DP(NETIF_MSG_LINK, "read phy register failed\n");
776
777 *ret_val = 0;
778 rc = -EFAULT;
779 }
780 }
781
782 /* Restore the saved mode */
e10bc84d 783 REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
ea4e040a
YR
784
785 return rc;
786}
787
e10bc84d
YR
788u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr,
789 u8 devad, u16 reg, u16 *ret_val)
790{
791 u8 phy_index;
792 /**
793 * Probe for the phy according to the given phy_addr, and execute
794 * the read request on it
795 */
796 for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
797 if (params->phy[phy_index].addr == phy_addr) {
798 return bnx2x_cl45_read(params->bp,
799 &params->phy[phy_index], devad,
800 reg, ret_val);
801 }
802 }
803 return -EINVAL;
804}
805
806u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr,
807 u8 devad, u16 reg, u16 val)
808{
809 u8 phy_index;
810 /**
811 * Probe for the phy according to the given phy_addr, and execute
812 * the write request on it
813 */
814 for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
815 if (params->phy[phy_index].addr == phy_addr) {
816 return bnx2x_cl45_write(params->bp,
817 &params->phy[phy_index], devad,
818 reg, val);
819 }
820 }
821 return -EINVAL;
822}
823
ea4e040a 824static void bnx2x_set_aer_mmd(struct link_params *params,
e10bc84d 825 struct bnx2x_phy *phy)
ea4e040a
YR
826{
827 struct bnx2x *bp = params->bp;
828 u32 ser_lane;
829 u16 offset;
830
831 ser_lane = ((params->lane_config &
832 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
833 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
834
e10bc84d
YR
835 offset = (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ?
836 (phy->addr + ser_lane) : 0;
ea4e040a 837
e10bc84d 838 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
839 MDIO_REG_BANK_AER_BLOCK,
840 MDIO_AER_BLOCK_AER_REG, 0x3800 + offset);
841}
842
de6eae1f
YR
843/******************************************************************/
844/* Internal phy section */
845/******************************************************************/
ea4e040a 846
de6eae1f
YR
847static void bnx2x_set_serdes_access(struct bnx2x *bp, u8 port)
848{
849 u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
ea4e040a 850
de6eae1f
YR
851 /* Set Clause 22 */
852 REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 1);
853 REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000);
854 udelay(500);
855 REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f);
856 udelay(500);
857 /* Set Clause 45 */
858 REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 0);
ea4e040a
YR
859}
860
de6eae1f 861static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
ea4e040a 862{
de6eae1f 863 u32 val;
ea4e040a 864
de6eae1f 865 DP(NETIF_MSG_LINK, "bnx2x_serdes_deassert\n");
ea4e040a 866
de6eae1f 867 val = SERDES_RESET_BITS << (port*16);
c1b73990 868
de6eae1f
YR
869 /* reset and unreset the SerDes/XGXS */
870 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
871 udelay(500);
872 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
ea4e040a 873
de6eae1f 874 bnx2x_set_serdes_access(bp, port);
ea4e040a 875
de6eae1f
YR
876 REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD +
877 port*0x10,
878 DEFAULT_PHY_DEV_ADDR);
879}
880
881static void bnx2x_xgxs_deassert(struct link_params *params)
882{
883 struct bnx2x *bp = params->bp;
884 u8 port;
885 u32 val;
886 DP(NETIF_MSG_LINK, "bnx2x_xgxs_deassert\n");
887 port = params->port;
888
889 val = XGXS_RESET_BITS << (port*16);
890
891 /* reset and unreset the SerDes/XGXS */
892 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
893 udelay(500);
894 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
895
896 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
897 port*0x18, 0);
898 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
899 params->phy[INT_PHY].def_md_devad);
900}
901
a22f0788 902
de6eae1f
YR
903void bnx2x_link_status_update(struct link_params *params,
904 struct link_vars *vars)
905{
906 struct bnx2x *bp = params->bp;
907 u8 link_10g;
908 u8 port = params->port;
909
de6eae1f
YR
910 vars->link_status = REG_RD(bp, params->shmem_base +
911 offsetof(struct shmem_region,
912 port_mb[port].link_status));
913
914 vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
915
916 if (vars->link_up) {
917 DP(NETIF_MSG_LINK, "phy link up\n");
918
919 vars->phy_link_up = 1;
920 vars->duplex = DUPLEX_FULL;
921 switch (vars->link_status &
922 LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
923 case LINK_10THD:
924 vars->duplex = DUPLEX_HALF;
925 /* fall thru */
926 case LINK_10TFD:
927 vars->line_speed = SPEED_10;
928 break;
929
930 case LINK_100TXHD:
931 vars->duplex = DUPLEX_HALF;
932 /* fall thru */
933 case LINK_100T4:
934 case LINK_100TXFD:
935 vars->line_speed = SPEED_100;
936 break;
937
938 case LINK_1000THD:
939 vars->duplex = DUPLEX_HALF;
940 /* fall thru */
941 case LINK_1000TFD:
942 vars->line_speed = SPEED_1000;
943 break;
944
945 case LINK_2500THD:
946 vars->duplex = DUPLEX_HALF;
947 /* fall thru */
948 case LINK_2500TFD:
949 vars->line_speed = SPEED_2500;
950 break;
951
952 case LINK_10GTFD:
953 vars->line_speed = SPEED_10000;
954 break;
955
956 case LINK_12GTFD:
957 vars->line_speed = SPEED_12000;
958 break;
959
960 case LINK_12_5GTFD:
961 vars->line_speed = SPEED_12500;
962 break;
963
964 case LINK_13GTFD:
965 vars->line_speed = SPEED_13000;
966 break;
967
968 case LINK_15GTFD:
969 vars->line_speed = SPEED_15000;
970 break;
971
972 case LINK_16GTFD:
973 vars->line_speed = SPEED_16000;
974 break;
975
976 default:
977 break;
978 }
de6eae1f
YR
979 vars->flow_ctrl = 0;
980 if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
981 vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
982
983 if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
984 vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
985
986 if (!vars->flow_ctrl)
987 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
988
989 if (vars->line_speed &&
990 ((vars->line_speed == SPEED_10) ||
991 (vars->line_speed == SPEED_100))) {
992 vars->phy_flags |= PHY_SGMII_FLAG;
993 } else {
994 vars->phy_flags &= ~PHY_SGMII_FLAG;
995 }
996
997 /* anything 10 and over uses the bmac */
998 link_10g = ((vars->line_speed == SPEED_10000) ||
999 (vars->line_speed == SPEED_12000) ||
1000 (vars->line_speed == SPEED_12500) ||
1001 (vars->line_speed == SPEED_13000) ||
1002 (vars->line_speed == SPEED_15000) ||
1003 (vars->line_speed == SPEED_16000));
1004 if (link_10g)
1005 vars->mac_type = MAC_TYPE_BMAC;
1006 else
1007 vars->mac_type = MAC_TYPE_EMAC;
1008
1009 } else { /* link down */
1010 DP(NETIF_MSG_LINK, "phy link down\n");
1011
1012 vars->phy_link_up = 0;
1013
1014 vars->line_speed = 0;
1015 vars->duplex = DUPLEX_FULL;
1016 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
1017
1018 /* indicate no mac active */
1019 vars->mac_type = MAC_TYPE_NONE;
1020 }
1021
1022 DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x\n",
1023 vars->link_status, vars->phy_link_up);
1024 DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n",
1025 vars->line_speed, vars->duplex, vars->flow_ctrl);
1026}
1027
1028
1029static void bnx2x_set_master_ln(struct link_params *params,
1030 struct bnx2x_phy *phy)
1031{
1032 struct bnx2x *bp = params->bp;
1033 u16 new_master_ln, ser_lane;
1034 ser_lane = ((params->lane_config &
1035 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
1036 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
1037
1038 /* set the master_ln for AN */
1039 CL45_RD_OVER_CL22(bp, phy,
1040 MDIO_REG_BANK_XGXS_BLOCK2,
1041 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
1042 &new_master_ln);
1043
1044 CL45_WR_OVER_CL22(bp, phy,
1045 MDIO_REG_BANK_XGXS_BLOCK2 ,
1046 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
1047 (new_master_ln | ser_lane));
1048}
1049
1050static u8 bnx2x_reset_unicore(struct link_params *params,
1051 struct bnx2x_phy *phy,
1052 u8 set_serdes)
1053{
1054 struct bnx2x *bp = params->bp;
1055 u16 mii_control;
1056 u16 i;
1057
1058 CL45_RD_OVER_CL22(bp, phy,
1059 MDIO_REG_BANK_COMBO_IEEE0,
1060 MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
1061
1062 /* reset the unicore */
1063 CL45_WR_OVER_CL22(bp, phy,
1064 MDIO_REG_BANK_COMBO_IEEE0,
1065 MDIO_COMBO_IEEE0_MII_CONTROL,
1066 (mii_control |
1067 MDIO_COMBO_IEEO_MII_CONTROL_RESET));
1068 if (set_serdes)
1069 bnx2x_set_serdes_access(bp, params->port);
1070
1071 /* wait for the reset to self clear */
1072 for (i = 0; i < MDIO_ACCESS_TIMEOUT; i++) {
1073 udelay(5);
1074
1075 /* the reset erased the previous bank value */
1076 CL45_RD_OVER_CL22(bp, phy,
1077 MDIO_REG_BANK_COMBO_IEEE0,
1078 MDIO_COMBO_IEEE0_MII_CONTROL,
1079 &mii_control);
1080
1081 if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) {
1082 udelay(5);
1083 return 0;
1084 }
1085 }
ea4e040a
YR
1086
1087 DP(NETIF_MSG_LINK, "BUG! XGXS is still in reset!\n");
1088 return -EINVAL;
1089
1090}
1091
e10bc84d
YR
1092static void bnx2x_set_swap_lanes(struct link_params *params,
1093 struct bnx2x_phy *phy)
ea4e040a
YR
1094{
1095 struct bnx2x *bp = params->bp;
1096 /* Each two bits represents a lane number:
1097 No swap is 0123 => 0x1b no need to enable the swap */
1098 u16 ser_lane, rx_lane_swap, tx_lane_swap;
1099
1100 ser_lane = ((params->lane_config &
1101 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
1102 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
1103 rx_lane_swap = ((params->lane_config &
1104 PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
1105 PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
1106 tx_lane_swap = ((params->lane_config &
1107 PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
1108 PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
1109
1110 if (rx_lane_swap != 0x1b) {
e10bc84d 1111 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1112 MDIO_REG_BANK_XGXS_BLOCK2,
1113 MDIO_XGXS_BLOCK2_RX_LN_SWAP,
1114 (rx_lane_swap |
1115 MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
1116 MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
1117 } else {
e10bc84d 1118 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1119 MDIO_REG_BANK_XGXS_BLOCK2,
1120 MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
1121 }
1122
1123 if (tx_lane_swap != 0x1b) {
e10bc84d 1124 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1125 MDIO_REG_BANK_XGXS_BLOCK2,
1126 MDIO_XGXS_BLOCK2_TX_LN_SWAP,
1127 (tx_lane_swap |
1128 MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
1129 } else {
e10bc84d 1130 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1131 MDIO_REG_BANK_XGXS_BLOCK2,
1132 MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
1133 }
1134}
1135
e10bc84d
YR
1136static void bnx2x_set_parallel_detection(struct bnx2x_phy *phy,
1137 struct link_params *params)
ea4e040a
YR
1138{
1139 struct bnx2x *bp = params->bp;
1140 u16 control2;
e10bc84d 1141 CL45_RD_OVER_CL22(bp, phy,
ea4e040a
YR
1142 MDIO_REG_BANK_SERDES_DIGITAL,
1143 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1144 &control2);
7aa0711f 1145 if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
18afb0a6
YR
1146 control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
1147 else
1148 control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
7aa0711f
YR
1149 DP(NETIF_MSG_LINK, "phy->speed_cap_mask = 0x%x, control2 = 0x%x\n",
1150 phy->speed_cap_mask, control2);
e10bc84d 1151 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1152 MDIO_REG_BANK_SERDES_DIGITAL,
1153 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1154 control2);
1155
e10bc84d 1156 if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
c18aa15d 1157 (phy->speed_cap_mask &
18afb0a6 1158 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
ea4e040a
YR
1159 DP(NETIF_MSG_LINK, "XGXS\n");
1160
e10bc84d 1161 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1162 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1163 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
1164 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
1165
e10bc84d 1166 CL45_RD_OVER_CL22(bp, phy,
ea4e040a
YR
1167 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1168 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
1169 &control2);
1170
1171
1172 control2 |=
1173 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
1174
e10bc84d 1175 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1176 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1177 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
1178 control2);
1179
1180 /* Disable parallel detection of HiG */
e10bc84d 1181 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1182 MDIO_REG_BANK_XGXS_BLOCK2,
1183 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
1184 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
1185 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
1186 }
1187}
1188
e10bc84d
YR
1189static void bnx2x_set_autoneg(struct bnx2x_phy *phy,
1190 struct link_params *params,
239d686d
EG
1191 struct link_vars *vars,
1192 u8 enable_cl73)
ea4e040a
YR
1193{
1194 struct bnx2x *bp = params->bp;
1195 u16 reg_val;
1196
1197 /* CL37 Autoneg */
e10bc84d 1198 CL45_RD_OVER_CL22(bp, phy,
ea4e040a
YR
1199 MDIO_REG_BANK_COMBO_IEEE0,
1200 MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1201
1202 /* CL37 Autoneg Enabled */
8c99e7b0 1203 if (vars->line_speed == SPEED_AUTO_NEG)
ea4e040a
YR
1204 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN;
1205 else /* CL37 Autoneg Disabled */
1206 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1207 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);
1208
e10bc84d 1209 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1210 MDIO_REG_BANK_COMBO_IEEE0,
1211 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1212
1213 /* Enable/Disable Autodetection */
1214
e10bc84d 1215 CL45_RD_OVER_CL22(bp, phy,
ea4e040a
YR
1216 MDIO_REG_BANK_SERDES_DIGITAL,
1217 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
239d686d
EG
1218 reg_val &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN |
1219 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT);
1220 reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE;
8c99e7b0 1221 if (vars->line_speed == SPEED_AUTO_NEG)
ea4e040a
YR
1222 reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1223 else
1224 reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1225
e10bc84d 1226 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1227 MDIO_REG_BANK_SERDES_DIGITAL,
1228 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
1229
1230 /* Enable TetonII and BAM autoneg */
e10bc84d 1231 CL45_RD_OVER_CL22(bp, phy,
ea4e040a
YR
1232 MDIO_REG_BANK_BAM_NEXT_PAGE,
1233 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1234 &reg_val);
8c99e7b0 1235 if (vars->line_speed == SPEED_AUTO_NEG) {
ea4e040a
YR
1236 /* Enable BAM aneg Mode and TetonII aneg Mode */
1237 reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1238 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1239 } else {
1240 /* TetonII and BAM Autoneg Disabled */
1241 reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1242 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1243 }
e10bc84d 1244 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1245 MDIO_REG_BANK_BAM_NEXT_PAGE,
1246 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1247 reg_val);
1248
239d686d
EG
1249 if (enable_cl73) {
1250 /* Enable Cl73 FSM status bits */
e10bc84d 1251 CL45_WR_OVER_CL22(bp, phy,
239d686d
EG
1252 MDIO_REG_BANK_CL73_USERB0,
1253 MDIO_CL73_USERB0_CL73_UCTRL,
7846e471 1254 0xe);
239d686d
EG
1255
1256 /* Enable BAM Station Manager*/
e10bc84d 1257 CL45_WR_OVER_CL22(bp, phy,
239d686d
EG
1258 MDIO_REG_BANK_CL73_USERB0,
1259 MDIO_CL73_USERB0_CL73_BAM_CTRL1,
1260 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
1261 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN |
1262 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN);
1263
7846e471 1264 /* Advertise CL73 link speeds */
e10bc84d 1265 CL45_RD_OVER_CL22(bp, phy,
239d686d
EG
1266 MDIO_REG_BANK_CL73_IEEEB1,
1267 MDIO_CL73_IEEEB1_AN_ADV2,
1268 &reg_val);
7aa0711f 1269 if (phy->speed_cap_mask &
7846e471
YR
1270 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
1271 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
7aa0711f 1272 if (phy->speed_cap_mask &
7846e471
YR
1273 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
1274 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
239d686d 1275
e10bc84d 1276 CL45_WR_OVER_CL22(bp, phy,
de6eae1f
YR
1277 MDIO_REG_BANK_CL73_IEEEB1,
1278 MDIO_CL73_IEEEB1_AN_ADV2,
1279 reg_val);
239d686d 1280
239d686d
EG
1281 /* CL73 Autoneg Enabled */
1282 reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;
1283
1284 } else /* CL73 Autoneg Disabled */
1285 reg_val = 0;
ea4e040a 1286
e10bc84d 1287 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1288 MDIO_REG_BANK_CL73_IEEEB0,
1289 MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
1290}
1291
1292/* program SerDes, forced speed */
e10bc84d
YR
1293static void bnx2x_program_serdes(struct bnx2x_phy *phy,
1294 struct link_params *params,
8c99e7b0 1295 struct link_vars *vars)
ea4e040a
YR
1296{
1297 struct bnx2x *bp = params->bp;
1298 u16 reg_val;
1299
57937203 1300 /* program duplex, disable autoneg and sgmii*/
e10bc84d 1301 CL45_RD_OVER_CL22(bp, phy,
ea4e040a
YR
1302 MDIO_REG_BANK_COMBO_IEEE0,
1303 MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1304 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
57937203
EG
1305 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1306 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK);
7aa0711f 1307 if (phy->req_duplex == DUPLEX_FULL)
ea4e040a 1308 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
e10bc84d 1309 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1310 MDIO_REG_BANK_COMBO_IEEE0,
1311 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1312
1313 /* program speed
1314 - needed only if the speed is greater than 1G (2.5G or 10G) */
e10bc84d 1315 CL45_RD_OVER_CL22(bp, phy,
ea4e040a
YR
1316 MDIO_REG_BANK_SERDES_DIGITAL,
1317 MDIO_SERDES_DIGITAL_MISC1, &reg_val);
8c99e7b0
YR
1318 /* clearing the speed value before setting the right speed */
1319 DP(NETIF_MSG_LINK, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x\n", reg_val);
1320
1321 reg_val &= ~(MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK |
1322 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
1323
1324 if (!((vars->line_speed == SPEED_1000) ||
1325 (vars->line_speed == SPEED_100) ||
1326 (vars->line_speed == SPEED_10))) {
1327
ea4e040a
YR
1328 reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M |
1329 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
8c99e7b0 1330 if (vars->line_speed == SPEED_10000)
ea4e040a
YR
1331 reg_val |=
1332 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
8c99e7b0 1333 if (vars->line_speed == SPEED_13000)
ea4e040a
YR
1334 reg_val |=
1335 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
8c99e7b0
YR
1336 }
1337
e10bc84d 1338 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1339 MDIO_REG_BANK_SERDES_DIGITAL,
1340 MDIO_SERDES_DIGITAL_MISC1, reg_val);
8c99e7b0 1341
ea4e040a
YR
1342}
1343
e10bc84d
YR
1344static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x_phy *phy,
1345 struct link_params *params)
ea4e040a
YR
1346{
1347 struct bnx2x *bp = params->bp;
1348 u16 val = 0;
1349
1350 /* configure the 48 bits for BAM AN */
1351
1352 /* set extended capabilities */
7aa0711f 1353 if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
ea4e040a 1354 val |= MDIO_OVER_1G_UP1_2_5G;
7aa0711f 1355 if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
ea4e040a 1356 val |= MDIO_OVER_1G_UP1_10G;
e10bc84d 1357 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1358 MDIO_REG_BANK_OVER_1G,
1359 MDIO_OVER_1G_UP1, val);
1360
e10bc84d 1361 CL45_WR_OVER_CL22(bp, phy,
ea4e040a 1362 MDIO_REG_BANK_OVER_1G,
239d686d 1363 MDIO_OVER_1G_UP3, 0x400);
ea4e040a
YR
1364}
1365
e10bc84d
YR
1366static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
1367 struct link_params *params, u16 *ieee_fc)
ea4e040a 1368{
d5cb9e99 1369 struct bnx2x *bp = params->bp;
8c99e7b0 1370 *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
ea4e040a
YR
1371 /* resolve pause mode and advertisement
1372 * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
1373
7aa0711f 1374 switch (phy->req_flow_ctrl) {
c0700f90
DM
1375 case BNX2X_FLOW_CTRL_AUTO:
1376 if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) {
8c99e7b0 1377 *ieee_fc |=
ea4e040a
YR
1378 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
1379 } else {
8c99e7b0 1380 *ieee_fc |=
ea4e040a
YR
1381 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1382 }
1383 break;
c0700f90 1384 case BNX2X_FLOW_CTRL_TX:
8c99e7b0 1385 *ieee_fc |=
ea4e040a
YR
1386 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1387 break;
1388
c0700f90
DM
1389 case BNX2X_FLOW_CTRL_RX:
1390 case BNX2X_FLOW_CTRL_BOTH:
8c99e7b0 1391 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
ea4e040a
YR
1392 break;
1393
c0700f90 1394 case BNX2X_FLOW_CTRL_NONE:
ea4e040a 1395 default:
8c99e7b0 1396 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
ea4e040a
YR
1397 break;
1398 }
d5cb9e99 1399 DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc);
8c99e7b0 1400}
ea4e040a 1401
e10bc84d
YR
1402static void bnx2x_set_ieee_aneg_advertisment(struct bnx2x_phy *phy,
1403 struct link_params *params,
1ef70b9c 1404 u16 ieee_fc)
8c99e7b0
YR
1405{
1406 struct bnx2x *bp = params->bp;
7846e471 1407 u16 val;
8c99e7b0 1408 /* for AN, we are always publishing full duplex */
ea4e040a 1409
e10bc84d 1410 CL45_WR_OVER_CL22(bp, phy,
ea4e040a 1411 MDIO_REG_BANK_COMBO_IEEE0,
1ef70b9c 1412 MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc);
e10bc84d 1413 CL45_RD_OVER_CL22(bp, phy,
7846e471
YR
1414 MDIO_REG_BANK_CL73_IEEEB1,
1415 MDIO_CL73_IEEEB1_AN_ADV1, &val);
1416 val &= ~MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH;
1417 val |= ((ieee_fc<<3) & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK);
e10bc84d 1418 CL45_WR_OVER_CL22(bp, phy,
7846e471
YR
1419 MDIO_REG_BANK_CL73_IEEEB1,
1420 MDIO_CL73_IEEEB1_AN_ADV1, val);
ea4e040a
YR
1421}
1422
e10bc84d
YR
1423static void bnx2x_restart_autoneg(struct bnx2x_phy *phy,
1424 struct link_params *params,
1425 u8 enable_cl73)
ea4e040a
YR
1426{
1427 struct bnx2x *bp = params->bp;
3a36f2ef 1428 u16 mii_control;
239d686d 1429
ea4e040a 1430 DP(NETIF_MSG_LINK, "bnx2x_restart_autoneg\n");
3a36f2ef 1431 /* Enable and restart BAM/CL37 aneg */
ea4e040a 1432
239d686d 1433 if (enable_cl73) {
e10bc84d 1434 CL45_RD_OVER_CL22(bp, phy,
239d686d
EG
1435 MDIO_REG_BANK_CL73_IEEEB0,
1436 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1437 &mii_control);
1438
e10bc84d 1439 CL45_WR_OVER_CL22(bp, phy,
239d686d
EG
1440 MDIO_REG_BANK_CL73_IEEEB0,
1441 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1442 (mii_control |
1443 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
1444 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
1445 } else {
1446
e10bc84d 1447 CL45_RD_OVER_CL22(bp, phy,
239d686d
EG
1448 MDIO_REG_BANK_COMBO_IEEE0,
1449 MDIO_COMBO_IEEE0_MII_CONTROL,
1450 &mii_control);
1451 DP(NETIF_MSG_LINK,
1452 "bnx2x_restart_autoneg mii_control before = 0x%x\n",
1453 mii_control);
e10bc84d 1454 CL45_WR_OVER_CL22(bp, phy,
239d686d
EG
1455 MDIO_REG_BANK_COMBO_IEEE0,
1456 MDIO_COMBO_IEEE0_MII_CONTROL,
1457 (mii_control |
1458 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1459 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
1460 }
ea4e040a
YR
1461}
1462
e10bc84d
YR
1463static void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy,
1464 struct link_params *params,
8c99e7b0 1465 struct link_vars *vars)
ea4e040a
YR
1466{
1467 struct bnx2x *bp = params->bp;
1468 u16 control1;
1469
1470 /* in SGMII mode, the unicore is always slave */
1471
e10bc84d 1472 CL45_RD_OVER_CL22(bp, phy,
ea4e040a
YR
1473 MDIO_REG_BANK_SERDES_DIGITAL,
1474 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1475 &control1);
1476 control1 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT;
1477 /* set sgmii mode (and not fiber) */
1478 control1 &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE |
1479 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET |
1480 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE);
e10bc84d 1481 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1482 MDIO_REG_BANK_SERDES_DIGITAL,
1483 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1484 control1);
1485
1486 /* if forced speed */
8c99e7b0 1487 if (!(vars->line_speed == SPEED_AUTO_NEG)) {
ea4e040a
YR
1488 /* set speed, disable autoneg */
1489 u16 mii_control;
1490
e10bc84d 1491 CL45_RD_OVER_CL22(bp, phy,
ea4e040a
YR
1492 MDIO_REG_BANK_COMBO_IEEE0,
1493 MDIO_COMBO_IEEE0_MII_CONTROL,
1494 &mii_control);
1495 mii_control &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1496 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK|
1497 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX);
1498
8c99e7b0 1499 switch (vars->line_speed) {
ea4e040a
YR
1500 case SPEED_100:
1501 mii_control |=
1502 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100;
1503 break;
1504 case SPEED_1000:
1505 mii_control |=
1506 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_1000;
1507 break;
1508 case SPEED_10:
1509 /* there is nothing to set for 10M */
1510 break;
1511 default:
1512 /* invalid speed for SGMII */
8c99e7b0
YR
1513 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
1514 vars->line_speed);
ea4e040a
YR
1515 break;
1516 }
1517
1518 /* setting the full duplex */
7aa0711f 1519 if (phy->req_duplex == DUPLEX_FULL)
ea4e040a
YR
1520 mii_control |=
1521 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
e10bc84d 1522 CL45_WR_OVER_CL22(bp, phy,
ea4e040a
YR
1523 MDIO_REG_BANK_COMBO_IEEE0,
1524 MDIO_COMBO_IEEE0_MII_CONTROL,
1525 mii_control);
1526
1527 } else { /* AN mode */
1528 /* enable and restart AN */
e10bc84d 1529 bnx2x_restart_autoneg(phy, params, 0);
ea4e040a
YR
1530 }
1531}
1532
1533
1534/*
1535 * link management
1536 */
1537
1538static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
8c99e7b0
YR
1539{ /* LD LP */
1540 switch (pause_result) { /* ASYM P ASYM P */
1541 case 0xb: /* 1 0 1 1 */
c0700f90 1542 vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
ea4e040a
YR
1543 break;
1544
8c99e7b0 1545 case 0xe: /* 1 1 1 0 */
c0700f90 1546 vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
ea4e040a
YR
1547 break;
1548
8c99e7b0
YR
1549 case 0x5: /* 0 1 0 1 */
1550 case 0x7: /* 0 1 1 1 */
1551 case 0xd: /* 1 1 0 1 */
1552 case 0xf: /* 1 1 1 1 */
c0700f90 1553 vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
ea4e040a
YR
1554 break;
1555
1556 default:
1557 break;
1558 }
7aa0711f
YR
1559 if (pause_result & (1<<0))
1560 vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
1561 if (pause_result & (1<<1))
1562 vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
ea4e040a
YR
1563}
1564
e10bc84d
YR
1565static u8 bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
1566 struct link_params *params)
15ddd2d0
YR
1567{
1568 struct bnx2x *bp = params->bp;
1569 u16 pd_10g, status2_1000x;
7aa0711f
YR
1570 if (phy->req_line_speed != SPEED_AUTO_NEG)
1571 return 0;
e10bc84d 1572 CL45_RD_OVER_CL22(bp, phy,
15ddd2d0
YR
1573 MDIO_REG_BANK_SERDES_DIGITAL,
1574 MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
1575 &status2_1000x);
e10bc84d 1576 CL45_RD_OVER_CL22(bp, phy,
15ddd2d0
YR
1577 MDIO_REG_BANK_SERDES_DIGITAL,
1578 MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
1579 &status2_1000x);
1580 if (status2_1000x & MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED) {
1581 DP(NETIF_MSG_LINK, "1G parallel detect link on port %d\n",
1582 params->port);
1583 return 1;
1584 }
1585
e10bc84d 1586 CL45_RD_OVER_CL22(bp, phy,
15ddd2d0
YR
1587 MDIO_REG_BANK_10G_PARALLEL_DETECT,
1588 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS,
1589 &pd_10g);
1590
1591 if (pd_10g & MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK) {
1592 DP(NETIF_MSG_LINK, "10G parallel detect link on port %d\n",
1593 params->port);
1594 return 1;
1595 }
1596 return 0;
1597}
ea4e040a 1598
e10bc84d
YR
1599static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
1600 struct link_params *params,
1601 struct link_vars *vars,
1602 u32 gp_status)
ea4e040a
YR
1603{
1604 struct bnx2x *bp = params->bp;
3196a88a
EG
1605 u16 ld_pause; /* local driver */
1606 u16 lp_pause; /* link partner */
ea4e040a
YR
1607 u16 pause_result;
1608
c0700f90 1609 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
ea4e040a
YR
1610
1611 /* resolve from gp_status in case of AN complete and not sgmii */
7aa0711f
YR
1612 if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
1613 vars->flow_ctrl = phy->req_flow_ctrl;
1614 else if (phy->req_line_speed != SPEED_AUTO_NEG)
1615 vars->flow_ctrl = params->req_fc_auto_adv;
1616 else if ((gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
1617 (!(vars->phy_flags & PHY_SGMII_FLAG))) {
e10bc84d 1618 if (bnx2x_direct_parallel_detect_used(phy, params)) {
15ddd2d0
YR
1619 vars->flow_ctrl = params->req_fc_auto_adv;
1620 return;
1621 }
7846e471
YR
1622 if ((gp_status &
1623 (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
1624 MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) ==
1625 (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
1626 MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {
1627
e10bc84d 1628 CL45_RD_OVER_CL22(bp, phy,
7846e471
YR
1629 MDIO_REG_BANK_CL73_IEEEB1,
1630 MDIO_CL73_IEEEB1_AN_ADV1,
1631 &ld_pause);
e10bc84d 1632 CL45_RD_OVER_CL22(bp, phy,
7846e471
YR
1633 MDIO_REG_BANK_CL73_IEEEB1,
1634 MDIO_CL73_IEEEB1_AN_LP_ADV1,
1635 &lp_pause);
1636 pause_result = (ld_pause &
1637 MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK)
1638 >> 8;
1639 pause_result |= (lp_pause &
1640 MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK)
1641 >> 10;
1642 DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n",
1643 pause_result);
1644 } else {
e10bc84d 1645 CL45_RD_OVER_CL22(bp, phy,
7846e471
YR
1646 MDIO_REG_BANK_COMBO_IEEE0,
1647 MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
1648 &ld_pause);
e10bc84d 1649 CL45_RD_OVER_CL22(bp, phy,
7846e471
YR
1650 MDIO_REG_BANK_COMBO_IEEE0,
1651 MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
1652 &lp_pause);
1653 pause_result = (ld_pause &
ea4e040a 1654 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
7846e471 1655 pause_result |= (lp_pause &
ea4e040a 1656 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
7846e471
YR
1657 DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n",
1658 pause_result);
1659 }
ea4e040a 1660 bnx2x_pause_resolve(vars, pause_result);
ea4e040a
YR
1661 }
1662 DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
1663}
1664
e10bc84d
YR
1665static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
1666 struct link_params *params)
239d686d
EG
1667{
1668 struct bnx2x *bp = params->bp;
1669 u16 rx_status, ustat_val, cl37_fsm_recieved;
1670 DP(NETIF_MSG_LINK, "bnx2x_check_fallback_to_cl37\n");
1671 /* Step 1: Make sure signal is detected */
e10bc84d 1672 CL45_RD_OVER_CL22(bp, phy,
239d686d
EG
1673 MDIO_REG_BANK_RX0,
1674 MDIO_RX0_RX_STATUS,
1675 &rx_status);
1676 if ((rx_status & MDIO_RX0_RX_STATUS_SIGDET) !=
1677 (MDIO_RX0_RX_STATUS_SIGDET)) {
1678 DP(NETIF_MSG_LINK, "Signal is not detected. Restoring CL73."
1679 "rx_status(0x80b0) = 0x%x\n", rx_status);
e10bc84d 1680 CL45_WR_OVER_CL22(bp, phy,
239d686d
EG
1681 MDIO_REG_BANK_CL73_IEEEB0,
1682 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1683 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN);
1684 return;
1685 }
1686 /* Step 2: Check CL73 state machine */
e10bc84d 1687 CL45_RD_OVER_CL22(bp, phy,
239d686d
EG
1688 MDIO_REG_BANK_CL73_USERB0,
1689 MDIO_CL73_USERB0_CL73_USTAT1,
1690 &ustat_val);
1691 if ((ustat_val &
1692 (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
1693 MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) !=
1694 (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
1695 MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) {
1696 DP(NETIF_MSG_LINK, "CL73 state-machine is not stable. "
1697 "ustat_val(0x8371) = 0x%x\n", ustat_val);
1698 return;
1699 }
1700 /* Step 3: Check CL37 Message Pages received to indicate LP
1701 supports only CL37 */
e10bc84d 1702 CL45_RD_OVER_CL22(bp, phy,
239d686d
EG
1703 MDIO_REG_BANK_REMOTE_PHY,
1704 MDIO_REMOTE_PHY_MISC_RX_STATUS,
1705 &cl37_fsm_recieved);
1706 if ((cl37_fsm_recieved &
1707 (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
1708 MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) !=
1709 (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
1710 MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) {
1711 DP(NETIF_MSG_LINK, "No CL37 FSM were received. "
1712 "misc_rx_status(0x8330) = 0x%x\n",
1713 cl37_fsm_recieved);
1714 return;
1715 }
1716 /* The combined cl37/cl73 fsm state information indicating that we are
1717 connected to a device which does not support cl73, but does support
1718 cl37 BAM. In this case we disable cl73 and restart cl37 auto-neg */
1719 /* Disable CL73 */
e10bc84d 1720 CL45_WR_OVER_CL22(bp, phy,
239d686d
EG
1721 MDIO_REG_BANK_CL73_IEEEB0,
1722 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1723 0);
1724 /* Restart CL37 autoneg */
e10bc84d 1725 bnx2x_restart_autoneg(phy, params, 0);
239d686d
EG
1726 DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n");
1727}
7aa0711f
YR
1728
1729static void bnx2x_xgxs_an_resolve(struct bnx2x_phy *phy,
1730 struct link_params *params,
1731 struct link_vars *vars,
1732 u32 gp_status)
1733{
1734 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE)
1735 vars->link_status |=
1736 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
1737
1738 if (bnx2x_direct_parallel_detect_used(phy, params))
1739 vars->link_status |=
1740 LINK_STATUS_PARALLEL_DETECTION_USED;
1741}
1742
b7737c9b
YR
1743static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
1744 struct link_params *params,
1745 struct link_vars *vars)
ea4e040a
YR
1746{
1747 struct bnx2x *bp = params->bp;
b7737c9b 1748 u16 new_line_speed , gp_status;
ea4e040a 1749 u8 rc = 0;
c18aa15d 1750
b7737c9b
YR
1751 /* Read gp_status */
1752 CL45_RD_OVER_CL22(bp, phy,
1753 MDIO_REG_BANK_GP_STATUS,
1754 MDIO_GP_STATUS_TOP_AN_STATUS1,
1755 &gp_status);
7f02c4ad 1756
7aa0711f
YR
1757 if (phy->req_line_speed == SPEED_AUTO_NEG)
1758 vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
ea4e040a
YR
1759 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
1760 DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
1761 gp_status);
1762
1763 vars->phy_link_up = 1;
1764 vars->link_status |= LINK_STATUS_LINK_UP;
1765
1766 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
1767 vars->duplex = DUPLEX_FULL;
1768 else
1769 vars->duplex = DUPLEX_HALF;
1770
7aa0711f
YR
1771 if (SINGLE_MEDIA_DIRECT(params)) {
1772 bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
1773 if (phy->req_line_speed == SPEED_AUTO_NEG)
1774 bnx2x_xgxs_an_resolve(phy, params, vars,
1775 gp_status);
1776 }
ea4e040a
YR
1777
1778 switch (gp_status & GP_STATUS_SPEED_MASK) {
1779 case GP_STATUS_10M:
6c55c3cd 1780 new_line_speed = SPEED_10;
ea4e040a
YR
1781 if (vars->duplex == DUPLEX_FULL)
1782 vars->link_status |= LINK_10TFD;
1783 else
1784 vars->link_status |= LINK_10THD;
1785 break;
1786
1787 case GP_STATUS_100M:
6c55c3cd 1788 new_line_speed = SPEED_100;
ea4e040a
YR
1789 if (vars->duplex == DUPLEX_FULL)
1790 vars->link_status |= LINK_100TXFD;
1791 else
1792 vars->link_status |= LINK_100TXHD;
1793 break;
1794
1795 case GP_STATUS_1G:
1796 case GP_STATUS_1G_KX:
6c55c3cd 1797 new_line_speed = SPEED_1000;
ea4e040a
YR
1798 if (vars->duplex == DUPLEX_FULL)
1799 vars->link_status |= LINK_1000TFD;
1800 else
1801 vars->link_status |= LINK_1000THD;
1802 break;
1803
1804 case GP_STATUS_2_5G:
6c55c3cd 1805 new_line_speed = SPEED_2500;
ea4e040a
YR
1806 if (vars->duplex == DUPLEX_FULL)
1807 vars->link_status |= LINK_2500TFD;
1808 else
1809 vars->link_status |= LINK_2500THD;
1810 break;
1811
1812 case GP_STATUS_5G:
1813 case GP_STATUS_6G:
1814 DP(NETIF_MSG_LINK,
1815 "link speed unsupported gp_status 0x%x\n",
1816 gp_status);
1817 return -EINVAL;
ab6ad5a4 1818
ea4e040a
YR
1819 case GP_STATUS_10G_KX4:
1820 case GP_STATUS_10G_HIG:
1821 case GP_STATUS_10G_CX4:
6c55c3cd 1822 new_line_speed = SPEED_10000;
ea4e040a
YR
1823 vars->link_status |= LINK_10GTFD;
1824 break;
1825
1826 case GP_STATUS_12G_HIG:
6c55c3cd 1827 new_line_speed = SPEED_12000;
ea4e040a
YR
1828 vars->link_status |= LINK_12GTFD;
1829 break;
1830
1831 case GP_STATUS_12_5G:
6c55c3cd 1832 new_line_speed = SPEED_12500;
ea4e040a
YR
1833 vars->link_status |= LINK_12_5GTFD;
1834 break;
1835
1836 case GP_STATUS_13G:
6c55c3cd 1837 new_line_speed = SPEED_13000;
ea4e040a
YR
1838 vars->link_status |= LINK_13GTFD;
1839 break;
1840
1841 case GP_STATUS_15G:
6c55c3cd 1842 new_line_speed = SPEED_15000;
ea4e040a
YR
1843 vars->link_status |= LINK_15GTFD;
1844 break;
1845
1846 case GP_STATUS_16G:
6c55c3cd 1847 new_line_speed = SPEED_16000;
ea4e040a
YR
1848 vars->link_status |= LINK_16GTFD;
1849 break;
1850
1851 default:
1852 DP(NETIF_MSG_LINK,
1853 "link speed unsupported gp_status 0x%x\n",
1854 gp_status);
ab6ad5a4 1855 return -EINVAL;
ea4e040a
YR
1856 }
1857
6c55c3cd 1858 vars->line_speed = new_line_speed;
ea4e040a 1859
ea4e040a
YR
1860 } else { /* link_down */
1861 DP(NETIF_MSG_LINK, "phy link down\n");
1862
1863 vars->phy_link_up = 0;
57963ed9 1864
ea4e040a 1865 vars->duplex = DUPLEX_FULL;
c0700f90 1866 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
ea4e040a 1867 vars->mac_type = MAC_TYPE_NONE;
239d686d 1868
c18aa15d
YR
1869 if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
1870 SINGLE_MEDIA_DIRECT(params)) {
239d686d 1871 /* Check signal is detected */
c18aa15d 1872 bnx2x_check_fallback_to_cl37(phy, params);
239d686d 1873 }
ea4e040a
YR
1874 }
1875
2381a55c 1876 DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x\n",
ea4e040a 1877 gp_status, vars->phy_link_up, vars->line_speed);
a22f0788
YR
1878 DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x link_status 0x%x\n",
1879 vars->duplex, vars->flow_ctrl, vars->link_status);
ea4e040a
YR
1880 return rc;
1881}
1882
ed8680a7 1883static void bnx2x_set_gmii_tx_driver(struct link_params *params)
ea4e040a
YR
1884{
1885 struct bnx2x *bp = params->bp;
e10bc84d 1886 struct bnx2x_phy *phy = &params->phy[INT_PHY];
ea4e040a
YR
1887 u16 lp_up2;
1888 u16 tx_driver;
c2c8b03e 1889 u16 bank;
ea4e040a
YR
1890
1891 /* read precomp */
e10bc84d 1892 CL45_RD_OVER_CL22(bp, phy,
ea4e040a
YR
1893 MDIO_REG_BANK_OVER_1G,
1894 MDIO_OVER_1G_LP_UP2, &lp_up2);
1895
ea4e040a
YR
1896 /* bits [10:7] at lp_up2, positioned at [15:12] */
1897 lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >>
1898 MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT) <<
1899 MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT);
1900
c2c8b03e
EG
1901 if (lp_up2 == 0)
1902 return;
1903
1904 for (bank = MDIO_REG_BANK_TX0; bank <= MDIO_REG_BANK_TX3;
1905 bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0)) {
e10bc84d 1906 CL45_RD_OVER_CL22(bp, phy,
c2c8b03e
EG
1907 bank,
1908 MDIO_TX0_TX_DRIVER, &tx_driver);
1909
1910 /* replace tx_driver bits [15:12] */
1911 if (lp_up2 !=
1912 (tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK)) {
1913 tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
1914 tx_driver |= lp_up2;
e10bc84d 1915 CL45_WR_OVER_CL22(bp, phy,
c2c8b03e
EG
1916 bank,
1917 MDIO_TX0_TX_DRIVER, tx_driver);
1918 }
ea4e040a
YR
1919 }
1920}
1921
1922static u8 bnx2x_emac_program(struct link_params *params,
b7737c9b 1923 struct link_vars *vars)
ea4e040a
YR
1924{
1925 struct bnx2x *bp = params->bp;
1926 u8 port = params->port;
1927 u16 mode = 0;
1928
1929 DP(NETIF_MSG_LINK, "setting link speed & duplex\n");
1930 bnx2x_bits_dis(bp, GRCBASE_EMAC0 + port*0x400 +
1931 EMAC_REG_EMAC_MODE,
1932 (EMAC_MODE_25G_MODE |
1933 EMAC_MODE_PORT_MII_10M |
1934 EMAC_MODE_HALF_DUPLEX));
b7737c9b 1935 switch (vars->line_speed) {
ea4e040a
YR
1936 case SPEED_10:
1937 mode |= EMAC_MODE_PORT_MII_10M;
1938 break;
1939
1940 case SPEED_100:
1941 mode |= EMAC_MODE_PORT_MII;
1942 break;
1943
1944 case SPEED_1000:
1945 mode |= EMAC_MODE_PORT_GMII;
1946 break;
1947
1948 case SPEED_2500:
1949 mode |= (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_GMII);
1950 break;
1951
1952 default:
1953 /* 10G not valid for EMAC */
b7737c9b
YR
1954 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
1955 vars->line_speed);
ea4e040a
YR
1956 return -EINVAL;
1957 }
1958
b7737c9b 1959 if (vars->duplex == DUPLEX_HALF)
ea4e040a
YR
1960 mode |= EMAC_MODE_HALF_DUPLEX;
1961 bnx2x_bits_en(bp,
1962 GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
1963 mode);
1964
7f02c4ad 1965 bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
ea4e040a
YR
1966 return 0;
1967}
1968
de6eae1f
YR
1969static void bnx2x_set_preemphasis(struct bnx2x_phy *phy,
1970 struct link_params *params)
b7737c9b 1971{
de6eae1f
YR
1972
1973 u16 bank, i = 0;
1974 struct bnx2x *bp = params->bp;
1975
1976 for (bank = MDIO_REG_BANK_RX0, i = 0; bank <= MDIO_REG_BANK_RX3;
1977 bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0), i++) {
1978 CL45_WR_OVER_CL22(bp, phy,
1979 bank,
1980 MDIO_RX0_RX_EQ_BOOST,
1981 phy->rx_preemphasis[i]);
1982 }
1983
1984 for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3;
1985 bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0), i++) {
1986 CL45_WR_OVER_CL22(bp, phy,
1987 bank,
1988 MDIO_TX0_TX_DRIVER,
1989 phy->tx_preemphasis[i]);
1990 }
1991}
1992
1993static void bnx2x_init_internal_phy(struct bnx2x_phy *phy,
1994 struct link_params *params,
1995 struct link_vars *vars)
1996{
1997 struct bnx2x *bp = params->bp;
1998 u8 enable_cl73 = (SINGLE_MEDIA_DIRECT(params) ||
1999 (params->loopback_mode == LOOPBACK_XGXS));
2000 if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
2001 if (SINGLE_MEDIA_DIRECT(params) &&
2002 (params->feature_config_flags &
2003 FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED))
2004 bnx2x_set_preemphasis(phy, params);
2005
2006 /* forced speed requested? */
2007 if (vars->line_speed != SPEED_AUTO_NEG ||
2008 (SINGLE_MEDIA_DIRECT(params) &&
2009 params->loopback_mode == LOOPBACK_EXT)) {
2010 DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
2011
2012 /* disable autoneg */
2013 bnx2x_set_autoneg(phy, params, vars, 0);
2014
2015 /* program speed and duplex */
2016 bnx2x_program_serdes(phy, params, vars);
2017
2018 } else { /* AN_mode */
2019 DP(NETIF_MSG_LINK, "not SGMII, AN\n");
2020
2021 /* AN enabled */
2022 bnx2x_set_brcm_cl37_advertisment(phy, params);
2023
2024 /* program duplex & pause advertisement (for aneg) */
2025 bnx2x_set_ieee_aneg_advertisment(phy, params,
2026 vars->ieee_fc);
2027
2028 /* enable autoneg */
2029 bnx2x_set_autoneg(phy, params, vars, enable_cl73);
2030
2031 /* enable and restart AN */
2032 bnx2x_restart_autoneg(phy, params, enable_cl73);
2033 }
2034
2035 } else { /* SGMII mode */
2036 DP(NETIF_MSG_LINK, "SGMII\n");
2037
2038 bnx2x_initialize_sgmii_process(phy, params, vars);
2039 }
2040}
2041
2042static u8 bnx2x_init_serdes(struct bnx2x_phy *phy,
2043 struct link_params *params,
2044 struct link_vars *vars)
2045{
2046 u8 rc;
2047 vars->phy_flags |= PHY_SGMII_FLAG;
b7737c9b
YR
2048 bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
2049 bnx2x_set_aer_mmd(params, phy);
2050 rc = bnx2x_reset_unicore(params, phy, 1);
2051 /* reset the SerDes and wait for reset bit return low */
2052 if (rc != 0)
2053 return rc;
2054 bnx2x_set_aer_mmd(params, phy);
2055
2056 return rc;
2057}
2058
2059static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
2060 struct link_params *params,
2061 struct link_vars *vars)
2062{
2063 u8 rc;
2064 vars->phy_flags = PHY_XGXS_FLAG;
2065 if ((phy->req_line_speed &&
2066 ((phy->req_line_speed == SPEED_100) ||
2067 (phy->req_line_speed == SPEED_10))) ||
2068 (!phy->req_line_speed &&
2069 (phy->speed_cap_mask >=
2070 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
2071 (phy->speed_cap_mask <
2072 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
2073 ))
2074 vars->phy_flags |= PHY_SGMII_FLAG;
2075 else
2076 vars->phy_flags &= ~PHY_SGMII_FLAG;
2077
2078 bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
2079 bnx2x_set_aer_mmd(params, phy);
2080 bnx2x_set_master_ln(params, phy);
2081
2082 rc = bnx2x_reset_unicore(params, phy, 0);
2083 /* reset the SerDes and wait for reset bit return low */
2084 if (rc != 0)
2085 return rc;
2086
2087 bnx2x_set_aer_mmd(params, phy);
e10bc84d 2088
b7737c9b
YR
2089 /* setting the masterLn_def again after the reset */
2090 bnx2x_set_master_ln(params, phy);
2091 bnx2x_set_swap_lanes(params, phy);
2092
2093 return rc;
2094}
c18aa15d 2095
de6eae1f
YR
2096static u16 bnx2x_wait_reset_complete(struct bnx2x *bp,
2097 struct bnx2x_phy *phy)
ea4e040a 2098{
de6eae1f
YR
2099 u16 cnt, ctrl;
2100 /* Wait for soft reset to get cleared upto 1 sec */
2101 for (cnt = 0; cnt < 1000; cnt++) {
2102 bnx2x_cl45_read(bp, phy,
2103 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, &ctrl);
2104 if (!(ctrl & (1<<15)))
2105 break;
2106 msleep(1);
2107 }
2108 DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n", ctrl, cnt);
2109 return cnt;
ea4e040a
YR
2110}
2111
de6eae1f 2112static void bnx2x_link_int_enable(struct link_params *params)
a35da8db 2113{
de6eae1f
YR
2114 u8 port = params->port;
2115 u32 mask;
2116 struct bnx2x *bp = params->bp;
c18aa15d 2117
de6eae1f
YR
2118 /* setting the status to report on link up
2119 for either XGXS or SerDes */
2120
2121 if (params->switch_cfg == SWITCH_CFG_10G) {
2122 mask = (NIG_MASK_XGXS0_LINK10G |
2123 NIG_MASK_XGXS0_LINK_STATUS);
2124 DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
2125 if (!(SINGLE_MEDIA_DIRECT(params)) &&
2126 params->phy[INT_PHY].type !=
2127 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) {
2128 mask |= NIG_MASK_MI_INT;
2129 DP(NETIF_MSG_LINK, "enabled external phy int\n");
2130 }
2131
2132 } else { /* SerDes */
2133 mask = NIG_MASK_SERDES0_LINK_STATUS;
2134 DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n");
2135 if (!(SINGLE_MEDIA_DIRECT(params)) &&
2136 params->phy[INT_PHY].type !=
2137 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN) {
2138 mask |= NIG_MASK_MI_INT;
2139 DP(NETIF_MSG_LINK, "enabled external phy int\n");
2140 }
2141 }
2142 bnx2x_bits_en(bp,
2143 NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
2144 mask);
2145
2146 DP(NETIF_MSG_LINK, "port %x, is_xgxs %x, int_status 0x%x\n", port,
2147 (params->switch_cfg == SWITCH_CFG_10G),
2148 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
2149 DP(NETIF_MSG_LINK, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n",
2150 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
2151 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
2152 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS+port*0x3c));
2153 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
2154 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
2155 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
a35da8db
EG
2156}
2157
a22f0788
YR
2158static void bnx2x_rearm_latch_signal(struct bnx2x *bp, u8 port,
2159 u8 exp_mi_int)
a35da8db 2160{
a22f0788
YR
2161 u32 latch_status = 0;
2162
2163 /**
2164 * Disable the MI INT ( external phy int ) by writing 1 to the
2165 * status register. Link down indication is high-active-signal,
2166 * so in this case we need to write the status to clear the XOR
de6eae1f
YR
2167 */
2168 /* Read Latched signals */
2169 latch_status = REG_RD(bp,
a22f0788
YR
2170 NIG_REG_LATCH_STATUS_0 + port*8);
2171 DP(NETIF_MSG_LINK, "latch_status = 0x%x\n", latch_status);
de6eae1f 2172 /* Handle only those with latched-signal=up.*/
a22f0788
YR
2173 if (exp_mi_int)
2174 bnx2x_bits_en(bp,
2175 NIG_REG_STATUS_INTERRUPT_PORT0
2176 + port*4,
2177 NIG_STATUS_EMAC0_MI_INT);
2178 else
2179 bnx2x_bits_dis(bp,
2180 NIG_REG_STATUS_INTERRUPT_PORT0
2181 + port*4,
2182 NIG_STATUS_EMAC0_MI_INT);
2183
de6eae1f 2184 if (latch_status & 1) {
a22f0788 2185
de6eae1f
YR
2186 /* For all latched-signal=up : Re-Arm Latch signals */
2187 REG_WR(bp, NIG_REG_LATCH_STATUS_0 + port*8,
7f02c4ad 2188 (latch_status & 0xfffe) | (latch_status & 1));
de6eae1f 2189 }
a22f0788 2190 /* For all latched-signal=up,Write original_signal to status */
a35da8db
EG
2191}
2192
de6eae1f 2193static void bnx2x_link_int_ack(struct link_params *params,
a22f0788 2194 struct link_vars *vars, u8 is_10g)
b1607af5 2195{
e10bc84d 2196 struct bnx2x *bp = params->bp;
de6eae1f 2197 u8 port = params->port;
e10bc84d 2198
de6eae1f
YR
2199 /* first reset all status
2200 * we assume only one line will be change at a time */
2201 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
2202 (NIG_STATUS_XGXS0_LINK10G |
2203 NIG_STATUS_XGXS0_LINK_STATUS |
2204 NIG_STATUS_SERDES0_LINK_STATUS));
de6eae1f
YR
2205 if (vars->phy_link_up) {
2206 if (is_10g) {
2207 /* Disable the 10G link interrupt
2208 * by writing 1 to the status register
2209 */
2210 DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
2211 bnx2x_bits_en(bp,
2212 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
2213 NIG_STATUS_XGXS0_LINK10G);
b1607af5 2214
de6eae1f
YR
2215 } else if (params->switch_cfg == SWITCH_CFG_10G) {
2216 /* Disable the link interrupt
2217 * by writing 1 to the relevant lane
2218 * in the status register
2219 */
2220 u32 ser_lane = ((params->lane_config &
2221 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
2222 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
b1607af5 2223
de6eae1f
YR
2224 DP(NETIF_MSG_LINK, "%d speed XGXS phy link up\n",
2225 vars->line_speed);
2226 bnx2x_bits_en(bp,
2227 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
2228 ((1 << ser_lane) <<
2229 NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
ea4e040a 2230
de6eae1f
YR
2231 } else { /* SerDes */
2232 DP(NETIF_MSG_LINK, "SerDes phy link up\n");
2233 /* Disable the link interrupt
2234 * by writing 1 to the status register
2235 */
2236 bnx2x_bits_en(bp,
2237 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
2238 NIG_STATUS_SERDES0_LINK_STATUS);
2239 }
ea4e040a 2240
ea4e040a 2241 }
ea4e040a 2242}
ea4e040a 2243
de6eae1f
YR
2244static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len)
2245{
2246 u8 *str_ptr = str;
2247 u32 mask = 0xf0000000;
2248 u8 shift = 8*4;
2249 u8 digit;
a22f0788 2250 u8 remove_leading_zeros = 1;
de6eae1f
YR
2251 if (*len < 10) {
2252 /* Need more than 10chars for this format */
2253 *str_ptr = '\0';
a22f0788 2254 (*len)--;
de6eae1f 2255 return -EINVAL;
ea4e040a 2256 }
de6eae1f 2257 while (shift > 0) {
ea4e040a 2258
de6eae1f
YR
2259 shift -= 4;
2260 digit = ((num & mask) >> shift);
a22f0788
YR
2261 if (digit == 0 && remove_leading_zeros) {
2262 mask = mask >> 4;
2263 continue;
2264 } else if (digit < 0xa)
de6eae1f
YR
2265 *str_ptr = digit + '0';
2266 else
2267 *str_ptr = digit - 0xa + 'a';
a22f0788 2268 remove_leading_zeros = 0;
de6eae1f 2269 str_ptr++;
a22f0788 2270 (*len)--;
de6eae1f
YR
2271 mask = mask >> 4;
2272 if (shift == 4*4) {
a22f0788 2273 *str_ptr = '.';
de6eae1f 2274 str_ptr++;
a22f0788
YR
2275 (*len)--;
2276 remove_leading_zeros = 1;
ea4e040a 2277 }
ea4e040a 2278 }
de6eae1f 2279 return 0;
ea4e040a
YR
2280}
2281
a22f0788 2282
de6eae1f 2283static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
ea4e040a 2284{
de6eae1f
YR
2285 str[0] = '\0';
2286 (*len)--;
2287 return 0;
2288}
ea4e040a 2289
de6eae1f
YR
2290u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
2291 u8 *version, u16 len)
2292{
2293 struct bnx2x *bp;
2294 u32 spirom_ver = 0;
2295 u8 status = 0;
2296 u8 *ver_p = version;
a22f0788 2297 u16 remain_len = len;
de6eae1f
YR
2298 if (version == NULL || params == NULL)
2299 return -EINVAL;
2300 bp = params->bp;
ea4e040a 2301
de6eae1f
YR
2302 /* Extract first external phy*/
2303 version[0] = '\0';
2304 spirom_ver = REG_RD(bp, params->phy[EXT_PHY1].ver_addr);
ea4e040a 2305
a22f0788 2306 if (params->phy[EXT_PHY1].format_fw_ver) {
de6eae1f
YR
2307 status |= params->phy[EXT_PHY1].format_fw_ver(spirom_ver,
2308 ver_p,
a22f0788
YR
2309 &remain_len);
2310 ver_p += (len - remain_len);
2311 }
2312 if ((params->num_phys == MAX_PHYS) &&
2313 (params->phy[EXT_PHY2].ver_addr != 0)) {
2314 spirom_ver = REG_RD(bp,
2315 params->phy[EXT_PHY2].ver_addr);
2316 if (params->phy[EXT_PHY2].format_fw_ver) {
2317 *ver_p = '/';
2318 ver_p++;
2319 remain_len--;
2320 status |= params->phy[EXT_PHY2].format_fw_ver(
2321 spirom_ver,
2322 ver_p,
2323 &remain_len);
2324 ver_p = version + (len - remain_len);
2325 }
2326 }
2327 *ver_p = '\0';
de6eae1f 2328 return status;
6bbca910 2329}
ea4e040a 2330
de6eae1f
YR
2331static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
2332 struct link_params *params)
589abe3a 2333{
de6eae1f 2334 u8 port = params->port;
589abe3a 2335 struct bnx2x *bp = params->bp;
589abe3a 2336
de6eae1f
YR
2337 if (phy->req_line_speed != SPEED_1000) {
2338 u32 md_devad;
589abe3a 2339
de6eae1f 2340 DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
589abe3a 2341
de6eae1f
YR
2342 /* change the uni_phy_addr in the nig */
2343 md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
2344 port*0x18));
cc1cb004 2345
de6eae1f 2346 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
589abe3a 2347
de6eae1f
YR
2348 bnx2x_cl45_write(bp, phy,
2349 5,
2350 (MDIO_REG_BANK_AER_BLOCK +
2351 (MDIO_AER_BLOCK_AER_REG & 0xf)),
2352 0x2800);
589abe3a 2353
de6eae1f
YR
2354 bnx2x_cl45_write(bp, phy,
2355 5,
2356 (MDIO_REG_BANK_CL73_IEEEB0 +
2357 (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
2358 0x6041);
2359 msleep(200);
2360 /* set aer mmd back */
2361 bnx2x_set_aer_mmd(params, phy);
589abe3a 2362
de6eae1f
YR
2363 /* and md_devad */
2364 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
2365 md_devad);
2366
2367 } else {
2368 u16 mii_ctrl;
2369 DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
2370 bnx2x_cl45_read(bp, phy, 5,
2371 (MDIO_REG_BANK_COMBO_IEEE0 +
2372 (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
2373 &mii_ctrl);
2374 bnx2x_cl45_write(bp, phy, 5,
2375 (MDIO_REG_BANK_COMBO_IEEE0 +
2376 (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
2377 mii_ctrl |
2378 MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK);
2379 }
589abe3a
EG
2380}
2381
de6eae1f
YR
2382/*
2383 *------------------------------------------------------------------------
2384 * bnx2x_override_led_value -
2385 *
2386 * Override the led value of the requested led
2387 *
2388 *------------------------------------------------------------------------
2389 */
2390u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port,
2391 u32 led_idx, u32 value)
589abe3a 2392{
de6eae1f 2393 u32 reg_val;
ab6ad5a4 2394
de6eae1f
YR
2395 /* If port 0 then use EMAC0, else use EMAC1*/
2396 u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
589abe3a 2397
de6eae1f
YR
2398 DP(NETIF_MSG_LINK,
2399 "bnx2x_override_led_value() port %x led_idx %d value %d\n",
2400 port, led_idx, value);
589abe3a 2401
de6eae1f
YR
2402 switch (led_idx) {
2403 case 0: /* 10MB led */
2404 /* Read the current value of the LED register in
2405 the EMAC block */
2406 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
2407 /* Set the OVERRIDE bit to 1 */
2408 reg_val |= EMAC_LED_OVERRIDE;
2409 /* If value is 1, set the 10M_OVERRIDE bit,
2410 otherwise reset it.*/
2411 reg_val = (value == 1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) :
2412 (reg_val & ~EMAC_LED_10MB_OVERRIDE);
2413 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
2414 break;
2415 case 1: /*100MB led */
2416 /*Read the current value of the LED register in
2417 the EMAC block */
2418 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
2419 /* Set the OVERRIDE bit to 1 */
2420 reg_val |= EMAC_LED_OVERRIDE;
2421 /* If value is 1, set the 100M_OVERRIDE bit,
2422 otherwise reset it.*/
2423 reg_val = (value == 1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) :
2424 (reg_val & ~EMAC_LED_100MB_OVERRIDE);
2425 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
2426 break;
2427 case 2: /* 1000MB led */
2428 /* Read the current value of the LED register in the
2429 EMAC block */
2430 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
2431 /* Set the OVERRIDE bit to 1 */
2432 reg_val |= EMAC_LED_OVERRIDE;
2433 /* If value is 1, set the 1000M_OVERRIDE bit, otherwise
2434 reset it. */
2435 reg_val = (value == 1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) :
2436 (reg_val & ~EMAC_LED_1000MB_OVERRIDE);
2437 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
2438 break;
2439 case 3: /* 2500MB led */
2440 /* Read the current value of the LED register in the
2441 EMAC block*/
2442 reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
2443 /* Set the OVERRIDE bit to 1 */
2444 reg_val |= EMAC_LED_OVERRIDE;
2445 /* If value is 1, set the 2500M_OVERRIDE bit, otherwise
2446 reset it.*/
2447 reg_val = (value == 1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) :
2448 (reg_val & ~EMAC_LED_2500MB_OVERRIDE);
2449 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
2450 break;
2451 case 4: /*10G led */
2452 if (port == 0) {
2453 REG_WR(bp, NIG_REG_LED_10G_P0,
2454 value);
2455 } else {
2456 REG_WR(bp, NIG_REG_LED_10G_P1,
2457 value);
2458 }
2459 break;
2460 case 5: /* TRAFFIC led */
2461 /* Find if the traffic control is via BMAC or EMAC */
2462 if (port == 0)
2463 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC0_EN);
2464 else
2465 reg_val = REG_RD(bp, NIG_REG_NIG_EMAC1_EN);
2466
2467 /* Override the traffic led in the EMAC:*/
2468 if (reg_val == 1) {
2469 /* Read the current value of the LED register in
2470 the EMAC block */
2471 reg_val = REG_RD(bp, emac_base +
2472 EMAC_REG_EMAC_LED);
2473 /* Set the TRAFFIC_OVERRIDE bit to 1 */
2474 reg_val |= EMAC_LED_OVERRIDE;
2475 /* If value is 1, set the TRAFFIC bit, otherwise
2476 reset it.*/
2477 reg_val = (value == 1) ? (reg_val | EMAC_LED_TRAFFIC) :
2478 (reg_val & ~EMAC_LED_TRAFFIC);
2479 REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
2480 } else { /* Override the traffic led in the BMAC: */
2481 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
2482 + port*4, 1);
2483 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port*4,
2484 value);
2485 }
2486 break;
2487 default:
2488 DP(NETIF_MSG_LINK,
2489 "bnx2x_override_led_value() unknown led index %d "
2490 "(should be 0-5)\n", led_idx);
2491 return -EINVAL;
2492 }
2493
2494 return 0;
589abe3a
EG
2495}
2496
7f02c4ad
YR
2497
2498u8 bnx2x_set_led(struct link_params *params,
2499 struct link_vars *vars, u8 mode, u32 speed)
4d295db0 2500{
de6eae1f
YR
2501 u8 port = params->port;
2502 u16 hw_led_mode = params->hw_led_mode;
7f02c4ad 2503 u8 rc = 0, phy_idx;
de6eae1f
YR
2504 u32 tmp;
2505 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
589abe3a 2506 struct bnx2x *bp = params->bp;
de6eae1f
YR
2507 DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
2508 DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
2509 speed, hw_led_mode);
7f02c4ad
YR
2510 /* In case */
2511 for (phy_idx = EXT_PHY1; phy_idx < MAX_PHYS; phy_idx++) {
2512 if (params->phy[phy_idx].set_link_led) {
2513 params->phy[phy_idx].set_link_led(
2514 &params->phy[phy_idx], params, mode);
2515 }
2516 }
2517
de6eae1f 2518 switch (mode) {
7f02c4ad 2519 case LED_MODE_FRONT_PANEL_OFF:
de6eae1f
YR
2520 case LED_MODE_OFF:
2521 REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0);
2522 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
2523 SHARED_HW_CFG_LED_MAC1);
589abe3a 2524
de6eae1f
YR
2525 tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
2526 EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE));
2527 break;
589abe3a 2528
de6eae1f 2529 case LED_MODE_OPER:
7f02c4ad
YR
2530 /**
2531 * For all other phys, OPER mode is same as ON, so in case
2532 * link is down, do nothing
2533 **/
2534 if (!vars->link_up)
2535 break;
2536 case LED_MODE_ON:
de6eae1f 2537 if (SINGLE_MEDIA_DIRECT(params)) {
7f02c4ad
YR
2538 /**
2539 * This is a work-around for HW issue found when link
2540 * is up in CL73
2541 */
de6eae1f
YR
2542 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
2543 REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
2544 } else {
2545 REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
2546 hw_led_mode);
2547 }
589abe3a 2548
de6eae1f
YR
2549 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
2550 port*4, 0);
2551 /* Set blinking rate to ~15.9Hz */
2552 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
2553 LED_BLINK_RATE_VAL);
2554 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
2555 port*4, 1);
2556 tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
2557 EMAC_WR(bp, EMAC_REG_EMAC_LED,
2558 (tmp & (~EMAC_LED_OVERRIDE)));
589abe3a 2559
de6eae1f
YR
2560 if (CHIP_IS_E1(bp) &&
2561 ((speed == SPEED_2500) ||
2562 (speed == SPEED_1000) ||
2563 (speed == SPEED_100) ||
2564 (speed == SPEED_10))) {
2565 /* On Everest 1 Ax chip versions for speeds less than
2566 10G LED scheme is different */
2567 REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
2568 + port*4, 1);
2569 REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
2570 port*4, 0);
2571 REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
2572 port*4, 1);
2573 }
2574 break;
589abe3a 2575
de6eae1f
YR
2576 default:
2577 rc = -EINVAL;
2578 DP(NETIF_MSG_LINK, "bnx2x_set_led: Invalid led mode %d\n",
2579 mode);
2580 break;
589abe3a 2581 }
de6eae1f 2582 return rc;
589abe3a 2583
4d295db0
EG
2584}
2585
a22f0788
YR
2586/**
2587 * This function comes to reflect the actual link state read DIRECTLY from the
2588 * HW
2589 */
2590u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars,
2591 u8 is_serdes)
4d295db0
EG
2592{
2593 struct bnx2x *bp = params->bp;
de6eae1f 2594 u16 gp_status = 0, phy_index = 0;
a22f0788
YR
2595 u8 ext_phy_link_up = 0, serdes_phy_type;
2596 struct link_vars temp_vars;
4d295db0 2597
de6eae1f
YR
2598 CL45_RD_OVER_CL22(bp, &params->phy[INT_PHY],
2599 MDIO_REG_BANK_GP_STATUS,
2600 MDIO_GP_STATUS_TOP_AN_STATUS1,
2601 &gp_status);
2602 /* link is up only if both local phy and external phy are up */
a22f0788
YR
2603 if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS))
2604 return -ESRCH;
2605
2606 switch (params->num_phys) {
2607 case 1:
2608 /* No external PHY */
2609 return 0;
2610 case 2:
2611 ext_phy_link_up = params->phy[EXT_PHY1].read_status(
2612 &params->phy[EXT_PHY1],
2613 params, &temp_vars);
2614 break;
2615 case 3: /* Dual Media */
de6eae1f
YR
2616 for (phy_index = EXT_PHY1; phy_index < params->num_phys;
2617 phy_index++) {
a22f0788
YR
2618 serdes_phy_type = ((params->phy[phy_index].media_type ==
2619 ETH_PHY_SFP_FIBER) ||
2620 (params->phy[phy_index].media_type ==
2621 ETH_PHY_XFP_FIBER));
2622
2623 if (is_serdes != serdes_phy_type)
2624 continue;
2625 if (params->phy[phy_index].read_status) {
2626 ext_phy_link_up |=
de6eae1f
YR
2627 params->phy[phy_index].read_status(
2628 &params->phy[phy_index],
2629 params, &temp_vars);
a22f0788 2630 }
de6eae1f 2631 }
a22f0788 2632 break;
4d295db0 2633 }
a22f0788
YR
2634 if (ext_phy_link_up)
2635 return 0;
de6eae1f
YR
2636 return -ESRCH;
2637}
4d295db0 2638
de6eae1f
YR
2639static u8 bnx2x_link_initialize(struct link_params *params,
2640 struct link_vars *vars)
2641{
2642 u8 rc = 0;
2643 u8 phy_index, non_ext_phy;
2644 struct bnx2x *bp = params->bp;
2645 /**
2646 * In case of external phy existence, the line speed would be the
2647 * line speed linked up by the external phy. In case it is direct
2648 * only, then the line_speed during initialization will be
2649 * equal to the req_line_speed
2650 */
2651 vars->line_speed = params->phy[INT_PHY].req_line_speed;
4d295db0 2652
de6eae1f
YR
2653 /**
2654 * Initialize the internal phy in case this is a direct board
2655 * (no external phys), or this board has external phy which requires
2656 * to first.
2657 */
4d295db0 2658
de6eae1f
YR
2659 if (params->phy[INT_PHY].config_init)
2660 params->phy[INT_PHY].config_init(
2661 &params->phy[INT_PHY],
2662 params, vars);
4d295db0 2663
de6eae1f
YR
2664 /* init ext phy and enable link state int */
2665 non_ext_phy = (SINGLE_MEDIA_DIRECT(params) ||
2666 (params->loopback_mode == LOOPBACK_XGXS));
4d295db0 2667
de6eae1f
YR
2668 if (non_ext_phy ||
2669 (params->phy[EXT_PHY1].flags & FLAGS_INIT_XGXS_FIRST) ||
2670 (params->loopback_mode == LOOPBACK_EXT_PHY)) {
2671 struct bnx2x_phy *phy = &params->phy[INT_PHY];
2672 if (vars->line_speed == SPEED_AUTO_NEG)
2673 bnx2x_set_parallel_detection(phy, params);
2674 bnx2x_init_internal_phy(phy, params, vars);
4d295db0
EG
2675 }
2676
de6eae1f
YR
2677 /* Init external phy*/
2678 if (!non_ext_phy)
2679 for (phy_index = EXT_PHY1; phy_index < params->num_phys;
2680 phy_index++) {
a22f0788
YR
2681 /**
2682 * No need to initialize second phy in case of first
2683 * phy only selection. In case of second phy, we do
2684 * need to initialize the first phy, since they are
2685 * connected.
2686 **/
2687 if (phy_index == EXT_PHY2 &&
2688 (bnx2x_phy_selection(params) ==
2689 PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) {
2690 DP(NETIF_MSG_LINK, "Not initializing"
2691 "second phy\n");
2692 continue;
2693 }
de6eae1f
YR
2694 params->phy[phy_index].config_init(
2695 &params->phy[phy_index],
2696 params, vars);
2697 }
4d295db0 2698
de6eae1f
YR
2699 /* Reset the interrupt indication after phy was initialized */
2700 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 +
2701 params->port*4,
2702 (NIG_STATUS_XGXS0_LINK10G |
2703 NIG_STATUS_XGXS0_LINK_STATUS |
2704 NIG_STATUS_SERDES0_LINK_STATUS |
2705 NIG_MASK_MI_INT));
2706 return rc;
2707}
4d295db0 2708
de6eae1f
YR
2709static void bnx2x_int_link_reset(struct bnx2x_phy *phy,
2710 struct link_params *params)
2711{
2712 /* reset the SerDes/XGXS */
2713 REG_WR(params->bp, GRCBASE_MISC +
2714 MISC_REGISTERS_RESET_REG_3_CLEAR,
2715 (0x1ff << (params->port*16)));
589abe3a
EG
2716}
2717
de6eae1f
YR
2718static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy,
2719 struct link_params *params)
4d295db0 2720{
de6eae1f
YR
2721 struct bnx2x *bp = params->bp;
2722 u8 gpio_port;
2723 /* HW reset */
2724 gpio_port = params->port;
2725 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
2726 MISC_REGISTERS_GPIO_OUTPUT_LOW,
2727 gpio_port);
2728 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
2729 MISC_REGISTERS_GPIO_OUTPUT_LOW,
2730 gpio_port);
2731 DP(NETIF_MSG_LINK, "reset external PHY\n");
4d295db0 2732}
589abe3a 2733
de6eae1f
YR
2734static u8 bnx2x_update_link_down(struct link_params *params,
2735 struct link_vars *vars)
589abe3a
EG
2736{
2737 struct bnx2x *bp = params->bp;
de6eae1f 2738 u8 port = params->port;
589abe3a 2739
de6eae1f 2740 DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
7f02c4ad 2741 bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
589abe3a 2742
de6eae1f
YR
2743 /* indicate no mac active */
2744 vars->mac_type = MAC_TYPE_NONE;
ab6ad5a4 2745
de6eae1f
YR
2746 /* update shared memory */
2747 vars->link_status = 0;
2748 vars->line_speed = 0;
2749 bnx2x_update_mng(params, vars->link_status);
589abe3a 2750
de6eae1f
YR
2751 /* activate nig drain */
2752 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
4d295db0 2753
de6eae1f
YR
2754 /* disable emac */
2755 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
2756
2757 msleep(10);
2758
2759 /* reset BigMac */
2760 bnx2x_bmac_rx_disable(bp, params->port);
2761 REG_WR(bp, GRCBASE_MISC +
2762 MISC_REGISTERS_RESET_REG_2_CLEAR,
2763 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
589abe3a
EG
2764 return 0;
2765}
de6eae1f
YR
2766
2767static u8 bnx2x_update_link_up(struct link_params *params,
2768 struct link_vars *vars,
2769 u8 link_10g)
589abe3a
EG
2770{
2771 struct bnx2x *bp = params->bp;
de6eae1f
YR
2772 u8 port = params->port;
2773 u8 rc = 0;
4d295db0 2774
de6eae1f 2775 vars->link_status |= LINK_STATUS_LINK_UP;
7f02c4ad 2776
de6eae1f
YR
2777 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
2778 vars->link_status |=
2779 LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
589abe3a 2780
de6eae1f
YR
2781 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
2782 vars->link_status |=
2783 LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
7f02c4ad 2784
de6eae1f
YR
2785 if (link_10g) {
2786 bnx2x_bmac_enable(params, vars, 0);
7f02c4ad
YR
2787 bnx2x_set_led(params, vars,
2788 LED_MODE_OPER, SPEED_10000);
de6eae1f
YR
2789 } else {
2790 rc = bnx2x_emac_program(params, vars);
cc1cb004 2791
de6eae1f 2792 bnx2x_emac_enable(params, vars, 0);
cc1cb004 2793
de6eae1f
YR
2794 /* AN complete? */
2795 if ((vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
2796 && (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
2797 SINGLE_MEDIA_DIRECT(params))
2798 bnx2x_set_gmii_tx_driver(params);
2799 }
cc1cb004 2800
de6eae1f
YR
2801 /* PBF - link up */
2802 rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
2803 vars->line_speed);
589abe3a 2804
de6eae1f
YR
2805 /* disable drain */
2806 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
589abe3a 2807
de6eae1f
YR
2808 /* update shared memory */
2809 bnx2x_update_mng(params, vars->link_status);
2810 msleep(20);
2811 return rc;
589abe3a 2812}
de6eae1f
YR
2813/**
2814 * The bnx2x_link_update function should be called upon link
2815 * interrupt.
2816 * Link is considered up as follows:
2817 * - DIRECT_SINGLE_MEDIA - Only XGXS link (internal link) needs
2818 * to be up
2819 * - SINGLE_MEDIA - The link between the 577xx and the external
2820 * phy (XGXS) need to up as well as the external link of the
2821 * phy (PHY_EXT1)
2822 * - DUAL_MEDIA - The link between the 577xx and the first
2823 * external phy needs to be up, and at least one of the 2
2824 * external phy link must be up.
2825 */
2826u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
4d295db0 2827{
de6eae1f
YR
2828 struct bnx2x *bp = params->bp;
2829 struct link_vars phy_vars[MAX_PHYS];
2830 u8 port = params->port;
2831 u8 link_10g, phy_index;
2832 u8 ext_phy_link_up = 0, cur_link_up, rc = 0;
2833 u8 is_mi_int = 0;
2834 u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
2835 u8 active_external_phy = INT_PHY;
2836 vars->link_status = 0;
2837 for (phy_index = INT_PHY; phy_index < params->num_phys;
2838 phy_index++) {
2839 phy_vars[phy_index].flow_ctrl = 0;
2840 phy_vars[phy_index].link_status = 0;
2841 phy_vars[phy_index].line_speed = 0;
2842 phy_vars[phy_index].duplex = DUPLEX_FULL;
2843 phy_vars[phy_index].phy_link_up = 0;
2844 phy_vars[phy_index].link_up = 0;
2845 }
4d295db0 2846
de6eae1f
YR
2847 DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
2848 port, (vars->phy_flags & PHY_XGXS_FLAG),
2849 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
4d295db0 2850
de6eae1f
YR
2851 is_mi_int = (u8)(REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT +
2852 port*0x18) > 0);
2853 DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
2854 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
2855 is_mi_int,
2856 REG_RD(bp,
2857 NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
4d295db0 2858
de6eae1f
YR
2859 DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
2860 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
2861 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
4d295db0 2862
de6eae1f
YR
2863 /* disable emac */
2864 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
4d295db0 2865
de6eae1f
YR
2866 /**
2867 * Step 1:
2868 * Check external link change only for external phys, and apply
2869 * priority selection between them in case the link on both phys
2870 * is up. Note that the instead of the common vars, a temporary
2871 * vars argument is used since each phy may have different link/
2872 * speed/duplex result
2873 */
2874 for (phy_index = EXT_PHY1; phy_index < params->num_phys;
2875 phy_index++) {
2876 struct bnx2x_phy *phy = &params->phy[phy_index];
2877 if (!phy->read_status)
2878 continue;
2879 /* Read link status and params of this ext phy */
2880 cur_link_up = phy->read_status(phy, params,
2881 &phy_vars[phy_index]);
2882 if (cur_link_up) {
2883 DP(NETIF_MSG_LINK, "phy in index %d link is up\n",
2884 phy_index);
2885 } else {
2886 DP(NETIF_MSG_LINK, "phy in index %d link is down\n",
2887 phy_index);
2888 continue;
2889 }
e10bc84d 2890
de6eae1f
YR
2891 if (!ext_phy_link_up) {
2892 ext_phy_link_up = 1;
2893 active_external_phy = phy_index;
a22f0788
YR
2894 } else {
2895 switch (bnx2x_phy_selection(params)) {
2896 case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
2897 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
2898 /**
2899 * In this option, the first PHY makes sure to pass the
2900 * traffic through itself only.
2901 * Its not clear how to reset the link on the second phy
2902 **/
2903 active_external_phy = EXT_PHY1;
2904 break;
2905 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
2906 /**
2907 * In this option, the first PHY makes sure to pass the
2908 * traffic through the second PHY.
2909 **/
2910 active_external_phy = EXT_PHY2;
2911 break;
2912 default:
2913 /**
2914 * Link indication on both PHYs with the following cases
2915 * is invalid:
2916 * - FIRST_PHY means that second phy wasn't initialized,
2917 * hence its link is expected to be down
2918 * - SECOND_PHY means that first phy should not be able
2919 * to link up by itself (using configuration)
2920 * - DEFAULT should be overriden during initialiazation
2921 **/
2922 DP(NETIF_MSG_LINK, "Invalid link indication"
2923 "mpc=0x%x. DISABLING LINK !!!\n",
2924 params->multi_phy_config);
2925 ext_phy_link_up = 0;
2926 break;
2927 }
589abe3a 2928 }
589abe3a 2929 }
de6eae1f
YR
2930 prev_line_speed = vars->line_speed;
2931 /**
2932 * Step 2:
2933 * Read the status of the internal phy. In case of
2934 * DIRECT_SINGLE_MEDIA board, this link is the external link,
2935 * otherwise this is the link between the 577xx and the first
2936 * external phy
4d295db0 2937 */
de6eae1f
YR
2938 if (params->phy[INT_PHY].read_status)
2939 params->phy[INT_PHY].read_status(
2940 &params->phy[INT_PHY],
2941 params, vars);
2942 /**
2943 * The INT_PHY flow control reside in the vars. This include the
2944 * case where the speed or flow control are not set to AUTO.
2945 * Otherwise, the active external phy flow control result is set
2946 * to the vars. The ext_phy_line_speed is needed to check if the
2947 * speed is different between the internal phy and external phy.
2948 * This case may be result of intermediate link speed change.
4d295db0 2949 */
de6eae1f
YR
2950 if (active_external_phy > INT_PHY) {
2951 vars->flow_ctrl = phy_vars[active_external_phy].flow_ctrl;
2952 /**
2953 * Link speed is taken from the XGXS. AN and FC result from
2954 * the external phy.
4d295db0 2955 */
de6eae1f 2956 vars->link_status |= phy_vars[active_external_phy].link_status;
a22f0788
YR
2957
2958 /**
2959 * if active_external_phy is first PHY and link is up - disable
2960 * disable TX on second external PHY
2961 */
2962 if (active_external_phy == EXT_PHY1) {
2963 if (params->phy[EXT_PHY2].phy_specific_func) {
2964 DP(NETIF_MSG_LINK, "Disabling TX on"
2965 " EXT_PHY2\n");
2966 params->phy[EXT_PHY2].phy_specific_func(
2967 &params->phy[EXT_PHY2],
2968 params, DISABLE_TX);
2969 }
2970 }
2971
de6eae1f
YR
2972 ext_phy_line_speed = phy_vars[active_external_phy].line_speed;
2973 vars->duplex = phy_vars[active_external_phy].duplex;
2974 if (params->phy[active_external_phy].supported &
2975 SUPPORTED_FIBRE)
2976 vars->link_status |= LINK_STATUS_SERDES_LINK;
2977 DP(NETIF_MSG_LINK, "Active external phy selected: %x\n",
2978 active_external_phy);
2979 }
a22f0788
YR
2980
2981 for (phy_index = EXT_PHY1; phy_index < params->num_phys;
2982 phy_index++) {
2983 if (params->phy[phy_index].flags &
2984 FLAGS_REARM_LATCH_SIGNAL) {
2985 bnx2x_rearm_latch_signal(bp, port,
2986 phy_index ==
2987 active_external_phy);
2988 break;
2989 }
2990 }
de6eae1f
YR
2991 DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x,"
2992 " ext_phy_line_speed = %d\n", vars->flow_ctrl,
2993 vars->link_status, ext_phy_line_speed);
2994 /**
2995 * Upon link speed change set the NIG into drain mode. Comes to
2996 * deals with possible FIFO glitch due to clk change when speed
2997 * is decreased without link down indicator
2998 */
4d295db0 2999
de6eae1f
YR
3000 if (vars->phy_link_up) {
3001 if (!(SINGLE_MEDIA_DIRECT(params)) && ext_phy_link_up &&
3002 (ext_phy_line_speed != vars->line_speed)) {
3003 DP(NETIF_MSG_LINK, "Internal link speed %d is"
3004 " different than the external"
3005 " link speed %d\n", vars->line_speed,
3006 ext_phy_line_speed);
3007 vars->phy_link_up = 0;
3008 } else if (prev_line_speed != vars->line_speed) {
3009 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
3010 + params->port*4, 0);
3011 msleep(1);
3012 }
3013 }
e10bc84d 3014
de6eae1f
YR
3015 /* anything 10 and over uses the bmac */
3016 link_10g = ((vars->line_speed == SPEED_10000) ||
3017 (vars->line_speed == SPEED_12000) ||
3018 (vars->line_speed == SPEED_12500) ||
3019 (vars->line_speed == SPEED_13000) ||
3020 (vars->line_speed == SPEED_15000) ||
3021 (vars->line_speed == SPEED_16000));
589abe3a 3022
a22f0788 3023 bnx2x_link_int_ack(params, vars, link_10g);
589abe3a 3024
de6eae1f
YR
3025 /**
3026 * In case external phy link is up, and internal link is down
3027 * (not initialized yet probably after link initialization, it
3028 * needs to be initialized.
3029 * Note that after link down-up as result of cable plug, the xgxs
3030 * link would probably become up again without the need
3031 * initialize it
3032 */
3033 if (!(SINGLE_MEDIA_DIRECT(params))) {
3034 DP(NETIF_MSG_LINK, "ext_phy_link_up = %d, int_link_up = %d,"
3035 " init_preceding = %d\n", ext_phy_link_up,
3036 vars->phy_link_up,
3037 params->phy[EXT_PHY1].flags &
3038 FLAGS_INIT_XGXS_FIRST);
3039 if (!(params->phy[EXT_PHY1].flags &
3040 FLAGS_INIT_XGXS_FIRST)
3041 && ext_phy_link_up && !vars->phy_link_up) {
3042 vars->line_speed = ext_phy_line_speed;
3043 if (vars->line_speed < SPEED_1000)
3044 vars->phy_flags |= PHY_SGMII_FLAG;
3045 else
3046 vars->phy_flags &= ~PHY_SGMII_FLAG;
3047 bnx2x_init_internal_phy(&params->phy[INT_PHY],
3048 params,
3049 vars);
4d295db0 3050 }
589abe3a 3051 }
de6eae1f
YR
3052 /**
3053 * Link is up only if both local phy and external phy (in case of
3054 * non-direct board) are up
4d295db0 3055 */
de6eae1f
YR
3056 vars->link_up = (vars->phy_link_up &&
3057 (ext_phy_link_up ||
3058 SINGLE_MEDIA_DIRECT(params)));
3059
3060 if (vars->link_up)
3061 rc = bnx2x_update_link_up(params, vars, link_10g);
4d295db0 3062 else
de6eae1f 3063 rc = bnx2x_update_link_down(params, vars);
589abe3a 3064
4d295db0 3065 return rc;
589abe3a
EG
3066}
3067
589abe3a 3068
de6eae1f
YR
3069/*****************************************************************************/
3070/* External Phy section */
3071/*****************************************************************************/
3072void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
3073{
3074 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
3075 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
3076 msleep(1);
3077 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
3078 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
3079}
589abe3a 3080
de6eae1f
YR
3081static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port,
3082 u32 spirom_ver, u32 ver_addr)
3083{
3084 DP(NETIF_MSG_LINK, "FW version 0x%x:0x%x for port %d\n",
3085 (u16)(spirom_ver>>16), (u16)spirom_ver, port);
4d295db0 3086
de6eae1f
YR
3087 if (ver_addr)
3088 REG_WR(bp, ver_addr, spirom_ver);
589abe3a
EG
3089}
3090
de6eae1f
YR
3091static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp,
3092 struct bnx2x_phy *phy,
3093 u8 port)
6bbca910 3094{
de6eae1f
YR
3095 u16 fw_ver1, fw_ver2;
3096
3097 bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
3098 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
3099 bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
3100 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
3101 bnx2x_save_spirom_version(bp, port, (u32)(fw_ver1<<16 | fw_ver2),
3102 phy->ver_addr);
ea4e040a 3103}
ab6ad5a4 3104
de6eae1f
YR
3105static void bnx2x_ext_phy_set_pause(struct link_params *params,
3106 struct bnx2x_phy *phy,
3107 struct link_vars *vars)
ea4e040a 3108{
ea4e040a 3109 u16 val;
de6eae1f
YR
3110 struct bnx2x *bp = params->bp;
3111 /* read modify write pause advertizing */
3112 bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val);
ea4e040a 3113
de6eae1f 3114 val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
ea4e040a 3115
de6eae1f
YR
3116 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
3117 bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
3118 if ((vars->ieee_fc &
3119 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
3120 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
3121 val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
3122 }
3123 if ((vars->ieee_fc &
3124 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
3125 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
3126 val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
3127 }
3128 DP(NETIF_MSG_LINK, "Ext phy AN advertize 0x%x\n", val);
3129 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val);
3130}
3131
3132static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
3133 struct link_params *params,
3134 struct link_vars *vars)
3135{
3136 struct bnx2x *bp = params->bp;
3137 u16 ld_pause; /* local */
3138 u16 lp_pause; /* link partner */
3139 u16 pause_result;
3140 u8 ret = 0;
3141 /* read twice */
3142
3143 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
3144
3145 if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
3146 vars->flow_ctrl = phy->req_flow_ctrl;
3147 else if (phy->req_line_speed != SPEED_AUTO_NEG)
3148 vars->flow_ctrl = params->req_fc_auto_adv;
3149 else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
3150 ret = 1;
3151 bnx2x_cl45_read(bp, phy,
3152 MDIO_AN_DEVAD,
3153 MDIO_AN_REG_ADV_PAUSE, &ld_pause);
3154 bnx2x_cl45_read(bp, phy,
3155 MDIO_AN_DEVAD,
3156 MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
3157 pause_result = (ld_pause &
3158 MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
3159 pause_result |= (lp_pause &
3160 MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
3161 DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
3162 pause_result);
3163 bnx2x_pause_resolve(vars, pause_result);
3164 }
3165 return ret;
3166}
3167
3168static void bnx2x_ext_phy_10G_an_resolve(struct bnx2x *bp,
3169 struct bnx2x_phy *phy,
3170 struct link_vars *vars)
3171{
3172 u16 val;
3173 bnx2x_cl45_read(bp, phy,
3174 MDIO_AN_DEVAD,
3175 MDIO_AN_REG_STATUS, &val);
3176 bnx2x_cl45_read(bp, phy,
3177 MDIO_AN_DEVAD,
3178 MDIO_AN_REG_STATUS, &val);
3179 if (val & (1<<5))
3180 vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
3181 if ((val & (1<<0)) == 0)
3182 vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED;
3183}
3184
3185/******************************************************************/
3186/* common BCM8073/BCM8727 PHY SECTION */
3187/******************************************************************/
3188static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy,
3189 struct link_params *params,
3190 struct link_vars *vars)
3191{
3192 struct bnx2x *bp = params->bp;
3193 if (phy->req_line_speed == SPEED_10 ||
3194 phy->req_line_speed == SPEED_100) {
3195 vars->flow_ctrl = phy->req_flow_ctrl;
3196 return;
3197 }
3198
3199 if (bnx2x_ext_phy_resolve_fc(phy, params, vars) &&
3200 (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE)) {
3201 u16 pause_result;
3202 u16 ld_pause; /* local */
3203 u16 lp_pause; /* link partner */
3204 bnx2x_cl45_read(bp, phy,
3205 MDIO_AN_DEVAD,
3206 MDIO_AN_REG_CL37_FC_LD, &ld_pause);
3207
3208 bnx2x_cl45_read(bp, phy,
3209 MDIO_AN_DEVAD,
3210 MDIO_AN_REG_CL37_FC_LP, &lp_pause);
3211 pause_result = (ld_pause &
3212 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
3213 pause_result |= (lp_pause &
3214 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
3215
3216 bnx2x_pause_resolve(vars, pause_result);
3217 DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n",
3218 pause_result);
3219 }
3220}
3221
3222static void bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
3223 struct bnx2x_phy *phy,
3224 u8 port)
3225{
3226 /* Boot port from external ROM */
3227 /* EDC grst */
3228 bnx2x_cl45_write(bp, phy,
3229 MDIO_PMA_DEVAD,
3230 MDIO_PMA_REG_GEN_CTRL,
3231 0x0001);
3232
3233 /* ucode reboot and rst */
3234 bnx2x_cl45_write(bp, phy,
3235 MDIO_PMA_DEVAD,
3236 MDIO_PMA_REG_GEN_CTRL,
3237 0x008c);
3238
3239 bnx2x_cl45_write(bp, phy,
3240 MDIO_PMA_DEVAD,
3241 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
3242
3243 /* Reset internal microprocessor */
3244 bnx2x_cl45_write(bp, phy,
3245 MDIO_PMA_DEVAD,
3246 MDIO_PMA_REG_GEN_CTRL,
3247 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
3248
3249 /* Release srst bit */
3250 bnx2x_cl45_write(bp, phy,
3251 MDIO_PMA_DEVAD,
3252 MDIO_PMA_REG_GEN_CTRL,
3253 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
3254
3255 /* wait for 120ms for code download via SPI port */
3256 msleep(120);
3257
3258 /* Clear ser_boot_ctl bit */
3259 bnx2x_cl45_write(bp, phy,
3260 MDIO_PMA_DEVAD,
3261 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
3262 bnx2x_save_bcm_spirom_ver(bp, phy, port);
3263}
3264
3265static void bnx2x_8073_set_xaui_low_power_mode(struct bnx2x *bp,
3266 struct bnx2x_phy *phy)
3267{
3268 u16 val;
3269 bnx2x_cl45_read(bp, phy,
3270 MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, &val);
3271
3272 if (val == 0) {
3273 /* Mustn't set low power mode in 8073 A0 */
3274 return;
3275 }
3276
3277 /* Disable PLL sequencer (use read-modify-write to clear bit 13) */
3278 bnx2x_cl45_read(bp, phy,
62b29a5d 3279 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val);
ea4e040a 3280 val &= ~(1<<13);
e10bc84d 3281 bnx2x_cl45_write(bp, phy,
ea4e040a
YR
3282 MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
3283
3284 /* PLL controls */
62b29a5d
YR
3285 bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805E, 0x1077);
3286 bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805D, 0x0000);
3287 bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805C, 0x030B);
3288 bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805B, 0x1240);
3289 bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805A, 0x2490);
ea4e040a
YR
3290
3291 /* Tx Controls */
62b29a5d
YR
3292 bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A7, 0x0C74);
3293 bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A6, 0x9041);
3294 bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A5, 0x4640);
ea4e040a
YR
3295
3296 /* Rx Controls */
62b29a5d
YR
3297 bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FE, 0x01C4);
3298 bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FD, 0x9249);
3299 bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FC, 0x2015);
ea4e040a
YR
3300
3301 /* Enable PLL sequencer (use read-modify-write to set bit 13) */
62b29a5d 3302 bnx2x_cl45_read(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val);
ea4e040a 3303 val |= (1<<13);
62b29a5d 3304 bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
ea4e040a 3305}
6bbca910 3306
de6eae1f
YR
3307/******************************************************************/
3308/* BCM8073 PHY SECTION */
3309/******************************************************************/
3310static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
3311{
3312 /* This is only required for 8073A1, version 102 only */
3313 u16 val;
3314
3315 /* Read 8073 HW revision*/
3316 bnx2x_cl45_read(bp, phy,
3317 MDIO_PMA_DEVAD,
3318 MDIO_PMA_REG_8073_CHIP_REV, &val);
3319
3320 if (val != 1) {
3321 /* No need to workaround in 8073 A1 */
3322 return 0;
3323 }
3324
3325 bnx2x_cl45_read(bp, phy,
3326 MDIO_PMA_DEVAD,
3327 MDIO_PMA_REG_ROM_VER2, &val);
3328
3329 /* SNR should be applied only for version 0x102 */
3330 if (val != 0x102)
3331 return 0;
3332
3333 return 1;
3334}
3335
3336static u8 bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
3337{
3338 u16 val, cnt, cnt1 ;
3339
3340 bnx2x_cl45_read(bp, phy,
3341 MDIO_PMA_DEVAD,
3342 MDIO_PMA_REG_8073_CHIP_REV, &val);
3343
3344 if (val > 0) {
3345 /* No need to workaround in 8073 A1 */
3346 return 0;
3347 }
3348 /* XAUI workaround in 8073 A0: */
3349
3350 /* After loading the boot ROM and restarting Autoneg,
3351 poll Dev1, Reg $C820: */
3352
3353 for (cnt = 0; cnt < 1000; cnt++) {
3354 bnx2x_cl45_read(bp, phy,
3355 MDIO_PMA_DEVAD,
3356 MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
3357 &val);
3358 /* If bit [14] = 0 or bit [13] = 0, continue on with
3359 system initialization (XAUI work-around not required,
3360 as these bits indicate 2.5G or 1G link up). */
3361 if (!(val & (1<<14)) || !(val & (1<<13))) {
3362 DP(NETIF_MSG_LINK, "XAUI work-around not required\n");
3363 return 0;
3364 } else if (!(val & (1<<15))) {
3365 DP(NETIF_MSG_LINK, "clc bit 15 went off\n");
3366 /* If bit 15 is 0, then poll Dev1, Reg $C841 until
3367 it's MSB (bit 15) goes to 1 (indicating that the
3368 XAUI workaround has completed),
3369 then continue on with system initialization.*/
3370 for (cnt1 = 0; cnt1 < 1000; cnt1++) {
3371 bnx2x_cl45_read(bp, phy,
3372 MDIO_PMA_DEVAD,
3373 MDIO_PMA_REG_8073_XAUI_WA, &val);
3374 if (val & (1<<15)) {
3375 DP(NETIF_MSG_LINK,
3376 "XAUI workaround has completed\n");
3377 return 0;
3378 }
3379 msleep(3);
3380 }
3381 break;
3382 }
3383 msleep(3);
3384 }
3385 DP(NETIF_MSG_LINK, "Warning: XAUI work-around timeout !!!\n");
3386 return -EINVAL;
3387}
3388
3389static void bnx2x_807x_force_10G(struct bnx2x *bp, struct bnx2x_phy *phy)
3390{
3391 /* Force KR or KX */
3392 bnx2x_cl45_write(bp, phy,
3393 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040);
3394 bnx2x_cl45_write(bp, phy,
3395 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0x000b);
3396 bnx2x_cl45_write(bp, phy,
3397 MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0000);
3398 bnx2x_cl45_write(bp, phy,
3399 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
3400}
3401
6bbca910 3402static void bnx2x_8073_set_pause_cl37(struct link_params *params,
e10bc84d
YR
3403 struct bnx2x_phy *phy,
3404 struct link_vars *vars)
ea4e040a 3405{
6bbca910 3406 u16 cl37_val;
e10bc84d
YR
3407 struct bnx2x *bp = params->bp;
3408 bnx2x_cl45_read(bp, phy,
62b29a5d 3409 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &cl37_val);
6bbca910
YR
3410
3411 cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
3412 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
e10bc84d 3413 bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
6bbca910
YR
3414 if ((vars->ieee_fc &
3415 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
3416 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
3417 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
3418 }
3419 if ((vars->ieee_fc &
3420 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
3421 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
3422 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
3423 }
3424 if ((vars->ieee_fc &
3425 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
3426 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
3427 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
3428 }
3429 DP(NETIF_MSG_LINK,
3430 "Ext phy AN advertize cl37 0x%x\n", cl37_val);
3431
e10bc84d 3432 bnx2x_cl45_write(bp, phy,
62b29a5d 3433 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, cl37_val);
6bbca910 3434 msleep(500);
ea4e040a
YR
3435}
3436
de6eae1f
YR
3437static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
3438 struct link_params *params,
3439 struct link_vars *vars)
ea4e040a 3440{
e10bc84d 3441 struct bnx2x *bp = params->bp;
de6eae1f
YR
3442 u16 val = 0, tmp1;
3443 u8 gpio_port;
3444 DP(NETIF_MSG_LINK, "Init 8073\n");
e10bc84d 3445
de6eae1f
YR
3446 gpio_port = params->port;
3447 /* Restore normal power mode*/
3448 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
3449 MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
e10bc84d 3450
de6eae1f
YR
3451 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
3452 MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
ea4e040a 3453
de6eae1f
YR
3454 /* enable LASI */
3455 bnx2x_cl45_write(bp, phy,
3456 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL, (1<<2));
3457 bnx2x_cl45_write(bp, phy,
3458 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x0004);
c2c8b03e 3459
de6eae1f 3460 bnx2x_8073_set_pause_cl37(params, phy, vars);
57963ed9 3461
de6eae1f 3462 bnx2x_8073_set_xaui_low_power_mode(bp, phy);
e10bc84d 3463
e10bc84d 3464 bnx2x_cl45_read(bp, phy,
de6eae1f 3465 MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
2f904460 3466
de6eae1f
YR
3467 bnx2x_cl45_read(bp, phy,
3468 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1);
2f904460 3469
de6eae1f 3470 DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1);
a1e4be39 3471
de6eae1f
YR
3472 /* Enable CL37 BAM */
3473 bnx2x_cl45_read(bp, phy,
3474 MDIO_AN_DEVAD,
3475 MDIO_AN_REG_8073_BAM, &val);
e10bc84d 3476 bnx2x_cl45_write(bp, phy,
a1e4be39 3477 MDIO_AN_DEVAD,
de6eae1f 3478 MDIO_AN_REG_8073_BAM, val | 1);
57963ed9 3479
de6eae1f
YR
3480 if (params->loopback_mode == LOOPBACK_EXT) {
3481 bnx2x_807x_force_10G(bp, phy);
3482 DP(NETIF_MSG_LINK, "Forced speed 10G on 807X\n");
3483 return 0;
3484 } else {
3485 bnx2x_cl45_write(bp, phy,
3486 MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0002);
3487 }
3488 if (phy->req_line_speed != SPEED_AUTO_NEG) {
3489 if (phy->req_line_speed == SPEED_10000) {
3490 val = (1<<7);
3491 } else if (phy->req_line_speed == SPEED_2500) {
3492 val = (1<<5);
3493 /* Note that 2.5G works only
3494 when used with 1G advertisment */
3495 } else
3496 val = (1<<5);
3497 } else {
3498 val = 0;
3499 if (phy->speed_cap_mask &
3500 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
3501 val |= (1<<7);
57963ed9 3502
de6eae1f
YR
3503 /* Note that 2.5G works only when
3504 used with 1G advertisment */
3505 if (phy->speed_cap_mask &
3506 (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
3507 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
3508 val |= (1<<5);
3509 DP(NETIF_MSG_LINK, "807x autoneg val = 0x%x\n", val);
3510 }
57963ed9 3511
de6eae1f
YR
3512 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV, val);
3513 bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, &tmp1);
57963ed9 3514
de6eae1f
YR
3515 if (((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
3516 (phy->req_line_speed == SPEED_AUTO_NEG)) ||
3517 (phy->req_line_speed == SPEED_2500)) {
3518 u16 phy_ver;
3519 /* Allow 2.5G for A1 and above */
3520 bnx2x_cl45_read(bp, phy,
3521 MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV,
3522 &phy_ver);
3523 DP(NETIF_MSG_LINK, "Add 2.5G\n");
3524 if (phy_ver > 0)
3525 tmp1 |= 1;
3526 else
3527 tmp1 &= 0xfffe;
3528 } else {
3529 DP(NETIF_MSG_LINK, "Disable 2.5G\n");
3530 tmp1 &= 0xfffe;
3531 }
57963ed9 3532
de6eae1f
YR
3533 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, tmp1);
3534 /* Add support for CL37 (passive mode) II */
57963ed9 3535
de6eae1f
YR
3536 bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &tmp1);
3537 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD,
3538 (tmp1 | ((phy->req_duplex == DUPLEX_FULL) ?
3539 0x20 : 0x40)));
57963ed9 3540
de6eae1f
YR
3541 /* Add support for CL37 (passive mode) III */
3542 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
57963ed9 3543
de6eae1f
YR
3544 /* The SNR will improve about 2db by changing
3545 BW and FEE main tap. Rest commands are executed
3546 after link is up*/
3547 if (bnx2x_8073_is_snr_needed(bp, phy))
3548 bnx2x_cl45_write(bp, phy,
3549 MDIO_PMA_DEVAD, MDIO_PMA_REG_EDC_FFE_MAIN,
3550 0xFB0C);
57963ed9 3551
de6eae1f
YR
3552 /* Enable FEC (Forware Error Correction) Request in the AN */
3553 bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, &tmp1);
3554 tmp1 |= (1<<15);
3555 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, tmp1);
57963ed9 3556
de6eae1f 3557 bnx2x_ext_phy_set_pause(params, phy, vars);
57963ed9 3558
de6eae1f
YR
3559 /* Restart autoneg */
3560 msleep(500);
3561 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
3562 DP(NETIF_MSG_LINK, "807x Autoneg Restart: Advertise 1G=%x, 10G=%x\n",
3563 ((val & (1<<5)) > 0), ((val & (1<<7)) > 0));
3564 return 0;
b7737c9b 3565}
ea4e040a 3566
de6eae1f 3567static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
b7737c9b
YR
3568 struct link_params *params,
3569 struct link_vars *vars)
3570{
3571 struct bnx2x *bp = params->bp;
de6eae1f
YR
3572 u8 link_up = 0;
3573 u16 val1, val2;
3574 u16 link_status = 0;
3575 u16 an1000_status = 0;
a35da8db 3576
de6eae1f
YR
3577 bnx2x_cl45_read(bp, phy,
3578 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
b7737c9b 3579
de6eae1f 3580 DP(NETIF_MSG_LINK, "8703 LASI status 0x%x\n", val1);
ea4e040a 3581
de6eae1f
YR
3582 /* clear the interrupt LASI status register */
3583 bnx2x_cl45_read(bp, phy,
3584 MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2);
3585 bnx2x_cl45_read(bp, phy,
3586 MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val1);
3587 DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n", val2, val1);
3588 /* Clear MSG-OUT */
3589 bnx2x_cl45_read(bp, phy,
3590 MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
3591
3592 /* Check the LASI */
3593 bnx2x_cl45_read(bp, phy,
3594 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2);
3595
3596 DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
3597
3598 /* Check the link status */
3599 bnx2x_cl45_read(bp, phy,
3600 MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2);
3601 DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
3602
3603 bnx2x_cl45_read(bp, phy,
3604 MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
3605 bnx2x_cl45_read(bp, phy,
3606 MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
3607 link_up = ((val1 & 4) == 4);
3608 DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
3609
3610 if (link_up &&
3611 ((phy->req_line_speed != SPEED_10000))) {
3612 if (bnx2x_8073_xaui_wa(bp, phy) != 0)
3613 return 0;
62b29a5d 3614 }
de6eae1f
YR
3615 bnx2x_cl45_read(bp, phy,
3616 MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status);
3617 bnx2x_cl45_read(bp, phy,
3618 MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status);
62b29a5d 3619
de6eae1f
YR
3620 /* Check the link status on 1.1.2 */
3621 bnx2x_cl45_read(bp, phy,
3622 MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
3623 bnx2x_cl45_read(bp, phy,
3624 MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
3625 DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x,"
3626 "an_link_status=0x%x\n", val2, val1, an1000_status);
62b29a5d 3627
de6eae1f
YR
3628 link_up = (((val1 & 4) == 4) || (an1000_status & (1<<1)));
3629 if (link_up && bnx2x_8073_is_snr_needed(bp, phy)) {
3630 /* The SNR will improve about 2dbby
3631 changing the BW and FEE main tap.*/
3632 /* The 1st write to change FFE main
3633 tap is set before restart AN */
3634 /* Change PLL Bandwidth in EDC
3635 register */
62b29a5d 3636 bnx2x_cl45_write(bp, phy,
de6eae1f
YR
3637 MDIO_PMA_DEVAD, MDIO_PMA_REG_PLL_BANDWIDTH,
3638 0x26BC);
62b29a5d 3639
de6eae1f 3640 /* Change CDR Bandwidth in EDC register */
62b29a5d 3641 bnx2x_cl45_write(bp, phy,
de6eae1f
YR
3642 MDIO_PMA_DEVAD, MDIO_PMA_REG_CDR_BANDWIDTH,
3643 0x0333);
3644 }
3645 bnx2x_cl45_read(bp, phy,
3646 MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
3647 &link_status);
62b29a5d 3648
de6eae1f
YR
3649 /* Bits 0..2 --> speed detected, bits 13..15--> link is down */
3650 if ((link_status & (1<<2)) && (!(link_status & (1<<15)))) {
3651 link_up = 1;
3652 vars->line_speed = SPEED_10000;
3653 DP(NETIF_MSG_LINK, "port %x: External link up in 10G\n",
3654 params->port);
3655 } else if ((link_status & (1<<1)) && (!(link_status & (1<<14)))) {
3656 link_up = 1;
3657 vars->line_speed = SPEED_2500;
3658 DP(NETIF_MSG_LINK, "port %x: External link up in 2.5G\n",
3659 params->port);
3660 } else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
3661 link_up = 1;
3662 vars->line_speed = SPEED_1000;
3663 DP(NETIF_MSG_LINK, "port %x: External link up in 1G\n",
3664 params->port);
3665 } else {
3666 link_up = 0;
3667 DP(NETIF_MSG_LINK, "port %x: External link is down\n",
3668 params->port);
62b29a5d 3669 }
de6eae1f
YR
3670
3671 if (link_up) {
3672 bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
3673 bnx2x_8073_resolve_fc(phy, params, vars);
3674 }
3675 return link_up;
b7737c9b
YR
3676}
3677
de6eae1f
YR
3678static void bnx2x_8073_link_reset(struct bnx2x_phy *phy,
3679 struct link_params *params)
3680{
3681 struct bnx2x *bp = params->bp;
3682 u8 gpio_port;
3683 gpio_port = params->port;
3684 DP(NETIF_MSG_LINK, "Setting 8073 port %d into low power mode\n",
3685 gpio_port);
3686 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
3687 MISC_REGISTERS_GPIO_OUTPUT_LOW,
3688 gpio_port);
3689}
3690
3691/******************************************************************/
3692/* BCM8705 PHY SECTION */
3693/******************************************************************/
3694static u8 bnx2x_8705_config_init(struct bnx2x_phy *phy,
b7737c9b
YR
3695 struct link_params *params,
3696 struct link_vars *vars)
3697{
3698 struct bnx2x *bp = params->bp;
de6eae1f 3699 DP(NETIF_MSG_LINK, "init 8705\n");
b7737c9b
YR
3700 /* Restore normal power mode*/
3701 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
3702 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
de6eae1f
YR
3703 /* HW reset */
3704 bnx2x_ext_phy_hw_reset(bp, params->port);
3705 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
b7737c9b
YR
3706 bnx2x_wait_reset_complete(bp, phy);
3707
de6eae1f
YR
3708 bnx2x_cl45_write(bp, phy,
3709 MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL, 0x8288);
3710 bnx2x_cl45_write(bp, phy,
3711 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, 0x7fbf);
3712 bnx2x_cl45_write(bp, phy,
3713 MDIO_PMA_DEVAD, MDIO_PMA_REG_CMU_PLL_BYPASS, 0x0100);
3714 bnx2x_cl45_write(bp, phy,
3715 MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_CNTL, 0x1);
3716 /* BCM8705 doesn't have microcode, hence the 0 */
3717 bnx2x_save_spirom_version(bp, params->port, params->shmem_base, 0);
3718 return 0;
3719}
4d295db0 3720
de6eae1f
YR
3721static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy,
3722 struct link_params *params,
3723 struct link_vars *vars)
3724{
3725 u8 link_up = 0;
3726 u16 val1, rx_sd;
3727 struct bnx2x *bp = params->bp;
3728 DP(NETIF_MSG_LINK, "read status 8705\n");
3729 bnx2x_cl45_read(bp, phy,
3730 MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1);
3731 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
62b29a5d 3732
de6eae1f
YR
3733 bnx2x_cl45_read(bp, phy,
3734 MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1);
3735 DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
62b29a5d 3736
de6eae1f
YR
3737 bnx2x_cl45_read(bp, phy,
3738 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd);
c2c8b03e 3739
de6eae1f
YR
3740 bnx2x_cl45_read(bp, phy,
3741 MDIO_PMA_DEVAD, 0xc809, &val1);
3742 bnx2x_cl45_read(bp, phy,
3743 MDIO_PMA_DEVAD, 0xc809, &val1);
c2c8b03e 3744
de6eae1f
YR
3745 DP(NETIF_MSG_LINK, "8705 1.c809 val=0x%x\n", val1);
3746 link_up = ((rx_sd & 0x1) && (val1 & (1<<9)) && ((val1 & (1<<8)) == 0));
3747 if (link_up) {
3748 vars->line_speed = SPEED_10000;
3749 bnx2x_ext_phy_resolve_fc(phy, params, vars);
62b29a5d 3750 }
de6eae1f
YR
3751 return link_up;
3752}
d90d96ba 3753
de6eae1f
YR
3754/******************************************************************/
3755/* SFP+ module Section */
3756/******************************************************************/
3757static void bnx2x_sfp_set_transmitter(struct bnx2x *bp,
3758 struct bnx2x_phy *phy,
3759 u8 port,
3760 u8 tx_en)
3761{
3762 u16 val;
d90d96ba 3763
de6eae1f
YR
3764 DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x\n",
3765 tx_en, port);
3766 /* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/
3767 bnx2x_cl45_read(bp, phy,
3768 MDIO_PMA_DEVAD,
3769 MDIO_PMA_REG_PHY_IDENTIFIER,
3770 &val);
d90d96ba 3771
de6eae1f
YR
3772 if (tx_en)
3773 val &= ~(1<<15);
3774 else
3775 val |= (1<<15);
b7737c9b 3776
de6eae1f
YR
3777 bnx2x_cl45_write(bp, phy,
3778 MDIO_PMA_DEVAD,
3779 MDIO_PMA_REG_PHY_IDENTIFIER,
3780 val);
b7737c9b
YR
3781}
3782
de6eae1f
YR
3783static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
3784 struct link_params *params,
3785 u16 addr, u8 byte_cnt, u8 *o_buf)
b7737c9b
YR
3786{
3787 struct bnx2x *bp = params->bp;
de6eae1f
YR
3788 u16 val = 0;
3789 u16 i;
3790 if (byte_cnt > 16) {
3791 DP(NETIF_MSG_LINK, "Reading from eeprom is"
3792 " is limited to 0xf\n");
3793 return -EINVAL;
3794 }
3795 /* Set the read command byte count */
62b29a5d 3796 bnx2x_cl45_write(bp, phy,
de6eae1f
YR
3797 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
3798 (byte_cnt | 0xa000));
ea4e040a 3799
de6eae1f
YR
3800 /* Set the read command address */
3801 bnx2x_cl45_write(bp, phy,
3802 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
3803 addr);
ea4e040a 3804
de6eae1f 3805 /* Activate read command */
62b29a5d 3806 bnx2x_cl45_write(bp, phy,
de6eae1f
YR
3807 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
3808 0x2c0f);
ea4e040a 3809
de6eae1f
YR
3810 /* Wait up to 500us for command complete status */
3811 for (i = 0; i < 100; i++) {
3812 bnx2x_cl45_read(bp, phy,
3813 MDIO_PMA_DEVAD,
3814 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
3815 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
3816 MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
3817 break;
3818 udelay(5);
62b29a5d 3819 }
62b29a5d 3820
de6eae1f
YR
3821 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
3822 MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
3823 DP(NETIF_MSG_LINK,
3824 "Got bad status 0x%x when reading from SFP+ EEPROM\n",
3825 (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK));
3826 return -EINVAL;
62b29a5d 3827 }
e10bc84d 3828
de6eae1f
YR
3829 /* Read the buffer */
3830 for (i = 0; i < byte_cnt; i++) {
62b29a5d 3831 bnx2x_cl45_read(bp, phy,
de6eae1f
YR
3832 MDIO_PMA_DEVAD,
3833 MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF + i, &val);
3834 o_buf[i] = (u8)(val & MDIO_PMA_REG_8726_TWO_WIRE_DATA_MASK);
62b29a5d 3835 }
6bbca910 3836
de6eae1f
YR
3837 for (i = 0; i < 100; i++) {
3838 bnx2x_cl45_read(bp, phy,
3839 MDIO_PMA_DEVAD,
3840 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
3841 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
3842 MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
3843 return 0;;
3844 msleep(1);
3845 }
3846 return -EINVAL;
b7737c9b 3847}
4d295db0 3848
de6eae1f
YR
3849static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
3850 struct link_params *params,
3851 u16 addr, u8 byte_cnt, u8 *o_buf)
b7737c9b 3852{
b7737c9b 3853 struct bnx2x *bp = params->bp;
de6eae1f 3854 u16 val, i;
ea4e040a 3855
de6eae1f
YR
3856 if (byte_cnt > 16) {
3857 DP(NETIF_MSG_LINK, "Reading from eeprom is"
3858 " is limited to 0xf\n");
3859 return -EINVAL;
3860 }
4d295db0 3861
de6eae1f
YR
3862 /* Need to read from 1.8000 to clear it */
3863 bnx2x_cl45_read(bp, phy,
3864 MDIO_PMA_DEVAD,
3865 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
3866 &val);
4d295db0 3867
de6eae1f 3868 /* Set the read command byte count */
62b29a5d 3869 bnx2x_cl45_write(bp, phy,
de6eae1f
YR
3870 MDIO_PMA_DEVAD,
3871 MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
3872 ((byte_cnt < 2) ? 2 : byte_cnt));
ea4e040a 3873
de6eae1f 3874 /* Set the read command address */
62b29a5d 3875 bnx2x_cl45_write(bp, phy,
de6eae1f
YR
3876 MDIO_PMA_DEVAD,
3877 MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
3878 addr);
3879 /* Set the destination address */
62b29a5d 3880 bnx2x_cl45_write(bp, phy,
de6eae1f
YR
3881 MDIO_PMA_DEVAD,
3882 0x8004,
3883 MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF);
62b29a5d 3884
de6eae1f 3885 /* Activate read command */
62b29a5d 3886 bnx2x_cl45_write(bp, phy,
de6eae1f
YR
3887 MDIO_PMA_DEVAD,
3888 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
3889 0x8002);
3890 /* Wait appropriate time for two-wire command to finish before
3891 polling the status register */
3892 msleep(1);
4d295db0 3893
de6eae1f
YR
3894 /* Wait up to 500us for command complete status */
3895 for (i = 0; i < 100; i++) {
62b29a5d 3896 bnx2x_cl45_read(bp, phy,
de6eae1f
YR
3897 MDIO_PMA_DEVAD,
3898 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
3899 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
3900 MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
3901 break;
3902 udelay(5);
62b29a5d 3903 }
4d295db0 3904
de6eae1f
YR
3905 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
3906 MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
3907 DP(NETIF_MSG_LINK,
3908 "Got bad status 0x%x when reading from SFP+ EEPROM\n",
3909 (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK));
3910 return -EINVAL;
3911 }
62b29a5d 3912
de6eae1f
YR
3913 /* Read the buffer */
3914 for (i = 0; i < byte_cnt; i++) {
3915 bnx2x_cl45_read(bp, phy,
3916 MDIO_PMA_DEVAD,
3917 MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF + i, &val);
3918 o_buf[i] = (u8)(val & MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK);
3919 }
4d295db0 3920
de6eae1f
YR
3921 for (i = 0; i < 100; i++) {
3922 bnx2x_cl45_read(bp, phy,
3923 MDIO_PMA_DEVAD,
3924 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
3925 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
3926 MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
3927 return 0;;
3928 msleep(1);
62b29a5d
YR
3929 }
3930
de6eae1f 3931 return -EINVAL;
b7737c9b
YR
3932}
3933
de6eae1f
YR
3934u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
3935 struct link_params *params, u16 addr,
3936 u8 byte_cnt, u8 *o_buf)
b7737c9b 3937{
de6eae1f
YR
3938 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
3939 return bnx2x_8726_read_sfp_module_eeprom(phy, params, addr,
3940 byte_cnt, o_buf);
3941 else if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
3942 return bnx2x_8727_read_sfp_module_eeprom(phy, params, addr,
3943 byte_cnt, o_buf);
3944 return -EINVAL;
b7737c9b
YR
3945}
3946
de6eae1f
YR
3947static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
3948 struct link_params *params,
3949 u16 *edc_mode)
b7737c9b
YR
3950{
3951 struct bnx2x *bp = params->bp;
de6eae1f
YR
3952 u8 val, check_limiting_mode = 0;
3953 *edc_mode = EDC_MODE_LIMITING;
62b29a5d 3954
de6eae1f
YR
3955 /* First check for copper cable */
3956 if (bnx2x_read_sfp_module_eeprom(phy,
3957 params,
3958 SFP_EEPROM_CON_TYPE_ADDR,
3959 1,
3960 &val) != 0) {
3961 DP(NETIF_MSG_LINK, "Failed to read from SFP+ module EEPROM\n");
3962 return -EINVAL;
3963 }
a1e4be39 3964
de6eae1f
YR
3965 switch (val) {
3966 case SFP_EEPROM_CON_TYPE_VAL_COPPER:
3967 {
3968 u8 copper_module_type;
62b29a5d 3969
de6eae1f
YR
3970 /* Check if its active cable( includes SFP+ module)
3971 of passive cable*/
3972 if (bnx2x_read_sfp_module_eeprom(phy,
3973 params,
3974 SFP_EEPROM_FC_TX_TECH_ADDR,
3975 1,
3976 &copper_module_type) !=
3977 0) {
3978 DP(NETIF_MSG_LINK,
3979 "Failed to read copper-cable-type"
3980 " from SFP+ EEPROM\n");
3981 return -EINVAL;
3982 }
4f60dab1 3983
de6eae1f
YR
3984 if (copper_module_type &
3985 SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
3986 DP(NETIF_MSG_LINK, "Active Copper cable detected\n");
3987 check_limiting_mode = 1;
3988 } else if (copper_module_type &
3989 SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
3990 DP(NETIF_MSG_LINK, "Passive Copper"
3991 " cable detected\n");
3992 *edc_mode =
3993 EDC_MODE_PASSIVE_DAC;
3994 } else {
3995 DP(NETIF_MSG_LINK, "Unknown copper-cable-"
3996 "type 0x%x !!!\n", copper_module_type);
3997 return -EINVAL;
3998 }
3999 break;
62b29a5d 4000 }
de6eae1f
YR
4001 case SFP_EEPROM_CON_TYPE_VAL_LC:
4002 DP(NETIF_MSG_LINK, "Optic module detected\n");
4003 check_limiting_mode = 1;
4004 break;
4005 default:
4006 DP(NETIF_MSG_LINK, "Unable to determine module type 0x%x !!!\n",
4007 val);
4008 return -EINVAL;
62b29a5d 4009 }
2f904460 4010
de6eae1f
YR
4011 if (check_limiting_mode) {
4012 u8 options[SFP_EEPROM_OPTIONS_SIZE];
4013 if (bnx2x_read_sfp_module_eeprom(phy,
4014 params,
4015 SFP_EEPROM_OPTIONS_ADDR,
4016 SFP_EEPROM_OPTIONS_SIZE,
4017 options) != 0) {
4018 DP(NETIF_MSG_LINK, "Failed to read Option"
4019 " field from module EEPROM\n");
4020 return -EINVAL;
4021 }
4022 if ((options[0] & SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK))
4023 *edc_mode = EDC_MODE_LINEAR;
4024 else
4025 *edc_mode = EDC_MODE_LIMITING;
62b29a5d 4026 }
de6eae1f 4027 DP(NETIF_MSG_LINK, "EDC mode is set to 0x%x\n", *edc_mode);
62b29a5d 4028 return 0;
b7737c9b 4029}
de6eae1f
YR
4030/* This function read the relevant field from the module ( SFP+ ),
4031 and verify it is compliant with this board */
4032static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
4033 struct link_params *params)
b7737c9b
YR
4034{
4035 struct bnx2x *bp = params->bp;
a22f0788
YR
4036 u32 val, cmd;
4037 u32 fw_resp, fw_cmd_param;
de6eae1f
YR
4038 char vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE+1];
4039 char vendor_pn[SFP_EEPROM_PART_NO_SIZE+1];
a22f0788 4040 phy->flags &= ~FLAGS_SFP_NOT_APPROVED;
de6eae1f
YR
4041 val = REG_RD(bp, params->shmem_base +
4042 offsetof(struct shmem_region, dev_info.
4043 port_feature_config[params->port].config));
4044 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
4045 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT) {
4046 DP(NETIF_MSG_LINK, "NOT enforcing module verification\n");
4047 return 0;
4048 }
ea4e040a 4049
a22f0788
YR
4050 if (params->feature_config_flags &
4051 FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY) {
4052 /* Use specific phy request */
4053 cmd = DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL;
4054 } else if (params->feature_config_flags &
4055 FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY) {
4056 /* Use first phy request only in case of non-dual media*/
4057 if (DUAL_MEDIA(params)) {
4058 DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
4059 "verification\n");
4060 return -EINVAL;
4061 }
4062 cmd = DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL;
4063 } else {
4064 /* No support in OPT MDL detection */
de6eae1f 4065 DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
a22f0788 4066 "verification\n");
de6eae1f
YR
4067 return -EINVAL;
4068 }
a22f0788
YR
4069 fw_cmd_param = FW_PARAM_SET(phy->addr, phy->type, phy->mdio_ctrl);
4070 fw_resp = bnx2x_fw_command(bp, cmd, fw_cmd_param);
de6eae1f
YR
4071 if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) {
4072 DP(NETIF_MSG_LINK, "Approved module\n");
4073 return 0;
4074 }
b7737c9b 4075
de6eae1f
YR
4076 /* format the warning message */
4077 if (bnx2x_read_sfp_module_eeprom(phy,
4078 params,
4079 SFP_EEPROM_VENDOR_NAME_ADDR,
4080 SFP_EEPROM_VENDOR_NAME_SIZE,
4081 (u8 *)vendor_name))
4082 vendor_name[0] = '\0';
4083 else
4084 vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE] = '\0';
4085 if (bnx2x_read_sfp_module_eeprom(phy,
4086 params,
4087 SFP_EEPROM_PART_NO_ADDR,
4088 SFP_EEPROM_PART_NO_SIZE,
4089 (u8 *)vendor_pn))
4090 vendor_pn[0] = '\0';
4091 else
4092 vendor_pn[SFP_EEPROM_PART_NO_SIZE] = '\0';
4093
4094 netdev_info(bp->dev, "Warning: Unqualified SFP+ module detected,"
4095 " Port %d from %s part number %s\n",
4096 params->port, vendor_name, vendor_pn);
a22f0788 4097 phy->flags |= FLAGS_SFP_NOT_APPROVED;
de6eae1f 4098 return -EINVAL;
b7737c9b 4099}
7aa0711f 4100
de6eae1f
YR
4101static u8 bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
4102 struct link_params *params)
7aa0711f 4103
4d295db0 4104{
de6eae1f 4105 u8 val;
4d295db0 4106 struct bnx2x *bp = params->bp;
de6eae1f
YR
4107 u16 timeout;
4108 /* Initialization time after hot-plug may take up to 300ms for some
4109 phys type ( e.g. JDSU ) */
4110 for (timeout = 0; timeout < 60; timeout++) {
4111 if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
4112 == 0) {
4113 DP(NETIF_MSG_LINK, "SFP+ module initialization "
4114 "took %d ms\n", timeout * 5);
4115 return 0;
4116 }
4117 msleep(5);
4118 }
4119 return -EINVAL;
4120}
4d295db0 4121
de6eae1f
YR
4122static void bnx2x_8727_power_module(struct bnx2x *bp,
4123 struct bnx2x_phy *phy,
4124 u8 is_power_up) {
4125 /* Make sure GPIOs are not using for LED mode */
4126 u16 val;
4127 /*
4128 * In the GPIO register, bit 4 is use to detemine if the GPIOs are
4129 * operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
4130 * output
4131 * Bits 0-1 determine the gpios value for OUTPUT in case bit 4 val is 0
4132 * Bits 8-9 determine the gpios value for INPUT in case bit 4 val is 1
4133 * where the 1st bit is the over-current(only input), and 2nd bit is
4134 * for power( only output )
4135 */
4d295db0 4136
de6eae1f
YR
4137 /*
4138 * In case of NOC feature is disabled and power is up, set GPIO control
4139 * as input to enable listening of over-current indication
4140 */
4141 if (phy->flags & FLAGS_NOC)
4142 return;
4143 if (!(phy->flags &
4144 FLAGS_NOC) && is_power_up)
4145 val = (1<<4);
4146 else
4147 /*
4148 * Set GPIO control to OUTPUT, and set the power bit
4149 * to according to the is_power_up
4150 */
4151 val = ((!(is_power_up)) << 1);
4d295db0 4152
de6eae1f
YR
4153 bnx2x_cl45_write(bp, phy,
4154 MDIO_PMA_DEVAD,
4155 MDIO_PMA_REG_8727_GPIO_CTRL,
4156 val);
4157}
4d295db0 4158
de6eae1f
YR
4159static u8 bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
4160 struct bnx2x_phy *phy,
4161 u16 edc_mode)
4162{
4163 u16 cur_limiting_mode;
4d295db0 4164
de6eae1f
YR
4165 bnx2x_cl45_read(bp, phy,
4166 MDIO_PMA_DEVAD,
4167 MDIO_PMA_REG_ROM_VER2,
4168 &cur_limiting_mode);
4169 DP(NETIF_MSG_LINK, "Current Limiting mode is 0x%x\n",
4170 cur_limiting_mode);
4171
4172 if (edc_mode == EDC_MODE_LIMITING) {
4173 DP(NETIF_MSG_LINK,
4174 "Setting LIMITING MODE\n");
e10bc84d 4175 bnx2x_cl45_write(bp, phy,
62b29a5d 4176 MDIO_PMA_DEVAD,
de6eae1f
YR
4177 MDIO_PMA_REG_ROM_VER2,
4178 EDC_MODE_LIMITING);
4179 } else { /* LRM mode ( default )*/
4d295db0 4180
de6eae1f 4181 DP(NETIF_MSG_LINK, "Setting LRM MODE\n");
4d295db0 4182
de6eae1f
YR
4183 /* Changing to LRM mode takes quite few seconds.
4184 So do it only if current mode is limiting
4185 ( default is LRM )*/
4186 if (cur_limiting_mode != EDC_MODE_LIMITING)
4187 return 0;
4d295db0 4188
de6eae1f
YR
4189 bnx2x_cl45_write(bp, phy,
4190 MDIO_PMA_DEVAD,
4191 MDIO_PMA_REG_LRM_MODE,
4192 0);
4193 bnx2x_cl45_write(bp, phy,
4194 MDIO_PMA_DEVAD,
4195 MDIO_PMA_REG_ROM_VER2,
4196 0x128);
4197 bnx2x_cl45_write(bp, phy,
4198 MDIO_PMA_DEVAD,
4199 MDIO_PMA_REG_MISC_CTRL0,
4200 0x4008);
4201 bnx2x_cl45_write(bp, phy,
4202 MDIO_PMA_DEVAD,
4203 MDIO_PMA_REG_LRM_MODE,
4204 0xaaaa);
4d295db0 4205 }
de6eae1f 4206 return 0;
4d295db0
EG
4207}
4208
de6eae1f
YR
4209static u8 bnx2x_8727_set_limiting_mode(struct bnx2x *bp,
4210 struct bnx2x_phy *phy,
4211 u16 edc_mode)
ea4e040a 4212{
de6eae1f
YR
4213 u16 phy_identifier;
4214 u16 rom_ver2_val;
62b29a5d 4215 bnx2x_cl45_read(bp, phy,
de6eae1f
YR
4216 MDIO_PMA_DEVAD,
4217 MDIO_PMA_REG_PHY_IDENTIFIER,
4218 &phy_identifier);
ea4e040a 4219
de6eae1f
YR
4220 bnx2x_cl45_write(bp, phy,
4221 MDIO_PMA_DEVAD,
4222 MDIO_PMA_REG_PHY_IDENTIFIER,
4223 (phy_identifier & ~(1<<9)));
ea4e040a 4224
62b29a5d 4225 bnx2x_cl45_read(bp, phy,
de6eae1f
YR
4226 MDIO_PMA_DEVAD,
4227 MDIO_PMA_REG_ROM_VER2,
4228 &rom_ver2_val);
4229 /* Keep the MSB 8-bits, and set the LSB 8-bits with the edc_mode */
4230 bnx2x_cl45_write(bp, phy,
4231 MDIO_PMA_DEVAD,
4232 MDIO_PMA_REG_ROM_VER2,
4233 (rom_ver2_val & 0xff00) | (edc_mode & 0x00ff));
4d295db0 4234
de6eae1f
YR
4235 bnx2x_cl45_write(bp, phy,
4236 MDIO_PMA_DEVAD,
4237 MDIO_PMA_REG_PHY_IDENTIFIER,
4238 (phy_identifier | (1<<9)));
4d295db0 4239
de6eae1f 4240 return 0;
b7737c9b 4241}
ea4e040a 4242
a22f0788
YR
4243static void bnx2x_8727_specific_func(struct bnx2x_phy *phy,
4244 struct link_params *params,
4245 u32 action)
4246{
4247 struct bnx2x *bp = params->bp;
4248
4249 switch (action) {
4250 case DISABLE_TX:
4251 bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
4252 break;
4253 case ENABLE_TX:
4254 if (!(phy->flags & FLAGS_SFP_NOT_APPROVED))
4255 bnx2x_sfp_set_transmitter(bp, phy, params->port, 1);
4256 break;
4257 default:
4258 DP(NETIF_MSG_LINK, "Function 0x%x not supported by 8727\n",
4259 action);
4260 return;
4261 }
4262}
4263
de6eae1f
YR
4264static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
4265 struct link_params *params)
b7737c9b 4266{
b7737c9b 4267 struct bnx2x *bp = params->bp;
de6eae1f
YR
4268 u16 edc_mode;
4269 u8 rc = 0;
ea4e040a 4270
de6eae1f
YR
4271 u32 val = REG_RD(bp, params->shmem_base +
4272 offsetof(struct shmem_region, dev_info.
4273 port_feature_config[params->port].config));
62b29a5d 4274
de6eae1f
YR
4275 DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n",
4276 params->port);
4277
4278 if (bnx2x_get_edc_mode(phy, params, &edc_mode) != 0) {
4279 DP(NETIF_MSG_LINK, "Failed to get valid module type\n");
4280 return -EINVAL;
4281 } else if (bnx2x_verify_sfp_module(phy, params) !=
4282 0) {
4283 /* check SFP+ module compatibility */
4284 DP(NETIF_MSG_LINK, "Module verification failed!!\n");
4285 rc = -EINVAL;
4286 /* Turn on fault module-detected led */
4287 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
4288 MISC_REGISTERS_GPIO_HIGH,
4289 params->port);
4290 if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) &&
4291 ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
4292 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN)) {
4293 /* Shutdown SFP+ module */
4294 DP(NETIF_MSG_LINK, "Shutdown SFP+ module!!\n");
4295 bnx2x_8727_power_module(bp, phy, 0);
4296 return rc;
4297 }
4298 } else {
4299 /* Turn off fault module-detected led */
4300 DP(NETIF_MSG_LINK, "Turn off fault module-detected led\n");
4301 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
4302 MISC_REGISTERS_GPIO_LOW,
4303 params->port);
62b29a5d 4304 }
b7737c9b 4305
de6eae1f
YR
4306 /* power up the SFP module */
4307 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
4308 bnx2x_8727_power_module(bp, phy, 1);
c18aa15d 4309
de6eae1f
YR
4310 /* Check and set limiting mode / LRM mode on 8726.
4311 On 8727 it is done automatically */
4312 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
4313 bnx2x_8726_set_limiting_mode(bp, phy, edc_mode);
4314 else
4315 bnx2x_8727_set_limiting_mode(bp, phy, edc_mode);
4316 /*
4317 * Enable transmit for this module if the module is approved, or
4318 * if unapproved modules should also enable the Tx laser
4319 */
4320 if (rc == 0 ||
4321 (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
4322 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
4323 bnx2x_sfp_set_transmitter(bp, phy, params->port, 1);
4324 else
4325 bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
b7737c9b 4326
de6eae1f
YR
4327 return rc;
4328}
4329
4330void bnx2x_handle_module_detect_int(struct link_params *params)
b7737c9b
YR
4331{
4332 struct bnx2x *bp = params->bp;
de6eae1f
YR
4333 struct bnx2x_phy *phy = &params->phy[EXT_PHY1];
4334 u32 gpio_val;
4335 u8 port = params->port;
4d295db0 4336
de6eae1f
YR
4337 /* Set valid module led off */
4338 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
4339 MISC_REGISTERS_GPIO_HIGH,
4340 params->port);
4d295db0 4341
de6eae1f
YR
4342 /* Get current gpio val refelecting module plugged in / out*/
4343 gpio_val = bnx2x_get_gpio(bp, MISC_REGISTERS_GPIO_3, port);
62b29a5d 4344
de6eae1f
YR
4345 /* Call the handling function in case module is detected */
4346 if (gpio_val == 0) {
4d295db0 4347
de6eae1f
YR
4348 bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
4349 MISC_REGISTERS_GPIO_INT_OUTPUT_CLR,
4350 port);
4d295db0 4351
de6eae1f
YR
4352 if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
4353 bnx2x_sfp_module_detection(phy, params);
4354 else
4355 DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
4356 } else {
4357 u32 val = REG_RD(bp, params->shmem_base +
4358 offsetof(struct shmem_region, dev_info.
4359 port_feature_config[params->port].
4360 config));
4d295db0 4361
de6eae1f
YR
4362 bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
4363 MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
4364 port);
4365 /* Module was plugged out. */
4366 /* Disable transmit for this module */
4367 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
4368 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
4369 bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
62b29a5d 4370 }
de6eae1f 4371}
62b29a5d 4372
de6eae1f
YR
4373/******************************************************************/
4374/* common BCM8706/BCM8726 PHY SECTION */
4375/******************************************************************/
4376static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
4377 struct link_params *params,
4378 struct link_vars *vars)
4379{
4380 u8 link_up = 0;
4381 u16 val1, val2, rx_sd, pcs_status;
4382 struct bnx2x *bp = params->bp;
4383 DP(NETIF_MSG_LINK, "XGXS 8706/8726\n");
4384 /* Clear RX Alarm*/
62b29a5d 4385 bnx2x_cl45_read(bp, phy,
de6eae1f
YR
4386 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2);
4387 /* clear LASI indication*/
4388 bnx2x_cl45_read(bp, phy,
4389 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
4390 bnx2x_cl45_read(bp, phy,
4391 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2);
4392 DP(NETIF_MSG_LINK, "8706/8726 LASI status 0x%x--> 0x%x\n", val1, val2);
62b29a5d
YR
4393
4394 bnx2x_cl45_read(bp, phy,
de6eae1f
YR
4395 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd);
4396 bnx2x_cl45_read(bp, phy,
4397 MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &pcs_status);
4398 bnx2x_cl45_read(bp, phy,
4399 MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2);
4400 bnx2x_cl45_read(bp, phy,
4401 MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2);
62b29a5d 4402
de6eae1f
YR
4403 DP(NETIF_MSG_LINK, "8706/8726 rx_sd 0x%x pcs_status 0x%x 1Gbps"
4404 " link_status 0x%x\n", rx_sd, pcs_status, val2);
4405 /* link is up if both bit 0 of pmd_rx_sd and
4406 * bit 0 of pcs_status are set, or if the autoneg bit
4407 * 1 is set
4408 */
4409 link_up = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1)));
4410 if (link_up) {
4411 if (val2 & (1<<1))
4412 vars->line_speed = SPEED_1000;
4413 else
4414 vars->line_speed = SPEED_10000;
62b29a5d 4415 bnx2x_ext_phy_resolve_fc(phy, params, vars);
de6eae1f 4416 }
62b29a5d 4417 return link_up;
b7737c9b 4418}
62b29a5d 4419
de6eae1f
YR
4420/******************************************************************/
4421/* BCM8706 PHY SECTION */
4422/******************************************************************/
4423static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
b7737c9b
YR
4424 struct link_params *params,
4425 struct link_vars *vars)
4426{
de6eae1f 4427 u16 cnt, val;
b7737c9b 4428 struct bnx2x *bp = params->bp;
de6eae1f
YR
4429 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4430 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
4431 /* HW reset */
4432 bnx2x_ext_phy_hw_reset(bp, params->port);
4433 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
4434 bnx2x_wait_reset_complete(bp, phy);
ea4e040a 4435
de6eae1f
YR
4436 /* Wait until fw is loaded */
4437 for (cnt = 0; cnt < 100; cnt++) {
4438 bnx2x_cl45_read(bp, phy,
4439 MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1, &val);
4440 if (val)
4441 break;
4442 msleep(10);
4443 }
4444 DP(NETIF_MSG_LINK, "XGXS 8706 is initialized after %d ms\n", cnt);
4445 if ((params->feature_config_flags &
4446 FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
4447 u8 i;
4448 u16 reg;
4449 for (i = 0; i < 4; i++) {
4450 reg = MDIO_XS_8706_REG_BANK_RX0 +
4451 i*(MDIO_XS_8706_REG_BANK_RX1 -
4452 MDIO_XS_8706_REG_BANK_RX0);
4453 bnx2x_cl45_read(bp, phy, MDIO_XS_DEVAD, reg, &val);
4454 /* Clear first 3 bits of the control */
4455 val &= ~0x7;
4456 /* Set control bits according to configuration */
4457 val |= (phy->rx_preemphasis[i] & 0x7);
4458 DP(NETIF_MSG_LINK, "Setting RX Equalizer to BCM8706"
4459 " reg 0x%x <-- val 0x%x\n", reg, val);
4460 bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, reg, val);
4461 }
4462 }
4463 /* Force speed */
4464 if (phy->req_line_speed == SPEED_10000) {
4465 DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n");
ea4e040a 4466
de6eae1f
YR
4467 bnx2x_cl45_write(bp, phy,
4468 MDIO_PMA_DEVAD,
4469 MDIO_PMA_REG_DIGITAL_CTRL, 0x400);
4470 bnx2x_cl45_write(bp, phy,
4471 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1);
4472 } else {
4473 /* Force 1Gbps using autoneg with 1G advertisment */
6bbca910 4474
de6eae1f
YR
4475 /* Allow CL37 through CL73 */
4476 DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
4477 bnx2x_cl45_write(bp, phy,
4478 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c);
6bbca910 4479
de6eae1f
YR
4480 /* Enable Full-Duplex advertisment on CL37 */
4481 bnx2x_cl45_write(bp, phy,
4482 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LP, 0x0020);
4483 /* Enable CL37 AN */
4484 bnx2x_cl45_write(bp, phy,
4485 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
4486 /* 1G support */
4487 bnx2x_cl45_write(bp, phy,
4488 MDIO_AN_DEVAD, MDIO_AN_REG_ADV, (1<<5));
6bbca910 4489
de6eae1f
YR
4490 /* Enable clause 73 AN */
4491 bnx2x_cl45_write(bp, phy,
4492 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
4493 bnx2x_cl45_write(bp, phy,
4494 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
4495 0x0400);
4496 bnx2x_cl45_write(bp, phy,
4497 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
4498 0x0004);
4499 }
4500 bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
4501 return 0;
4502}
ea4e040a 4503
de6eae1f
YR
4504static u8 bnx2x_8706_read_status(struct bnx2x_phy *phy,
4505 struct link_params *params,
4506 struct link_vars *vars)
4507{
4508 return bnx2x_8706_8726_read_status(phy, params, vars);
4509}
6bbca910 4510
de6eae1f
YR
4511/******************************************************************/
4512/* BCM8726 PHY SECTION */
4513/******************************************************************/
4514static void bnx2x_8726_config_loopback(struct bnx2x_phy *phy,
4515 struct link_params *params)
4516{
4517 struct bnx2x *bp = params->bp;
4518 DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n");
4519 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0001);
4520}
62b29a5d 4521
de6eae1f
YR
4522static void bnx2x_8726_external_rom_boot(struct bnx2x_phy *phy,
4523 struct link_params *params)
4524{
4525 struct bnx2x *bp = params->bp;
4526 /* Need to wait 100ms after reset */
4527 msleep(100);
62b29a5d 4528
de6eae1f
YR
4529 /* Micro controller re-boot */
4530 bnx2x_cl45_write(bp, phy,
4531 MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x018B);
62b29a5d 4532
de6eae1f
YR
4533 /* Set soft reset */
4534 bnx2x_cl45_write(bp, phy,
4535 MDIO_PMA_DEVAD,
4536 MDIO_PMA_REG_GEN_CTRL,
4537 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
62b29a5d 4538
de6eae1f
YR
4539 bnx2x_cl45_write(bp, phy,
4540 MDIO_PMA_DEVAD,
4541 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
6bbca910 4542
de6eae1f
YR
4543 bnx2x_cl45_write(bp, phy,
4544 MDIO_PMA_DEVAD,
4545 MDIO_PMA_REG_GEN_CTRL,
4546 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
4547
4548 /* wait for 150ms for microcode load */
4549 msleep(150);
4550
4551 /* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO */
4552 bnx2x_cl45_write(bp, phy,
4553 MDIO_PMA_DEVAD,
4554 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
4555
4556 msleep(200);
4557 bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
b7737c9b
YR
4558}
4559
de6eae1f 4560static u8 bnx2x_8726_read_status(struct bnx2x_phy *phy,
b7737c9b
YR
4561 struct link_params *params,
4562 struct link_vars *vars)
4563{
4564 struct bnx2x *bp = params->bp;
de6eae1f
YR
4565 u16 val1;
4566 u8 link_up = bnx2x_8706_8726_read_status(phy, params, vars);
62b29a5d
YR
4567 if (link_up) {
4568 bnx2x_cl45_read(bp, phy,
de6eae1f
YR
4569 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
4570 &val1);
4571 if (val1 & (1<<15)) {
4572 DP(NETIF_MSG_LINK, "Tx is disabled\n");
4573 link_up = 0;
4574 vars->line_speed = 0;
4575 }
62b29a5d
YR
4576 }
4577 return link_up;
b7737c9b
YR
4578}
4579
de6eae1f
YR
4580
4581static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
4582 struct link_params *params,
4583 struct link_vars *vars)
b7737c9b
YR
4584{
4585 struct bnx2x *bp = params->bp;
de6eae1f
YR
4586 u32 val;
4587 u32 swap_val, swap_override, aeu_gpio_mask, offset;
4588 DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
4589 /* Restore normal power mode*/
4590 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4591 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
b7737c9b 4592
de6eae1f
YR
4593 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
4594 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
62b29a5d 4595
de6eae1f
YR
4596 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
4597 bnx2x_wait_reset_complete(bp, phy);
62b29a5d 4598
de6eae1f 4599 bnx2x_8726_external_rom_boot(phy, params);
62b29a5d 4600
de6eae1f
YR
4601 /* Need to call module detected on initialization since
4602 the module detection triggered by actual module
4603 insertion might occur before driver is loaded, and when
4604 driver is loaded, it reset all registers, including the
4605 transmitter */
4606 bnx2x_sfp_module_detection(phy, params);
62b29a5d 4607
de6eae1f
YR
4608 if (phy->req_line_speed == SPEED_1000) {
4609 DP(NETIF_MSG_LINK, "Setting 1G force\n");
4610 bnx2x_cl45_write(bp, phy,
4611 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40);
4612 bnx2x_cl45_write(bp, phy,
4613 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
4614 bnx2x_cl45_write(bp, phy,
4615 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x5);
4616 bnx2x_cl45_write(bp, phy,
4617 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
4618 0x400);
4619 } else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
4620 (phy->speed_cap_mask &
4621 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) &&
4622 ((phy->speed_cap_mask &
4623 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) !=
4624 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
4625 DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
4626 /* Set Flow control */
4627 bnx2x_ext_phy_set_pause(params, phy, vars);
4628 bnx2x_cl45_write(bp, phy,
4629 MDIO_AN_DEVAD, MDIO_AN_REG_ADV, 0x20);
4630 bnx2x_cl45_write(bp, phy,
4631 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c);
4632 bnx2x_cl45_write(bp, phy,
4633 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, 0x0020);
4634 bnx2x_cl45_write(bp, phy,
4635 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
4636 bnx2x_cl45_write(bp, phy,
4637 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
4638 /* Enable RX-ALARM control to receive
4639 interrupt for 1G speed change */
4640 bnx2x_cl45_write(bp, phy,
4641 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x4);
4642 bnx2x_cl45_write(bp, phy,
4643 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
4644 0x400);
62b29a5d 4645
de6eae1f
YR
4646 } else { /* Default 10G. Set only LASI control */
4647 bnx2x_cl45_write(bp, phy,
4648 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1);
7aa0711f
YR
4649 }
4650
de6eae1f
YR
4651 /* Set TX PreEmphasis if needed */
4652 if ((params->feature_config_flags &
4653 FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
4654 DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
4655 "TX_CTRL2 0x%x\n",
4656 phy->tx_preemphasis[0],
4657 phy->tx_preemphasis[1]);
4658 bnx2x_cl45_write(bp, phy,
4659 MDIO_PMA_DEVAD,
4660 MDIO_PMA_REG_8726_TX_CTRL1,
4661 phy->tx_preemphasis[0]);
c18aa15d 4662
de6eae1f
YR
4663 bnx2x_cl45_write(bp, phy,
4664 MDIO_PMA_DEVAD,
4665 MDIO_PMA_REG_8726_TX_CTRL2,
4666 phy->tx_preemphasis[1]);
4667 }
ab6ad5a4 4668
de6eae1f
YR
4669 /* Set GPIO3 to trigger SFP+ module insertion/removal */
4670 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
4671 MISC_REGISTERS_GPIO_INPUT_HI_Z, params->port);
ea4e040a 4672
de6eae1f
YR
4673 /* The GPIO should be swapped if the swap register is set and active */
4674 swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
4675 swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
ea4e040a 4676
de6eae1f
YR
4677 /* Select function upon port-swap configuration */
4678 if (params->port == 0) {
4679 offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
4680 aeu_gpio_mask = (swap_val && swap_override) ?
4681 AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 :
4682 AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0;
4683 } else {
4684 offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
4685 aeu_gpio_mask = (swap_val && swap_override) ?
4686 AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 :
4687 AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1;
ea4e040a 4688 }
de6eae1f
YR
4689 val = REG_RD(bp, offset);
4690 /* add GPIO3 to group */
4691 val |= aeu_gpio_mask;
4692 REG_WR(bp, offset, val);
4693 return 0;
ab6ad5a4 4694
ea4e040a
YR
4695}
4696
de6eae1f
YR
4697static void bnx2x_8726_link_reset(struct bnx2x_phy *phy,
4698 struct link_params *params)
2f904460 4699{
de6eae1f
YR
4700 struct bnx2x *bp = params->bp;
4701 DP(NETIF_MSG_LINK, "bnx2x_8726_link_reset port %d\n", params->port);
4702 /* Set serial boot control for external load */
4703 bnx2x_cl45_write(bp, phy,
4704 MDIO_PMA_DEVAD,
4705 MDIO_PMA_REG_GEN_CTRL, 0x0001);
4706}
4707
4708/******************************************************************/
4709/* BCM8727 PHY SECTION */
4710/******************************************************************/
7f02c4ad
YR
4711
4712static void bnx2x_8727_set_link_led(struct bnx2x_phy *phy,
4713 struct link_params *params, u8 mode)
4714{
4715 struct bnx2x *bp = params->bp;
4716 u16 led_mode_bitmask = 0;
4717 u16 gpio_pins_bitmask = 0;
4718 u16 val;
4719 /* Only NOC flavor requires to set the LED specifically */
4720 if (!(phy->flags & FLAGS_NOC))
4721 return;
4722 switch (mode) {
4723 case LED_MODE_FRONT_PANEL_OFF:
4724 case LED_MODE_OFF:
4725 led_mode_bitmask = 0;
4726 gpio_pins_bitmask = 0x03;
4727 break;
4728 case LED_MODE_ON:
4729 led_mode_bitmask = 0;
4730 gpio_pins_bitmask = 0x02;
4731 break;
4732 case LED_MODE_OPER:
4733 led_mode_bitmask = 0x60;
4734 gpio_pins_bitmask = 0x11;
4735 break;
4736 }
4737 bnx2x_cl45_read(bp, phy,
4738 MDIO_PMA_DEVAD,
4739 MDIO_PMA_REG_8727_PCS_OPT_CTRL,
4740 &val);
4741 val &= 0xff8f;
4742 val |= led_mode_bitmask;
4743 bnx2x_cl45_write(bp, phy,
4744 MDIO_PMA_DEVAD,
4745 MDIO_PMA_REG_8727_PCS_OPT_CTRL,
4746 val);
4747 bnx2x_cl45_read(bp, phy,
4748 MDIO_PMA_DEVAD,
4749 MDIO_PMA_REG_8727_GPIO_CTRL,
4750 &val);
4751 val &= 0xffe0;
4752 val |= gpio_pins_bitmask;
4753 bnx2x_cl45_write(bp, phy,
4754 MDIO_PMA_DEVAD,
4755 MDIO_PMA_REG_8727_GPIO_CTRL,
4756 val);
4757}
de6eae1f
YR
4758static void bnx2x_8727_hw_reset(struct bnx2x_phy *phy,
4759 struct link_params *params) {
4760 u32 swap_val, swap_override;
4761 u8 port;
4762 /**
4763 * The PHY reset is controlled by GPIO 1. Fake the port number
4764 * to cancel the swap done in set_gpio()
2f904460 4765 */
de6eae1f
YR
4766 struct bnx2x *bp = params->bp;
4767 swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
4768 swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
4769 port = (swap_val && swap_override) ^ 1;
4770 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
4771 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
2f904460 4772}
e10bc84d 4773
de6eae1f
YR
4774static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
4775 struct link_params *params,
4776 struct link_vars *vars)
ea4e040a 4777{
de6eae1f
YR
4778 u16 tmp1, val, mod_abs;
4779 u16 rx_alarm_ctrl_val;
4780 u16 lasi_ctrl_val;
ea4e040a 4781 struct bnx2x *bp = params->bp;
de6eae1f 4782 /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
ea4e040a 4783
de6eae1f
YR
4784 bnx2x_wait_reset_complete(bp, phy);
4785 rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
4786 lasi_ctrl_val = 0x0004;
ea4e040a 4787
de6eae1f
YR
4788 DP(NETIF_MSG_LINK, "Initializing BCM8727\n");
4789 /* enable LASI */
4790 bnx2x_cl45_write(bp, phy,
4791 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
4792 rx_alarm_ctrl_val);
ea4e040a 4793
de6eae1f
YR
4794 bnx2x_cl45_write(bp, phy,
4795 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, lasi_ctrl_val);
ea4e040a 4796
de6eae1f
YR
4797 /* Initially configure MOD_ABS to interrupt when
4798 module is presence( bit 8) */
4799 bnx2x_cl45_read(bp, phy,
4800 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
4801 /* Set EDC off by setting OPTXLOS signal input to low
4802 (bit 9).
4803 When the EDC is off it locks onto a reference clock and
4804 avoids becoming 'lost'.*/
7f02c4ad
YR
4805 mod_abs &= ~(1<<8);
4806 if (!(phy->flags & FLAGS_NOC))
4807 mod_abs &= ~(1<<9);
de6eae1f
YR
4808 bnx2x_cl45_write(bp, phy,
4809 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
ea4e040a 4810
ea4e040a 4811
de6eae1f
YR
4812 /* Make MOD_ABS give interrupt on change */
4813 bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL,
4814 &val);
4815 val |= (1<<12);
7f02c4ad
YR
4816 if (phy->flags & FLAGS_NOC)
4817 val |= (3<<5);
b7737c9b 4818
7f02c4ad
YR
4819 /**
4820 * Set 8727 GPIOs to input to allow reading from the 8727 GPIO0
4821 * status which reflect SFP+ module over-current
4822 */
4823 if (!(phy->flags & FLAGS_NOC))
4824 val &= 0xff8f; /* Reset bits 4-6 */
de6eae1f
YR
4825 bnx2x_cl45_write(bp, phy,
4826 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL, val);
ea4e040a 4827
de6eae1f
YR
4828 bnx2x_8727_power_module(bp, phy, 1);
4829
4830 bnx2x_cl45_read(bp, phy,
4831 MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
4832
4833 bnx2x_cl45_read(bp, phy,
4834 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1);
4835
4836 /* Set option 1G speed */
4837 if (phy->req_line_speed == SPEED_1000) {
4838 DP(NETIF_MSG_LINK, "Setting 1G force\n");
4839 bnx2x_cl45_write(bp, phy,
4840 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40);
4841 bnx2x_cl45_write(bp, phy,
4842 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
4843 bnx2x_cl45_read(bp, phy,
4844 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1);
4845 DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1);
a22f0788
YR
4846 /**
4847 * Power down the XAUI until link is up in case of dual-media
4848 * and 1G
4849 */
4850 if (DUAL_MEDIA(params)) {
4851 bnx2x_cl45_read(bp, phy,
4852 MDIO_PMA_DEVAD,
4853 MDIO_PMA_REG_8727_PCS_GP, &val);
4854 val |= (3<<10);
4855 bnx2x_cl45_write(bp, phy,
4856 MDIO_PMA_DEVAD,
4857 MDIO_PMA_REG_8727_PCS_GP, val);
4858 }
de6eae1f
YR
4859 } else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
4860 ((phy->speed_cap_mask &
4861 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) &&
4862 ((phy->speed_cap_mask &
4863 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) !=
4864 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
4865
4866 DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
4867 bnx2x_cl45_write(bp, phy,
4868 MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL, 0);
4869 bnx2x_cl45_write(bp, phy,
4870 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1300);
4871 } else {
4872 /**
4873 * Since the 8727 has only single reset pin, need to set the 10G
4874 * registers although it is default
4875 */
4876 bnx2x_cl45_write(bp, phy,
4877 MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL,
4878 0x0020);
4879 bnx2x_cl45_write(bp, phy,
4880 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x0100);
4881 bnx2x_cl45_write(bp, phy,
4882 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040);
4883 bnx2x_cl45_write(bp, phy,
4884 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2,
4885 0x0008);
ea4e040a 4886 }
ea4e040a 4887
de6eae1f
YR
4888 /* Set 2-wire transfer rate of SFP+ module EEPROM
4889 * to 100Khz since some DACs(direct attached cables) do
4890 * not work at 400Khz.
4891 */
4892 bnx2x_cl45_write(bp, phy,
4893 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR,
4894 0xa001);
b7737c9b 4895
de6eae1f
YR
4896 /* Set TX PreEmphasis if needed */
4897 if ((params->feature_config_flags &
4898 FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
4899 DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x\n",
4900 phy->tx_preemphasis[0],
4901 phy->tx_preemphasis[1]);
4902 bnx2x_cl45_write(bp, phy,
4903 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL1,
4904 phy->tx_preemphasis[0]);
ea4e040a 4905
de6eae1f
YR
4906 bnx2x_cl45_write(bp, phy,
4907 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL2,
4908 phy->tx_preemphasis[1]);
4909 }
ea4e040a 4910
de6eae1f 4911 return 0;
ea4e040a
YR
4912}
4913
de6eae1f
YR
4914static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
4915 struct link_params *params)
ea4e040a 4916{
ea4e040a 4917 struct bnx2x *bp = params->bp;
de6eae1f
YR
4918 u16 mod_abs, rx_alarm_status;
4919 u32 val = REG_RD(bp, params->shmem_base +
4920 offsetof(struct shmem_region, dev_info.
4921 port_feature_config[params->port].
4922 config));
4923 bnx2x_cl45_read(bp, phy,
4924 MDIO_PMA_DEVAD,
4925 MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
4926 if (mod_abs & (1<<8)) {
ea4e040a 4927
de6eae1f
YR
4928 /* Module is absent */
4929 DP(NETIF_MSG_LINK, "MOD_ABS indication "
4930 "show module is absent\n");
ea4e040a 4931
de6eae1f
YR
4932 /* 1. Set mod_abs to detect next module
4933 presence event
4934 2. Set EDC off by setting OPTXLOS signal input to low
4935 (bit 9).
4936 When the EDC is off it locks onto a reference clock and
4937 avoids becoming 'lost'.*/
7f02c4ad
YR
4938 mod_abs &= ~(1<<8);
4939 if (!(phy->flags & FLAGS_NOC))
4940 mod_abs &= ~(1<<9);
de6eae1f
YR
4941 bnx2x_cl45_write(bp, phy,
4942 MDIO_PMA_DEVAD,
4943 MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
ea4e040a 4944
de6eae1f
YR
4945 /* Clear RX alarm since it stays up as long as
4946 the mod_abs wasn't changed */
4947 bnx2x_cl45_read(bp, phy,
4948 MDIO_PMA_DEVAD,
4949 MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
ea4e040a 4950
de6eae1f
YR
4951 } else {
4952 /* Module is present */
4953 DP(NETIF_MSG_LINK, "MOD_ABS indication "
4954 "show module is present\n");
4955 /* First thing, disable transmitter,
4956 and if the module is ok, the
4957 module_detection will enable it*/
ea4e040a 4958
de6eae1f
YR
4959 /* 1. Set mod_abs to detect next module
4960 absent event ( bit 8)
4961 2. Restore the default polarity of the OPRXLOS signal and
4962 this signal will then correctly indicate the presence or
4963 absence of the Rx signal. (bit 9) */
7f02c4ad
YR
4964 mod_abs |= (1<<8);
4965 if (!(phy->flags & FLAGS_NOC))
4966 mod_abs |= (1<<9);
e10bc84d 4967 bnx2x_cl45_write(bp, phy,
de6eae1f
YR
4968 MDIO_PMA_DEVAD,
4969 MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
ea4e040a 4970
de6eae1f
YR
4971 /* Clear RX alarm since it stays up as long as
4972 the mod_abs wasn't changed. This is need to be done
4973 before calling the module detection, otherwise it will clear
4974 the link update alarm */
4975 bnx2x_cl45_read(bp, phy,
4976 MDIO_PMA_DEVAD,
4977 MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
ea4e040a 4978
ea4e040a 4979
de6eae1f
YR
4980 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
4981 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
4982 bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
4983
4984 if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
4985 bnx2x_sfp_module_detection(phy, params);
4986 else
4987 DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
ea4e040a 4988 }
de6eae1f
YR
4989
4990 DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS 0x%x\n",
4991 rx_alarm_status);
4992 /* No need to check link status in case of
4993 module plugged in/out */
ea4e040a
YR
4994}
4995
de6eae1f
YR
4996static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
4997 struct link_params *params,
4998 struct link_vars *vars)
4999
ea4e040a
YR
5000{
5001 struct bnx2x *bp = params->bp;
de6eae1f
YR
5002 u8 link_up = 0;
5003 u16 link_status = 0;
a22f0788
YR
5004 u16 rx_alarm_status, lasi_ctrl, val1;
5005
5006 /* If PHY is not initialized, do not check link status */
5007 bnx2x_cl45_read(bp, phy,
5008 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
5009 &lasi_ctrl);
5010 if (!lasi_ctrl)
5011 return 0;
5012
de6eae1f
YR
5013 /* Check the LASI */
5014 bnx2x_cl45_read(bp, phy,
5015 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM,
5016 &rx_alarm_status);
5017 vars->line_speed = 0;
5018 DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS 0x%x\n", rx_alarm_status);
5019
5020 bnx2x_cl45_read(bp, phy,
5021 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
5022
5023 DP(NETIF_MSG_LINK, "8727 LASI status 0x%x\n", val1);
5024
5025 /* Clear MSG-OUT */
5026 bnx2x_cl45_read(bp, phy,
5027 MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
5028
5029 /**
5030 * If a module is present and there is need to check
5031 * for over current
5032 */
5033 if (!(phy->flags & FLAGS_NOC) && !(rx_alarm_status & (1<<5))) {
5034 /* Check over-current using 8727 GPIO0 input*/
5035 bnx2x_cl45_read(bp, phy,
5036 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_GPIO_CTRL,
5037 &val1);
5038
5039 if ((val1 & (1<<8)) == 0) {
5040 DP(NETIF_MSG_LINK, "8727 Power fault has been detected"
5041 " on port %d\n", params->port);
5042 netdev_err(bp->dev, "Error: Power fault on Port %d has"
5043 " been detected and the power to "
5044 "that SFP+ module has been removed"
5045 " to prevent failure of the card."
5046 " Please remove the SFP+ module and"
5047 " restart the system to clear this"
5048 " error.\n",
5049 params->port);
5050
5051 /*
5052 * Disable all RX_ALARMs except for
5053 * mod_abs
5054 */
5055 bnx2x_cl45_write(bp, phy,
5056 MDIO_PMA_DEVAD,
5057 MDIO_PMA_REG_RX_ALARM_CTRL, (1<<5));
5058
5059 bnx2x_cl45_read(bp, phy,
5060 MDIO_PMA_DEVAD,
5061 MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
5062 /* Wait for module_absent_event */
5063 val1 |= (1<<8);
5064 bnx2x_cl45_write(bp, phy,
5065 MDIO_PMA_DEVAD,
5066 MDIO_PMA_REG_PHY_IDENTIFIER, val1);
5067 /* Clear RX alarm */
5068 bnx2x_cl45_read(bp, phy,
5069 MDIO_PMA_DEVAD,
5070 MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
5071 return 0;
5072 }
5073 } /* Over current check */
5074
5075 /* When module absent bit is set, check module */
5076 if (rx_alarm_status & (1<<5)) {
5077 bnx2x_8727_handle_mod_abs(phy, params);
5078 /* Enable all mod_abs and link detection bits */
5079 bnx2x_cl45_write(bp, phy,
5080 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
5081 ((1<<5) | (1<<2)));
5082 }
a22f0788
YR
5083 DP(NETIF_MSG_LINK, "Enabling 8727 TX laser if SFP is approved\n");
5084 bnx2x_8727_specific_func(phy, params, ENABLE_TX);
de6eae1f
YR
5085 /* If transmitter is disabled, ignore false link up indication */
5086 bnx2x_cl45_read(bp, phy,
5087 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
5088 if (val1 & (1<<15)) {
5089 DP(NETIF_MSG_LINK, "Tx is disabled\n");
5090 return 0;
5091 }
5092
5093 bnx2x_cl45_read(bp, phy,
5094 MDIO_PMA_DEVAD,
5095 MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &link_status);
5096
5097 /* Bits 0..2 --> speed detected,
5098 bits 13..15--> link is down */
5099 if ((link_status & (1<<2)) && (!(link_status & (1<<15)))) {
5100 link_up = 1;
5101 vars->line_speed = SPEED_10000;
5102 } else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
5103 link_up = 1;
5104 vars->line_speed = SPEED_1000;
5105 DP(NETIF_MSG_LINK, "port %x: External link up in 1G\n",
5106 params->port);
5107 } else {
5108 link_up = 0;
5109 DP(NETIF_MSG_LINK, "port %x: External link is down\n",
5110 params->port);
5111 }
5112 if (link_up)
5113 bnx2x_ext_phy_resolve_fc(phy, params, vars);
a22f0788
YR
5114
5115 if ((DUAL_MEDIA(params)) &&
5116 (phy->req_line_speed == SPEED_1000)) {
5117 bnx2x_cl45_read(bp, phy,
5118 MDIO_PMA_DEVAD,
5119 MDIO_PMA_REG_8727_PCS_GP, &val1);
5120 /**
5121 * In case of dual-media board and 1G, power up the XAUI side,
5122 * otherwise power it down. For 10G it is done automatically
5123 */
5124 if (link_up)
5125 val1 &= ~(3<<10);
5126 else
5127 val1 |= (3<<10);
5128 bnx2x_cl45_write(bp, phy,
5129 MDIO_PMA_DEVAD,
5130 MDIO_PMA_REG_8727_PCS_GP, val1);
5131 }
de6eae1f 5132 return link_up;
b7737c9b 5133}
ea4e040a 5134
de6eae1f
YR
5135static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
5136 struct link_params *params)
b7737c9b
YR
5137{
5138 struct bnx2x *bp = params->bp;
de6eae1f
YR
5139 /* Disable Transmitter */
5140 bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
a22f0788
YR
5141 /* Clear LASI */
5142 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0);
5143
ea4e040a 5144}
c18aa15d 5145
de6eae1f
YR
5146/******************************************************************/
5147/* BCM8481/BCM84823/BCM84833 PHY SECTION */
5148/******************************************************************/
5149static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
5150 struct link_params *params)
ea4e040a 5151{
de6eae1f
YR
5152 u16 val, fw_ver1, fw_ver2, cnt;
5153 struct bnx2x *bp = params->bp;
ea4e040a 5154
de6eae1f
YR
5155 /* For the 32 bits registers in 848xx, access via MDIO2ARM interface.*/
5156 /* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
5157 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
5158 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
5159 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
5160 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
5161 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
ea4e040a 5162
de6eae1f
YR
5163 for (cnt = 0; cnt < 100; cnt++) {
5164 bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
5165 if (val & 1)
5166 break;
5167 udelay(5);
5168 }
5169 if (cnt == 100) {
5170 DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(1)\n");
5171 bnx2x_save_spirom_version(bp, params->port, 0,
5172 phy->ver_addr);
5173 return;
5174 }
ea4e040a 5175
ea4e040a 5176
de6eae1f
YR
5177 /* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
5178 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000);
5179 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
5180 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A);
5181 for (cnt = 0; cnt < 100; cnt++) {
5182 bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
5183 if (val & 1)
5184 break;
5185 udelay(5);
5186 }
5187 if (cnt == 100) {
5188 DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(2)\n");
5189 bnx2x_save_spirom_version(bp, params->port, 0,
5190 phy->ver_addr);
5191 return;
ea4e040a
YR
5192 }
5193
de6eae1f
YR
5194 /* lower 16 bits of the register SPI_FW_STATUS */
5195 bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
5196 /* upper 16 bits of register SPI_FW_STATUS */
5197 bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
ea4e040a 5198
de6eae1f
YR
5199 bnx2x_save_spirom_version(bp, params->port, (fw_ver2<<16) | fw_ver1,
5200 phy->ver_addr);
5201}
ea4e040a 5202
de6eae1f
YR
5203static void bnx2x_848xx_set_led(struct bnx2x *bp,
5204 struct bnx2x_phy *phy)
ea4e040a 5205{
de6eae1f 5206 u16 val;
7846e471 5207
de6eae1f
YR
5208 /* PHYC_CTL_LED_CTL */
5209 bnx2x_cl45_read(bp, phy,
5210 MDIO_PMA_DEVAD,
5211 MDIO_PMA_REG_8481_LINK_SIGNAL, &val);
5212 val &= 0xFE00;
5213 val |= 0x0092;
345b5d52 5214
de6eae1f
YR
5215 bnx2x_cl45_write(bp, phy,
5216 MDIO_PMA_DEVAD,
5217 MDIO_PMA_REG_8481_LINK_SIGNAL, val);
ea4e040a 5218
de6eae1f
YR
5219 bnx2x_cl45_write(bp, phy,
5220 MDIO_PMA_DEVAD,
5221 MDIO_PMA_REG_8481_LED1_MASK,
5222 0x80);
ea4e040a 5223
de6eae1f
YR
5224 bnx2x_cl45_write(bp, phy,
5225 MDIO_PMA_DEVAD,
5226 MDIO_PMA_REG_8481_LED2_MASK,
5227 0x18);
ea4e040a 5228
de6eae1f
YR
5229 bnx2x_cl45_write(bp, phy,
5230 MDIO_PMA_DEVAD,
5231 MDIO_PMA_REG_8481_LED3_MASK,
5232 0x0040);
ea4e040a 5233
de6eae1f
YR
5234 /* 'Interrupt Mask' */
5235 bnx2x_cl45_write(bp, phy,
5236 MDIO_AN_DEVAD,
5237 0xFFFB, 0xFFFD);
ea4e040a
YR
5238}
5239
de6eae1f 5240static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
a22f0788
YR
5241 struct link_params *params,
5242 struct link_vars *vars)
ea4e040a 5243{
c18aa15d 5244 struct bnx2x *bp = params->bp;
de6eae1f 5245 u16 autoneg_val, an_1000_val, an_10_100_val;
de6eae1f
YR
5246 bnx2x_wait_reset_complete(bp, phy);
5247 bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4,
5248 1 << NIG_LATCH_BC_ENABLE_MI_INT);
ea4e040a 5249
de6eae1f
YR
5250 bnx2x_cl45_write(bp, phy,
5251 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0000);
ea4e040a 5252
de6eae1f 5253 bnx2x_848xx_set_led(bp, phy);
ea4e040a 5254
de6eae1f
YR
5255 /* set 1000 speed advertisement */
5256 bnx2x_cl45_read(bp, phy,
5257 MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
5258 &an_1000_val);
57963ed9 5259
de6eae1f
YR
5260 bnx2x_ext_phy_set_pause(params, phy, vars);
5261 bnx2x_cl45_read(bp, phy,
5262 MDIO_AN_DEVAD,
5263 MDIO_AN_REG_8481_LEGACY_AN_ADV,
5264 &an_10_100_val);
5265 bnx2x_cl45_read(bp, phy,
5266 MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_CTRL,
5267 &autoneg_val);
5268 /* Disable forced speed */
5269 autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13));
5270 an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8));
ea4e040a 5271
de6eae1f
YR
5272 if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
5273 (phy->speed_cap_mask &
5274 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
5275 (phy->req_line_speed == SPEED_1000)) {
5276 an_1000_val |= (1<<8);
5277 autoneg_val |= (1<<9 | 1<<12);
5278 if (phy->req_duplex == DUPLEX_FULL)
5279 an_1000_val |= (1<<9);
5280 DP(NETIF_MSG_LINK, "Advertising 1G\n");
5281 } else
5282 an_1000_val &= ~((1<<8) | (1<<9));
ea4e040a 5283
de6eae1f
YR
5284 bnx2x_cl45_write(bp, phy,
5285 MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
5286 an_1000_val);
ea4e040a 5287
de6eae1f
YR
5288 /* set 10 speed advertisement */
5289 if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
5290 (phy->speed_cap_mask &
5291 (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
5292 PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
5293 an_10_100_val |= (1<<7);
5294 /* Enable autoneg and restart autoneg for legacy speeds */
5295 autoneg_val |= (1<<9 | 1<<12);
b7737c9b 5296
de6eae1f
YR
5297 if (phy->req_duplex == DUPLEX_FULL)
5298 an_10_100_val |= (1<<8);
5299 DP(NETIF_MSG_LINK, "Advertising 100M\n");
5300 }
5301 /* set 10 speed advertisement */
5302 if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
5303 (phy->speed_cap_mask &
5304 (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
5305 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
5306 an_10_100_val |= (1<<5);
5307 autoneg_val |= (1<<9 | 1<<12);
5308 if (phy->req_duplex == DUPLEX_FULL)
5309 an_10_100_val |= (1<<6);
5310 DP(NETIF_MSG_LINK, "Advertising 10M\n");
5311 }
b7737c9b 5312
de6eae1f
YR
5313 /* Only 10/100 are allowed to work in FORCE mode */
5314 if (phy->req_line_speed == SPEED_100) {
5315 autoneg_val |= (1<<13);
5316 /* Enabled AUTO-MDIX when autoneg is disabled */
5317 bnx2x_cl45_write(bp, phy,
5318 MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
5319 (1<<15 | 1<<9 | 7<<0));
5320 DP(NETIF_MSG_LINK, "Setting 100M force\n");
5321 }
5322 if (phy->req_line_speed == SPEED_10) {
5323 /* Enabled AUTO-MDIX when autoneg is disabled */
5324 bnx2x_cl45_write(bp, phy,
5325 MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
5326 (1<<15 | 1<<9 | 7<<0));
5327 DP(NETIF_MSG_LINK, "Setting 10M force\n");
5328 }
b7737c9b 5329
de6eae1f
YR
5330 bnx2x_cl45_write(bp, phy,
5331 MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_AN_ADV,
5332 an_10_100_val);
b7737c9b 5333
de6eae1f
YR
5334 if (phy->req_duplex == DUPLEX_FULL)
5335 autoneg_val |= (1<<8);
b7737c9b 5336
de6eae1f
YR
5337 bnx2x_cl45_write(bp, phy,
5338 MDIO_AN_DEVAD,
5339 MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val);
b7737c9b 5340
de6eae1f
YR
5341 if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
5342 (phy->speed_cap_mask &
5343 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
5344 (phy->req_line_speed == SPEED_10000)) {
5345 DP(NETIF_MSG_LINK, "Advertising 10G\n");
5346 /* Restart autoneg for 10G*/
5347
5348 bnx2x_cl45_write(bp, phy,
5349 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
5350 0x3200);
5351 } else if (phy->req_line_speed != SPEED_10 &&
5352 phy->req_line_speed != SPEED_100) {
5353 bnx2x_cl45_write(bp, phy,
5354 MDIO_AN_DEVAD,
5355 MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
5356 1);
b7737c9b 5357 }
de6eae1f
YR
5358 /* Save spirom version */
5359 bnx2x_save_848xx_spirom_version(phy, params);
5360
5361 return 0;
b7737c9b
YR
5362}
5363
de6eae1f
YR
5364static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy,
5365 struct link_params *params,
5366 struct link_vars *vars)
ea4e040a
YR
5367{
5368 struct bnx2x *bp = params->bp;
de6eae1f
YR
5369 /* Restore normal power mode*/
5370 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
5371 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
b7737c9b 5372
de6eae1f
YR
5373 /* HW reset */
5374 bnx2x_ext_phy_hw_reset(bp, params->port);
ab6ad5a4 5375
de6eae1f
YR
5376 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
5377 return bnx2x_848xx_cmn_config_init(phy, params, vars);
5378}
ea4e040a 5379
de6eae1f
YR
5380static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
5381 struct link_params *params,
5382 struct link_vars *vars)
5383{
5384 struct bnx2x *bp = params->bp;
7f02c4ad 5385 u8 port = params->port, initialize = 1;
a22f0788 5386 u16 val;
de6eae1f 5387 u16 temp;
a22f0788
YR
5388 u32 actual_phy_selection;
5389 u8 rc = 0;
7f02c4ad
YR
5390
5391 /* This is just for MDIO_CTL_REG_84823_MEDIA register. */
5392
de6eae1f
YR
5393 msleep(1);
5394 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
5395 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
7f02c4ad 5396 port);
de6eae1f 5397 msleep(200); /* 100 is not enough */
ea4e040a 5398
7f02c4ad
YR
5399 /* BCM84823 requires that XGXS links up first @ 10G for normal
5400 behavior */
de6eae1f
YR
5401 temp = vars->line_speed;
5402 vars->line_speed = SPEED_10000;
a22f0788
YR
5403 bnx2x_set_autoneg(&params->phy[INT_PHY], params, vars, 0);
5404 bnx2x_program_serdes(&params->phy[INT_PHY], params, vars);
de6eae1f 5405 vars->line_speed = temp;
a22f0788
YR
5406
5407 /* Set dual-media configuration according to configuration */
5408
5409 bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
5410 MDIO_CTL_REG_84823_MEDIA, &val);
5411 val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
5412 MDIO_CTL_REG_84823_MEDIA_LINE_MASK |
5413 MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN |
5414 MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK |
5415 MDIO_CTL_REG_84823_MEDIA_FIBER_1G);
5416 val |= MDIO_CTL_REG_84823_CTRL_MAC_XFI |
5417 MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L;
5418
5419 actual_phy_selection = bnx2x_phy_selection(params);
5420
5421 switch (actual_phy_selection) {
5422 case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
5423 /* Do nothing. Essentialy this is like the priority copper */
5424 break;
5425 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
5426 val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER;
5427 break;
5428 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
5429 val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER;
5430 break;
5431 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
5432 /* Do nothing here. The first PHY won't be initialized at all */
5433 break;
5434 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
5435 val |= MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN;
5436 initialize = 0;
5437 break;
5438 }
5439 if (params->phy[EXT_PHY2].req_line_speed == SPEED_1000)
5440 val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G;
5441
5442 bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
5443 MDIO_CTL_REG_84823_MEDIA, val);
5444 DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
5445 params->multi_phy_config, val);
5446
5447 if (initialize)
5448 rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
5449 else
5450 bnx2x_save_848xx_spirom_version(phy, params);
5451 return rc;
de6eae1f 5452}
ea4e040a 5453
de6eae1f
YR
5454static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
5455 struct link_params *params,
5456 struct link_vars *vars)
5457{
5458 struct bnx2x *bp = params->bp;
5459 u16 val, val1, val2;
5460 u8 link_up = 0;
ea4e040a 5461
de6eae1f
YR
5462 /* Check 10G-BaseT link status */
5463 /* Check PMD signal ok */
5464 bnx2x_cl45_read(bp, phy,
5465 MDIO_AN_DEVAD, 0xFFFA, &val1);
5466 bnx2x_cl45_read(bp, phy,
5467 MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL,
5468 &val2);
5469 DP(NETIF_MSG_LINK, "BCM848xx: PMD_SIGNAL 1.a811 = 0x%x\n", val2);
ea4e040a 5470
de6eae1f
YR
5471 /* Check link 10G */
5472 if (val2 & (1<<11)) {
ea4e040a 5473 vars->line_speed = SPEED_10000;
de6eae1f
YR
5474 link_up = 1;
5475 bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
5476 } else { /* Check Legacy speed link */
5477 u16 legacy_status, legacy_speed;
ea4e040a 5478
de6eae1f
YR
5479 /* Enable expansion register 0x42 (Operation mode status) */
5480 bnx2x_cl45_write(bp, phy,
5481 MDIO_AN_DEVAD,
5482 MDIO_AN_REG_8481_EXPANSION_REG_ACCESS, 0xf42);
ea4e040a 5483
de6eae1f
YR
5484 /* Get legacy speed operation status */
5485 bnx2x_cl45_read(bp, phy,
5486 MDIO_AN_DEVAD,
5487 MDIO_AN_REG_8481_EXPANSION_REG_RD_RW,
5488 &legacy_status);
ea4e040a 5489
de6eae1f
YR
5490 DP(NETIF_MSG_LINK, "Legacy speed status"
5491 " = 0x%x\n", legacy_status);
5492 link_up = ((legacy_status & (1<<11)) == (1<<11));
5493 if (link_up) {
5494 legacy_speed = (legacy_status & (3<<9));
5495 if (legacy_speed == (0<<9))
5496 vars->line_speed = SPEED_10;
5497 else if (legacy_speed == (1<<9))
5498 vars->line_speed = SPEED_100;
5499 else if (legacy_speed == (2<<9))
5500 vars->line_speed = SPEED_1000;
5501 else /* Should not happen */
5502 vars->line_speed = 0;
ea4e040a 5503
de6eae1f
YR
5504 if (legacy_status & (1<<8))
5505 vars->duplex = DUPLEX_FULL;
5506 else
5507 vars->duplex = DUPLEX_HALF;
ea4e040a 5508
de6eae1f
YR
5509 DP(NETIF_MSG_LINK, "Link is up in %dMbps,"
5510 " is_duplex_full= %d\n", vars->line_speed,
5511 (vars->duplex == DUPLEX_FULL));
5512 /* Check legacy speed AN resolution */
5513 bnx2x_cl45_read(bp, phy,
5514 MDIO_AN_DEVAD,
5515 MDIO_AN_REG_8481_LEGACY_MII_STATUS,
5516 &val);
5517 if (val & (1<<5))
5518 vars->link_status |=
5519 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
5520 bnx2x_cl45_read(bp, phy,
5521 MDIO_AN_DEVAD,
5522 MDIO_AN_REG_8481_LEGACY_AN_EXPANSION,
5523 &val);
5524 if ((val & (1<<0)) == 0)
5525 vars->link_status |=
5526 LINK_STATUS_PARALLEL_DETECTION_USED;
ea4e040a 5527 }
ea4e040a 5528 }
de6eae1f
YR
5529 if (link_up) {
5530 DP(NETIF_MSG_LINK, "BCM84823: link speed is %d\n",
5531 vars->line_speed);
5532 bnx2x_ext_phy_resolve_fc(phy, params, vars);
5533 }
589abe3a 5534
de6eae1f 5535 return link_up;
b7737c9b
YR
5536}
5537
de6eae1f 5538static u8 bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
b7737c9b 5539{
de6eae1f
YR
5540 u8 status = 0;
5541 u32 spirom_ver;
5542 spirom_ver = ((raw_ver & 0xF80) >> 7) << 16 | (raw_ver & 0x7F);
5543 status = bnx2x_format_ver(spirom_ver, str, len);
5544 return status;
b7737c9b 5545}
de6eae1f
YR
5546
5547static void bnx2x_8481_hw_reset(struct bnx2x_phy *phy,
5548 struct link_params *params)
b7737c9b 5549{
de6eae1f
YR
5550 bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
5551 MISC_REGISTERS_GPIO_OUTPUT_LOW, 0);
5552 bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
5553 MISC_REGISTERS_GPIO_OUTPUT_LOW, 1);
b7737c9b 5554}
de6eae1f 5555
b7737c9b
YR
5556static void bnx2x_8481_link_reset(struct bnx2x_phy *phy,
5557 struct link_params *params)
5558{
5559 bnx2x_cl45_write(params->bp, phy,
5560 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
5561 bnx2x_cl45_write(params->bp, phy,
5562 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1);
5563}
5564
5565static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
5566 struct link_params *params)
5567{
5568 struct bnx2x *bp = params->bp;
5569 u8 port = params->port;
5570 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
5571 MISC_REGISTERS_GPIO_OUTPUT_LOW,
5572 port);
5573}
5574
7f02c4ad
YR
5575static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
5576 struct link_params *params, u8 mode)
5577{
5578 struct bnx2x *bp = params->bp;
5579 u16 val;
5580
5581 switch (mode) {
5582 case LED_MODE_OFF:
5583
5584 DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OFF\n", params->port);
5585
5586 if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
5587 SHARED_HW_CFG_LED_EXTPHY1) {
5588
5589 /* Set LED masks */
5590 bnx2x_cl45_write(bp, phy,
5591 MDIO_PMA_DEVAD,
5592 MDIO_PMA_REG_8481_LED1_MASK,
5593 0x0);
5594
5595 bnx2x_cl45_write(bp, phy,
5596 MDIO_PMA_DEVAD,
5597 MDIO_PMA_REG_8481_LED2_MASK,
5598 0x0);
5599
5600 bnx2x_cl45_write(bp, phy,
5601 MDIO_PMA_DEVAD,
5602 MDIO_PMA_REG_8481_LED3_MASK,
5603 0x0);
5604
5605 bnx2x_cl45_write(bp, phy,
5606 MDIO_PMA_DEVAD,
5607 MDIO_PMA_REG_8481_LED5_MASK,
5608 0x0);
5609
5610 } else {
5611 bnx2x_cl45_write(bp, phy,
5612 MDIO_PMA_DEVAD,
5613 MDIO_PMA_REG_8481_LED1_MASK,
5614 0x0);
5615 }
5616 break;
5617 case LED_MODE_FRONT_PANEL_OFF:
5618
5619 DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE FRONT PANEL OFF\n",
5620 params->port);
5621
5622 if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
5623 SHARED_HW_CFG_LED_EXTPHY1) {
5624
5625 /* Set LED masks */
5626 bnx2x_cl45_write(bp, phy,
5627 MDIO_PMA_DEVAD,
5628 MDIO_PMA_REG_8481_LED1_MASK,
5629 0x0);
5630
5631 bnx2x_cl45_write(bp, phy,
5632 MDIO_PMA_DEVAD,
5633 MDIO_PMA_REG_8481_LED2_MASK,
5634 0x0);
5635
5636 bnx2x_cl45_write(bp, phy,
5637 MDIO_PMA_DEVAD,
5638 MDIO_PMA_REG_8481_LED3_MASK,
5639 0x0);
5640
5641 bnx2x_cl45_write(bp, phy,
5642 MDIO_PMA_DEVAD,
5643 MDIO_PMA_REG_8481_LED5_MASK,
5644 0x20);
5645
5646 } else {
5647 bnx2x_cl45_write(bp, phy,
5648 MDIO_PMA_DEVAD,
5649 MDIO_PMA_REG_8481_LED1_MASK,
5650 0x0);
5651 }
5652 break;
5653 case LED_MODE_ON:
5654
5655 DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE ON\n", params->port);
5656
5657 if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
5658 SHARED_HW_CFG_LED_EXTPHY1) {
5659 /* Set control reg */
5660 bnx2x_cl45_read(bp, phy,
5661 MDIO_PMA_DEVAD,
5662 MDIO_PMA_REG_8481_LINK_SIGNAL,
5663 &val);
5664 val &= 0x8000;
5665 val |= 0x2492;
5666
5667 bnx2x_cl45_write(bp, phy,
5668 MDIO_PMA_DEVAD,
5669 MDIO_PMA_REG_8481_LINK_SIGNAL,
5670 val);
5671
5672 /* Set LED masks */
5673 bnx2x_cl45_write(bp, phy,
5674 MDIO_PMA_DEVAD,
5675 MDIO_PMA_REG_8481_LED1_MASK,
5676 0x0);
5677
5678 bnx2x_cl45_write(bp, phy,
5679 MDIO_PMA_DEVAD,
5680 MDIO_PMA_REG_8481_LED2_MASK,
5681 0x20);
5682
5683 bnx2x_cl45_write(bp, phy,
5684 MDIO_PMA_DEVAD,
5685 MDIO_PMA_REG_8481_LED3_MASK,
5686 0x20);
5687
5688 bnx2x_cl45_write(bp, phy,
5689 MDIO_PMA_DEVAD,
5690 MDIO_PMA_REG_8481_LED5_MASK,
5691 0x0);
5692 } else {
5693 bnx2x_cl45_write(bp, phy,
5694 MDIO_PMA_DEVAD,
5695 MDIO_PMA_REG_8481_LED1_MASK,
5696 0x20);
5697 }
5698 break;
5699
5700 case LED_MODE_OPER:
5701
5702 DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OPER\n", params->port);
5703
5704 if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
5705 SHARED_HW_CFG_LED_EXTPHY1) {
5706
5707 /* Set control reg */
5708 bnx2x_cl45_read(bp, phy,
5709 MDIO_PMA_DEVAD,
5710 MDIO_PMA_REG_8481_LINK_SIGNAL,
5711 &val);
5712
5713 if (!((val &
5714 MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK)
5715 >> MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT)){
5716 DP(NETIF_MSG_LINK, "Seting LINK_SIGNAL\n");
5717 bnx2x_cl45_write(bp, phy,
5718 MDIO_PMA_DEVAD,
5719 MDIO_PMA_REG_8481_LINK_SIGNAL,
5720 0xa492);
5721 }
5722
5723 /* Set LED masks */
5724 bnx2x_cl45_write(bp, phy,
5725 MDIO_PMA_DEVAD,
5726 MDIO_PMA_REG_8481_LED1_MASK,
5727 0x10);
5728
5729 bnx2x_cl45_write(bp, phy,
5730 MDIO_PMA_DEVAD,
5731 MDIO_PMA_REG_8481_LED2_MASK,
5732 0x80);
5733
5734 bnx2x_cl45_write(bp, phy,
5735 MDIO_PMA_DEVAD,
5736 MDIO_PMA_REG_8481_LED3_MASK,
5737 0x98);
5738
5739 bnx2x_cl45_write(bp, phy,
5740 MDIO_PMA_DEVAD,
5741 MDIO_PMA_REG_8481_LED5_MASK,
5742 0x40);
5743
5744 } else {
5745 bnx2x_cl45_write(bp, phy,
5746 MDIO_PMA_DEVAD,
5747 MDIO_PMA_REG_8481_LED1_MASK,
5748 0x80);
5749 }
5750 break;
5751 }
5752}
de6eae1f
YR
5753/******************************************************************/
5754/* SFX7101 PHY SECTION */
5755/******************************************************************/
5756static void bnx2x_7101_config_loopback(struct bnx2x_phy *phy,
5757 struct link_params *params)
b7737c9b
YR
5758{
5759 struct bnx2x *bp = params->bp;
de6eae1f
YR
5760 /* SFX7101_XGXS_TEST1 */
5761 bnx2x_cl45_write(bp, phy,
5762 MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100);
589abe3a
EG
5763}
5764
de6eae1f
YR
5765static u8 bnx2x_7101_config_init(struct bnx2x_phy *phy,
5766 struct link_params *params,
5767 struct link_vars *vars)
ea4e040a 5768{
de6eae1f 5769 u16 fw_ver1, fw_ver2, val;
ea4e040a 5770 struct bnx2x *bp = params->bp;
de6eae1f 5771 DP(NETIF_MSG_LINK, "Setting the SFX7101 LASI indication\n");
ea4e040a 5772
de6eae1f
YR
5773 /* Restore normal power mode*/
5774 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
5775 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
5776 /* HW reset */
5777 bnx2x_ext_phy_hw_reset(bp, params->port);
5778 bnx2x_wait_reset_complete(bp, phy);
ea4e040a 5779
de6eae1f
YR
5780 bnx2x_cl45_write(bp, phy,
5781 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x1);
5782 DP(NETIF_MSG_LINK, "Setting the SFX7101 LED to blink on traffic\n");
5783 bnx2x_cl45_write(bp, phy,
5784 MDIO_PMA_DEVAD, MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
ea4e040a 5785
de6eae1f
YR
5786 bnx2x_ext_phy_set_pause(params, phy, vars);
5787 /* Restart autoneg */
5788 bnx2x_cl45_read(bp, phy,
5789 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, &val);
5790 val |= 0x200;
5791 bnx2x_cl45_write(bp, phy,
5792 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, val);
ea4e040a 5793
de6eae1f
YR
5794 /* Save spirom version */
5795 bnx2x_cl45_read(bp, phy,
5796 MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER1, &fw_ver1);
ea4e040a 5797
de6eae1f
YR
5798 bnx2x_cl45_read(bp, phy,
5799 MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2, &fw_ver2);
5800 bnx2x_save_spirom_version(bp, params->port,
5801 (u32)(fw_ver1<<16 | fw_ver2), phy->ver_addr);
5802 return 0;
5803}
ea4e040a 5804
de6eae1f
YR
5805static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
5806 struct link_params *params,
5807 struct link_vars *vars)
57963ed9
YR
5808{
5809 struct bnx2x *bp = params->bp;
de6eae1f
YR
5810 u8 link_up;
5811 u16 val1, val2;
5812 bnx2x_cl45_read(bp, phy,
5813 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2);
5814 bnx2x_cl45_read(bp, phy,
5815 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
5816 DP(NETIF_MSG_LINK, "10G-base-T LASI status 0x%x->0x%x\n",
5817 val2, val1);
5818 bnx2x_cl45_read(bp, phy,
5819 MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
5820 bnx2x_cl45_read(bp, phy,
5821 MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
5822 DP(NETIF_MSG_LINK, "10G-base-T PMA status 0x%x->0x%x\n",
5823 val2, val1);
5824 link_up = ((val1 & 4) == 4);
5825 /* if link is up
5826 * print the AN outcome of the SFX7101 PHY
5827 */
5828 if (link_up) {
5829 bnx2x_cl45_read(bp, phy,
5830 MDIO_AN_DEVAD, MDIO_AN_REG_MASTER_STATUS,
5831 &val2);
5832 vars->line_speed = SPEED_10000;
5833 DP(NETIF_MSG_LINK, "SFX7101 AN status 0x%x->Master=%x\n",
5834 val2, (val2 & (1<<14)));
5835 bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
5836 bnx2x_ext_phy_resolve_fc(phy, params, vars);
5837 }
5838 return link_up;
5839}
6c55c3cd 5840
6c55c3cd 5841
de6eae1f
YR
5842static u8 bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
5843{
5844 if (*len < 5)
5845 return -EINVAL;
5846 str[0] = (spirom_ver & 0xFF);
5847 str[1] = (spirom_ver & 0xFF00) >> 8;
5848 str[2] = (spirom_ver & 0xFF0000) >> 16;
5849 str[3] = (spirom_ver & 0xFF000000) >> 24;
5850 str[4] = '\0';
5851 *len -= 5;
57963ed9
YR
5852 return 0;
5853}
5854
de6eae1f 5855void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy)
57963ed9 5856{
de6eae1f 5857 u16 val, cnt;
7aa0711f 5858
de6eae1f
YR
5859 bnx2x_cl45_read(bp, phy,
5860 MDIO_PMA_DEVAD,
5861 MDIO_PMA_REG_7101_RESET, &val);
57963ed9 5862
de6eae1f
YR
5863 for (cnt = 0; cnt < 10; cnt++) {
5864 msleep(50);
5865 /* Writes a self-clearing reset */
5866 bnx2x_cl45_write(bp, phy,
5867 MDIO_PMA_DEVAD,
5868 MDIO_PMA_REG_7101_RESET,
5869 (val | (1<<15)));
5870 /* Wait for clear */
5871 bnx2x_cl45_read(bp, phy,
5872 MDIO_PMA_DEVAD,
5873 MDIO_PMA_REG_7101_RESET, &val);
0c786f02 5874
de6eae1f
YR
5875 if ((val & (1<<15)) == 0)
5876 break;
57963ed9 5877 }
57963ed9 5878}
ea4e040a 5879
de6eae1f
YR
5880static void bnx2x_7101_hw_reset(struct bnx2x_phy *phy,
5881 struct link_params *params) {
5882 /* Low power mode is controlled by GPIO 2 */
5883 bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_2,
5884 MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
5885 /* The PHY reset is controlled by GPIO 1 */
5886 bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
5887 MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
5888}
ea4e040a 5889
7f02c4ad
YR
5890static void bnx2x_7101_set_link_led(struct bnx2x_phy *phy,
5891 struct link_params *params, u8 mode)
5892{
5893 u16 val = 0;
5894 struct bnx2x *bp = params->bp;
5895 switch (mode) {
5896 case LED_MODE_FRONT_PANEL_OFF:
5897 case LED_MODE_OFF:
5898 val = 2;
5899 break;
5900 case LED_MODE_ON:
5901 val = 1;
5902 break;
5903 case LED_MODE_OPER:
5904 val = 0;
5905 break;
5906 }
5907 bnx2x_cl45_write(bp, phy,
5908 MDIO_PMA_DEVAD,
5909 MDIO_PMA_REG_7107_LINK_LED_CNTL,
5910 val);
5911}
5912
de6eae1f
YR
5913/******************************************************************/
5914/* STATIC PHY DECLARATION */
5915/******************************************************************/
ea4e040a 5916
de6eae1f
YR
5917static struct bnx2x_phy phy_null = {
5918 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
5919 .addr = 0,
5920 .flags = FLAGS_INIT_XGXS_FIRST,
5921 .def_md_devad = 0,
5922 .reserved = 0,
5923 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
5924 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
5925 .mdio_ctrl = 0,
5926 .supported = 0,
5927 .media_type = ETH_PHY_NOT_PRESENT,
5928 .ver_addr = 0,
5929 .req_flow_ctrl = 0,
5930 .req_line_speed = 0,
5931 .speed_cap_mask = 0,
5932 .req_duplex = 0,
5933 .rsrv = 0,
5934 .config_init = (config_init_t)NULL,
5935 .read_status = (read_status_t)NULL,
5936 .link_reset = (link_reset_t)NULL,
5937 .config_loopback = (config_loopback_t)NULL,
5938 .format_fw_ver = (format_fw_ver_t)NULL,
5939 .hw_reset = (hw_reset_t)NULL,
a22f0788
YR
5940 .set_link_led = (set_link_led_t)NULL,
5941 .phy_specific_func = (phy_specific_func_t)NULL
de6eae1f 5942};
ea4e040a 5943
de6eae1f
YR
5944static struct bnx2x_phy phy_serdes = {
5945 .type = PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
5946 .addr = 0xff,
5947 .flags = 0,
5948 .def_md_devad = 0,
5949 .reserved = 0,
5950 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
5951 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
5952 .mdio_ctrl = 0,
5953 .supported = (SUPPORTED_10baseT_Half |
5954 SUPPORTED_10baseT_Full |
5955 SUPPORTED_100baseT_Half |
5956 SUPPORTED_100baseT_Full |
5957 SUPPORTED_1000baseT_Full |
5958 SUPPORTED_2500baseX_Full |
5959 SUPPORTED_TP |
5960 SUPPORTED_Autoneg |
5961 SUPPORTED_Pause |
5962 SUPPORTED_Asym_Pause),
5963 .media_type = ETH_PHY_UNSPECIFIED,
5964 .ver_addr = 0,
5965 .req_flow_ctrl = 0,
5966 .req_line_speed = 0,
5967 .speed_cap_mask = 0,
5968 .req_duplex = 0,
5969 .rsrv = 0,
5970 .config_init = (config_init_t)bnx2x_init_serdes,
5971 .read_status = (read_status_t)bnx2x_link_settings_status,
5972 .link_reset = (link_reset_t)bnx2x_int_link_reset,
5973 .config_loopback = (config_loopback_t)NULL,
5974 .format_fw_ver = (format_fw_ver_t)NULL,
5975 .hw_reset = (hw_reset_t)NULL,
a22f0788
YR
5976 .set_link_led = (set_link_led_t)NULL,
5977 .phy_specific_func = (phy_specific_func_t)NULL
de6eae1f 5978};
b7737c9b
YR
5979
5980static struct bnx2x_phy phy_xgxs = {
5981 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
5982 .addr = 0xff,
5983 .flags = 0,
5984 .def_md_devad = 0,
5985 .reserved = 0,
5986 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
5987 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
5988 .mdio_ctrl = 0,
5989 .supported = (SUPPORTED_10baseT_Half |
5990 SUPPORTED_10baseT_Full |
5991 SUPPORTED_100baseT_Half |
5992 SUPPORTED_100baseT_Full |
5993 SUPPORTED_1000baseT_Full |
5994 SUPPORTED_2500baseX_Full |
5995 SUPPORTED_10000baseT_Full |
5996 SUPPORTED_FIBRE |
5997 SUPPORTED_Autoneg |
5998 SUPPORTED_Pause |
5999 SUPPORTED_Asym_Pause),
6000 .media_type = ETH_PHY_UNSPECIFIED,
6001 .ver_addr = 0,
6002 .req_flow_ctrl = 0,
6003 .req_line_speed = 0,
6004 .speed_cap_mask = 0,
6005 .req_duplex = 0,
6006 .rsrv = 0,
6007 .config_init = (config_init_t)bnx2x_init_xgxs,
6008 .read_status = (read_status_t)bnx2x_link_settings_status,
6009 .link_reset = (link_reset_t)bnx2x_int_link_reset,
6010 .config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback,
6011 .format_fw_ver = (format_fw_ver_t)NULL,
6012 .hw_reset = (hw_reset_t)NULL,
a22f0788
YR
6013 .set_link_led = (set_link_led_t)NULL,
6014 .phy_specific_func = (phy_specific_func_t)NULL
b7737c9b
YR
6015};
6016
6017static struct bnx2x_phy phy_7101 = {
6018 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
6019 .addr = 0xff,
6020 .flags = FLAGS_FAN_FAILURE_DET_REQ,
6021 .def_md_devad = 0,
6022 .reserved = 0,
6023 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6024 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6025 .mdio_ctrl = 0,
6026 .supported = (SUPPORTED_10000baseT_Full |
6027 SUPPORTED_TP |
6028 SUPPORTED_Autoneg |
6029 SUPPORTED_Pause |
6030 SUPPORTED_Asym_Pause),
6031 .media_type = ETH_PHY_BASE_T,
6032 .ver_addr = 0,
6033 .req_flow_ctrl = 0,
6034 .req_line_speed = 0,
6035 .speed_cap_mask = 0,
6036 .req_duplex = 0,
6037 .rsrv = 0,
6038 .config_init = (config_init_t)bnx2x_7101_config_init,
6039 .read_status = (read_status_t)bnx2x_7101_read_status,
6040 .link_reset = (link_reset_t)bnx2x_common_ext_link_reset,
6041 .config_loopback = (config_loopback_t)bnx2x_7101_config_loopback,
6042 .format_fw_ver = (format_fw_ver_t)bnx2x_7101_format_ver,
6043 .hw_reset = (hw_reset_t)bnx2x_7101_hw_reset,
7f02c4ad 6044 .set_link_led = (set_link_led_t)bnx2x_7101_set_link_led,
a22f0788 6045 .phy_specific_func = (phy_specific_func_t)NULL
b7737c9b
YR
6046};
6047static struct bnx2x_phy phy_8073 = {
6048 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
6049 .addr = 0xff,
6050 .flags = FLAGS_HW_LOCK_REQUIRED,
6051 .def_md_devad = 0,
6052 .reserved = 0,
6053 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6054 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6055 .mdio_ctrl = 0,
6056 .supported = (SUPPORTED_10000baseT_Full |
6057 SUPPORTED_2500baseX_Full |
6058 SUPPORTED_1000baseT_Full |
6059 SUPPORTED_FIBRE |
6060 SUPPORTED_Autoneg |
6061 SUPPORTED_Pause |
6062 SUPPORTED_Asym_Pause),
6063 .media_type = ETH_PHY_UNSPECIFIED,
6064 .ver_addr = 0,
6065 .req_flow_ctrl = 0,
6066 .req_line_speed = 0,
6067 .speed_cap_mask = 0,
6068 .req_duplex = 0,
6069 .rsrv = 0,
62b29a5d 6070 .config_init = (config_init_t)bnx2x_8073_config_init,
b7737c9b
YR
6071 .read_status = (read_status_t)bnx2x_8073_read_status,
6072 .link_reset = (link_reset_t)bnx2x_8073_link_reset,
6073 .config_loopback = (config_loopback_t)NULL,
6074 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
6075 .hw_reset = (hw_reset_t)NULL,
a22f0788
YR
6076 .set_link_led = (set_link_led_t)NULL,
6077 .phy_specific_func = (phy_specific_func_t)NULL
b7737c9b
YR
6078};
6079static struct bnx2x_phy phy_8705 = {
6080 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
6081 .addr = 0xff,
6082 .flags = FLAGS_INIT_XGXS_FIRST,
6083 .def_md_devad = 0,
6084 .reserved = 0,
6085 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6086 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6087 .mdio_ctrl = 0,
6088 .supported = (SUPPORTED_10000baseT_Full |
6089 SUPPORTED_FIBRE |
6090 SUPPORTED_Pause |
6091 SUPPORTED_Asym_Pause),
6092 .media_type = ETH_PHY_XFP_FIBER,
6093 .ver_addr = 0,
6094 .req_flow_ctrl = 0,
6095 .req_line_speed = 0,
6096 .speed_cap_mask = 0,
6097 .req_duplex = 0,
6098 .rsrv = 0,
6099 .config_init = (config_init_t)bnx2x_8705_config_init,
6100 .read_status = (read_status_t)bnx2x_8705_read_status,
6101 .link_reset = (link_reset_t)bnx2x_common_ext_link_reset,
6102 .config_loopback = (config_loopback_t)NULL,
6103 .format_fw_ver = (format_fw_ver_t)bnx2x_null_format_ver,
6104 .hw_reset = (hw_reset_t)NULL,
a22f0788
YR
6105 .set_link_led = (set_link_led_t)NULL,
6106 .phy_specific_func = (phy_specific_func_t)NULL
b7737c9b
YR
6107};
6108static struct bnx2x_phy phy_8706 = {
6109 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
6110 .addr = 0xff,
6111 .flags = FLAGS_INIT_XGXS_FIRST,
6112 .def_md_devad = 0,
6113 .reserved = 0,
6114 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6115 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6116 .mdio_ctrl = 0,
6117 .supported = (SUPPORTED_10000baseT_Full |
6118 SUPPORTED_1000baseT_Full |
6119 SUPPORTED_FIBRE |
6120 SUPPORTED_Pause |
6121 SUPPORTED_Asym_Pause),
6122 .media_type = ETH_PHY_SFP_FIBER,
6123 .ver_addr = 0,
6124 .req_flow_ctrl = 0,
6125 .req_line_speed = 0,
6126 .speed_cap_mask = 0,
6127 .req_duplex = 0,
6128 .rsrv = 0,
6129 .config_init = (config_init_t)bnx2x_8706_config_init,
6130 .read_status = (read_status_t)bnx2x_8706_read_status,
6131 .link_reset = (link_reset_t)bnx2x_common_ext_link_reset,
6132 .config_loopback = (config_loopback_t)NULL,
6133 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
6134 .hw_reset = (hw_reset_t)NULL,
a22f0788
YR
6135 .set_link_led = (set_link_led_t)NULL,
6136 .phy_specific_func = (phy_specific_func_t)NULL
b7737c9b
YR
6137};
6138
6139static struct bnx2x_phy phy_8726 = {
6140 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
6141 .addr = 0xff,
6142 .flags = (FLAGS_HW_LOCK_REQUIRED |
6143 FLAGS_INIT_XGXS_FIRST),
6144 .def_md_devad = 0,
6145 .reserved = 0,
6146 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6147 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6148 .mdio_ctrl = 0,
6149 .supported = (SUPPORTED_10000baseT_Full |
6150 SUPPORTED_1000baseT_Full |
6151 SUPPORTED_Autoneg |
6152 SUPPORTED_FIBRE |
6153 SUPPORTED_Pause |
6154 SUPPORTED_Asym_Pause),
6155 .media_type = ETH_PHY_SFP_FIBER,
6156 .ver_addr = 0,
6157 .req_flow_ctrl = 0,
6158 .req_line_speed = 0,
6159 .speed_cap_mask = 0,
6160 .req_duplex = 0,
6161 .rsrv = 0,
6162 .config_init = (config_init_t)bnx2x_8726_config_init,
6163 .read_status = (read_status_t)bnx2x_8726_read_status,
6164 .link_reset = (link_reset_t)bnx2x_8726_link_reset,
6165 .config_loopback = (config_loopback_t)bnx2x_8726_config_loopback,
6166 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
6167 .hw_reset = (hw_reset_t)NULL,
a22f0788
YR
6168 .set_link_led = (set_link_led_t)NULL,
6169 .phy_specific_func = (phy_specific_func_t)NULL
b7737c9b
YR
6170};
6171
6172static struct bnx2x_phy phy_8727 = {
6173 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
6174 .addr = 0xff,
6175 .flags = FLAGS_FAN_FAILURE_DET_REQ,
6176 .def_md_devad = 0,
6177 .reserved = 0,
6178 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6179 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6180 .mdio_ctrl = 0,
6181 .supported = (SUPPORTED_10000baseT_Full |
6182 SUPPORTED_1000baseT_Full |
b7737c9b
YR
6183 SUPPORTED_FIBRE |
6184 SUPPORTED_Pause |
6185 SUPPORTED_Asym_Pause),
6186 .media_type = ETH_PHY_SFP_FIBER,
6187 .ver_addr = 0,
6188 .req_flow_ctrl = 0,
6189 .req_line_speed = 0,
6190 .speed_cap_mask = 0,
6191 .req_duplex = 0,
6192 .rsrv = 0,
6193 .config_init = (config_init_t)bnx2x_8727_config_init,
6194 .read_status = (read_status_t)bnx2x_8727_read_status,
6195 .link_reset = (link_reset_t)bnx2x_8727_link_reset,
6196 .config_loopback = (config_loopback_t)NULL,
6197 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
6198 .hw_reset = (hw_reset_t)bnx2x_8727_hw_reset,
7f02c4ad 6199 .set_link_led = (set_link_led_t)bnx2x_8727_set_link_led,
a22f0788 6200 .phy_specific_func = (phy_specific_func_t)bnx2x_8727_specific_func
b7737c9b
YR
6201};
6202static struct bnx2x_phy phy_8481 = {
6203 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
6204 .addr = 0xff,
a22f0788
YR
6205 .flags = FLAGS_FAN_FAILURE_DET_REQ |
6206 FLAGS_REARM_LATCH_SIGNAL,
b7737c9b
YR
6207 .def_md_devad = 0,
6208 .reserved = 0,
6209 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6210 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6211 .mdio_ctrl = 0,
6212 .supported = (SUPPORTED_10baseT_Half |
6213 SUPPORTED_10baseT_Full |
6214 SUPPORTED_100baseT_Half |
6215 SUPPORTED_100baseT_Full |
6216 SUPPORTED_1000baseT_Full |
6217 SUPPORTED_10000baseT_Full |
6218 SUPPORTED_TP |
6219 SUPPORTED_Autoneg |
6220 SUPPORTED_Pause |
6221 SUPPORTED_Asym_Pause),
6222 .media_type = ETH_PHY_BASE_T,
6223 .ver_addr = 0,
6224 .req_flow_ctrl = 0,
6225 .req_line_speed = 0,
6226 .speed_cap_mask = 0,
6227 .req_duplex = 0,
6228 .rsrv = 0,
6229 .config_init = (config_init_t)bnx2x_8481_config_init,
6230 .read_status = (read_status_t)bnx2x_848xx_read_status,
6231 .link_reset = (link_reset_t)bnx2x_8481_link_reset,
6232 .config_loopback = (config_loopback_t)NULL,
6233 .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver,
6234 .hw_reset = (hw_reset_t)bnx2x_8481_hw_reset,
7f02c4ad 6235 .set_link_led = (set_link_led_t)bnx2x_848xx_set_link_led,
a22f0788 6236 .phy_specific_func = (phy_specific_func_t)NULL
b7737c9b
YR
6237};
6238
de6eae1f
YR
6239static struct bnx2x_phy phy_84823 = {
6240 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
6241 .addr = 0xff,
a22f0788
YR
6242 .flags = FLAGS_FAN_FAILURE_DET_REQ |
6243 FLAGS_REARM_LATCH_SIGNAL,
de6eae1f
YR
6244 .def_md_devad = 0,
6245 .reserved = 0,
6246 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6247 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6248 .mdio_ctrl = 0,
6249 .supported = (SUPPORTED_10baseT_Half |
6250 SUPPORTED_10baseT_Full |
6251 SUPPORTED_100baseT_Half |
6252 SUPPORTED_100baseT_Full |
6253 SUPPORTED_1000baseT_Full |
6254 SUPPORTED_10000baseT_Full |
6255 SUPPORTED_TP |
6256 SUPPORTED_Autoneg |
6257 SUPPORTED_Pause |
6258 SUPPORTED_Asym_Pause),
6259 .media_type = ETH_PHY_BASE_T,
6260 .ver_addr = 0,
6261 .req_flow_ctrl = 0,
6262 .req_line_speed = 0,
6263 .speed_cap_mask = 0,
6264 .req_duplex = 0,
6265 .rsrv = 0,
6266 .config_init = (config_init_t)bnx2x_848x3_config_init,
6267 .read_status = (read_status_t)bnx2x_848xx_read_status,
6268 .link_reset = (link_reset_t)bnx2x_848x3_link_reset,
6269 .config_loopback = (config_loopback_t)NULL,
6270 .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver,
6271 .hw_reset = (hw_reset_t)NULL,
7f02c4ad 6272 .set_link_led = (set_link_led_t)bnx2x_848xx_set_link_led,
a22f0788 6273 .phy_specific_func = (phy_specific_func_t)NULL
de6eae1f
YR
6274};
6275
6276/*****************************************************************/
6277/* */
6278/* Populate the phy according. Main function: bnx2x_populate_phy */
6279/* */
6280/*****************************************************************/
6281
6282static void bnx2x_populate_preemphasis(struct bnx2x *bp, u32 shmem_base,
6283 struct bnx2x_phy *phy, u8 port,
6284 u8 phy_index)
6285{
6286 /* Get the 4 lanes xgxs config rx and tx */
6287 u32 rx = 0, tx = 0, i;
6288 for (i = 0; i < 2; i++) {
6289 /**
6290 * INT_PHY and EXT_PHY1 share the same value location in the
6291 * shmem. When num_phys is greater than 1, than this value
6292 * applies only to EXT_PHY1
6293 */
a22f0788
YR
6294 if (phy_index == INT_PHY || phy_index == EXT_PHY1) {
6295 rx = REG_RD(bp, shmem_base +
6296 offsetof(struct shmem_region,
6297 dev_info.port_hw_config[port].xgxs_config_rx[i<<1]));
6298
6299 tx = REG_RD(bp, shmem_base +
6300 offsetof(struct shmem_region,
6301 dev_info.port_hw_config[port].xgxs_config_tx[i<<1]));
6302 } else {
6303 rx = REG_RD(bp, shmem_base +
6304 offsetof(struct shmem_region,
6305 dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
de6eae1f 6306
a22f0788
YR
6307 tx = REG_RD(bp, shmem_base +
6308 offsetof(struct shmem_region,
6309 dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
6310 }
de6eae1f
YR
6311
6312 phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff);
6313 phy->rx_preemphasis[(i << 1) + 1] = (rx & 0xffff);
6314
6315 phy->tx_preemphasis[i << 1] = ((tx>>16) & 0xffff);
6316 phy->tx_preemphasis[(i << 1) + 1] = (tx & 0xffff);
6317 }
6318}
6319
6320static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base,
6321 u8 phy_index, u8 port)
6322{
6323 u32 ext_phy_config = 0;
6324 switch (phy_index) {
6325 case EXT_PHY1:
6326 ext_phy_config = REG_RD(bp, shmem_base +
6327 offsetof(struct shmem_region,
6328 dev_info.port_hw_config[port].external_phy_config));
6329 break;
a22f0788
YR
6330 case EXT_PHY2:
6331 ext_phy_config = REG_RD(bp, shmem_base +
6332 offsetof(struct shmem_region,
6333 dev_info.port_hw_config[port].external_phy_config2));
6334 break;
de6eae1f
YR
6335 default:
6336 DP(NETIF_MSG_LINK, "Invalid phy_index %d\n", phy_index);
6337 return -EINVAL;
6338 }
6339
6340 return ext_phy_config;
6341}
6342static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
6343 struct bnx2x_phy *phy)
6344{
6345 u32 phy_addr;
6346 u32 chip_id;
6347 u32 switch_cfg = (REG_RD(bp, shmem_base +
6348 offsetof(struct shmem_region,
6349 dev_info.port_feature_config[port].link_config)) &
6350 PORT_FEATURE_CONNECTED_SWITCH_MASK);
6351 chip_id = REG_RD(bp, MISC_REG_CHIP_NUM) << 16;
6352 switch (switch_cfg) {
6353 case SWITCH_CFG_1G:
6354 phy_addr = REG_RD(bp,
6355 NIG_REG_SERDES0_CTRL_PHY_ADDR +
6356 port * 0x10);
6357 *phy = phy_serdes;
6358 break;
6359 case SWITCH_CFG_10G:
6360 phy_addr = REG_RD(bp,
6361 NIG_REG_XGXS0_CTRL_PHY_ADDR +
6362 port * 0x18);
6363 *phy = phy_xgxs;
6364 break;
6365 default:
6366 DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
6367 return -EINVAL;
6368 }
6369 phy->addr = (u8)phy_addr;
6370 phy->mdio_ctrl = bnx2x_get_emac_base(bp,
6371 SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH,
6372 port);
6373 phy->def_md_devad = DEFAULT_PHY_DEV_ADDR;
6374
6375 DP(NETIF_MSG_LINK, "Internal phy port=%d, addr=0x%x, mdio_ctl=0x%x\n",
6376 port, phy->addr, phy->mdio_ctrl);
6377
6378 bnx2x_populate_preemphasis(bp, shmem_base, phy, port, INT_PHY);
6379 return 0;
6380}
6381
6382static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
6383 u8 phy_index,
6384 u32 shmem_base,
a22f0788 6385 u32 shmem2_base,
de6eae1f
YR
6386 u8 port,
6387 struct bnx2x_phy *phy)
6388{
6389 u32 ext_phy_config, phy_type, config2;
6390 u32 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH;
6391 ext_phy_config = bnx2x_get_ext_phy_config(bp, shmem_base,
6392 phy_index, port);
6393 phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
6394 /* Select the phy type */
6395 switch (phy_type) {
6396 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
6397 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED;
6398 *phy = phy_8073;
6399 break;
6400 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
6401 *phy = phy_8705;
6402 break;
6403 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
6404 *phy = phy_8706;
6405 break;
6406 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
6407 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
6408 *phy = phy_8726;
6409 break;
6410 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
6411 /* BCM8727_NOC => BCM8727 no over current */
6412 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
6413 *phy = phy_8727;
6414 phy->flags |= FLAGS_NOC;
6415 break;
6416 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
6417 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
6418 *phy = phy_8727;
6419 break;
6420 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
6421 *phy = phy_8481;
6422 break;
6423 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
6424 *phy = phy_84823;
6425 break;
6426 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
6427 *phy = phy_7101;
6428 break;
6429 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
6430 *phy = phy_null;
6431 return -EINVAL;
6432 default:
6433 *phy = phy_null;
6434 return 0;
6435 }
6436
6437 phy->addr = XGXS_EXT_PHY_ADDR(ext_phy_config);
6438 bnx2x_populate_preemphasis(bp, shmem_base, phy, port, phy_index);
6439
6440 /**
6441 * The shmem address of the phy version is located on different
6442 * structures. In case this structure is too old, do not set
6443 * the address
6444 */
6445 config2 = REG_RD(bp, shmem_base + offsetof(struct shmem_region,
6446 dev_info.shared_hw_config.config2));
a22f0788
YR
6447 if (phy_index == EXT_PHY1) {
6448 phy->ver_addr = shmem_base + offsetof(struct shmem_region,
6449 port_mb[port].ext_phy_fw_version);
de6eae1f
YR
6450
6451 /* Check specific mdc mdio settings */
6452 if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK)
6453 mdc_mdio_access = config2 &
6454 SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK;
a22f0788
YR
6455 } else {
6456 u32 size = REG_RD(bp, shmem2_base);
de6eae1f 6457
a22f0788
YR
6458 if (size >
6459 offsetof(struct shmem2_region, ext_phy_fw_version2)) {
6460 phy->ver_addr = shmem2_base +
6461 offsetof(struct shmem2_region,
6462 ext_phy_fw_version2[port]);
6463 }
6464 /* Check specific mdc mdio settings */
6465 if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK)
6466 mdc_mdio_access = (config2 &
6467 SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK) >>
6468 (SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT -
6469 SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT);
6470 }
de6eae1f
YR
6471 phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port);
6472
6473 /**
6474 * In case mdc/mdio_access of the external phy is different than the
6475 * mdc/mdio access of the XGXS, a HW lock must be taken in each access
6476 * to prevent one port interfere with another port's CL45 operations.
6477 */
6478 if (mdc_mdio_access != SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH)
6479 phy->flags |= FLAGS_HW_LOCK_REQUIRED;
6480 DP(NETIF_MSG_LINK, "phy_type 0x%x port %d found in index %d\n",
6481 phy_type, port, phy_index);
6482 DP(NETIF_MSG_LINK, " addr=0x%x, mdio_ctl=0x%x\n",
6483 phy->addr, phy->mdio_ctrl);
6484 return 0;
6485}
6486
6487static u8 bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
a22f0788 6488 u32 shmem2_base, u8 port, struct bnx2x_phy *phy)
de6eae1f
YR
6489{
6490 u8 status = 0;
6491 phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN;
6492 if (phy_index == INT_PHY)
6493 return bnx2x_populate_int_phy(bp, shmem_base, port, phy);
a22f0788 6494 status = bnx2x_populate_ext_phy(bp, phy_index, shmem_base, shmem2_base,
de6eae1f
YR
6495 port, phy);
6496 return status;
6497}
6498
6499static void bnx2x_phy_def_cfg(struct link_params *params,
6500 struct bnx2x_phy *phy,
a22f0788 6501 u8 phy_index)
de6eae1f
YR
6502{
6503 struct bnx2x *bp = params->bp;
6504 u32 link_config;
6505 /* Populate the default phy configuration for MF mode */
a22f0788
YR
6506 if (phy_index == EXT_PHY2) {
6507 link_config = REG_RD(bp, params->shmem_base +
6508 offsetof(struct shmem_region, dev_info.
6509 port_feature_config[params->port].link_config2));
6510 phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
6511 offsetof(struct shmem_region, dev_info.
6512 port_hw_config[params->port].speed_capability_mask2));
6513 } else {
6514 link_config = REG_RD(bp, params->shmem_base +
6515 offsetof(struct shmem_region, dev_info.
6516 port_feature_config[params->port].link_config));
6517 phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
de6eae1f 6518 offsetof(struct shmem_region, dev_info.
a22f0788
YR
6519 port_hw_config[params->port].speed_capability_mask));
6520 }
6521 DP(NETIF_MSG_LINK, "Default config phy idx %x cfg 0x%x speed_cap_mask"
6522 " 0x%x\n", phy_index, link_config, phy->speed_cap_mask);
de6eae1f
YR
6523
6524 phy->req_duplex = DUPLEX_FULL;
6525 switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) {
6526 case PORT_FEATURE_LINK_SPEED_10M_HALF:
6527 phy->req_duplex = DUPLEX_HALF;
6528 case PORT_FEATURE_LINK_SPEED_10M_FULL:
6529 phy->req_line_speed = SPEED_10;
6530 break;
6531 case PORT_FEATURE_LINK_SPEED_100M_HALF:
6532 phy->req_duplex = DUPLEX_HALF;
6533 case PORT_FEATURE_LINK_SPEED_100M_FULL:
6534 phy->req_line_speed = SPEED_100;
6535 break;
6536 case PORT_FEATURE_LINK_SPEED_1G:
6537 phy->req_line_speed = SPEED_1000;
6538 break;
6539 case PORT_FEATURE_LINK_SPEED_2_5G:
6540 phy->req_line_speed = SPEED_2500;
6541 break;
6542 case PORT_FEATURE_LINK_SPEED_10G_CX4:
6543 phy->req_line_speed = SPEED_10000;
6544 break;
6545 default:
6546 phy->req_line_speed = SPEED_AUTO_NEG;
6547 break;
6548 }
6549
6550 switch (link_config & PORT_FEATURE_FLOW_CONTROL_MASK) {
6551 case PORT_FEATURE_FLOW_CONTROL_AUTO:
6552 phy->req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
6553 break;
6554 case PORT_FEATURE_FLOW_CONTROL_TX:
6555 phy->req_flow_ctrl = BNX2X_FLOW_CTRL_TX;
6556 break;
6557 case PORT_FEATURE_FLOW_CONTROL_RX:
6558 phy->req_flow_ctrl = BNX2X_FLOW_CTRL_RX;
6559 break;
6560 case PORT_FEATURE_FLOW_CONTROL_BOTH:
6561 phy->req_flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
6562 break;
6563 default:
6564 phy->req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
6565 break;
6566 }
6567}
6568
a22f0788
YR
6569u32 bnx2x_phy_selection(struct link_params *params)
6570{
6571 u32 phy_config_swapped, prio_cfg;
6572 u32 return_cfg = PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT;
6573
6574 phy_config_swapped = params->multi_phy_config &
6575 PORT_HW_CFG_PHY_SWAPPED_ENABLED;
6576
6577 prio_cfg = params->multi_phy_config &
6578 PORT_HW_CFG_PHY_SELECTION_MASK;
6579
6580 if (phy_config_swapped) {
6581 switch (prio_cfg) {
6582 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
6583 return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY;
6584 break;
6585 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
6586 return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY;
6587 break;
6588 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
6589 return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
6590 break;
6591 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
6592 return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
6593 break;
6594 }
6595 } else
6596 return_cfg = prio_cfg;
6597
6598 return return_cfg;
6599}
6600
6601
de6eae1f
YR
6602u8 bnx2x_phy_probe(struct link_params *params)
6603{
6604 u8 phy_index, actual_phy_idx, link_cfg_idx;
a22f0788 6605 u32 phy_config_swapped;
de6eae1f
YR
6606 struct bnx2x *bp = params->bp;
6607 struct bnx2x_phy *phy;
6608 params->num_phys = 0;
6609 DP(NETIF_MSG_LINK, "Begin phy probe\n");
a22f0788
YR
6610 phy_config_swapped = params->multi_phy_config &
6611 PORT_HW_CFG_PHY_SWAPPED_ENABLED;
de6eae1f
YR
6612
6613 for (phy_index = INT_PHY; phy_index < MAX_PHYS;
6614 phy_index++) {
6615 link_cfg_idx = LINK_CONFIG_IDX(phy_index);
6616 actual_phy_idx = phy_index;
a22f0788
YR
6617 if (phy_config_swapped) {
6618 if (phy_index == EXT_PHY1)
6619 actual_phy_idx = EXT_PHY2;
6620 else if (phy_index == EXT_PHY2)
6621 actual_phy_idx = EXT_PHY1;
6622 }
6623 DP(NETIF_MSG_LINK, "phy_config_swapped %x, phy_index %x,"
6624 " actual_phy_idx %x\n", phy_config_swapped,
6625 phy_index, actual_phy_idx);
de6eae1f
YR
6626 phy = &params->phy[actual_phy_idx];
6627 if (bnx2x_populate_phy(bp, phy_index, params->shmem_base,
a22f0788 6628 params->shmem2_base, params->port,
de6eae1f
YR
6629 phy) != 0) {
6630 params->num_phys = 0;
6631 DP(NETIF_MSG_LINK, "phy probe failed in phy index %d\n",
6632 phy_index);
6633 for (phy_index = INT_PHY;
6634 phy_index < MAX_PHYS;
6635 phy_index++)
6636 *phy = phy_null;
6637 return -EINVAL;
6638 }
6639 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
6640 break;
6641
a22f0788 6642 bnx2x_phy_def_cfg(params, phy, phy_index);
de6eae1f
YR
6643 params->num_phys++;
6644 }
6645
6646 DP(NETIF_MSG_LINK, "End phy probe. #phys found %x\n", params->num_phys);
6647 return 0;
6648}
6649
6650u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx)
6651{
6652 if (phy_idx < params->num_phys)
6653 return params->phy[phy_idx].supported;
6654 return 0;
6655}
6656
6657static void set_phy_vars(struct link_params *params)
6658{
6659 struct bnx2x *bp = params->bp;
a22f0788
YR
6660 u8 actual_phy_idx, phy_index, link_cfg_idx;
6661 u8 phy_config_swapped = params->multi_phy_config &
6662 PORT_HW_CFG_PHY_SWAPPED_ENABLED;
de6eae1f
YR
6663 for (phy_index = INT_PHY; phy_index < params->num_phys;
6664 phy_index++) {
a22f0788 6665 link_cfg_idx = LINK_CONFIG_IDX(phy_index);
de6eae1f 6666 actual_phy_idx = phy_index;
a22f0788
YR
6667 if (phy_config_swapped) {
6668 if (phy_index == EXT_PHY1)
6669 actual_phy_idx = EXT_PHY2;
6670 else if (phy_index == EXT_PHY2)
6671 actual_phy_idx = EXT_PHY1;
6672 }
de6eae1f 6673 params->phy[actual_phy_idx].req_flow_ctrl =
a22f0788 6674 params->req_flow_ctrl[link_cfg_idx];
de6eae1f
YR
6675
6676 params->phy[actual_phy_idx].req_line_speed =
a22f0788 6677 params->req_line_speed[link_cfg_idx];
de6eae1f
YR
6678
6679 params->phy[actual_phy_idx].speed_cap_mask =
a22f0788 6680 params->speed_cap_mask[link_cfg_idx];
de6eae1f
YR
6681
6682 params->phy[actual_phy_idx].req_duplex =
a22f0788 6683 params->req_duplex[link_cfg_idx];
de6eae1f
YR
6684
6685 DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
6686 " speed_cap_mask %x\n",
6687 params->phy[actual_phy_idx].req_flow_ctrl,
6688 params->phy[actual_phy_idx].req_line_speed,
6689 params->phy[actual_phy_idx].speed_cap_mask);
6690 }
6691}
6692
6693u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
6694{
6695 struct bnx2x *bp = params->bp;
de6eae1f 6696 DP(NETIF_MSG_LINK, "Phy Initialization started\n");
a22f0788
YR
6697 DP(NETIF_MSG_LINK, "(1) req_speed %d, req_flowctrl %d\n",
6698 params->req_line_speed[0], params->req_flow_ctrl[0]);
6699 DP(NETIF_MSG_LINK, "(2) req_speed %d, req_flowctrl %d\n",
6700 params->req_line_speed[1], params->req_flow_ctrl[1]);
de6eae1f
YR
6701 vars->link_status = 0;
6702 vars->phy_link_up = 0;
6703 vars->link_up = 0;
6704 vars->line_speed = 0;
6705 vars->duplex = DUPLEX_FULL;
6706 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
6707 vars->mac_type = MAC_TYPE_NONE;
6708 vars->phy_flags = 0;
6709
6710 /* disable attentions */
6711 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
6712 (NIG_MASK_XGXS0_LINK_STATUS |
6713 NIG_MASK_XGXS0_LINK10G |
6714 NIG_MASK_SERDES0_LINK_STATUS |
6715 NIG_MASK_MI_INT));
6716
6717 bnx2x_emac_init(params, vars);
6718
6719 if (params->num_phys == 0) {
6720 DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
6721 return -EINVAL;
6722 }
6723 set_phy_vars(params);
6724
6725 DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
6726 if (CHIP_REV_IS_FPGA(bp)) {
6727
6728 vars->link_up = 1;
6729 vars->line_speed = SPEED_10000;
6730 vars->duplex = DUPLEX_FULL;
6731 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
6732 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
6733 /* enable on E1.5 FPGA */
6734 if (CHIP_IS_E1H(bp)) {
6735 vars->flow_ctrl |=
6736 (BNX2X_FLOW_CTRL_TX |
6737 BNX2X_FLOW_CTRL_RX);
6738 vars->link_status |=
6739 (LINK_STATUS_TX_FLOW_CONTROL_ENABLED |
6740 LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
6741 }
6742
6743 bnx2x_emac_enable(params, vars, 0);
6744 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
6745 /* disable drain */
6746 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
6747
6748 /* update shared memory */
6749 bnx2x_update_mng(params, vars->link_status);
6750
6751 return 0;
6752
6753 } else
6754 if (CHIP_REV_IS_EMUL(bp)) {
6755
6756 vars->link_up = 1;
6757 vars->line_speed = SPEED_10000;
6758 vars->duplex = DUPLEX_FULL;
6759 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
6760 vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
6761
6762 bnx2x_bmac_enable(params, vars, 0);
6763
6764 bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
6765 /* Disable drain */
6766 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
6767 + params->port*4, 0);
6768
6769 /* update shared memory */
6770 bnx2x_update_mng(params, vars->link_status);
6771
6772 return 0;
6773
6774 } else
6775 if (params->loopback_mode == LOOPBACK_BMAC) {
6776
6777 vars->link_up = 1;
6778 vars->line_speed = SPEED_10000;
6779 vars->duplex = DUPLEX_FULL;
6780 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
6781 vars->mac_type = MAC_TYPE_BMAC;
b7737c9b 6782
de6eae1f 6783 vars->phy_flags = PHY_XGXS_FLAG;
b7737c9b 6784
de6eae1f 6785 bnx2x_xgxs_deassert(params);
b7737c9b 6786
de6eae1f
YR
6787 /* set bmac loopback */
6788 bnx2x_bmac_enable(params, vars, 1);
b7737c9b 6789
de6eae1f
YR
6790 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
6791 params->port*4, 0);
b7737c9b 6792
de6eae1f 6793 } else if (params->loopback_mode == LOOPBACK_EMAC) {
b7737c9b 6794
de6eae1f
YR
6795 vars->link_up = 1;
6796 vars->line_speed = SPEED_1000;
6797 vars->duplex = DUPLEX_FULL;
6798 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
6799 vars->mac_type = MAC_TYPE_EMAC;
b7737c9b 6800
de6eae1f 6801 vars->phy_flags = PHY_XGXS_FLAG;
e10bc84d 6802
de6eae1f
YR
6803 bnx2x_xgxs_deassert(params);
6804 /* set bmac loopback */
6805 bnx2x_emac_enable(params, vars, 1);
6806 bnx2x_emac_program(params, vars);
6807 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
6808 params->port*4, 0);
b7737c9b 6809
de6eae1f
YR
6810 } else if ((params->loopback_mode == LOOPBACK_XGXS) ||
6811 (params->loopback_mode == LOOPBACK_EXT_PHY)) {
b7737c9b 6812
de6eae1f 6813 vars->link_up = 1;
de6eae1f 6814 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
a22f0788
YR
6815 vars->duplex = DUPLEX_FULL;
6816 if (params->req_line_speed[0] == SPEED_1000) {
6817 vars->line_speed = SPEED_1000;
6818 vars->mac_type = MAC_TYPE_EMAC;
6819 } else {
6820 vars->line_speed = SPEED_10000;
6821 vars->mac_type = MAC_TYPE_BMAC;
6822 }
62b29a5d 6823
de6eae1f
YR
6824 bnx2x_xgxs_deassert(params);
6825 bnx2x_link_initialize(params, vars);
c18aa15d 6826
a22f0788
YR
6827 if (params->req_line_speed[0] == SPEED_1000) {
6828 bnx2x_emac_program(params, vars);
6829 bnx2x_emac_enable(params, vars, 0);
6830 } else
de6eae1f 6831 bnx2x_bmac_enable(params, vars, 0);
c18aa15d 6832
de6eae1f
YR
6833 if (params->loopback_mode == LOOPBACK_XGXS) {
6834 /* set 10G XGXS loopback */
6835 params->phy[INT_PHY].config_loopback(
6836 &params->phy[INT_PHY],
6837 params);
c18aa15d 6838
de6eae1f
YR
6839 } else {
6840 /* set external phy loopback */
6841 u8 phy_index;
6842 for (phy_index = EXT_PHY1;
6843 phy_index < params->num_phys; phy_index++) {
6844 if (params->phy[phy_index].config_loopback)
6845 params->phy[phy_index].config_loopback(
6846 &params->phy[phy_index],
6847 params);
6848 }
6849 }
6850
6851 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
6852 params->port*4, 0);
6853
7f02c4ad
YR
6854 bnx2x_set_led(params, vars,
6855 LED_MODE_OPER, vars->line_speed);
de6eae1f
YR
6856 } else
6857 /* No loopback */
6858 {
6859 if (params->switch_cfg == SWITCH_CFG_10G)
6860 bnx2x_xgxs_deassert(params);
6861 else
6862 bnx2x_serdes_deassert(bp, params->port);
7f02c4ad 6863
de6eae1f
YR
6864 bnx2x_link_initialize(params, vars);
6865 msleep(30);
6866 bnx2x_link_int_enable(params);
6867 }
e10bc84d
YR
6868 return 0;
6869}
de6eae1f
YR
6870u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
6871 u8 reset_ext_phy)
b7737c9b
YR
6872{
6873 struct bnx2x *bp = params->bp;
de6eae1f
YR
6874 u8 phy_index, port = params->port;
6875 DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port);
6876 /* disable attentions */
6877 vars->link_status = 0;
6878 bnx2x_update_mng(params, vars->link_status);
6879 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
6880 (NIG_MASK_XGXS0_LINK_STATUS |
6881 NIG_MASK_XGXS0_LINK10G |
6882 NIG_MASK_SERDES0_LINK_STATUS |
6883 NIG_MASK_MI_INT));
b7737c9b 6884
de6eae1f
YR
6885 /* activate nig drain */
6886 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
b7737c9b 6887
de6eae1f
YR
6888 /* disable nig egress interface */
6889 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
6890 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
b7737c9b 6891
de6eae1f
YR
6892 /* Stop BigMac rx */
6893 bnx2x_bmac_rx_disable(bp, port);
b7737c9b 6894
de6eae1f
YR
6895 /* disable emac */
6896 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
b7737c9b 6897
de6eae1f
YR
6898 msleep(10);
6899 /* The PHY reset is controled by GPIO 1
6900 * Hold it as vars low
6901 */
6902 /* clear link led */
7f02c4ad
YR
6903 bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
6904
de6eae1f
YR
6905 if (reset_ext_phy) {
6906 for (phy_index = EXT_PHY1; phy_index < params->num_phys;
6907 phy_index++) {
6908 if (params->phy[phy_index].link_reset)
6909 params->phy[phy_index].link_reset(
6910 &params->phy[phy_index],
6911 params);
b7737c9b 6912 }
b7737c9b
YR
6913 }
6914
de6eae1f
YR
6915 if (params->phy[INT_PHY].link_reset)
6916 params->phy[INT_PHY].link_reset(
6917 &params->phy[INT_PHY], params);
6918 /* reset BigMac */
6919 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
6920 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
b7737c9b 6921
de6eae1f
YR
6922 /* disable nig ingress interface */
6923 REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
6924 REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
6925 REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
6926 REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
6927 vars->link_up = 0;
b7737c9b
YR
6928 return 0;
6929}
6930
de6eae1f
YR
6931/****************************************************************************/
6932/* Common function */
6933/****************************************************************************/
a22f0788 6934static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base, u8 phy_index)
6bbca910 6935{
e10bc84d
YR
6936 struct bnx2x_phy phy[PORT_MAX];
6937 struct bnx2x_phy *phy_blk[PORT_MAX];
6bbca910
YR
6938 u16 val;
6939 s8 port;
6940
6941 /* PART1 - Reset both phys */
6942 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
6943 /* Extract the ext phy address for the port */
a22f0788 6944 if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
e10bc84d
YR
6945 port, &phy[port]) !=
6946 0) {
6947 DP(NETIF_MSG_LINK, "populate_phy failed\n");
6948 return -EINVAL;
6949 }
6bbca910
YR
6950 /* disable attentions */
6951 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
6952 (NIG_MASK_XGXS0_LINK_STATUS |
6953 NIG_MASK_XGXS0_LINK10G |
6954 NIG_MASK_SERDES0_LINK_STATUS |
6955 NIG_MASK_MI_INT));
6956
6bbca910
YR
6957 /* Need to take the phy out of low power mode in order
6958 to write to access its registers */
6959 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
6960 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
6961
6962 /* Reset the phy */
e10bc84d 6963 bnx2x_cl45_write(bp, &phy[port],
6bbca910
YR
6964 MDIO_PMA_DEVAD,
6965 MDIO_PMA_REG_CTRL,
6966 1<<15);
6967 }
6968
6969 /* Add delay of 150ms after reset */
6970 msleep(150);
6971
e10bc84d
YR
6972 if (phy[PORT_0].addr & 0x1) {
6973 phy_blk[PORT_0] = &(phy[PORT_1]);
6974 phy_blk[PORT_1] = &(phy[PORT_0]);
6975 } else {
6976 phy_blk[PORT_0] = &(phy[PORT_0]);
6977 phy_blk[PORT_1] = &(phy[PORT_1]);
6978 }
6979
6bbca910
YR
6980 /* PART2 - Download firmware to both phys */
6981 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
6982 u16 fw_ver1;
6983
e10bc84d 6984 bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
c18aa15d 6985 port);
6bbca910 6986
e10bc84d 6987 bnx2x_cl45_read(bp, phy_blk[port],
6bbca910
YR
6988 MDIO_PMA_DEVAD,
6989 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
16b311cc 6990 if (fw_ver1 == 0 || fw_ver1 == 0x4321) {
6bbca910 6991 DP(NETIF_MSG_LINK,
16b311cc
EG
6992 "bnx2x_8073_common_init_phy port %x:"
6993 "Download failed. fw version = 0x%x\n",
6994 port, fw_ver1);
6bbca910
YR
6995 return -EINVAL;
6996 }
6997
6998 /* Only set bit 10 = 1 (Tx power down) */
e10bc84d 6999 bnx2x_cl45_read(bp, phy_blk[port],
6bbca910
YR
7000 MDIO_PMA_DEVAD,
7001 MDIO_PMA_REG_TX_POWER_DOWN, &val);
7002
7003 /* Phase1 of TX_POWER_DOWN reset */
e10bc84d 7004 bnx2x_cl45_write(bp, phy_blk[port],
6bbca910
YR
7005 MDIO_PMA_DEVAD,
7006 MDIO_PMA_REG_TX_POWER_DOWN,
7007 (val | 1<<10));
7008 }
7009
7010 /* Toggle Transmitter: Power down and then up with 600ms
7011 delay between */
7012 msleep(600);
7013
7014 /* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low */
7015 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
f5372251 7016 /* Phase2 of POWER_DOWN_RESET */
6bbca910 7017 /* Release bit 10 (Release Tx power down) */
e10bc84d 7018 bnx2x_cl45_read(bp, phy_blk[port],
6bbca910
YR
7019 MDIO_PMA_DEVAD,
7020 MDIO_PMA_REG_TX_POWER_DOWN, &val);
7021
e10bc84d 7022 bnx2x_cl45_write(bp, phy_blk[port],
6bbca910
YR
7023 MDIO_PMA_DEVAD,
7024 MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
7025 msleep(15);
7026
7027 /* Read modify write the SPI-ROM version select register */
e10bc84d 7028 bnx2x_cl45_read(bp, phy_blk[port],
6bbca910
YR
7029 MDIO_PMA_DEVAD,
7030 MDIO_PMA_REG_EDC_FFE_MAIN, &val);
e10bc84d 7031 bnx2x_cl45_write(bp, phy_blk[port],
6bbca910
YR
7032 MDIO_PMA_DEVAD,
7033 MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
7034
7035 /* set GPIO2 back to LOW */
7036 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
7037 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
7038 }
7039 return 0;
6bbca910
YR
7040}
7041
a22f0788
YR
7042static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base,
7043 u32 shmem2_base, u8 phy_index)
de6eae1f
YR
7044{
7045 u32 val;
7046 s8 port;
7047 struct bnx2x_phy phy;
7048 /* Use port1 because of the static port-swap */
7049 /* Enable the module detection interrupt */
7050 val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
7051 val |= ((1<<MISC_REGISTERS_GPIO_3)|
7052 (1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT)));
7053 REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
7054
7055 bnx2x_ext_phy_hw_reset(bp, 1);
7056 msleep(5);
7057 for (port = 0; port < PORT_MAX; port++) {
7058 /* Extract the ext phy address for the port */
a22f0788 7059 if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
de6eae1f
YR
7060 port, &phy) !=
7061 0) {
7062 DP(NETIF_MSG_LINK, "populate phy failed\n");
7063 return -EINVAL;
7064 }
7065
7066 /* Reset phy*/
7067 bnx2x_cl45_write(bp, &phy,
7068 MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x0001);
7069
7070
7071 /* Set fault module detected LED on */
7072 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
7073 MISC_REGISTERS_GPIO_HIGH,
7074 port);
7075 }
7076
7077 return 0;
7078}
a22f0788
YR
7079static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base,
7080 u32 shmem2_base, u8 phy_index)
4d295db0 7081{
a22f0788 7082 s8 port;
4d295db0 7083 u32 swap_val, swap_override;
e10bc84d
YR
7084 struct bnx2x_phy phy[PORT_MAX];
7085 struct bnx2x_phy *phy_blk[PORT_MAX];
4d295db0
EG
7086 DP(NETIF_MSG_LINK, "Executing BCM8727 common init\n");
7087 swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
7088 swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
7089
a22f0788 7090 port = 1;
4d295db0 7091
a22f0788
YR
7092 bnx2x_ext_phy_hw_reset(bp, port ^ (swap_val && swap_override));
7093
7094 /* Calculate the port based on port swap */
7095 port ^= (swap_val && swap_override);
7096
7097 msleep(5);
bc7f0a05 7098
4d295db0 7099 /* PART1 - Reset both phys */
a22f0788 7100 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4d295db0 7101 /* Extract the ext phy address for the port */
a22f0788 7102 if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
e10bc84d
YR
7103 port, &phy[port]) !=
7104 0) {
7105 DP(NETIF_MSG_LINK, "populate phy failed\n");
7106 return -EINVAL;
7107 }
4d295db0
EG
7108 /* disable attentions */
7109 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
7110 (NIG_MASK_XGXS0_LINK_STATUS |
7111 NIG_MASK_XGXS0_LINK10G |
7112 NIG_MASK_SERDES0_LINK_STATUS |
7113 NIG_MASK_MI_INT));
7114
4d295db0
EG
7115
7116 /* Reset the phy */
e10bc84d 7117 bnx2x_cl45_write(bp, &phy[port],
4d295db0
EG
7118 MDIO_PMA_DEVAD,
7119 MDIO_PMA_REG_CTRL,
7120 1<<15);
7121 }
7122
7123 /* Add delay of 150ms after reset */
7124 msleep(150);
e10bc84d
YR
7125 if (phy[PORT_0].addr & 0x1) {
7126 phy_blk[PORT_0] = &(phy[PORT_1]);
7127 phy_blk[PORT_1] = &(phy[PORT_0]);
7128 } else {
7129 phy_blk[PORT_0] = &(phy[PORT_0]);
7130 phy_blk[PORT_1] = &(phy[PORT_1]);
7131 }
4d295db0 7132 /* PART2 - Download firmware to both phys */
e10bc84d 7133 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
4d295db0
EG
7134 u16 fw_ver1;
7135
e10bc84d 7136 bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
c18aa15d 7137 port);
e10bc84d 7138 bnx2x_cl45_read(bp, phy_blk[port],
4d295db0
EG
7139 MDIO_PMA_DEVAD,
7140 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
7141 if (fw_ver1 == 0 || fw_ver1 == 0x4321) {
7142 DP(NETIF_MSG_LINK,
bc7f0a05 7143 "bnx2x_8727_common_init_phy port %x:"
4d295db0
EG
7144 "Download failed. fw version = 0x%x\n",
7145 port, fw_ver1);
7146 return -EINVAL;
7147 }
4d295db0
EG
7148 }
7149
4d295db0
EG
7150 return 0;
7151}
7152
a22f0788
YR
7153static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base,
7154 u32 shmem2_base, u8 phy_index,
7155 u32 ext_phy_type)
6bbca910
YR
7156{
7157 u8 rc = 0;
6bbca910
YR
7158
7159 switch (ext_phy_type) {
7160 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
a22f0788
YR
7161 rc = bnx2x_8073_common_init_phy(bp, shmem_base,
7162 shmem2_base, phy_index);
6bbca910 7163 break;
4d295db0
EG
7164
7165 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
7166 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
a22f0788
YR
7167 rc = bnx2x_8727_common_init_phy(bp, shmem_base,
7168 shmem2_base, phy_index);
4d295db0
EG
7169 break;
7170
589abe3a
EG
7171 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
7172 /* GPIO1 affects both ports, so there's need to pull
7173 it for single port alone */
a22f0788
YR
7174 rc = bnx2x_8726_common_init_phy(bp, shmem_base,
7175 shmem2_base, phy_index);
7176 break;
7177 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
7178 rc = -EINVAL;
4f60dab1 7179 break;
6bbca910
YR
7180 default:
7181 DP(NETIF_MSG_LINK,
7182 "bnx2x_common_init_phy: ext_phy 0x%x not required\n",
7183 ext_phy_type);
7184 break;
7185 }
7186
7187 return rc;
7188}
7189
a22f0788
YR
7190u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base,
7191 u32 shmem2_base)
7192{
7193 u8 rc = 0;
7194 u8 phy_index;
7195 u32 ext_phy_type, ext_phy_config;
7196 DP(NETIF_MSG_LINK, "Begin common phy init\n");
7197
7198 if (CHIP_REV_IS_EMUL(bp))
7199 return 0;
7200
7201 /* Read the ext_phy_type for arbitrary port(0) */
7202 for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
7203 phy_index++) {
7204 ext_phy_config = bnx2x_get_ext_phy_config(bp,
7205 shmem_base,
7206 phy_index, 0);
7207 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
7208 rc |= bnx2x_ext_phy_common_init(bp, shmem_base,
7209 shmem2_base,
7210 phy_index, ext_phy_type);
7211 }
7212 return rc;
7213}
d90d96ba 7214
a22f0788 7215u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
d90d96ba
YR
7216{
7217 u8 phy_index;
7218 struct bnx2x_phy phy;
7219 for (phy_index = INT_PHY; phy_index < MAX_PHYS;
7220 phy_index++) {
a22f0788 7221 if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
d90d96ba
YR
7222 0, &phy) != 0) {
7223 DP(NETIF_MSG_LINK, "populate phy failed\n");
7224 return 0;
7225 }
7226
7227 if (phy.flags & FLAGS_HW_LOCK_REQUIRED)
7228 return 1;
7229 }
7230 return 0;
7231}
7232
7233u8 bnx2x_fan_failure_det_req(struct bnx2x *bp,
7234 u32 shmem_base,
a22f0788 7235 u32 shmem2_base,
d90d96ba
YR
7236 u8 port)
7237{
7238 u8 phy_index, fan_failure_det_req = 0;
7239 struct bnx2x_phy phy;
7240 for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
7241 phy_index++) {
a22f0788 7242 if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
d90d96ba
YR
7243 port, &phy)
7244 != 0) {
7245 DP(NETIF_MSG_LINK, "populate phy failed\n");
7246 return 0;
7247 }
7248 fan_failure_det_req |= (phy.flags &
7249 FLAGS_FAN_FAILURE_DET_REQ);
7250 }
7251 return fan_failure_det_req;
7252}
7253
7254void bnx2x_hw_reset_phy(struct link_params *params)
7255{
7256 u8 phy_index;
7257 for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
7258 phy_index++) {
7259 if (params->phy[phy_index].hw_reset) {
7260 params->phy[phy_index].hw_reset(
7261 &params->phy[phy_index],
7262 params);
7263 params->phy[phy_index] = phy_null;
7264 }
7265 }
7266}