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