]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/dev/bxe/bxe_link.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / dev / bxe / bxe_link.c
1 /*-
2  * Copyright (c) 2007-2010 Broadcom Corporation. All rights reserved.
3  *
4  *    Gary Zambrano <zambrano@broadcom.com>
5  *    David Christensen <davidch@broadcom.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of Broadcom Corporation nor the name of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written consent.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30  * THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include "opt_bxe.h"
37 #include "bxe_include.h"
38 #include "if_bxe.h"
39
40 void bxe_write_dmae(struct bxe_softc *, bus_addr_t, uint32_t, uint32_t);
41 void bxe_read_dmae(struct bxe_softc *, uint32_t, uint32_t);
42 int bxe_set_gpio(struct bxe_softc *, int, uint32_t, uint8_t);
43 int bxe_get_gpio(struct bxe_softc *, int, uint8_t);
44 int bxe_set_spio(struct bxe_softc *, int, uint32_t);
45 int bxe_set_gpio_int(struct bxe_softc *, int, uint32_t, uint8_t);
46 int bxe_fw_command(struct bxe_softc *, uint32_t);
47
48 #ifdef BXE_DEBUG
49 extern uint32_t
50 bxe_reg_read32  (struct bxe_softc *, bus_size_t);
51 extern void
52 bxe_reg_write32 (struct bxe_softc *, bus_size_t, uint32_t);
53 #endif
54
55 #undef msleep
56 #define msleep(m) DELAY(m * 1000)
57
58 #define EMAC_RX_MODE_KEEP_MAC_CONTROL   (1L<<3)
59 #define EMAC_RX_MODE_KEEP_VLAN_TAG              (1L<<10)
60 #define MDIO_PMA_REG_8481_LED1_MASK             0xa82c
61 #define MDIO_PMA_REG_8481_LED2_MASK             0xa82f
62 #define MDIO_PMA_REG_8481_LED3_MASK             0xa832
63 /*
64  * [RW 27] 0 - must be active for Everest A0; 1- for Everest B0 when latch
65  * logic for interrupts must be used. Enable per bit of interrupt of
66  * ~latch_status.latch_status.
67  */
68 #define NIG_REG_LATCH_BC_0                                      0x16210
69 /*
70  * [RW 27] Latch for each interrupt from Unicore.b[0]
71  * status_emac0_misc_mi_int; b[1] status_emac0_misc_mi_complete;
72  * b[2]status_emac0_misc_cfg_change; b[3]status_emac0_misc_link_status;
73  * b[4]status_emac0_misc_link_change; b[5]status_emac0_misc_attn;
74  * b[6]status_serdes0_mac_crs; b[7]status_serdes0_autoneg_complete;
75  * b[8]status_serdes0_fiber_rxact; b[9]status_serdes0_link_status;
76  * b[10]status_serdes0_mr_page_rx; b[11]status_serdes0_cl73_an_complete;
77  * b[12]status_serdes0_cl73_mr_page_rx; b[13]status_serdes0_rx_sigdet;
78  * b[14]status_xgxs0_remotemdioreq; b[15]status_xgxs0_link10g;
79  * b[16]status_xgxs0_autoneg_complete; b[17]status_xgxs0_fiber_rxact;
80  * b[21:18]status_xgxs0_link_status; b[22]status_xgxs0_mr_page_rx;
81  * b[23]status_xgxs0_cl73_an_complete; b[24]status_xgxs0_cl73_mr_page_rx;
82  * b[25]status_xgxs0_rx_sigdet; b[26]status_xgxs0_mac_crs
83  */
84 #define NIG_REG_LATCH_STATUS_0                                  0x18000
85
86 #define ETH_HLEN                        14
87 #define ETH_OVREHEAD                    (ETH_HLEN + 8)/* 8 for CRC + VLAN*/
88 #define ETH_MIN_PACKET_SIZE             60
89 #define ETH_MAX_PACKET_SIZE             1500
90 #define ETH_MAX_JUMBO_PACKET_SIZE       9600
91 #define MDIO_ACCESS_TIMEOUT             1000
92 #define BMAC_CONTROL_RX_ENABLE          2
93
94 struct bxe_image_header {
95         uint32_t        magic;
96 #define FILE_MAGIC                      0x669955aa
97         uint32_t        version;
98 #define FORMAT_VERSION_2                0x2
99         uint32_t        type;
100 #define IMAGE_HDR_TYPE_BCM8073          0x33373038
101 #define IMAGE_HDR_TYPE_BCM8726          0x36323738
102 #define IMAGE_HDR_TYPE_BCM8727          0x37323738
103 #define IMAGE_HDR_TYPE_BCM8481          0x31383438
104 #define IMAGE_HDR_TYPE_SFX7101          0x68706673
105         uint32_t        image_info;
106         uint32_t        byte_cnt;
107 };
108
109 /*
110  * Shortcut definitions
111  */
112
113 #define NIG_LATCH_BC_ENABLE_MI_INT              0
114
115 #define NIG_STATUS_EMAC0_MI_INT                 \
116         NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_INT
117 #define NIG_STATUS_XGXS0_LINK10G                \
118         NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G
119 #define NIG_STATUS_XGXS0_LINK_STATUS            \
120         NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS
121 #define NIG_STATUS_XGXS0_LINK_STATUS_SIZE       \
122         NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE
123 #define NIG_STATUS_SERDES0_LINK_STATUS          \
124         NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS
125 #define NIG_MASK_MI_INT                         \
126         NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT
127 #define NIG_MASK_XGXS0_LINK10G                  \
128         NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G
129 #define NIG_MASK_XGXS0_LINK_STATUS              \
130         NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK_STATUS
131 #define NIG_MASK_SERDES0_LINK_STATUS            \
132         NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS
133
134 #define MDIO_AN_CL73_OR_37_COMPLETE                                     \
135         (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |          \
136         MDIO_GP_STATUS_TOP_AN_STATUS1_CL37_AUTONEG_COMPLETE)
137
138 #define XGXS_RESET_BITS                                                 \
139         (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW |        \
140         MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_IDDQ |            \
141         MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN |          \
142         MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN_SD |       \
143         MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB)
144
145 #define SERDES_RESET_BITS                                               \
146         (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_RSTB_HW |      \
147         MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ |          \
148         MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN |        \
149         MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN_SD)
150
151 #define AUTONEG_CL37            SHARED_HW_CFG_AN_ENABLE_CL37
152 #define AUTONEG_CL73            SHARED_HW_CFG_AN_ENABLE_CL73
153 #define AUTONEG_BAM             SHARED_HW_CFG_AN_ENABLE_BAM
154 #define AUTONEG_PARALLEL        SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
155 #define AUTONEG_SGMII_FIBER_AUTODET     \
156         SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT
157 #define AUTONEG_REMOTE_PHY      SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY
158
159 #define GP_STATUS_PAUSE_RSOLUTION_TXSIDE        \
160         MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE
161 #define GP_STATUS_PAUSE_RSOLUTION_RXSIDE        \
162         MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_RXSIDE
163 #define GP_STATUS_SPEED_MASK            \
164         MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_MASK
165 #define GP_STATUS_10M           MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10M
166 #define GP_STATUS_100M          MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_100M
167 #define GP_STATUS_1G            MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G
168 #define GP_STATUS_2_5G          MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_2_5G
169 #define GP_STATUS_5G            MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_5G
170 #define GP_STATUS_6G            MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_6G
171 #define GP_STATUS_10G_HIG       \
172         MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG
173 #define GP_STATUS_10G_CX4       \
174         MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4
175 #define GP_STATUS_12G_HIG       \
176         MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12G_HIG
177 #define GP_STATUS_12_5G         MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12_5G
178 #define GP_STATUS_13G           MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_13G
179 #define GP_STATUS_15G           MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_15G
180 #define GP_STATUS_16G           MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G
181 #define GP_STATUS_1G_KX         MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX
182 #define GP_STATUS_10G_KX4       \
183         MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
184
185 #define LINK_10THD              LINK_STATUS_SPEED_AND_DUPLEX_10THD
186 #define LINK_10TFD              LINK_STATUS_SPEED_AND_DUPLEX_10TFD
187 #define LINK_100TXHD            LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
188 #define LINK_100T4              LINK_STATUS_SPEED_AND_DUPLEX_100T4
189 #define LINK_100TXFD            LINK_STATUS_SPEED_AND_DUPLEX_100TXFD
190 #define LINK_1000THD            LINK_STATUS_SPEED_AND_DUPLEX_1000THD
191 #define LINK_1000TFD            LINK_STATUS_SPEED_AND_DUPLEX_1000TFD
192 #define LINK_1000XFD            LINK_STATUS_SPEED_AND_DUPLEX_1000XFD
193 #define LINK_2500THD            LINK_STATUS_SPEED_AND_DUPLEX_2500THD
194 #define LINK_2500TFD            LINK_STATUS_SPEED_AND_DUPLEX_2500TFD
195 #define LINK_2500XFD            LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
196 #define LINK_10GTFD             LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
197 #define LINK_10GXFD             LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
198 #define LINK_12GTFD             LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
199 #define LINK_12GXFD             LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
200 #define LINK_12_5GTFD           LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD
201 #define LINK_12_5GXFD           LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD
202 #define LINK_13GTFD             LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
203 #define LINK_13GXFD             LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
204 #define LINK_15GTFD             LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
205 #define LINK_15GXFD             LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
206 #define LINK_16GTFD             LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
207 #define LINK_16GXFD             LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
208
209 #define PHY_XGXS_FLAG                           0x1
210 #define PHY_SGMII_FLAG                          0x2
211 #define PHY_SERDES_FLAG                         0x4
212
213 #define SFP_EEPROM_CON_TYPE_ADDR                0x2
214 #define SFP_EEPROM_CON_TYPE_VAL_LC              0x7
215 #define SFP_EEPROM_CON_TYPE_VAL_COPPER          0x21
216
217 #define SFP_EEPROM_COMP_CODE_ADDR               0x3
218 #define SFP_EEPROM_COMP_CODE_SR_MASK            (1 << 4)
219 #define SFP_EEPROM_COMP_CODE_LR_MASK            (1 << 5)
220 #define SFP_EEPROM_COMP_CODE_LRM_MASK           (1 << 6)
221
222 #define SFP_EEPROM_FC_TX_TECH_ADDR              0x8
223 #define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE    0x4
224 #define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE     0x8
225
226 #define SFP_EEPROM_OPTIONS_ADDR                 0x40
227 #define SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK   0x1
228 #define SFP_EEPROM_OPTIONS_SIZE                 2
229
230 #define EDC_MODE_LINEAR                         0x0022
231 #define EDC_MODE_LIMITING                       0x0044
232 #define EDC_MODE_PASSIVE_DAC                    0x0055
233
234 /*
235  * 8073 Download definitions.
236  */
237 /* spi Parameters.*/
238 #define SPI_CTRL_1_L    0xC000
239 #define SPI_CTRL_1_H    0xC002
240 #define SPI_CTRL_2_L    0xC400
241 #define SPI_CTRL_2_H    0xC402
242 #define SPI_TXFIFO      0xD000
243 #define SPI_RXFIFO      0xD400
244
245 /* Input Command Messages.*/
246 /*
247  * Write CPU/SPI Control Regs, followed by Count And
248  * CPU/SPI Controller Reg add/data pairs.
249  */
250 #define WR_CPU_CTRL_REGS        0x11
251 /*
252  * Read CPU/SPI Control Regs, followed by Count and
253  * CPU/SPI Controller Register Add.
254  */
255 #define RD_CPU_CTRL_REGS        0xEE
256 /*
257  * Write CPU/SPI Control Regs Continously, followed by
258  * Count and CPU/SPI Controller Reg addr and data's.
259  */
260 #define WR_CPU_CTRL_FIFO        0x66
261 /* Output Command Messages.*/
262 #define DONE                    0x4321
263
264 /* SPI Controller Commands (known As messages).*/
265 #define MSGTYPE_HWR             0x40
266 #define MSGTYPE_HRD             0x80
267 #define WRSR_OPCODE             0x01
268 #define WR_OPCODE               0x02
269 #define RD_OPCODE               0x03
270 #define WRDI_OPCODE             0x04
271 #define RDSR_OPCODE             0x05
272 #define WREN_OPCODE             0x06
273 #define WR_BLOCK_SIZE           0x40 /* Maximum 64 Bytes Writes.*/
274
275 #define BUF_SIZE_BCM            0x4000 /* Code Size is 16k bytes.*/
276 #define UPGRADE_TIMEOUT_BCM     1000
277
278 /*
279  * INTERFACE
280  */
281 #define CL45_WR_OVER_CL22(_sc, _port, _phy_addr, _bank, _addr, _val)    \
282         bxe_cl45_write(_sc, _port, 0, _phy_addr, DEFAULT_PHY_DEV_ADDR,  \
283         (_bank + (_addr & 0xf)), _val)
284
285 #define CL45_RD_OVER_CL22(_sc, _port, _phy_addr, _bank, _addr, _val)    \
286         bxe_cl45_read(_sc, _port, 0, _phy_addr, DEFAULT_PHY_DEV_ADDR,   \
287         (_bank + (_addr & 0xf)), _val)
288
289 static void
290 bxe_set_serdes_access(struct link_params *params)
291 {
292         struct bxe_softc *sc;
293         uint32_t emac_base;
294
295         sc = params->sc;
296         emac_base = (params->port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
297
298         /* Set Clause 22 */
299         REG_WR(sc, NIG_REG_SERDES0_CTRL_MD_ST + params->port * 0x10, 1);
300         REG_WR(sc, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000);
301         DELAY(500);
302         REG_WR(sc, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f);
303         DELAY(500);
304          /* Set Clause 45 */
305         REG_WR(sc, NIG_REG_SERDES0_CTRL_MD_ST + params->port * 0x10, 0);
306 }
307
308 static void
309 bxe_set_phy_mdio(struct link_params *params, uint8_t phy_flags)
310 {
311         struct bxe_softc *sc;
312
313         sc = params->sc;
314         if (phy_flags & PHY_XGXS_FLAG) {
315                 REG_WR(sc, NIG_REG_XGXS0_CTRL_MD_ST + params->port * 0x18, 0);
316                 REG_WR(sc, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port * 0x18,
317                     DEFAULT_PHY_DEV_ADDR);
318         } else {
319                 bxe_set_serdes_access(params);
320
321                 REG_WR(sc, NIG_REG_SERDES0_CTRL_MD_DEVAD + params->port * 0x10,
322                     DEFAULT_PHY_DEV_ADDR);
323         }
324 }
325
326 static uint32_t
327 bxe_bits_en(struct bxe_softc *sc, uint32_t reg, uint32_t bits)
328 {
329         uint32_t val;
330
331         val = REG_RD(sc, reg);
332         val |= bits;
333         REG_WR(sc, reg, val);
334         return (val);
335 }
336
337 static uint32_t
338 bxe_bits_dis(struct bxe_softc *sc, uint32_t reg, uint32_t bits)
339 {
340         uint32_t val;
341
342         val = REG_RD(sc, reg);
343         val &= ~bits;
344         REG_WR(sc, reg, val);
345         return (val);
346 }
347
348 static void
349 bxe_emac_init(struct link_params *params, struct link_vars *vars)
350 {
351         struct bxe_softc *sc;
352         uint32_t emac_base, val;
353         uint16_t timeout;
354         uint8_t port;
355
356         /* reset and unreset the emac core */
357         sc = params->sc;
358         port = params->port;
359         emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
360
361         REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
362             (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
363         DELAY(5);
364         REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
365             (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
366
367         /* Init emac - use read-modify-write. */
368         /* self clear reset */
369         val = REG_RD(sc, emac_base + EMAC_REG_EMAC_MODE);
370         EMAC_WR(sc, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET));
371
372         timeout = 200;
373         do {
374                 val = REG_RD(sc, emac_base + EMAC_REG_EMAC_MODE);
375                 DBPRINT(sc, BXE_VERBOSE_PHY, "EMAC reset reg is %u\n", val);
376                 if (!timeout) {
377                         DBPRINT(sc, BXE_VERBOSE_PHY, "EMAC timeout!\n");
378                         return;
379                 }
380                 timeout--;
381         } while (val & EMAC_MODE_RESET);
382
383         /* Set mac address. */
384         val = ((params->mac_addr[0] << 8) | params->mac_addr[1]);
385         EMAC_WR(sc, EMAC_REG_EMAC_MAC_MATCH, val);
386
387         val = ((params->mac_addr[2] << 24) | (params->mac_addr[3] << 16) |
388             (params->mac_addr[4] << 8) | params->mac_addr[5]);
389         EMAC_WR(sc, EMAC_REG_EMAC_MAC_MATCH + 4, val);
390 }
391
392 static uint8_t
393 bxe_emac_enable(struct link_params *params, struct link_vars *vars, uint8_t lb)
394 {
395         struct bxe_softc *sc;
396         uint32_t emac_base, ser_lane, val;
397         uint8_t port;
398
399         sc = params->sc;
400         DBPRINT(sc, BXE_VERBOSE_PHY, "enabling EMAC\n");
401
402         port = params->port;
403         emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
404
405         /* enable emac and not bmac */
406         REG_WR(sc, NIG_REG_EGRESS_EMAC0_PORT + port * 4, 1);
407
408         if (vars->phy_flags & PHY_XGXS_FLAG) {
409                 ser_lane = ((params->lane_config &
410                     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
411                     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
412
413                 DBPRINT(sc, BXE_VERBOSE_PHY, "XGXS\n");
414                 /* select the master lanes (out of 0-3) */
415                 REG_WR(sc, NIG_REG_XGXS_LANE_SEL_P0 + port * 4, ser_lane);
416                 /* select XGXS */
417                 REG_WR(sc, NIG_REG_XGXS_SERDES0_MODE_SEL + port * 4, 1);
418
419         } else { /* SerDes */
420                 DBPRINT(sc, BXE_VERBOSE_PHY, "SerDes\n");
421                 /* select SerDes */
422                 REG_WR(sc, NIG_REG_XGXS_SERDES0_MODE_SEL + port * 4, 0);
423         }
424
425         bxe_bits_en(sc, emac_base + EMAC_REG_EMAC_RX_MODE, EMAC_RX_MODE_RESET);
426         bxe_bits_en(sc, emac_base + EMAC_REG_EMAC_TX_MODE, EMAC_TX_MODE_RESET);
427
428         /* pause enable/disable */
429         bxe_bits_dis(sc, emac_base + EMAC_REG_EMAC_RX_MODE,
430             EMAC_RX_MODE_FLOW_EN);
431         if (vars->flow_ctrl & FLOW_CTRL_RX)
432                 bxe_bits_en(sc, emac_base + EMAC_REG_EMAC_RX_MODE,
433                     EMAC_RX_MODE_FLOW_EN);
434
435         bxe_bits_dis(sc, emac_base + EMAC_REG_EMAC_TX_MODE,
436             (EMAC_TX_MODE_EXT_PAUSE_EN | EMAC_TX_MODE_FLOW_EN));
437         if (vars->flow_ctrl & FLOW_CTRL_TX)
438                 bxe_bits_en(sc, emac_base + EMAC_REG_EMAC_TX_MODE,
439                     (EMAC_TX_MODE_EXT_PAUSE_EN | EMAC_TX_MODE_FLOW_EN));
440
441         /* KEEP_VLAN_TAG, promiscuous */
442         val = REG_RD(sc, emac_base + EMAC_REG_EMAC_RX_MODE);
443         val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
444
445         EMAC_WR(sc, EMAC_REG_EMAC_RX_MODE, val);
446
447         /* Set Loopback */
448         val = REG_RD(sc, emac_base + EMAC_REG_EMAC_MODE);
449         if (lb)
450                 val |= 0x810;
451         else
452                 val &= ~0x810;
453         EMAC_WR(sc, EMAC_REG_EMAC_MODE, val);
454
455         /* enable emac */
456         REG_WR(sc, NIG_REG_NIG_EMAC0_EN + port * 4, 1);
457
458         /* Enable emac for jumbo packets. */
459         EMAC_WR(sc, EMAC_REG_EMAC_RX_MTU_SIZE, (EMAC_RX_MTU_SIZE_JUMBO_ENA |
460             (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD)));
461
462         /* strip CRC */
463         REG_WR(sc, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port * 4, 0x1);
464
465         /* Disable the NIG in/out to the bmac. */
466         REG_WR(sc, NIG_REG_BMAC0_IN_EN + port * 4, 0x0);
467         REG_WR(sc, NIG_REG_BMAC0_PAUSE_OUT_EN + port * 4, 0x0);
468         REG_WR(sc, NIG_REG_BMAC0_OUT_EN + port * 4, 0x0);
469
470         /* Enable the NIG in/out to the emac. */
471         REG_WR(sc, NIG_REG_EMAC0_IN_EN + port * 4, 0x1);
472         val = 0;
473         if (vars->flow_ctrl & FLOW_CTRL_TX)
474                 val = 1;
475
476         REG_WR(sc, NIG_REG_EMAC0_PAUSE_OUT_EN + port * 4, val);
477         REG_WR(sc, NIG_REG_EGRESS_EMAC0_OUT_EN + port * 4, 0x1);
478
479         REG_WR(sc, NIG_REG_BMAC0_REGS_OUT_EN + port * 4, 0x0);
480
481         vars->mac_type = MAC_TYPE_EMAC;
482         return (0);
483 }
484
485 static uint8_t
486 bxe_bmac1_enable(struct link_params *params, struct link_vars *vars,
487     uint8_t is_lb)
488 {
489         struct bxe_softc *sc;
490         uint32_t bmac_addr, wb_data[2], val;
491         uint8_t port;
492
493         sc = params->sc;
494         DBPRINT(sc, BXE_VERBOSE_PHY, "Enabling BigMAC1\n");
495
496         port = params->port;
497         bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
498             NIG_REG_INGRESS_BMAC0_MEM;
499
500         /* XGXS control */
501         wb_data[0] = 0x3c;
502         wb_data[1] = 0;
503         REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_BMAC_XGXS_CONTROL, wb_data,
504             2);
505
506         /* tx MAC SA */
507         wb_data[0] = ((params->mac_addr[2] << 24) |
508             (params->mac_addr[3] << 16) | (params->mac_addr[4] << 8) |
509             params->mac_addr[5]);
510         wb_data[1] = ((params->mac_addr[0] << 8) | params->mac_addr[1]);
511         REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR, wb_data, 2);
512
513         /* tx control */
514         val = 0xc0;
515         if (vars->flow_ctrl & FLOW_CTRL_TX)
516                 val |= 0x800000;
517         wb_data[0] = val;
518         wb_data[1] = 0;
519         REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_TX_CONTROL, wb_data, 2);
520
521         /* mac control */
522         val = 0x3;
523         if (is_lb) {
524                 val |= 0x4;
525                 DBPRINT(sc, BXE_VERBOSE_PHY, "enable bmac loopback\n");
526         }
527         wb_data[0] = val;
528         wb_data[1] = 0;
529         REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL, wb_data, 2);
530
531         /* set rx mtu */
532         wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
533         wb_data[1] = 0;
534         REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE, wb_data, 2);
535
536         /* rx control set to don't strip crc */
537         val = 0x14;
538         if (vars->flow_ctrl & FLOW_CTRL_RX)
539                 val |= 0x20;
540
541         wb_data[0] = val;
542         wb_data[1] = 0;
543         REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_RX_CONTROL, wb_data, 2);
544
545         /* set tx mtu */
546         wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
547         wb_data[1] = 0;
548         REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE,
549                         wb_data, 2);
550
551         /* set cnt max size */
552         wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
553         wb_data[1] = 0;
554         REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE, wb_data, 2);
555
556         /* configure safc */
557         wb_data[0] = 0x1000200;
558         wb_data[1] = 0;
559         REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS, wb_data,
560             2);
561
562         return (0);
563 }
564
565 static uint8_t
566 bxe_bmac_enable(struct link_params *params, struct link_vars *vars,
567     uint8_t is_lb)
568 {
569         struct bxe_softc *sc;
570         uint32_t val;
571         uint8_t rc, port;
572
573         sc = params->sc;
574         port = params->port;
575
576         /* reset and unreset the BigMac */
577         REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
578             (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
579         msleep(1);
580
581         REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
582             (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
583
584         /* enable access for bmac registers */
585         REG_WR(sc, NIG_REG_BMAC0_REGS_OUT_EN + port * 4, 0x1);
586
587         rc = bxe_bmac1_enable(params, vars, is_lb);
588
589         REG_WR(sc, NIG_REG_XGXS_SERDES0_MODE_SEL + port * 4, 0x1);
590         REG_WR(sc, NIG_REG_XGXS_LANE_SEL_P0 + port * 4, 0x0);
591         REG_WR(sc, NIG_REG_EGRESS_EMAC0_PORT + port * 4, 0x0);
592         val = 0;
593         if (vars->flow_ctrl & FLOW_CTRL_TX)
594                 val = 1;
595         REG_WR(sc, NIG_REG_BMAC0_PAUSE_OUT_EN + port * 4, val);
596         REG_WR(sc, NIG_REG_EGRESS_EMAC0_OUT_EN + port * 4, 0x0);
597         REG_WR(sc, NIG_REG_EMAC0_IN_EN + port * 4, 0x0);
598         REG_WR(sc, NIG_REG_EMAC0_PAUSE_OUT_EN + port * 4, 0x0);
599         REG_WR(sc, NIG_REG_BMAC0_IN_EN + port * 4, 0x1);
600         REG_WR(sc, NIG_REG_BMAC0_OUT_EN + port * 4, 0x1);
601
602         vars->mac_type = MAC_TYPE_BMAC;
603         return (rc);
604 }
605
606 static void
607 bxe_phy_deassert(struct link_params *params, uint8_t phy_flags)
608 {
609         struct bxe_softc *sc;
610         uint32_t val;
611
612         sc = params->sc;
613         if (phy_flags & PHY_XGXS_FLAG) {
614                 DBPRINT(sc, BXE_VERBOSE_PHY, "bxe_phy_deassert:XGXS\n");
615                 val = XGXS_RESET_BITS;
616
617         } else { /* SerDes */
618                 DBPRINT(sc, BXE_VERBOSE_PHY, "bxe_phy_deassert:SerDes\n");
619                 val = SERDES_RESET_BITS;
620         }
621
622         val = val << (params->port * 16);
623
624         /* reset and unreset the SerDes/XGXS */
625         REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
626         DELAY(500);
627         REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
628         bxe_set_phy_mdio(params, phy_flags);
629 }
630
631 void
632 bxe_link_status_update(struct link_params *params, struct link_vars *vars)
633 {
634         struct bxe_softc *sc;
635         uint8_t link_10g, port;
636
637         sc = params->sc;
638         port = params->port;
639
640         if (params->switch_cfg == SWITCH_CFG_1G)
641                 vars->phy_flags = PHY_SERDES_FLAG;
642         else
643                 vars->phy_flags = PHY_XGXS_FLAG;
644         vars->link_status = REG_RD(sc, params->shmem_base +
645             offsetof(struct shmem_region, port_mb[port].link_status));
646
647         vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
648
649         if (vars->link_up) {
650                 DBPRINT(sc, BXE_VERBOSE_PHY, "phy link up\n");
651
652                 vars->phy_link_up = 1;
653                 vars->duplex = DUPLEX_FULL;
654                 switch (vars->link_status & LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
655                 case LINK_10THD:
656                         vars->duplex = DUPLEX_HALF;
657                         /* FALLTHROUGH */
658                 case LINK_10TFD:
659                         vars->line_speed = SPEED_10;
660                         break;
661                 case LINK_100TXHD:
662                         vars->duplex = DUPLEX_HALF;
663                         /* FALLTHROUGH */
664                 case LINK_100T4:
665                 case LINK_100TXFD:
666                         vars->line_speed = SPEED_100;
667                         break;
668                 case LINK_1000THD:
669                         vars->duplex = DUPLEX_HALF;
670                         /* FALLTHROUGH */
671                 case LINK_1000TFD:
672                         vars->line_speed = SPEED_1000;
673                         break;
674                 case LINK_2500THD:
675                         vars->duplex = DUPLEX_HALF;
676                         /* FALLTHROUGH */
677                 case LINK_2500TFD:
678                         vars->line_speed = SPEED_2500;
679                         break;
680                 case LINK_10GTFD:
681                         vars->line_speed = SPEED_10000;
682                         break;
683                 case LINK_12GTFD:
684                         vars->line_speed = SPEED_12000;
685                         break;
686                 case LINK_12_5GTFD:
687                         vars->line_speed = SPEED_12500;
688                         break;
689                 case LINK_13GTFD:
690                         vars->line_speed = SPEED_13000;
691                         break;
692                 case LINK_15GTFD:
693                         vars->line_speed = SPEED_15000;
694                         break;
695                 case LINK_16GTFD:
696                         vars->line_speed = SPEED_16000;
697                         break;
698                 default:
699                         break;
700                 }
701
702                 if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
703                         vars->flow_ctrl |= FLOW_CTRL_TX;
704                 else
705                         vars->flow_ctrl &= ~FLOW_CTRL_TX;
706
707                 if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
708                         vars->flow_ctrl |= FLOW_CTRL_RX;
709                 else
710                         vars->flow_ctrl &= ~FLOW_CTRL_RX;
711
712                 if (vars->phy_flags & PHY_XGXS_FLAG) {
713                         if (vars->line_speed &&
714                             ((vars->line_speed == SPEED_10) ||
715                             (vars->line_speed == SPEED_100))) {
716                                 vars->phy_flags |= PHY_SGMII_FLAG;
717                         } else
718                                 vars->phy_flags &= ~PHY_SGMII_FLAG;
719                 }
720
721                 /* Anything 10 and over uses the bmac. */
722                 link_10g = ((vars->line_speed == SPEED_10000) ||
723                     (vars->line_speed == SPEED_12000) ||
724                     (vars->line_speed == SPEED_12500) ||
725                     (vars->line_speed == SPEED_13000) ||
726                     (vars->line_speed == SPEED_15000) ||
727                     (vars->line_speed == SPEED_16000));
728                 if (link_10g)
729                         vars->mac_type = MAC_TYPE_BMAC;
730                 else
731                         vars->mac_type = MAC_TYPE_EMAC;
732
733         } else {
734                 /* link down */
735                 DBPRINT(sc, BXE_VERBOSE_PHY, "phy link down\n");
736
737                 vars->phy_link_up = 0;
738
739                 vars->line_speed = 0;
740                 vars->duplex = DUPLEX_FULL;
741                 vars->flow_ctrl = FLOW_CTRL_NONE;
742
743                 /* Indicate no mac active. */
744                 vars->mac_type = MAC_TYPE_NONE;
745         }
746
747         DBPRINT(sc, BXE_VERBOSE_PHY, "link_status 0x%x phy_link_up %x\n",
748             vars->link_status, vars->phy_link_up);
749         DBPRINT(sc, BXE_VERBOSE_PHY, "line_speed %x duplex %x flow_ctrl 0x%x\n",
750             vars->line_speed, vars->duplex, vars->flow_ctrl);
751 }
752
753 static void
754 bxe_update_mng(struct link_params *params, uint32_t link_status)
755 {
756         struct bxe_softc *sc;
757
758         sc = params->sc;
759         REG_WR(sc, params->shmem_base + offsetof(struct shmem_region,
760             port_mb[params->port].link_status), link_status);
761 }
762
763 static void
764 bxe_bmac_rx_disable(struct bxe_softc *sc, uint32_t chip_id, uint8_t port)
765 {
766         uint32_t bmac_addr, wb_data[2];
767         uint32_t nig_bmac_enable;
768
769         bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
770             NIG_REG_INGRESS_BMAC0_MEM;
771         nig_bmac_enable = REG_RD(sc, NIG_REG_BMAC0_REGS_OUT_EN + port * 4);
772
773         /* Only if the bmac is out of reset */
774         if (REG_RD(sc, MISC_REG_RESET_REG_2) &
775             (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) && nig_bmac_enable) {
776                 REG_RD_DMAE(sc, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
777                     wb_data, 2);
778                 wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
779                 REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
780                     wb_data, 2);
781
782                 msleep(1);
783         }
784 }
785
786 static uint8_t
787 bxe_pbf_update(struct link_params *params, uint32_t flow_ctrl,
788     uint32_t line_speed)
789 {
790         struct bxe_softc *sc;
791         uint32_t count, crd, init_crd;
792         uint32_t thresh;
793         uint8_t port;
794
795         sc = params->sc;
796         port = params->port;
797
798         /* Disable port. */
799         REG_WR(sc, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port * 4, 0x1);
800
801         /* Wait for init credit. */
802         init_crd = REG_RD(sc, PBF_REG_P0_INIT_CRD + port * 4);
803         crd = REG_RD(sc, PBF_REG_P0_CREDIT + port * 8);
804         DBPRINT(sc, BXE_VERBOSE_PHY, "init_crd 0x%x crd 0x%x\n", init_crd, crd);
805
806         count = 1000;
807         while ((init_crd != crd) && count) {
808                 msleep(5);
809
810                 crd = REG_RD(sc, PBF_REG_P0_CREDIT + port * 8);
811                 count--;
812         }
813         crd = REG_RD(sc, PBF_REG_P0_CREDIT + port*8);
814         if (init_crd != crd) {
815                 DBPRINT(sc, BXE_VERBOSE_PHY, "BUG! init_crd 0x%x != crd 0x%x\n",
816                     init_crd, crd);
817                 return (-EINVAL);
818         }
819
820         if (flow_ctrl & FLOW_CTRL_RX || line_speed == SPEED_10 ||
821             line_speed == SPEED_100 || line_speed == SPEED_1000 ||
822             line_speed == SPEED_2500) {
823                 REG_WR(sc, PBF_REG_P0_PAUSE_ENABLE + port * 4, 1);
824                 /* Update threshold. */
825                 REG_WR(sc, PBF_REG_P0_ARB_THRSH + port * 4, 0);
826                 /* Update init credit. */
827                 init_crd = 778;         /* (800-18-4) */
828         } else {
829                 thresh = (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD) / 16;
830                 REG_WR(sc, PBF_REG_P0_PAUSE_ENABLE + port * 4, 0);
831                 /* Update threshold. */
832                 REG_WR(sc, PBF_REG_P0_ARB_THRSH + port * 4, thresh);
833                 /* Update init credit. */
834                 switch (line_speed) {
835                 case SPEED_10000:
836                         init_crd = thresh + 553 - 22;
837                         break;
838                 case SPEED_12000:
839                         init_crd = thresh + 664 - 22;
840                         break;
841                 case SPEED_13000:
842                         init_crd = thresh + 742 - 22;
843                         break;
844                 case SPEED_16000:
845                         init_crd = thresh + 778 - 22;
846                         break;
847                 default:
848                         DBPRINT(sc, BXE_VERBOSE_PHY,
849                             "Invalid line_speed 0x%x\n", line_speed);
850                         return (-EINVAL);
851                 }
852         }
853         REG_WR(sc, PBF_REG_P0_INIT_CRD + port * 4, init_crd);
854         DBPRINT(sc, BXE_VERBOSE_PHY, "PBF updated to speed %d credit %d\n",
855             line_speed, init_crd);
856
857         /* Probe the credit changes. */
858         REG_WR(sc, PBF_REG_INIT_P0 + port * 4, 0x1);
859         msleep(5);
860         REG_WR(sc, PBF_REG_INIT_P0 + port * 4, 0x0);
861
862         /* Enable port. */
863         REG_WR(sc, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port * 4, 0x0);
864         return (0);
865 }
866
867 static uint32_t
868 bxe_get_emac_base(struct bxe_softc *sc, uint32_t ext_phy_type, uint8_t port)
869 {
870         uint32_t emac_base;
871
872         switch (ext_phy_type) {
873         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
874         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
875         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
876                 /* All MDC/MDIO is directed through single EMAC. */
877                 if (REG_RD(sc, NIG_REG_PORT_SWAP))
878                         emac_base = GRCBASE_EMAC0;
879                 else
880                         emac_base = GRCBASE_EMAC1;
881                 break;
882         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
883                 emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
884                 break;
885         default:
886                 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
887                 break;
888         }
889         return (emac_base);
890 }
891
892 uint8_t
893 bxe_cl45_write(struct bxe_softc *sc, uint8_t port, uint32_t ext_phy_type,
894     uint8_t phy_addr, uint8_t devad, uint16_t reg, uint16_t val)
895 {
896         uint32_t mdio_ctrl, saved_mode, tmp;
897         uint8_t i, rc;
898
899         rc = 0;
900         mdio_ctrl = bxe_get_emac_base(sc, ext_phy_type, port);
901
902         /*
903          * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
904          * (a value of 49==0x31) and make sure that the AUTO poll is off.
905          */
906
907         saved_mode = REG_RD(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
908         tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
909             EMAC_MDIO_MODE_CLOCK_CNT);
910         tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
911             (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
912         REG_WR(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
913         REG_RD(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
914         DELAY(40);
915
916         /* address */
917
918         tmp = ((phy_addr << 21) | (devad << 16) | reg |
919             EMAC_MDIO_COMM_COMMAND_ADDRESS | EMAC_MDIO_COMM_START_BUSY);
920         REG_WR(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
921
922         for (i = 0; i < 50; i++) {
923                 DELAY(10);
924
925                 tmp = REG_RD(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
926                 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
927                         DELAY(5);
928                         break;
929                 }
930         }
931         if (tmp & EMAC_MDIO_COMM_START_BUSY) {
932                 DBPRINT(sc, BXE_VERBOSE_PHY, "write phy register failed\n");
933                 rc = -EINVAL;
934         } else {
935                 /* data */
936                 tmp = ((phy_addr << 21) | (devad << 16) | val |
937                     EMAC_MDIO_COMM_COMMAND_WRITE_45 |
938                     EMAC_MDIO_COMM_START_BUSY);
939                 REG_WR(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
940
941                 for (i = 0; i < 50; i++) {
942                         DELAY(10);
943
944                         tmp = REG_RD(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
945                         if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
946                                 DELAY(5);
947                                 break;
948                         }
949                 }
950                 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
951                         DBPRINT(sc, BXE_VERBOSE_PHY,
952                             "write phy register failed\n");
953                         rc = -EINVAL;
954                 }
955         }
956
957         /* Restore the saved mode. */
958         REG_WR(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
959
960         return (rc);
961 }
962
963 uint8_t
964 bxe_cl45_read(struct bxe_softc *sc, uint8_t port, uint32_t ext_phy_type,
965     uint8_t phy_addr, uint8_t devad, uint16_t reg, uint16_t *ret_val)
966 {
967         uint32_t mdio_ctrl, saved_mode, val;
968         uint16_t i;
969         uint8_t rc;
970
971         rc = 0;
972         mdio_ctrl = bxe_get_emac_base(sc, ext_phy_type, port);
973
974         /*
975          * set clause 45 mode, slow down the MDIO clock to 2.5MHz
976          * (a value of 49==0x31) and make sure that the AUTO poll is off.
977          */
978         saved_mode = REG_RD(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
979         val = saved_mode & ((EMAC_MDIO_MODE_AUTO_POLL |
980             EMAC_MDIO_MODE_CLOCK_CNT));
981         val |= (EMAC_MDIO_MODE_CLAUSE_45 |
982             (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
983         REG_WR(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
984         REG_RD(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
985         DELAY(40);
986
987         /* address */
988         val = ((phy_addr << 21) | (devad << 16) | reg |
989             EMAC_MDIO_COMM_COMMAND_ADDRESS | EMAC_MDIO_COMM_START_BUSY);
990         REG_WR(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
991
992         for (i = 0; i < 50; i++) {
993                 DELAY(10);
994
995                 val = REG_RD(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
996                 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
997                         DELAY(5);
998                         break;
999                 }
1000         }
1001         if (val & EMAC_MDIO_COMM_START_BUSY) {
1002                 DBPRINT(sc, BXE_VERBOSE_PHY, "read phy register failed\n");
1003
1004                 *ret_val = 0;
1005                 rc = -EINVAL;
1006         } else {
1007                 /* data */
1008                 val = ((phy_addr << 21) | (devad << 16) |
1009                     EMAC_MDIO_COMM_COMMAND_READ_45 | EMAC_MDIO_COMM_START_BUSY);
1010                 REG_WR(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
1011
1012                 for (i = 0; i < 50; i++) {
1013                         DELAY(10);
1014
1015                         val = REG_RD(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
1016                         if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
1017                                 *ret_val = (uint16_t)(val &
1018                                     EMAC_MDIO_COMM_DATA);
1019                                 break;
1020                         }
1021                 }
1022                 if (val & EMAC_MDIO_COMM_START_BUSY) {
1023                         DBPRINT(sc, BXE_VERBOSE_PHY,
1024                             "read phy register failed\n");
1025
1026                         *ret_val = 0;
1027                         rc = -EINVAL;
1028                 }
1029         }
1030
1031         /* Restore the saved mode. */
1032         REG_WR(sc, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
1033
1034         return (rc);
1035 }
1036
1037 static void
1038 bxe_set_aer_mmd(struct link_params *params, struct link_vars *vars)
1039 {
1040         struct bxe_softc *sc;
1041         uint32_t ser_lane;
1042         uint16_t offset;
1043
1044         sc = params->sc;
1045         ser_lane = ((params->lane_config &
1046             PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
1047             PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
1048
1049         offset = (vars->phy_flags & PHY_XGXS_FLAG) ?
1050             (params->phy_addr + ser_lane) : 0;
1051
1052         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1053             MDIO_REG_BANK_AER_BLOCK, MDIO_AER_BLOCK_AER_REG, 0x3800 + offset);
1054 }
1055
1056 static void
1057 bxe_set_master_ln(struct link_params *params)
1058 {
1059         struct bxe_softc *sc;
1060         uint16_t new_master_ln, ser_lane;
1061
1062         sc = params->sc;
1063         ser_lane = ((params->lane_config &
1064             PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
1065             PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
1066
1067         /* Set the master_ln for AN. */
1068         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1069             MDIO_REG_BANK_XGXS_BLOCK2, MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
1070             &new_master_ln);
1071
1072         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1073             MDIO_REG_BANK_XGXS_BLOCK2 , MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
1074             (new_master_ln | ser_lane));
1075 }
1076
1077 static uint8_t
1078 bxe_reset_unicore(struct link_params *params)
1079 {
1080         struct bxe_softc *sc;
1081         uint16_t mii_control;
1082         uint16_t i;
1083
1084         sc = params->sc;
1085         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1086             MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL,
1087             &mii_control);
1088
1089         /* Reset the unicore. */
1090         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1091             MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL,
1092             (mii_control | MDIO_COMBO_IEEO_MII_CONTROL_RESET));
1093         if (params->switch_cfg == SWITCH_CFG_1G)
1094                 bxe_set_serdes_access(params);
1095
1096         /* Wait for the reset to self clear. */
1097         for (i = 0; i < MDIO_ACCESS_TIMEOUT; i++) {
1098                 DELAY(5);
1099
1100                 /* The reset erased the previous bank value. */
1101                 CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1102                     MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL,
1103                     &mii_control);
1104
1105                 if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) {
1106                         DELAY(5);
1107                         return (0);
1108                 }
1109         }
1110
1111         DBPRINT(sc, BXE_VERBOSE_PHY, "BUG! XGXS is still in reset!\n");
1112         return (-EINVAL);
1113 }
1114
1115 static void
1116 bxe_set_swap_lanes(struct link_params *params)
1117 {
1118         struct bxe_softc *sc;
1119         uint16_t ser_lane, rx_lane_swap, tx_lane_swap;
1120
1121         sc = params->sc;
1122         /*
1123          * Each two bits represents a lane number:
1124          *  No swap is 0123 => 0x1b no need to enable the swap.
1125          */
1126
1127         ser_lane = ((params->lane_config &
1128             PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
1129             PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
1130         rx_lane_swap = ((params->lane_config &
1131             PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
1132             PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
1133         tx_lane_swap = ((params->lane_config &
1134             PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
1135             PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
1136
1137         if (rx_lane_swap != 0x1b) {
1138                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1139                     MDIO_REG_BANK_XGXS_BLOCK2, MDIO_XGXS_BLOCK2_RX_LN_SWAP,
1140                     (rx_lane_swap | MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
1141                     MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
1142         } else {
1143                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1144                     MDIO_REG_BANK_XGXS_BLOCK2, MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
1145         }
1146
1147         if (tx_lane_swap != 0x1b) {
1148                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1149                     MDIO_REG_BANK_XGXS_BLOCK2, MDIO_XGXS_BLOCK2_TX_LN_SWAP,
1150                     (tx_lane_swap | MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
1151         } else {
1152                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1153                     MDIO_REG_BANK_XGXS_BLOCK2, MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
1154         }
1155 }
1156
1157 static void
1158 bxe_set_parallel_detection(struct link_params *params, uint8_t phy_flags)
1159 {
1160         struct bxe_softc *sc;
1161         uint16_t control2;
1162
1163         sc = params->sc;
1164         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1165             MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1166             &control2);
1167         if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
1168                 control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
1169         else
1170                 control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
1171
1172         DBPRINT(sc, BXE_VERBOSE_PHY, "%s(): params->speed_cap_mask = 0x%x, "
1173             "control2 = 0x%x\n", __FUNCTION__, params->speed_cap_mask, control2);
1174
1175         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1176             MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1177             control2);
1178
1179         if ((phy_flags & PHY_XGXS_FLAG) && (params->speed_cap_mask &
1180             PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
1181                 DBPRINT(sc, BXE_VERBOSE_PHY, "%s(): XGXS\n", __FUNCTION__);
1182
1183                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1184                     MDIO_REG_BANK_10G_PARALLEL_DETECT,
1185                     MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
1186                     MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
1187
1188                 CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1189                     MDIO_REG_BANK_10G_PARALLEL_DETECT,
1190                     MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL, &control2);
1191
1192                 control2 |=
1193                     MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
1194
1195                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1196                     MDIO_REG_BANK_10G_PARALLEL_DETECT,
1197                     MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL, control2);
1198
1199                 /* Disable parallel detection of HiG. */
1200                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1201                     MDIO_REG_BANK_XGXS_BLOCK2,
1202                     MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
1203                     MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
1204                     MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
1205         }
1206 }
1207
1208 static void
1209 bxe_set_autoneg(struct link_params *params, struct link_vars *vars,
1210     uint8_t enable_cl73)
1211 {
1212         struct bxe_softc *sc;
1213         uint16_t reg_val;
1214
1215         sc = params->sc;
1216         /* CL37 Autoneg */
1217         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1218             MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1219
1220         /* CL37 Autoneg Enabled */
1221         if (vars->line_speed == SPEED_AUTO_NEG)
1222                 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN;
1223         else /* CL37 Autoneg Disabled */
1224                 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1225                     MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);
1226
1227         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1228             MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1229
1230         /* Enable/Disable Autodetection */
1231         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1232             MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1233             &reg_val);
1234         reg_val &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN |
1235             MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT);
1236         reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE;
1237
1238         if (vars->line_speed == SPEED_AUTO_NEG)
1239                 reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1240         else
1241                 reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
1242
1243         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1244             MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1245             reg_val);
1246
1247         /* Enable TetonII and BAM autoneg. */
1248         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1249             MDIO_REG_BANK_BAM_NEXT_PAGE, MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1250             &reg_val);
1251         if (vars->line_speed == SPEED_AUTO_NEG) {
1252                 /* Enable BAM aneg Mode and TetonII aneg Mode. */
1253                 reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1254                     MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1255         } else {
1256                 /* TetonII and BAM Autoneg Disabled. */
1257                 reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
1258                     MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
1259         }
1260         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1261             MDIO_REG_BANK_BAM_NEXT_PAGE, MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
1262             reg_val);
1263
1264         if (enable_cl73) {
1265                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1266                     MDIO_REG_BANK_CL73_USERB0, MDIO_CL73_USERB0_CL73_UCTRL,
1267                     0xe);
1268
1269                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1270                     MDIO_REG_BANK_CL73_USERB0, MDIO_CL73_USERB0_CL73_BAM_CTRL1,
1271                     MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
1272                     MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN |
1273                     MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN);
1274
1275                 /* Set the CL73 AN speed. */
1276                 CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1277                     MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV2,
1278                     &reg_val);
1279                 if (params->speed_cap_mask &
1280                     PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
1281                         reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
1282                 if (params->speed_cap_mask &
1283                     PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
1284                         reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
1285
1286                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1287                     MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV2,
1288                     reg_val);
1289
1290                 /* CL73 Autoneg Enabled. */
1291                 reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;
1292
1293         } else /* CL73 Autoneg Disabled */
1294                 reg_val = 0;
1295
1296         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1297             MDIO_REG_BANK_CL73_IEEEB0, MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1298             reg_val);
1299 }
1300
1301 /* Program SerDes, forced speed. */
1302 static void
1303 bxe_program_serdes(struct link_params *params, struct link_vars *vars)
1304 {
1305         struct bxe_softc *sc;
1306         uint16_t reg_val;
1307
1308         sc = params->sc;
1309         /* Program duplex, disable autoneg and sgmii.*/
1310         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1311             MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
1312         reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
1313             MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1314             MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK);
1315         if (params->req_duplex == DUPLEX_FULL)
1316                 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
1317         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1318             MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
1319
1320         /*
1321          * Program speed
1322          * - needed only if the speed is greater than 1G (2.5G or 10G).
1323          */
1324         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1325             MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_MISC1, &reg_val);
1326         /* Clearing the speed value before setting the right speed. */
1327         DBPRINT(sc, BXE_VERBOSE_PHY, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x\n",
1328             reg_val);
1329
1330         reg_val &= ~(MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK |
1331             MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
1332
1333         if (!((vars->line_speed == SPEED_1000) ||
1334             (vars->line_speed == SPEED_100) ||
1335             (vars->line_speed == SPEED_10))) {
1336                 reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M |
1337                     MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
1338                 if (vars->line_speed == SPEED_10000)
1339                         reg_val |=
1340                             MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
1341                 if (vars->line_speed == SPEED_13000)
1342                         reg_val |=
1343                             MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
1344         }
1345
1346         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1347             MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_MISC1, reg_val);
1348 }
1349
1350 static void
1351 bxe_set_brcm_cl37_advertisment(struct link_params *params)
1352 {
1353         struct bxe_softc *sc;
1354         uint16_t val;
1355
1356         sc = params->sc;
1357         val = 0;
1358
1359         /* Configure the 48 bits for BAM AN. */
1360
1361         /* Set extended capabilities. */
1362         if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
1363                 val |= MDIO_OVER_1G_UP1_2_5G;
1364         if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
1365                 val |= MDIO_OVER_1G_UP1_10G;
1366         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1367             MDIO_REG_BANK_OVER_1G, MDIO_OVER_1G_UP1, val);
1368
1369         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1370             MDIO_REG_BANK_OVER_1G, MDIO_OVER_1G_UP3, 0x400);
1371 }
1372
1373 static void
1374 bxe_calc_ieee_aneg_adv(struct link_params *params, uint16_t *ieee_fc)
1375 {
1376
1377         *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
1378         /*
1379          * Resolve pause mode and advertisement.
1380          * Please refer to Table 28B-3 of the 802.3ab-1999 spec.
1381          */
1382
1383         switch (params->req_flow_ctrl) {
1384         case FLOW_CTRL_AUTO:
1385                 if (params->req_fc_auto_adv == FLOW_CTRL_BOTH) {
1386                         *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
1387                 } else {
1388                         *ieee_fc |=
1389                             MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1390                 }
1391                 break;
1392         case FLOW_CTRL_TX:
1393                 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
1394                 break;
1395         case FLOW_CTRL_RX:
1396         case FLOW_CTRL_BOTH:
1397                 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
1398                 break;
1399         case FLOW_CTRL_NONE:
1400         default:
1401                 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
1402                 break;
1403         }
1404 }
1405
1406 static void
1407 bxe_set_ieee_aneg_advertisment(struct link_params *params, uint16_t ieee_fc)
1408 {
1409         struct bxe_softc *sc;
1410         uint16_t val;
1411
1412         sc = params->sc;
1413
1414         /* For AN, we are always publishing full duplex. */
1415
1416         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1417             MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc);
1418         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1419             MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV1, &val);
1420         val &= ~MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH;
1421         val |= ((ieee_fc<<3) & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK);
1422         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1423             MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV1, val);
1424 }
1425
1426 static void
1427 bxe_restart_autoneg(struct link_params *params, uint8_t enable_cl73)
1428 {
1429         struct bxe_softc *sc;
1430         uint16_t mii_control;
1431
1432         sc = params->sc;
1433         DBPRINT(sc, BXE_VERBOSE_PHY, "bxe_restart_autoneg\n");
1434         /* Enable and restart BAM/CL37 aneg. */
1435
1436         if (enable_cl73) {
1437                 CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1438                     MDIO_REG_BANK_CL73_IEEEB0, MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1439                     &mii_control);
1440
1441                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1442                     MDIO_REG_BANK_CL73_IEEEB0, MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1443                     (mii_control | MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
1444                     MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
1445         } else {
1446                 CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1447                     MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL,
1448                     &mii_control);
1449                 DBPRINT(sc, BXE_VERBOSE_PHY,
1450                     "bxe_restart_autoneg mii_control before = 0x%x\n",
1451                     mii_control);
1452                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1453                     MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL,
1454                     (mii_control | MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1455                     MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
1456         }
1457 }
1458
1459 static void
1460 bxe_initialize_sgmii_process(struct link_params *params, struct link_vars *vars)
1461 {
1462         struct bxe_softc *sc;
1463         uint16_t control1, mii_control;
1464
1465         sc = params->sc;
1466         /* In SGMII mode, the unicore is always slave. */
1467
1468         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1469             MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1470             &control1);
1471         control1 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT;
1472         /* set sgmii mode (and not fiber) */
1473         control1 &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE |
1474             MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET |
1475             MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE);
1476         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1477             MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
1478             control1);
1479
1480         /* if forced speed */
1481         if (!(vars->line_speed == SPEED_AUTO_NEG)) {
1482                 /* Set speed, disable autoneg. */
1483                 CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1484                     MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL,
1485                     &mii_control);
1486                 mii_control &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1487                     MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK|
1488                     MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX);
1489
1490                 switch (vars->line_speed) {
1491                 case SPEED_100:
1492                         mii_control |=
1493                             MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100;
1494                         break;
1495                 case SPEED_1000:
1496                         mii_control |=
1497                             MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_1000;
1498                         break;
1499                 case SPEED_10:
1500                         /* There is nothing to set for 10M. */
1501                         break;
1502                 default:
1503                         /* Invalid speed for SGMII. */
1504                         DBPRINT(sc, BXE_VERBOSE_PHY,
1505                             "Invalid line_speed 0x%x\n", vars->line_speed);
1506                         break;
1507                 }
1508
1509                 /* Setting the full duplex. */
1510                 if (params->req_duplex == DUPLEX_FULL)
1511                         mii_control |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
1512                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1513                     MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL,
1514                     mii_control);
1515         } else { /* AN mode */
1516                 /* Enable and restart AN. */
1517                 bxe_restart_autoneg(params, 0);
1518         }
1519 }
1520
1521 /*
1522  * Link management.
1523  */
1524 static void
1525 bxe_pause_resolve(struct link_vars *vars, uint32_t pause_result)
1526 {
1527
1528                                                 /*  LD      LP   */
1529         switch (pause_result) {                 /* ASYM P ASYM P */
1530         case 0xb:                               /*   1  0   1  1 */
1531                 vars->flow_ctrl = FLOW_CTRL_TX;
1532                 break;
1533         case 0xe:                               /*   1  1   1  0 */
1534                 vars->flow_ctrl = FLOW_CTRL_RX;
1535                 break;
1536         case 0x5:                               /*   0  1   0  1 */
1537         case 0x7:                               /*   0  1   1  1 */
1538         case 0xd:                               /*   1  1   0  1 */
1539         case 0xf:                               /*   1  1   1  1 */
1540                 vars->flow_ctrl = FLOW_CTRL_BOTH;
1541                 break;
1542         default:
1543                 break;
1544         }
1545         if (pause_result & (1<<0))
1546                 vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
1547         if (pause_result & (1<<1))
1548                 vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
1549 }
1550
1551 static uint8_t
1552 bxe_ext_phy_resolve_fc(struct link_params *params, struct link_vars *vars)
1553 {
1554         struct bxe_softc *sc;
1555         uint32_t ext_phy_type;
1556         uint8_t ext_phy_addr;
1557         uint16_t ld_pause;   /* local */
1558         uint16_t lp_pause;   /* link partner */
1559         uint16_t pause_result;
1560         uint8_t port, ret;
1561
1562         sc = params->sc;
1563         ret = 0;
1564         port = params->port;
1565         /* Read twice. */
1566         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
1567         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1568
1569         if (vars->autoneg & AUTO_NEG_COMPLETE) {
1570                 ret = 1;
1571                 bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr,
1572                     MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &ld_pause);
1573                 bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr,
1574                     MDIO_AN_DEVAD, MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
1575                 pause_result = (ld_pause & MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
1576                 pause_result |= (lp_pause & MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
1577                 DBPRINT(sc, BXE_VERBOSE_PHY, "Ext PHY pause result 0x%x \n",
1578                     pause_result);
1579                 bxe_pause_resolve(vars, pause_result);
1580                 if (vars->flow_ctrl == FLOW_CTRL_NONE && ext_phy_type ==
1581                     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
1582                         bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr,
1583                             MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &ld_pause);
1584
1585                         bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr,
1586                             MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LP, &lp_pause);
1587                         pause_result = (ld_pause &
1588                             MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
1589                         pause_result |= (lp_pause &
1590                             MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
1591
1592                         bxe_pause_resolve(vars, pause_result);
1593                         DBPRINT(sc, BXE_VERBOSE_PHY,
1594                             "Ext PHY CL37 pause result 0x%x \n", pause_result);
1595                 }
1596         }
1597         return (ret);
1598 }
1599
1600 uint8_t bxe_direct_parallel_detect_used(struct link_params *);
1601
1602 uint8_t
1603 bxe_direct_parallel_detect_used(struct link_params *params)
1604 {
1605         struct bxe_softc *sc;
1606         uint16_t pd_10g, status2_1000x;
1607
1608         sc = params->sc;
1609         if (params->req_line_speed != SPEED_AUTO_NEG)
1610                 return (0);
1611         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1612             MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
1613             &status2_1000x);
1614         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1615             MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
1616             &status2_1000x);
1617         if (status2_1000x & MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED) {
1618                 DBPRINT(sc, BXE_VERBOSE_PHY,
1619                     "1G parallel detect link on port %d\n", params->port);
1620                 return (1);
1621         }
1622         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1623             MDIO_REG_BANK_10G_PARALLEL_DETECT,
1624             MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS, &pd_10g);
1625         if (pd_10g & MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK) {
1626                 DBPRINT(sc, BXE_VERBOSE_PHY,
1627                     "10G parallel detect link on port %d\n", params->port);
1628                 return (1);
1629         }
1630         return (0);
1631 }
1632
1633 static void
1634 bxe_flow_ctrl_resolve(struct link_params *params, struct link_vars *vars,
1635     uint32_t gp_status)
1636 {
1637         struct bxe_softc *sc;
1638         uint16_t ld_pause;   /* local driver */
1639         uint16_t lp_pause;   /* link partner */
1640         uint16_t pause_result;
1641
1642         sc = params->sc;
1643         vars->flow_ctrl = FLOW_CTRL_NONE;
1644
1645         /* Resolve from gp_status in case of AN complete and not sgmii. */
1646         if (params->req_flow_ctrl != FLOW_CTRL_AUTO)
1647                 vars->flow_ctrl = params->req_flow_ctrl;
1648         else if (params->req_line_speed != SPEED_AUTO_NEG)
1649                 vars->flow_ctrl = params->req_fc_auto_adv;
1650         else if (XGXS_EXT_PHY_TYPE(params->ext_phy_config) !=
1651             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
1652                 bxe_ext_phy_resolve_fc(params, vars);
1653         else if ((gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
1654             (!(vars->phy_flags & PHY_SGMII_FLAG))) {
1655                 if (bxe_direct_parallel_detect_used(params)) {
1656                         vars->flow_ctrl = params->req_fc_auto_adv;
1657                         return;
1658                 }
1659                 if ((gp_status &
1660                     (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
1661                     MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) ==
1662                     (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
1663                     MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {
1664                         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1665                             MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV1,
1666                             &ld_pause);
1667                         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1668                             MDIO_REG_BANK_CL73_IEEEB1,
1669                             MDIO_CL73_IEEEB1_AN_LP_ADV1, &lp_pause);
1670                         pause_result = (ld_pause &
1671                             MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK) >> 8;
1672                         pause_result |= (lp_pause &
1673                             MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK) >> 10;
1674                         DBPRINT(sc, BXE_VERBOSE_PHY, "pause_result CL73 0x%x\n",
1675                             pause_result);
1676                 } else {
1677                         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1678                             MDIO_REG_BANK_COMBO_IEEE0,
1679                             MDIO_COMBO_IEEE0_AUTO_NEG_ADV, &ld_pause);
1680                         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1681                             MDIO_REG_BANK_COMBO_IEEE0,
1682                             MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
1683                             &lp_pause);
1684                         pause_result = (ld_pause &
1685                             MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) >> 5;
1686                         pause_result |= (lp_pause &
1687                             MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
1688                         DBPRINT(sc, BXE_VERBOSE_PHY, "pause_result CL37 0x%x\n",
1689                             pause_result);
1690                 }
1691                 bxe_pause_resolve(vars, pause_result);
1692         }
1693
1694         DBPRINT(sc, BXE_VERBOSE_PHY, "%s(): flow_ctrl 0x%x\n",
1695             __FUNCTION__, vars->flow_ctrl);
1696 }
1697
1698 static void
1699 bxe_check_fallback_to_cl37(struct link_params *params)
1700 {
1701         struct bxe_softc *sc;
1702         uint16_t rx_status, ustat_val, cl37_fsm_recieved;
1703
1704         sc = params->sc;
1705
1706         DBPRINT(sc, BXE_VERBOSE_PHY, "%s(): IEEE 802.3 Clause 37 Fallback\n",
1707              __FUNCTION__);
1708
1709         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr, MDIO_REG_BANK_RX0,
1710             MDIO_RX0_RX_STATUS, &rx_status);
1711         if ((rx_status & MDIO_RX0_RX_STATUS_SIGDET) !=
1712             (MDIO_RX0_RX_STATUS_SIGDET)) {
1713                 DBPRINT(sc, BXE_VERBOSE_PHY,
1714                     "No signal detected. Restoring CL73."
1715                     "rx_status(0x80b0) = 0x%x\n", rx_status);
1716                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1717                     MDIO_REG_BANK_CL73_IEEEB0, MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
1718                     MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN);
1719                 return;
1720         }
1721         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1722             MDIO_REG_BANK_CL73_USERB0, MDIO_CL73_USERB0_CL73_USTAT1,
1723             &ustat_val);
1724         if ((ustat_val & (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
1725             MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) !=
1726             (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
1727             MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) {
1728                 DBPRINT(sc, BXE_VERBOSE_PHY,
1729                     "CL73 state-machine is not stable. "
1730                     "ustat_val(0x8371) = 0x%x\n", ustat_val);
1731                 return;
1732         }
1733         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
1734             MDIO_REG_BANK_REMOTE_PHY, MDIO_REMOTE_PHY_MISC_RX_STATUS,
1735             &cl37_fsm_recieved);
1736         if ((cl37_fsm_recieved &
1737             (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
1738             MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) !=
1739             (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
1740             MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) {
1741                 DBPRINT(sc, BXE_VERBOSE_PHY, "No CL37 FSM were received. "
1742                     "misc_rx_status(0x8330) = 0x%x\n", cl37_fsm_recieved);
1743                 return;
1744         }
1745         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
1746             MDIO_REG_BANK_CL73_IEEEB0, MDIO_CL73_IEEEB0_CL73_AN_CONTROL, 0);
1747         bxe_restart_autoneg(params, 0);
1748
1749         DBPRINT(sc, BXE_INFO, "%s(): Disabling CL73 and restarting CL37 "
1750             "autoneg\n", __FUNCTION__);
1751 }
1752
1753 static void
1754 bxe_an_resolve(struct link_params *params, struct link_vars *vars,
1755     uint32_t gp_status)
1756
1757 {
1758         struct bxe_softc *sc;
1759         uint32_t ext_phy_type;
1760         uint16_t val;
1761         uint8_t ext_phy_addr;
1762
1763         sc = params->sc;
1764         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
1765         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
1766
1767         switch (ext_phy_type) {
1768         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
1769                 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
1770                         vars->autoneg |= AUTO_NEG_COMPLETE;
1771                         vars->link_status |=
1772                             LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
1773                 }
1774
1775                 if (bxe_direct_parallel_detect_used(params)) {
1776                         vars->autoneg |= AUTO_NEG_PARALLEL_DETECTION_USED;
1777                         vars->link_status |=
1778                             LINK_STATUS_PARALLEL_DETECTION_USED;
1779                 }
1780                 break;
1781         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
1782         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
1783                 if (vars->line_speed < SPEED_10000) {
1784                         bxe_cl45_read(sc, params->port, ext_phy_type,
1785                             ext_phy_addr, MDIO_AN_DEVAD,
1786                             MDIO_AN_REG_8481_LEGACY_MII_STATUS, &val);
1787                         if (val & (1 << 5)) {
1788                                 vars->autoneg |= AUTO_NEG_COMPLETE;
1789                                 vars->link_status |=
1790                                     LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
1791                         }
1792                         bxe_cl45_read(sc, params->port, ext_phy_type,
1793                             ext_phy_addr, MDIO_AN_DEVAD,
1794                             MDIO_AN_REG_8481_LEGACY_AN_EXPANSION, &val);
1795                         if ((val & (1 << 0)) == 0) {
1796                                 vars->autoneg |=
1797                                     AUTO_NEG_PARALLEL_DETECTION_USED;
1798                                 vars->link_status |=
1799                                         LINK_STATUS_PARALLEL_DETECTION_USED;
1800                         }
1801                         break;
1802                 };
1803         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
1804         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
1805                 bxe_cl45_read(sc, params->port, ext_phy_type, ext_phy_addr,
1806                     MDIO_AN_DEVAD, MDIO_AN_REG_STATUS, &val);
1807                 bxe_cl45_read(sc, params->port, ext_phy_type, ext_phy_addr,
1808                     MDIO_AN_DEVAD, MDIO_AN_REG_STATUS, &val);
1809                 if (val & (1 << 5)) {
1810                         vars->autoneg |= AUTO_NEG_COMPLETE;
1811                         vars->link_status |=
1812                             LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
1813                 }
1814                 if ((val & (1 << 0)) == 0) {
1815                         vars->autoneg |= AUTO_NEG_PARALLEL_DETECTION_USED;
1816                         vars->link_status |=
1817                             LINK_STATUS_PARALLEL_DETECTION_USED;
1818                 }
1819                 break;
1820         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
1821         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
1822                 vars->autoneg |= AUTO_NEG_COMPLETE;
1823                 vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
1824                 break;
1825         default:
1826                 break;
1827         }
1828         DBPRINT(sc, BXE_VERBOSE_PHY, "AN result for port %d: 0x%x\n",
1829             params->port, vars->autoneg);
1830 }
1831
1832 static uint8_t
1833 bxe_link_settings_status(struct link_params *params, struct link_vars *vars,
1834     uint32_t gp_status, uint8_t ext_phy_link_up)
1835 {
1836         struct bxe_softc *sc;
1837         uint16_t new_line_speed;
1838
1839         sc = params->sc;
1840         vars->link_status = 0;
1841         vars->autoneg = 0;
1842         if (params->req_line_speed == SPEED_AUTO_NEG) {
1843                 vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
1844                 vars->autoneg |= AUTO_NEG_ENABLED;
1845         }
1846         if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
1847                 DBPRINT(sc, BXE_VERBOSE_PHY, "phy link up gp_status=0x%x\n",
1848                          gp_status);
1849
1850                 vars->phy_link_up = 1;
1851                 vars->link_status |= LINK_STATUS_LINK_UP;
1852
1853                 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
1854                         vars->duplex = DUPLEX_FULL;
1855                 else
1856                         vars->duplex = DUPLEX_HALF;
1857                 if (params->req_line_speed == SPEED_AUTO_NEG)
1858                         bxe_an_resolve(params, vars, gp_status);
1859
1860                 bxe_flow_ctrl_resolve(params, vars, gp_status);
1861
1862                 switch (gp_status & GP_STATUS_SPEED_MASK) {
1863                 case GP_STATUS_10M:
1864                         new_line_speed = SPEED_10;
1865                         if (vars->duplex == DUPLEX_FULL)
1866                                 vars->link_status |= LINK_10TFD;
1867                         else
1868                                 vars->link_status |= LINK_10THD;
1869                         break;
1870                 case GP_STATUS_100M:
1871                         new_line_speed = SPEED_100;
1872                         if (vars->duplex == DUPLEX_FULL)
1873                                 vars->link_status |= LINK_100TXFD;
1874                         else
1875                                 vars->link_status |= LINK_100TXHD;
1876                         break;
1877                 case GP_STATUS_1G:
1878                 case GP_STATUS_1G_KX:
1879                         new_line_speed = SPEED_1000;
1880                         if (vars->duplex == DUPLEX_FULL)
1881                                 vars->link_status |= LINK_1000TFD;
1882                         else
1883                                 vars->link_status |= LINK_1000THD;
1884                         break;
1885                 case GP_STATUS_2_5G:
1886                         new_line_speed = SPEED_2500;
1887                         if (vars->duplex == DUPLEX_FULL)
1888                                 vars->link_status |= LINK_2500TFD;
1889                         else
1890                                 vars->link_status |= LINK_2500THD;
1891                         break;
1892                 case GP_STATUS_5G:
1893                 case GP_STATUS_6G:
1894                         DBPRINT(sc, BXE_VERBOSE_PHY,
1895                                  "link speed unsupported  gp_status 0x%x\n",
1896                                   gp_status);
1897                         return (-EINVAL);
1898                 case GP_STATUS_10G_KX4:
1899                 case GP_STATUS_10G_HIG:
1900                 case GP_STATUS_10G_CX4:
1901                         new_line_speed = SPEED_10000;
1902                         vars->link_status |= LINK_10GTFD;
1903                         break;
1904                 case GP_STATUS_12G_HIG:
1905                         new_line_speed = SPEED_12000;
1906                         vars->link_status |= LINK_12GTFD;
1907                         break;
1908                 case GP_STATUS_12_5G:
1909                         new_line_speed = SPEED_12500;
1910                         vars->link_status |= LINK_12_5GTFD;
1911                         break;
1912                 case GP_STATUS_13G:
1913                         new_line_speed = SPEED_13000;
1914                         vars->link_status |= LINK_13GTFD;
1915                         break;
1916                 case GP_STATUS_15G:
1917                         new_line_speed = SPEED_15000;
1918                         vars->link_status |= LINK_15GTFD;
1919                         break;
1920                 case GP_STATUS_16G:
1921                         new_line_speed = SPEED_16000;
1922                         vars->link_status |= LINK_16GTFD;
1923                         break;
1924                 default:
1925                         DBPRINT(sc, BXE_VERBOSE_PHY,
1926                             "link speed unsupported gp_status 0x%x\n",
1927                             gp_status);
1928                         return (-EINVAL);
1929                 }
1930
1931                 /*
1932                  * Upon link speed change set the NIG into drain mode.
1933                  * Comes to deals with possible FIFO glitch due to clk change
1934                  * when speed is decreased without link down indicator.
1935                  */
1936                 if (new_line_speed != vars->line_speed) {
1937                         if (XGXS_EXT_PHY_TYPE(params->ext_phy_config) !=
1938                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT &&
1939                             ext_phy_link_up) {
1940                                 DBPRINT(sc, BXE_VERBOSE_PHY,
1941                                     "Internal link speed %d is different "
1942                                     "than the external link speed %d\n",
1943                                     new_line_speed, vars->line_speed);
1944                                 vars->phy_link_up = 0;
1945                                 return (0);
1946                         }
1947                         REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE +
1948                             params->port * 4, 0);
1949                         msleep(1);
1950                 }
1951                 vars->line_speed = new_line_speed;
1952
1953                 if (vars->flow_ctrl & FLOW_CTRL_TX)
1954                         vars->link_status |=
1955                             LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
1956
1957                 if (vars->flow_ctrl & FLOW_CTRL_RX)
1958                         vars->link_status |=
1959                             LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
1960
1961                 if (!ext_phy_link_up)
1962                         vars->link_status = 0;
1963         } else { /* link_down */
1964                 DBPRINT(sc, BXE_VERBOSE_PHY, "phy link down\n");
1965
1966                 vars->phy_link_up = 0;
1967
1968                 vars->duplex = DUPLEX_FULL;
1969                 vars->flow_ctrl = FLOW_CTRL_NONE;
1970                 vars->autoneg = AUTO_NEG_DISABLED;
1971                 vars->mac_type = MAC_TYPE_NONE;
1972                 if ((params->req_line_speed == SPEED_AUTO_NEG) &&
1973                     ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
1974                     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT))) {
1975                         bxe_check_fallback_to_cl37(params);
1976                 }
1977         }
1978         DBPRINT(sc, BXE_VERBOSE_PHY,
1979             "gp_status 0x%x  phy_link_up %x line_speed %x \n", gp_status,
1980             vars->phy_link_up, vars->line_speed);
1981         DBPRINT(sc, BXE_VERBOSE_PHY,
1982             "duplex %x  flow_ctrl 0x%x autoneg 0x%x\n", vars->duplex,
1983             vars->flow_ctrl, vars->autoneg);
1984         DBPRINT(sc, BXE_VERBOSE_PHY, "link_status 0x%x\n", vars->link_status);
1985
1986         return (0);
1987 }
1988
1989 static void
1990 bxe_set_gmii_tx_driver(struct link_params *params)
1991 {
1992         struct bxe_softc *sc;
1993         uint16_t lp_up2;
1994         uint16_t tx_driver;
1995         uint16_t bank;
1996
1997         sc = params->sc;
1998         /* read precomp */
1999         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
2000             MDIO_REG_BANK_OVER_1G, MDIO_OVER_1G_LP_UP2, &lp_up2);
2001
2002         /* bits [10:7] at lp_up2, positioned at [15:12] */
2003         lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >>
2004             MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT) <<
2005             MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT);
2006
2007         if (lp_up2 == 0)
2008                 return;
2009
2010         for (bank = MDIO_REG_BANK_TX0; bank <= MDIO_REG_BANK_TX3;
2011             bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0)) {
2012                 CL45_RD_OVER_CL22(sc, params->port, params->phy_addr, bank,
2013                     MDIO_TX0_TX_DRIVER, &tx_driver);
2014
2015                 /* Replace tx_driver bits [15:12] */
2016                 if (lp_up2 != (tx_driver &
2017                     MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK)) {
2018                         tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
2019                         tx_driver |= lp_up2;
2020                         CL45_WR_OVER_CL22(sc, params->port, params->phy_addr,
2021                             bank, MDIO_TX0_TX_DRIVER, tx_driver);
2022                 }
2023         }
2024 }
2025
2026 static uint8_t
2027 bxe_emac_program(struct link_params *params, uint32_t line_speed,
2028     uint32_t duplex)
2029 {
2030         struct bxe_softc *sc;
2031         uint16_t mode;
2032         uint8_t port;
2033
2034         sc = params->sc;
2035         port = params->port;
2036         mode = 0;
2037
2038         DBPRINT(sc, BXE_VERBOSE_PHY, "setting link speed & duplex\n");
2039         bxe_bits_dis(sc, GRCBASE_EMAC0 + port * 0x400 + EMAC_REG_EMAC_MODE,
2040             (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_MII_10M |
2041             EMAC_MODE_HALF_DUPLEX));
2042         switch (line_speed) {
2043         case SPEED_10:
2044                 mode |= EMAC_MODE_PORT_MII_10M;
2045                 break;
2046         case SPEED_100:
2047                 mode |= EMAC_MODE_PORT_MII;
2048                 break;
2049         case SPEED_1000:
2050                 mode |= EMAC_MODE_PORT_GMII;
2051                 break;
2052         case SPEED_2500:
2053                 mode |= (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_GMII);
2054                 break;
2055         default:
2056                 /* 10G not valid for EMAC */
2057                 DBPRINT(sc, BXE_VERBOSE_PHY, "Invalid line_speed 0x%x\n",
2058                     line_speed);
2059                 return (-EINVAL);
2060         }
2061
2062         if (duplex == DUPLEX_HALF)
2063                 mode |= EMAC_MODE_HALF_DUPLEX;
2064         bxe_bits_en(sc, GRCBASE_EMAC0 + port * 0x400 + EMAC_REG_EMAC_MODE,
2065             mode);
2066
2067         bxe_set_led(params, LED_MODE_OPER, line_speed);
2068         return (0);
2069 }
2070
2071 /*
2072  * External Phy section
2073  */
2074 void
2075 bxe_ext_phy_hw_reset(struct bxe_softc *sc, uint8_t port)
2076 {
2077
2078         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_OUTPUT_LOW,
2079             port);
2080         msleep(1);
2081         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_OUTPUT_HIGH,
2082             port);
2083 }
2084
2085 static void
2086 bxe_ext_phy_reset(struct link_params *params, struct link_vars *vars)
2087 {
2088         struct bxe_softc *sc;
2089         uint32_t ext_phy_type;
2090         uint8_t ext_phy_addr;
2091
2092         sc = params->sc;
2093         DBPRINT(sc, BXE_VERBOSE_PHY, "Port %x: bxe_ext_phy_reset\n",
2094             params->port);
2095         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
2096         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2097
2098         /*
2099          * The PHY reset is controled by GPIO 1.
2100          * Give it 1ms of reset pulse.
2101          */
2102         if (vars->phy_flags & PHY_XGXS_FLAG) {
2103                 switch (ext_phy_type) {
2104                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
2105                         DBPRINT(sc, BXE_VERBOSE_PHY, "XGXS Direct\n");
2106                         break;
2107                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2108                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2109                         DBPRINT(sc, BXE_VERBOSE_PHY, "XGXS 8705/8706\n");
2110
2111                         /* Restore normal power mode*/
2112                         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_2,
2113                             MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
2114
2115                         /* HW reset */
2116                         bxe_ext_phy_hw_reset(sc, params->port);
2117
2118                         bxe_cl45_write(sc, params->port, ext_phy_type,
2119                             ext_phy_addr, MDIO_PMA_DEVAD,
2120                             MDIO_PMA_REG_CTRL, 0xa040);
2121                         break;
2122                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
2123                         break;
2124                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
2125                         /* Restore normal power mode*/
2126                         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_2,
2127                             MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
2128
2129                         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_1,
2130                             MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
2131
2132                         bxe_cl45_write(sc, params->port, ext_phy_type,
2133                             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL,
2134                             1 << 15);
2135                         break;
2136                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2137                         DBPRINT(sc, BXE_VERBOSE_PHY, "XGXS 8072\n");
2138
2139                         /*
2140                          * Unset Low Power Mode and SW reset.
2141                          * Restore normal power mode.
2142                          */
2143                         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_2,
2144                             MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
2145
2146                         bxe_cl45_write(sc, params->port, ext_phy_type,
2147                             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL,
2148                             1 << 15);
2149                         break;
2150                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2151                         DBPRINT(sc, BXE_VERBOSE_PHY, "XGXS 8073\n");
2152
2153                         /* Restore normal power mode. */
2154                         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_2,
2155                             MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
2156
2157                         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_1,
2158                             MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
2159                         break;
2160                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
2161                         DBPRINT(sc, BXE_VERBOSE_PHY, "XGXS SFX7101\n");
2162
2163                         /* Restore normal power mode. */
2164                         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_2,
2165                             MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
2166
2167                         /* HW reset */
2168                         bxe_ext_phy_hw_reset(sc, params->port);
2169                         break;
2170                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
2171                         /* Restore normal power mode. */
2172                         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_2,
2173                             MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
2174
2175                         /* HW reset */
2176                         bxe_ext_phy_hw_reset(sc, params->port);
2177
2178                         bxe_cl45_write(sc, params->port, ext_phy_type,
2179                             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL,
2180                             1 << 15);
2181                         break;
2182                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
2183                         break;
2184                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
2185                         DBPRINT(sc, BXE_VERBOSE_PHY,
2186                             "XGXS PHY Failure detected\n");
2187                         break;
2188
2189                 default:
2190                         DBPRINT(sc, BXE_VERBOSE_PHY,
2191                             "BAD XGXS ext_phy_config 0x%x\n",
2192                             params->ext_phy_config);
2193                         break;
2194                 }
2195
2196         } else { /* SerDes */
2197                 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
2198                 switch (ext_phy_type) {
2199                 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
2200                         DBPRINT(sc, BXE_VERBOSE_PHY, "SerDes Direct\n");
2201                         break;
2202                 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
2203                         DBPRINT(sc, BXE_VERBOSE_PHY, "SerDes 5482\n");
2204                         bxe_ext_phy_hw_reset(sc, params->port);
2205                         break;
2206                 default:
2207                         DBPRINT(sc, BXE_VERBOSE_PHY,
2208                             "BAD SerDes ext_phy_config 0x%x\n",
2209                             params->ext_phy_config);
2210                         break;
2211                 }
2212         }
2213 }
2214
2215 static void
2216 bxe_save_spirom_version(struct bxe_softc *sc, uint8_t port, uint32_t shmem_base,
2217     uint32_t spirom_ver)
2218 {
2219
2220         DBPRINT(sc, BXE_VERBOSE_PHY, "FW version 0x%x:0x%x\n",
2221             (uint16_t)(spirom_ver >> 16), (uint16_t)spirom_ver);
2222         REG_WR(sc, shmem_base + offsetof(struct shmem_region,
2223             port_mb[port].ext_phy_fw_version), spirom_ver);
2224 }
2225
2226 static void
2227 bxe_save_bcm_spirom_ver(struct bxe_softc *sc, uint8_t port,
2228     uint32_t ext_phy_type, uint8_t ext_phy_addr, uint32_t shmem_base)
2229 {
2230         uint16_t fw_ver1, fw_ver2;
2231         uint8_t status;
2232
2233         status = 0;
2234         status = bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr,
2235             MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1, &fw_ver1);
2236         status |= bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr,
2237             MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2, &fw_ver2);
2238         bxe_save_spirom_version(sc, port, shmem_base,
2239             (uint32_t)(fw_ver1 << 16 | fw_ver2));
2240
2241         if (status)
2242                 BXE_PRINTF("Reading the external PHY ROM failed. Status:0x%x\n",
2243                     status);
2244 }
2245
2246 static void
2247 bxe_save_8481_spirom_version(struct bxe_softc *sc, uint8_t port,
2248     uint8_t ext_phy_addr, uint32_t shmem_base)
2249 {
2250         uint16_t val, fw_ver1, fw_ver2, cnt;
2251         /*
2252          * For the 32 bits registers in 8481, access via MDIO2ARM interface.
2253          * (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000.
2254          */
2255         bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
2256             ext_phy_addr, MDIO_PMA_DEVAD, 0xA819, 0x0014);
2257         bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
2258             ext_phy_addr, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
2259         bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
2260             ext_phy_addr, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
2261         bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
2262             ext_phy_addr, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
2263         bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
2264             ext_phy_addr, MDIO_PMA_DEVAD, 0xA817, 0x0009);
2265
2266         for (cnt = 0; cnt < 100; cnt++) {
2267                 bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
2268                     ext_phy_addr, MDIO_PMA_DEVAD, 0xA818, &val);
2269                 if (val & 1)
2270                         break;
2271                 DELAY(5);
2272         }
2273         if (cnt == 100) {
2274                 DBPRINT(sc, BXE_VERBOSE_PHY,
2275                     "Unable to read 8481 phy fw version(1)\n");
2276                 bxe_save_spirom_version(sc, port, shmem_base, 0);
2277                 return;
2278         }
2279
2280         /* 2) read register 0xc200_0000 (SPI_FW_STATUS). */
2281         bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
2282             ext_phy_addr, MDIO_PMA_DEVAD, 0xA819, 0x0000);
2283         bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
2284             ext_phy_addr, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
2285         bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
2286             ext_phy_addr, MDIO_PMA_DEVAD, 0xA817, 0x000A);
2287         for (cnt = 0; cnt < 100; cnt++) {
2288                 bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
2289                     ext_phy_addr, MDIO_PMA_DEVAD, 0xA818, &val);
2290                 if (val & 1)
2291                         break;
2292                 DELAY(5);
2293         }
2294         if (cnt == 100) {
2295                 DBPRINT(sc, BXE_VERBOSE_PHY,
2296                     "Unable to read 8481 phy fw version(2)\n");
2297                 bxe_save_spirom_version(sc, port, shmem_base, 0);
2298                 return;
2299         }
2300
2301         /* Lower 16 bits of the register SPI_FW_STATUS. */
2302         bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
2303             ext_phy_addr, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
2304         /* Upper 16 bits of register SPI_FW_STATUS. */
2305         bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
2306             ext_phy_addr, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
2307
2308         bxe_save_spirom_version(sc, port, shmem_base, (fw_ver2<<16) | fw_ver1);
2309 }
2310
2311 static void
2312 bxe_bcm8072_external_rom_boot(struct link_params *params)
2313 {
2314         struct bxe_softc *sc;
2315         uint32_t ext_phy_type;
2316         uint8_t ext_phy_addr, port;
2317
2318         sc = params->sc;
2319         port = params->port;
2320         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
2321         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2322
2323         /* Need to wait 200ms after reset. */
2324         msleep(200);
2325         /*
2326          * Boot port from external ROM.
2327          * Set ser_boot_ctl bit in the MISC_CTRL1 register.
2328          */
2329         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2330             MDIO_PMA_REG_MISC_CTRL1, 0x0001);
2331
2332         /* Reset internal microprocessor */
2333         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2334             MDIO_PMA_REG_GEN_CTRL, MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2335         /* Set micro reset = 0. */
2336         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2337             MDIO_PMA_REG_GEN_CTRL, MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
2338         /* Reset internal microprocessor. */
2339         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2340             MDIO_PMA_REG_GEN_CTRL, MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2341         /* Wait for 100ms for code download via SPI port. */
2342         msleep(100);
2343
2344         /* Clear ser_boot_ctl bit. */
2345         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2346             MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2347         /* Wait 100ms. */
2348         msleep(100);
2349
2350         bxe_save_bcm_spirom_ver(sc, port, ext_phy_type, ext_phy_addr,
2351             params->shmem_base);
2352 }
2353
2354 /* This is only required for 8073A1, version 102 only. */
2355 static uint8_t
2356 bxe_8073_is_snr_needed(struct link_params *params)
2357 {
2358         struct bxe_softc *sc;
2359         uint8_t ext_phy_addr;
2360         uint16_t val;
2361
2362         sc = params->sc;
2363         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
2364
2365         /* Read 8073 HW revision. */
2366         bxe_cl45_read(sc, params->port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2367             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, &val);
2368
2369         if (val != 1) {
2370                 /* No need to workaround in 8073 A1. */
2371                 return (0);
2372         }
2373
2374         bxe_cl45_read(sc, params->port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2375             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2, &val);
2376
2377         /* SNR should be applied only for version 0x102. */
2378         if (val != 0x102)
2379                 return (0);
2380
2381         return (1);
2382 }
2383
2384 static uint8_t
2385 bxe_bcm8073_xaui_wa(struct link_params *params)
2386 {
2387         struct bxe_softc *sc;
2388         uint16_t cnt, cnt1, val;
2389         uint8_t ext_phy_addr;
2390
2391         sc = params->sc;
2392         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
2393
2394         bxe_cl45_read(sc, params->port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2395             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, &val);
2396
2397         if (val > 0) {
2398                 /* No need to workaround in 8073 A1. */
2399                 return (0);
2400         }
2401         /* XAUI workaround in 8073 A0: */
2402
2403         /*
2404          * After loading the boot ROM and restarting Autoneg,
2405          * poll Dev1, Reg $C820:
2406          */
2407
2408         for (cnt = 0; cnt < 1000; cnt++) {
2409                 bxe_cl45_read(sc, params->port,
2410                     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073, ext_phy_addr,
2411                     MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &val);
2412                 /*
2413                  * If bit [14] = 0 or bit [13] = 0, continue on with
2414                  * system initialization (XAUI work-around not required,
2415                  * as these bits indicate 2.5G or 1G link up).
2416                  */
2417                 if (!(val & (1<<14)) || !(val & (1<<13))) {
2418                         DBPRINT(sc, BXE_VERBOSE_PHY,
2419                             "XAUI work-around not required\n");
2420                         return (0);
2421                 } else if (!(val & (1<<15))) {
2422                         DBPRINT(sc, BXE_VERBOSE_PHY, "clc bit 15 went off\n");
2423                         /*
2424                          * If bit 15 is 0, then poll Dev1, Reg $C841 until
2425                          * it's MSB (bit 15) goes to 1 (indicating that the
2426                          * XAUI workaround has completed), then continue on
2427                          * with system initialization.
2428                          */
2429                         for (cnt1 = 0; cnt1 < 1000; cnt1++) {
2430                                 bxe_cl45_read(sc, params->port,
2431                                     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
2432                                     ext_phy_addr, MDIO_PMA_DEVAD,
2433                                     MDIO_PMA_REG_8073_XAUI_WA, &val);
2434                                 if (val & (1<<15)) {
2435                                         DBPRINT(sc, BXE_VERBOSE_PHY,
2436                                             "XAUI workaround has completed\n");
2437                                         return (0);
2438                                  }
2439                                  msleep(3);
2440                         }
2441                         break;
2442                 }
2443                 msleep(3);
2444         }
2445         DBPRINT(sc, BXE_VERBOSE_PHY, "Warning: XAUI work-around timeout !!!\n");
2446         return (-EINVAL);
2447 }
2448
2449 static void
2450 bxe_bcm8073_bcm8727_external_rom_boot(struct bxe_softc *sc, uint8_t port,
2451     uint8_t ext_phy_addr, uint32_t ext_phy_type, uint32_t shmem_base)
2452 {
2453
2454         /* Boot port from external ROM.  */
2455         /* EDC grst */
2456         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2457             MDIO_PMA_REG_GEN_CTRL, 0x0001);
2458
2459         /* ucode reboot and rst. */
2460         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2461             MDIO_PMA_REG_GEN_CTRL, 0x008c);
2462
2463         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2464             MDIO_PMA_REG_MISC_CTRL1, 0x0001);
2465
2466         /* Reset internal microprocessor. */
2467         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2468             MDIO_PMA_REG_GEN_CTRL, MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
2469
2470         /* Release srst bit. */
2471         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2472             MDIO_PMA_REG_GEN_CTRL, MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2473
2474         /* Wait for 100ms for code download via SPI port. */
2475         msleep(100);
2476
2477         /* Clear ser_boot_ctl bit. */
2478         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2479             MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2480
2481         bxe_save_bcm_spirom_ver(sc, port, ext_phy_type, ext_phy_addr,
2482             shmem_base);
2483 }
2484
2485 static void
2486 bxe_bcm8073_external_rom_boot(struct bxe_softc *sc, uint8_t port,
2487     uint8_t ext_phy_addr, uint32_t shmem_base)
2488 {
2489
2490         bxe_bcm8073_bcm8727_external_rom_boot(sc, port, ext_phy_addr,
2491             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073, shmem_base);
2492 }
2493
2494 static void
2495 bxe_bcm8727_external_rom_boot(struct bxe_softc *sc, uint8_t port,
2496     uint8_t ext_phy_addr, uint32_t shmem_base)
2497 {
2498
2499         bxe_bcm8073_bcm8727_external_rom_boot(sc, port, ext_phy_addr,
2500             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727, shmem_base);
2501 }
2502
2503 static void
2504 bxe_bcm8726_external_rom_boot(struct link_params *params)
2505 {
2506         struct bxe_softc *sc;
2507         uint32_t ext_phy_type;
2508         uint8_t ext_phy_addr, port;
2509
2510         sc = params->sc;
2511         port = params->port;
2512         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
2513         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2514
2515         /* Need to wait 100ms after reset. */
2516         msleep(100);
2517
2518         /* Set serial boot control for external load. */
2519
2520         /* Micro controller re-boot. */
2521         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2522             MDIO_PMA_REG_GEN_CTRL, 0x018B);
2523
2524         /* Set soft reset. */
2525         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2526             MDIO_PMA_REG_GEN_CTRL, MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
2527
2528         /* Set PLL register value to be same like in P13 ver. */
2529         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2530             MDIO_PMA_REG_MISC_CTRL1, 0x0001);
2531
2532         /*
2533          * Clear soft reset.
2534          * Will automatically reset micro-controller re-boot.
2535          */
2536         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2537             MDIO_PMA_REG_GEN_CTRL, MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
2538
2539         /* Wait for 150ms for microcode load. */
2540         msleep(150);
2541
2542         /* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO. */
2543         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2544             MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2545
2546         msleep(200);
2547         bxe_save_bcm_spirom_ver(sc, port, ext_phy_type, ext_phy_addr,
2548             params->shmem_base);
2549 }
2550
2551 static void
2552 bxe_sfp_set_transmitter(struct bxe_softc *sc, uint8_t port,
2553     uint32_t ext_phy_type, uint8_t ext_phy_addr, uint8_t tx_en)
2554 {
2555         uint16_t val;
2556
2557         DBPRINT(sc, BXE_VERBOSE_PHY,
2558             "Setting transmitter tx_en=%x for port %x\n", tx_en, port);
2559         /* Disable/Enable transmitter ( TX laser of the SFP+ module.). */
2560         bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2561             MDIO_PMA_REG_PHY_IDENTIFIER, &val);
2562
2563         if (tx_en)
2564                 val &= ~(1<<15);
2565         else
2566                 val |= (1<<15);
2567
2568         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2569             MDIO_PMA_REG_PHY_IDENTIFIER, val);
2570 }
2571
2572 static uint8_t
2573 bxe_8726_read_sfp_module_eeprom(struct link_params *params, uint16_t addr,
2574     uint8_t byte_cnt, uint8_t *o_buf)
2575 {
2576         struct bxe_softc *sc;
2577         uint32_t ext_phy_type;
2578         uint16_t i, val;
2579         uint8_t ext_phy_addr, port;
2580
2581         sc = params->sc;
2582         val = 0;
2583         port = params->port;
2584         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
2585         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2586
2587         if (byte_cnt > 16) {
2588                 DBPRINT(sc, BXE_VERBOSE_PHY,
2589                     "Reading from eeprom is limited to 0xf\n");
2590                 return (-EINVAL);
2591         }
2592         /* Set the read command byte count. */
2593         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2594             MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT, (byte_cnt | 0xa000));
2595
2596         /* Set the read command address. */
2597         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2598             MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR, addr);
2599
2600         /* Activate read command. */
2601         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2602             MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, 0x2c0f);
2603
2604         /* Wait up to 500us for command complete status. */
2605         for (i = 0; i < 100; i++) {
2606                 bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr,
2607                     MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
2608                 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
2609                     MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
2610                         break;
2611                 DELAY(5);
2612         }
2613
2614         if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
2615             MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
2616                 DBPRINT(sc, BXE_VERBOSE_PHY,
2617                     "Got bad status 0x%x when reading from SFP+ EEPROM\n",
2618                     (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK));
2619                 return (-EINVAL);
2620         }
2621
2622         /* Read the buffer. */
2623         for (i = 0; i < byte_cnt; i++) {
2624                 bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr,
2625                     MDIO_PMA_DEVAD, MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF + i,
2626                     &val);
2627                 o_buf[i] = (uint8_t)(val &
2628                     MDIO_PMA_REG_8726_TWO_WIRE_DATA_MASK);
2629         }
2630
2631         for (i = 0; i < 100; i++) {
2632                 bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr,
2633                     MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
2634                 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
2635                     MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
2636                         return (0);
2637                 msleep(1);
2638         }
2639         return (-EINVAL);
2640 }
2641
2642 static uint8_t
2643 bxe_8727_read_sfp_module_eeprom(struct link_params *params, uint16_t addr,
2644     uint8_t byte_cnt, uint8_t *o_buf)
2645 {
2646         struct bxe_softc *sc;
2647         uint32_t ext_phy_type;
2648         uint16_t val, i;
2649         uint8_t ext_phy_addr, port;
2650
2651         sc = params->sc;
2652         port = params->port;
2653         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
2654         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2655
2656         if (byte_cnt > 16) {
2657                 DBPRINT(sc, BXE_VERBOSE_PHY,
2658                     "Reading from eeprom is limited to 0xf\n");
2659                 return (-EINVAL);
2660         }
2661
2662         /* Need to read from 1.8000 to clear it. */
2663         bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
2664             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
2665             &val);
2666
2667         /* Set the read command byte count. */
2668         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2669             MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
2670             ((byte_cnt < 2) ? 2 : byte_cnt));
2671
2672         /* Set the read command address. */
2673         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2674             MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR, addr);
2675         /* Set the destination address. */
2676         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2677             0x8004, MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF);
2678
2679         /* Activate read command. */
2680         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
2681             MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, 0x8002);
2682         /*
2683          * Wait appropriate time for two-wire command to finish before
2684          * polling the status register.
2685          */
2686         msleep(1);
2687
2688         /* Wait up to 500us for command complete status. */
2689         for (i = 0; i < 100; i++) {
2690                 bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr,
2691                     MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
2692                 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
2693                     MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
2694                         break;
2695                 DELAY(5);
2696         }
2697
2698         if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
2699             MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
2700                 DBPRINT(sc, BXE_VERBOSE_PHY,
2701                     "Got bad status 0x%x when reading from SFP+ EEPROM\n",
2702                     (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK));
2703                 return (-EINVAL);
2704         }
2705
2706         /* Read the buffer. */
2707         for (i = 0; i < byte_cnt; i++) {
2708                 bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr,
2709                     MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF + i,
2710                     &val);
2711                 o_buf[i] = (uint8_t)(val &
2712                     MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK);
2713         }
2714
2715         for (i = 0; i < 100; i++) {
2716                 bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr,
2717                     MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
2718                 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
2719                     MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
2720                         return (0);
2721                 msleep(1);
2722         }
2723
2724         return (-EINVAL);
2725 }
2726
2727 uint8_t
2728 bxe_read_sfp_module_eeprom(struct link_params *params, uint16_t addr,
2729     uint8_t byte_cnt, uint8_t *o_buf)
2730 {
2731         uint32_t ext_phy_type;
2732
2733         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
2734         if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
2735                 return (bxe_8726_read_sfp_module_eeprom(params, addr, byte_cnt,
2736                     o_buf));
2737         else if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
2738                 return (bxe_8727_read_sfp_module_eeprom(params, addr, byte_cnt,
2739                     o_buf));
2740         return (-EINVAL);
2741 }
2742
2743 static uint8_t
2744 bxe_get_edc_mode(struct link_params *params, uint16_t *edc_mode)
2745 {
2746 #ifdef BXE_DEBUG
2747         struct bxe_softc *sc = params->sc;
2748 #endif
2749         uint8_t copper_module_type;
2750         uint8_t options[SFP_EEPROM_OPTIONS_SIZE];
2751         uint8_t val, check_limiting_mode;
2752
2753         check_limiting_mode = 0;
2754         *edc_mode = EDC_MODE_LIMITING;
2755
2756         /* First check for copper cable. */
2757         if (bxe_read_sfp_module_eeprom(params, SFP_EEPROM_CON_TYPE_ADDR, 1,
2758             &val) != 0) {
2759                 DBPRINT(sc, BXE_VERBOSE_PHY,
2760                     "Failed to read from SFP+ module EEPROM\n");
2761                 return (-EINVAL);
2762         }
2763
2764         switch (val) {
2765         case SFP_EEPROM_CON_TYPE_VAL_COPPER:
2766                 /*
2767                  * Check if its active cable( includes SFP+ module)
2768                  * of passive cable.
2769                  */
2770                 if (bxe_read_sfp_module_eeprom(params,
2771                     SFP_EEPROM_FC_TX_TECH_ADDR, 1, &copper_module_type) != 0) {
2772                         DBPRINT(sc, BXE_VERBOSE_PHY,
2773                             "Failed to read copper-cable-type"
2774                             " from SFP+ EEPROM\n");
2775                         return (-EINVAL);
2776                 }
2777
2778                 if (copper_module_type &
2779                     SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
2780                         DBPRINT(sc, BXE_VERBOSE_PHY,
2781                             "Active Copper cable detected\n");
2782                         check_limiting_mode = 1;
2783                 } else if (copper_module_type &
2784                     SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
2785                         DBPRINT(sc, BXE_VERBOSE_PHY,
2786                             "Passive Copper cable detected\n");
2787                         *edc_mode = EDC_MODE_PASSIVE_DAC;
2788                 } else {
2789                         DBPRINT(sc, BXE_VERBOSE_PHY,
2790                             "Unknown copper-cable-type 0x%x !!!\n",
2791                             copper_module_type);
2792                         return (-EINVAL);
2793                 }
2794                 break;
2795         case SFP_EEPROM_CON_TYPE_VAL_LC:
2796                 DBPRINT(sc, BXE_VERBOSE_PHY, "Optic module detected\n");
2797                 check_limiting_mode = 1;
2798                 break;
2799         default:
2800                 DBPRINT(sc, BXE_VERBOSE_PHY,
2801                     "Unable to determine module type 0x%x !!!\n", val);
2802                 return (-EINVAL);
2803         }
2804
2805         if (check_limiting_mode) {
2806                 if (bxe_read_sfp_module_eeprom(params, SFP_EEPROM_OPTIONS_ADDR,
2807                     SFP_EEPROM_OPTIONS_SIZE, options) != 0) {
2808                         DBPRINT(sc, BXE_VERBOSE_PHY, "Failed to read Option"
2809                             " field from module EEPROM\n");
2810                         return (-EINVAL);
2811                 }
2812                 if ((options[0] & SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK))
2813                         *edc_mode = EDC_MODE_LINEAR;
2814                 else
2815                         *edc_mode = EDC_MODE_LIMITING;
2816         }
2817         DBPRINT(sc, BXE_VERBOSE_PHY, "EDC mode is set to 0x%x\n", *edc_mode);
2818         return (0);
2819 }
2820
2821 /*
2822  * This function read the relevant field from the module ( SFP+ ),
2823  * and verify it is compliant with this board.
2824  */
2825 static uint8_t bxe_verify_sfp_module(struct link_params *params)
2826 {
2827         struct bxe_softc *sc = params->sc;
2828         uint32_t val;
2829         /* uint32_t fw_resp; */
2830         char vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE + 1];
2831         char vendor_pn[SFP_EEPROM_PART_NO_SIZE + 1];
2832
2833         sc = params->sc;
2834         val = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region,
2835             dev_info.port_feature_config[params->port].config));
2836         if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
2837             PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT) {
2838                 DBPRINT(sc, BXE_VERBOSE_PHY,
2839                     "NOT enforcing module verification\n");
2840                 return (0);
2841         }
2842
2843         /* Ask the FW to validate the module. */
2844         if (!(params->feature_config_flags &
2845             FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY)) {
2846                 DBPRINT(sc, BXE_VERBOSE_PHY,
2847                     "FW does not support OPT MDL verification\n");
2848                 return (-EINVAL);
2849         }
2850         /* Format the warning message. */
2851         if (bxe_read_sfp_module_eeprom(params, SFP_EEPROM_VENDOR_NAME_ADDR,
2852             SFP_EEPROM_VENDOR_NAME_SIZE, (uint8_t *)vendor_name))
2853                 vendor_name[0] = '\0';
2854         else
2855                 vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE] = '\0';
2856         if (bxe_read_sfp_module_eeprom(params, SFP_EEPROM_PART_NO_ADDR,
2857             SFP_EEPROM_PART_NO_SIZE, (uint8_t *)vendor_pn))
2858                 vendor_pn[0] = '\0';
2859         else
2860                 vendor_pn[SFP_EEPROM_PART_NO_SIZE] = '\0';
2861
2862         printf("Warning: Unqualified SFP+ module detected on %s, "
2863             "Port %d from %s part number %s\n", sc->name, params->port,
2864             vendor_name, vendor_pn);
2865         return (-EINVAL);
2866 }
2867
2868 static uint8_t
2869 bxe_bcm8726_set_limiting_mode(struct link_params *params, uint16_t edc_mode)
2870 {
2871         struct bxe_softc *sc;
2872         uint16_t cur_limiting_mode;
2873         uint8_t ext_phy_addr, port;
2874
2875         sc = params->sc;
2876         port = params->port;
2877         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
2878
2879         bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
2880             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2,
2881             &cur_limiting_mode);
2882         DBPRINT(sc, BXE_VERBOSE_PHY, "Current Limiting mode is 0x%x\n",
2883             cur_limiting_mode);
2884
2885         if (edc_mode == EDC_MODE_LIMITING) {
2886                 DBPRINT(sc, BXE_VERBOSE_PHY, "Setting LIMITING MODE\n");
2887                 bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
2888                     ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2,
2889                     EDC_MODE_LIMITING);
2890         } else { /* LRM mode ( default )*/
2891
2892                 DBPRINT(sc, BXE_VERBOSE_PHY, "Setting LRM MODE\n");
2893
2894                 /*
2895                  * Changing to LRM mode takes quite few seconds.
2896                  * So do it only if current mode is limiting
2897                  * ( default is LRM ).
2898                  */
2899                 if (cur_limiting_mode != EDC_MODE_LIMITING)
2900                         return (0);
2901
2902                 bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
2903                     ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_LRM_MODE, 0);
2904                 bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
2905                     ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2, 0x128);
2906                 bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
2907                     ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL0,
2908                     0x4008);
2909                 bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
2910                     ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_LRM_MODE,
2911                     0xaaaa);
2912         }
2913         return (0);
2914 }
2915
2916 static uint8_t
2917 bxe_bcm8727_set_limiting_mode(struct link_params *params, uint16_t edc_mode)
2918 {
2919         struct bxe_softc *sc;
2920         uint8_t ext_phy_addr, port;
2921         uint16_t phy_identifier;
2922         uint16_t rom_ver2_val;
2923
2924         sc = params->sc;
2925         port = params->port;
2926         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
2927
2928         bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
2929             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
2930             &phy_identifier);
2931
2932         bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
2933             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
2934             (phy_identifier & ~(1 << 9)));
2935
2936         bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
2937             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2, &rom_ver2_val);
2938         /* Keep the MSB 8-bits, and set the LSB 8-bits with the edc_mode. */
2939         bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
2940             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2,
2941             (rom_ver2_val & 0xff00) | (edc_mode & 0x00ff));
2942
2943         bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
2944             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
2945             (phy_identifier | (1<<9)));
2946
2947         return (0);
2948 }
2949
2950 static uint8_t
2951 bxe_wait_for_sfp_module_initialized(struct link_params *params)
2952 {
2953         struct bxe_softc *sc;
2954         uint16_t timeout;
2955         uint8_t val;
2956
2957         sc = params->sc;
2958         /*
2959          * Initialization time after hot-plug may take up to 300ms for some
2960          * phys type ( e.g. JDSU ).
2961          */
2962         for (timeout = 0; timeout < 60; timeout++) {
2963                 if (bxe_read_sfp_module_eeprom(params, 1, 1, &val)
2964                     == 0) {
2965                         DBPRINT(sc, BXE_VERBOSE_PHY,
2966                             "SFP+ module initialization took %d ms\n",
2967                             timeout * 5);
2968                         return (0);
2969                 }
2970                 msleep(5);
2971         }
2972         return (-EINVAL);
2973 }
2974
2975 /* Make sure GPIOs are not using for LED mode. */
2976 static void
2977 bxe_8727_power_module(struct bxe_softc *sc, struct link_params *params,
2978     uint8_t ext_phy_addr, uint8_t is_power_up)
2979 {
2980         uint16_t val;
2981         uint8_t port;
2982
2983         port = params->port;
2984         /*
2985          * In the GPIO register, bit 4 is use to detemine if the GPIOs are
2986          * operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
2987          * output
2988          * Bits 0-1 determine the gpios value for OUTPUT in case bit 4 val is 0
2989          * Bits 8-9 determine the gpios value for INPUT in case bit 4 val is 1
2990          * where the 1st bit is the over-current(only input), and 2nd bit is
2991          * for power( only output ).
2992          */
2993
2994         /*
2995          * In case of NOC feature is disabled and power is up, set GPIO control
2996          *  as input to enable listening of over-current indication.
2997          */
2998
2999         if (!(params->feature_config_flags & FEATURE_CONFIG_BCM8727_NOC) &&
3000             is_power_up)
3001                 val = (1<<4);
3002         else
3003                 /*
3004                  * Set GPIO control to OUTPUT, and set the power bit
3005                  * to according to the is_power_up.
3006                  */
3007                 val = ((!(is_power_up)) << 1);
3008
3009         bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
3010             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_GPIO_CTRL, val);
3011 }
3012
3013 static uint8_t
3014 bxe_sfp_module_detection(struct link_params *params)
3015 {
3016         struct bxe_softc *sc;
3017         uint32_t ext_phy_type, val;
3018         uint16_t edc_mode;
3019         uint8_t ext_phy_addr, rc;
3020
3021         sc = params->sc;
3022         rc = 0;
3023         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
3024         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3025         val = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region,
3026             dev_info.port_feature_config[params->port].config));
3027
3028         DBPRINT(sc, BXE_VERBOSE_PHY,
3029             "SFP+ module plugged in/out detected on port %d\n", params->port);
3030
3031         if (bxe_get_edc_mode(params, &edc_mode) != 0) {
3032                 DBPRINT(sc, BXE_VERBOSE_PHY,
3033                     "Failed to get valid module type\n");
3034                 return (-EINVAL);
3035         } else if (bxe_verify_sfp_module(params) != 0) {
3036                 /* Check SFP+ module compatibility. */
3037                 DBPRINT(sc, BXE_VERBOSE_PHY, "Module verification failed!!\n");
3038                 rc = -EINVAL;
3039                 /* Turn on fault module-detected led. */
3040                 bxe_set_gpio(sc, MISC_REGISTERS_GPIO_0,
3041                     MISC_REGISTERS_GPIO_HIGH, params->port);
3042                 if ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) &&
3043                     ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
3044                     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN)) {
3045                         /* Shutdown SFP+ module. */
3046                         DBPRINT(sc, BXE_VERBOSE_PHY,
3047                             "Shutdown SFP+ module!!\n");
3048                         bxe_8727_power_module(sc, params, ext_phy_addr, 0);
3049                         return (rc);
3050                 }
3051         } else {
3052                 /* Turn off fault module-detected led. */
3053                 DBPRINT(sc, BXE_VERBOSE_PHY,
3054                     "Turn off fault module-detected led\n");
3055                 bxe_set_gpio(sc, MISC_REGISTERS_GPIO_0, MISC_REGISTERS_GPIO_LOW,
3056                     params->port);
3057         }
3058
3059         /* Power up the SFP module. */
3060         if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
3061                 bxe_8727_power_module(sc, params, ext_phy_addr, 1);
3062
3063         /*
3064          * Check and set limiting mode / LRM mode on 8726.
3065          * On 8727 it is done automatically.
3066          */
3067         if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
3068                 bxe_bcm8726_set_limiting_mode(params, edc_mode);
3069         else
3070                 bxe_bcm8727_set_limiting_mode(params, edc_mode);
3071         /*
3072          * Enable transmit for this module if the module is approved, or
3073          * if unapproved modules should also enable the Tx laser.
3074          */
3075         if (rc == 0 || (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
3076             PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
3077                 bxe_sfp_set_transmitter(sc, params->port, ext_phy_type,
3078                     ext_phy_addr, 1);
3079         else
3080                 bxe_sfp_set_transmitter(sc, params->port, ext_phy_type,
3081                     ext_phy_addr, 0);
3082
3083         return (rc);
3084 }
3085
3086 void
3087 bxe_handle_module_detect_int(struct link_params *params)
3088 {
3089         struct bxe_softc *sc;
3090         uint32_t ext_phy_type, gpio_val, val;
3091         uint8_t ext_phy_addr, port;
3092
3093         sc = params->sc;
3094         port = params->port;
3095
3096         /* Set valid module led off. */
3097         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_0, MISC_REGISTERS_GPIO_HIGH,
3098             params->port);
3099
3100         /* Get current gpio val refelecting module plugged in / out. */
3101         gpio_val = bxe_get_gpio(sc,  MISC_REGISTERS_GPIO_3, port);
3102
3103         /* Call the handling function in case module is detected. */
3104         if (gpio_val == 0) {
3105                 bxe_set_gpio_int(sc, MISC_REGISTERS_GPIO_3,
3106                     MISC_REGISTERS_GPIO_INT_OUTPUT_CLR, port);
3107
3108                 if (bxe_wait_for_sfp_module_initialized(params) == 0)
3109                         bxe_sfp_module_detection(params);
3110                 else
3111                         DBPRINT(sc, BXE_VERBOSE_PHY,
3112                             "SFP+ module is not initialized\n");
3113         } else {
3114                 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
3115                 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3116                 val = REG_RD(sc, params->shmem_base +
3117                     offsetof(struct shmem_region,
3118                     dev_info.port_feature_config[params->port].config));
3119
3120                 bxe_set_gpio_int(sc, MISC_REGISTERS_GPIO_3,
3121                     MISC_REGISTERS_GPIO_INT_OUTPUT_SET, port);
3122                 /* Module was plugged out. */
3123                 /* Disable transmit for this module. */
3124                 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
3125                     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
3126                         bxe_sfp_set_transmitter(sc, params->port, ext_phy_type,
3127                             ext_phy_addr, 0);
3128         }
3129 }
3130
3131 static void
3132 bxe_bcm807x_force_10G(struct link_params *params)
3133 {
3134         struct bxe_softc *sc;
3135         uint32_t ext_phy_type;
3136         uint8_t ext_phy_addr, port;
3137
3138         sc = params->sc;
3139         port = params->port;
3140         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
3141         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3142
3143         /* Force KR or KX. */
3144         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
3145             MDIO_PMA_REG_CTRL, 0x2040);
3146         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
3147             MDIO_PMA_REG_10G_CTRL2, 0x000b);
3148         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
3149             MDIO_PMA_REG_BCM_CTRL, 0x0000);
3150         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_AN_DEVAD,
3151             MDIO_AN_REG_CTRL, 0x0000);
3152 }
3153
3154 static void
3155 bxe_bcm8073_set_xaui_low_power_mode(struct link_params *params)
3156 {
3157         struct bxe_softc *sc;
3158         uint32_t ext_phy_type;
3159         uint16_t val;
3160         uint8_t ext_phy_addr, port;
3161
3162         sc = params->sc;
3163         port = params->port;
3164         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
3165         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3166
3167         bxe_cl45_read(sc, params->port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
3168             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, &val);
3169
3170         if (val == 0) {
3171                 /* Mustn't set low power mode in 8073 A0. */
3172                 return;
3173         }
3174
3175         /* Disable PLL sequencer (use read-modify-write to clear bit 13). */
3176         bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3177             MDIO_XS_PLL_SEQUENCER, &val);
3178         val &= ~(1 << 13);
3179         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3180             MDIO_XS_PLL_SEQUENCER, val);
3181
3182         /* PLL controls */
3183         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3184             0x805E, 0x1077);
3185         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3186             0x805D, 0x0000);
3187         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3188             0x805C, 0x030B);
3189         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3190             0x805B, 0x1240);
3191         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3192             0x805A, 0x2490);
3193
3194         /* Tx Controls */
3195         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3196             0x80A7, 0x0C74);
3197         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3198             0x80A6, 0x9041);
3199         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3200             0x80A5, 0x4640);
3201
3202         /* Rx Controls */
3203         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3204             0x80FE, 0x01C4);
3205         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3206             0x80FD, 0x9249);
3207         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3208             0x80FC, 0x2015);
3209
3210         /* Enable PLL sequencer (use read-modify-write to set bit 13). */
3211         bxe_cl45_read(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3212             MDIO_XS_PLL_SEQUENCER, &val);
3213         val |= (1 << 13);
3214         bxe_cl45_write(sc, port, ext_phy_type, ext_phy_addr, MDIO_XS_DEVAD,
3215             MDIO_XS_PLL_SEQUENCER, val);
3216 }
3217
3218 static void
3219 bxe_8073_set_pause_cl37(struct link_params *params, struct link_vars *vars)
3220 {
3221         struct bxe_softc *sc;
3222         uint32_t ext_phy_type;
3223         uint16_t cl37_val;
3224         uint8_t ext_phy_addr;
3225
3226         sc = params->sc;
3227         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
3228         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3229
3230         bxe_cl45_read(sc, params->port, ext_phy_type, ext_phy_addr,
3231             MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &cl37_val);
3232
3233         cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
3234         /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
3235
3236         if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
3237             MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC)
3238                 cl37_val |=  MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
3239         if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
3240             MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC)
3241                 cl37_val |=  MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
3242         if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
3243             MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
3244                 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
3245         DBPRINT(sc, BXE_VERBOSE_PHY, "Ext phy AN advertize cl37 0x%x\n",
3246             cl37_val);
3247
3248         bxe_cl45_write(sc, params->port, ext_phy_type, ext_phy_addr,
3249             MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, cl37_val);
3250         msleep(500);
3251 }
3252
3253 static void
3254 bxe_ext_phy_set_pause(struct link_params *params, struct link_vars *vars)
3255 {
3256         struct bxe_softc *sc;
3257         uint32_t ext_phy_type;
3258         uint16_t val;
3259         uint8_t ext_phy_addr;
3260
3261         sc = params->sc;
3262         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
3263         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3264
3265         /* Read modify write pause advertizing. */
3266         bxe_cl45_read(sc, params->port, ext_phy_type, ext_phy_addr,
3267             MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val);
3268
3269         val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
3270
3271         /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
3272
3273         if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
3274             MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC)
3275                 val |=  MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
3276         if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
3277             MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
3278                 val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
3279         DBPRINT(sc, BXE_VERBOSE_PHY, "Ext phy AN advertize 0x%x\n", val);
3280         bxe_cl45_write(sc, params->port, ext_phy_type, ext_phy_addr,
3281             MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val);
3282 }
3283
3284 static void
3285 bxe_set_preemphasis(struct link_params *params)
3286 {
3287         struct bxe_softc *sc = params->sc;
3288         uint16_t bank, i;
3289
3290         sc = params->sc;
3291         for (bank = MDIO_REG_BANK_RX0, i = 0; bank <= MDIO_REG_BANK_RX3;
3292             bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0), i++) {
3293                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr, bank,
3294                     MDIO_RX0_RX_EQ_BOOST, params->xgxs_config_rx[i]);
3295         }
3296
3297         for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3;
3298             bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0), i++) {
3299                 CL45_WR_OVER_CL22(sc, params->port, params->phy_addr, bank,
3300                     MDIO_TX0_TX_DRIVER, params->xgxs_config_tx[i]);
3301         }
3302 }
3303
3304 static void
3305 bxe_8481_set_led4(struct link_params *params, uint32_t ext_phy_type,
3306     uint8_t ext_phy_addr)
3307 {
3308         struct bxe_softc *sc;
3309
3310         sc = params->sc;
3311         /* PHYC_CTL_LED_CTL */
3312
3313         /* Enable continous signal to go active on link. */
3314         bxe_cl45_write(sc, params->port, ext_phy_type, ext_phy_addr,
3315             MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, 0xa482);
3316
3317         /* Unmask LED4 for 10G link. */
3318         bxe_cl45_write(sc, params->port, ext_phy_type, ext_phy_addr,
3319             MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_SIGNAL_MASK, (1 << 6));
3320         /* Unmask LED4 for 10G link. */
3321         bxe_cl45_write(sc, params->port, ext_phy_type, ext_phy_addr,
3322             MDIO_AN_DEVAD, 0xFFFB, 0xFFFD);
3323 }
3324
3325 static void
3326 bxe_8481_set_legacy_led_mode(struct link_params *params, uint32_t ext_phy_type,
3327     uint8_t ext_phy_addr)
3328 {
3329         struct bxe_softc *sc;
3330
3331         sc = params->sc;
3332         /*
3333          * LED1 (10G Link): Disable LED1 when 10/100/1000 link.
3334          * LED2 (1G/100/10 Link): Enable LED2 when 10/100/1000 link).
3335          */
3336         bxe_cl45_write(sc, params->port, ext_phy_type, ext_phy_addr,
3337             MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_SHADOW, (1<<15) |
3338             (0xd << 10) | (0xc<<4) | 0xe);
3339 }
3340
3341 static void
3342 bxe_8481_set_10G_led_mode(struct link_params *params, uint32_t ext_phy_type,
3343     uint8_t ext_phy_addr)
3344 {
3345         struct bxe_softc *sc;
3346         uint16_t val1;
3347
3348         sc = params->sc;
3349         /*
3350          * LED1 (10G Link)
3351          * Enable continuse based on source 7(10G-link).
3352          */
3353         bxe_cl45_read(sc, params->port, ext_phy_type, ext_phy_addr,
3354             MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, &val1);
3355         /* Set bit 2 to 0, and bits [1:0] to 10. */
3356         val1 &= ~((1<<0) | (1<<2) | (1<<7)); /* Clear bits 0,2,7*/
3357         val1 |= ((1<<1) | (1<<6)); /* Set bit 1, 6 */
3358
3359         bxe_cl45_write(sc, params->port, ext_phy_type, ext_phy_addr,
3360             MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, val1);
3361
3362         /* Unmask LED1 for 10G link. */
3363         bxe_cl45_read(sc, params->port, ext_phy_type, ext_phy_addr,
3364             MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, &val1);
3365         /* Set bit 2 to 0, and bits [1:0] to 10. */
3366         val1 |= (1<<7);
3367         bxe_cl45_write(sc, params->port, ext_phy_type, ext_phy_addr,
3368             MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, val1);
3369
3370         /*
3371          * LED2 (1G/100/10G Link).
3372          * Mask LED2 for 10G link.
3373          */
3374         bxe_cl45_write(sc, params->port, ext_phy_type, ext_phy_addr,
3375             MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0);
3376
3377         /* Unmask LED3 for 10G link. */
3378         bxe_cl45_write(sc, params->port, ext_phy_type, ext_phy_addr,
3379             MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x6);
3380         bxe_cl45_write(sc, params->port, ext_phy_type, ext_phy_addr,
3381             MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_BLINK, 0);
3382 }
3383
3384 static void
3385 bxe_init_internal_phy(struct link_params *params, struct link_vars *vars,
3386     uint8_t enable_cl73)
3387 {
3388         struct bxe_softc *sc;
3389
3390         sc = params->sc;
3391         if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
3392                 if ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
3393                     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
3394                     (params->feature_config_flags &
3395                     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED))
3396                         bxe_set_preemphasis(params);
3397
3398                 /* Forced speed requested? */
3399                 if (vars->line_speed != SPEED_AUTO_NEG ||
3400                     ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
3401                     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
3402                     params->loopback_mode == LOOPBACK_EXT)) {
3403                         DBPRINT(sc, BXE_VERBOSE_PHY, "%s(): Not SGMII, no AN\n",
3404                             __FUNCTION__);
3405
3406                         /* Disable autoneg. */
3407                         bxe_set_autoneg(params, vars, 0);
3408
3409                         /* Program speed and duplex. */
3410                         bxe_program_serdes(params, vars);
3411
3412                 } else { /* AN_mode */
3413                         DBPRINT(sc, BXE_VERBOSE_PHY, "not SGMII, AN\n");
3414
3415                         /* AN enabled. */
3416                         bxe_set_brcm_cl37_advertisment(params);
3417
3418                         /* Program duplex & pause advertisement (for aneg). */
3419                         bxe_set_ieee_aneg_advertisment(params, vars->ieee_fc);
3420
3421                         /* Enable autoneg. */
3422                         bxe_set_autoneg(params, vars, enable_cl73);
3423
3424                         /* Enable and restart AN. */
3425                         bxe_restart_autoneg(params, enable_cl73);
3426                 }
3427
3428         } else { /* SGMII mode */
3429                 DBPRINT(sc, BXE_VERBOSE_PHY, "SGMII\n");
3430
3431                 bxe_initialize_sgmii_process(params, vars);
3432         }
3433 }
3434
3435 static uint8_t
3436 bxe_ext_phy_init(struct link_params *params, struct link_vars *vars)
3437 {
3438         struct bxe_softc *sc;
3439         uint32_t ext_phy_type;
3440         uint16_t cnt, ctrl, reg, val;
3441         uint16_t fw_ver1, fw_ver2;
3442         uint16_t lasi_ctrl_val, rx_alarm_ctrl_val, tmp1;
3443         uint16_t mod_abs, phy_ver;
3444         uint16_t autoneg_val, an_1000_val, an_10_100_val;
3445         uint16_t autoneg_ctrl, pma_ctrl;
3446         uint8_t ext_phy_addr, i, rc;
3447
3448         sc = params->sc;
3449         ctrl = 0;
3450         val = 0;
3451         rc = 0;
3452
3453         if (vars->phy_flags & PHY_XGXS_FLAG) {
3454                 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
3455
3456                 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
3457                 /*
3458                  * Make sure that the soft reset is off (expect for the 8072:
3459                  * due to the lock, it will be done inside the specific
3460                  * handling).
3461                  */
3462                 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
3463                     (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
3464                     (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) &&
3465                     (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
3466                     (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
3467                         /* Wait for soft reset to get cleared upto 1 sec. */
3468                         for (cnt = 0; cnt < 1000; cnt++) {
3469                                 bxe_cl45_read(sc, params->port, ext_phy_type,
3470                                     ext_phy_addr, MDIO_PMA_DEVAD,
3471                                     MDIO_PMA_REG_CTRL, &ctrl);
3472                                 if (!(ctrl & (1<<15)))
3473                                         break;
3474                                 msleep(1);
3475                         }
3476                         DBPRINT(sc, BXE_VERBOSE_PHY,
3477                             "control reg 0x%x (after %d ms)\n", ctrl, cnt);
3478                 }
3479
3480                 switch (ext_phy_type) {
3481                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3482                         break;
3483                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
3484                         DBPRINT(sc, BXE_VERBOSE_PHY, "XGXS 8705\n");
3485
3486                         bxe_cl45_write(sc, params->port, ext_phy_type,
3487                             ext_phy_addr, MDIO_PMA_DEVAD,
3488                             MDIO_PMA_REG_MISC_CTRL, 0x8288);
3489                         bxe_cl45_write(sc, params->port, ext_phy_type,
3490                             ext_phy_addr, MDIO_PMA_DEVAD,
3491                             MDIO_PMA_REG_PHY_IDENTIFIER, 0x7fbf);
3492                         bxe_cl45_write(sc, params->port, ext_phy_type,
3493                             ext_phy_addr, MDIO_PMA_DEVAD,
3494                             MDIO_PMA_REG_CMU_PLL_BYPASS, 0x0100);
3495                         bxe_cl45_write(sc, params->port, ext_phy_type,
3496                             ext_phy_addr, MDIO_WIS_DEVAD,
3497                             MDIO_WIS_REG_LASI_CNTL, 0x1);
3498
3499                         /* BCM8705 doesn't have microcode, hence the 0. */
3500                         bxe_save_spirom_version(sc, params->port,
3501                             params->shmem_base, 0);
3502                         break;
3503                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
3504                         /* Wait until fw is loaded. */
3505                         for (cnt = 0; cnt < 100; cnt++) {
3506                                 bxe_cl45_read(sc, params->port, ext_phy_type,
3507                                     ext_phy_addr, MDIO_PMA_DEVAD,
3508                                     MDIO_PMA_REG_ROM_VER1, &val);
3509                                 if (val)
3510                                         break;
3511                                 msleep(10);
3512                         }
3513                         DBPRINT(sc, BXE_VERBOSE_PHY,
3514                             "XGXS 8706 is initialized after %d ms\n", cnt);
3515                         if ((params->feature_config_flags &
3516                             FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
3517                                 for (i = 0; i < 4; i++) {
3518                                         reg = MDIO_XS_8706_REG_BANK_RX0 +
3519                                             i * (MDIO_XS_8706_REG_BANK_RX1 -
3520                                             MDIO_XS_8706_REG_BANK_RX0);
3521                                         bxe_cl45_read(sc, params->port,
3522                                             ext_phy_type, ext_phy_addr,
3523                                             MDIO_XS_DEVAD, reg, &val);
3524                                         /* Clear first 3 bits of the control. */
3525                                         val &= ~0x7;
3526                                         /*
3527                                          * Set control bits according to
3528                                          * configuation.
3529                                          */
3530                                         val |= (params->xgxs_config_rx[i] &
3531                                             0x7);
3532                                         DBPRINT(sc, BXE_VERBOSE_PHY,
3533                 "Setting RX Equalizer to BCM8706 reg 0x%x <-- val 0x%x\n",
3534                                             reg, val);
3535                                         bxe_cl45_write(sc, params->port,
3536                                             ext_phy_type, ext_phy_addr,
3537                                             MDIO_XS_DEVAD, reg, val);
3538                                 }
3539                         }
3540                         /* Force speed */
3541                         if (params->req_line_speed == SPEED_10000) {
3542                                 DBPRINT(sc, BXE_VERBOSE_PHY,
3543                                     "XGXS 8706 force 10Gbps\n");
3544
3545                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3546                                     ext_phy_addr, MDIO_PMA_DEVAD,
3547                                     MDIO_PMA_REG_DIGITAL_CTRL, 0x400);
3548                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3549                                     ext_phy_addr, MDIO_PMA_DEVAD,
3550                                     MDIO_PMA_REG_LASI_CTRL, 1);
3551                         } else {
3552                                 /*
3553                                  * Force 1Gbps using autoneg with 1G
3554                                  * advertisment.
3555                                  */
3556
3557                                 /* Allow CL37 through CL73. */
3558                                 DBPRINT(sc, BXE_VERBOSE_PHY,
3559                                     "XGXS 8706 AutoNeg\n");
3560                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3561                                     ext_phy_addr, MDIO_AN_DEVAD,
3562                                     MDIO_AN_REG_CL37_CL73, 0x040c);
3563
3564                                 /* Enable Full-Duplex advertisment on CL37. */
3565                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3566                                     ext_phy_addr, MDIO_AN_DEVAD,
3567                                     MDIO_AN_REG_CL37_FC_LP, 0x0020);
3568                                 /* Enable CL37 AN. */
3569                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3570                                     ext_phy_addr, MDIO_AN_DEVAD,
3571                                     MDIO_AN_REG_CL37_AN, 0x1000);
3572                                 /* 1G support */
3573                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3574                                     ext_phy_addr, MDIO_AN_DEVAD,
3575                                     MDIO_AN_REG_ADV, (1 << 5));
3576
3577                                 /* Enable clause 73 AN. */
3578                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3579                                     ext_phy_addr, MDIO_AN_DEVAD,
3580                                     MDIO_AN_REG_CTRL, 0x1200);
3581                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3582                                     ext_phy_addr, MDIO_PMA_DEVAD,
3583                                     MDIO_PMA_REG_RX_ALARM_CTRL, 0x0400);
3584                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3585                                     ext_phy_addr, MDIO_PMA_DEVAD,
3586                                     MDIO_PMA_REG_LASI_CTRL, 0x0004);
3587
3588                         }
3589                         bxe_save_bcm_spirom_ver(sc, params->port, ext_phy_type,
3590                             ext_phy_addr, params->shmem_base);
3591                         break;
3592                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
3593                         DBPRINT(sc, BXE_VERBOSE_PHY, "Initializing BCM8726\n");
3594                         bxe_bcm8726_external_rom_boot(params);
3595
3596                         /*
3597                          * Need to call module detected on initialization since
3598                          * the module detection triggered by actual module
3599                          * insertion might occur before driver is loaded, and
3600                          * when driver is loaded, it reset all registers,
3601                          * including the transmitter.
3602                          */
3603                         bxe_sfp_module_detection(params);
3604
3605                         /* Set Flow control */
3606                         bxe_ext_phy_set_pause(params, vars);
3607                         if (params->req_line_speed == SPEED_1000) {
3608                                 DBPRINT(sc, BXE_VERBOSE_PHY,
3609                                     "Setting 1G force\n");
3610                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3611                                     ext_phy_addr, MDIO_PMA_DEVAD,
3612                                     MDIO_PMA_REG_CTRL, 0x40);
3613                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3614                                     ext_phy_addr, MDIO_PMA_DEVAD,
3615                                     MDIO_PMA_REG_10G_CTRL2, 0xD);
3616                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3617                                     ext_phy_addr, MDIO_PMA_DEVAD,
3618                                     MDIO_PMA_REG_LASI_CTRL, 0x5);
3619                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3620                                     ext_phy_addr, MDIO_PMA_DEVAD,
3621                                     MDIO_PMA_REG_RX_ALARM_CTRL, 0x400);
3622                         } else if ((params->req_line_speed == SPEED_AUTO_NEG) &&
3623                             ((params->speed_cap_mask &
3624                             PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))) {
3625                                 DBPRINT(sc, BXE_VERBOSE_PHY,
3626                                     "Setting 1G clause37 \n");
3627                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3628                                     ext_phy_addr, MDIO_AN_DEVAD,
3629                                     MDIO_AN_REG_ADV, 0x20);
3630                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3631                                     ext_phy_addr, MDIO_AN_DEVAD,
3632                                     MDIO_AN_REG_CL37_CL73, 0x040c);
3633                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3634                                     ext_phy_addr, MDIO_AN_DEVAD,
3635                                     MDIO_AN_REG_CL37_FC_LD, 0x0020);
3636                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3637                                     ext_phy_addr, MDIO_AN_DEVAD,
3638                                     MDIO_AN_REG_CL37_AN, 0x1000);
3639                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3640                                     ext_phy_addr, MDIO_AN_DEVAD,
3641                                     MDIO_AN_REG_CTRL, 0x1200);
3642
3643                                 /*
3644                                  * Enable RX-ALARM control to receive
3645                                  * interrupt for 1G speed change.
3646                                  */
3647                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3648                                     ext_phy_addr, MDIO_PMA_DEVAD,
3649                                     MDIO_PMA_REG_LASI_CTRL, 0x4);
3650                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3651                                     ext_phy_addr, MDIO_PMA_DEVAD,
3652                                     MDIO_PMA_REG_RX_ALARM_CTRL, 0x400);
3653
3654                         } else { /* Default 10G. Set only LASI control */
3655                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3656                                     ext_phy_addr, MDIO_PMA_DEVAD,
3657                                     MDIO_PMA_REG_LASI_CTRL, 1);
3658                         }
3659
3660                         /* Set TX PreEmphasis if needed. */
3661                         if ((params->feature_config_flags &
3662                             FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
3663                                 DBPRINT(sc, BXE_VERBOSE_PHY,
3664                                     "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x\n",
3665                                     params->xgxs_config_tx[0],
3666                                     params->xgxs_config_tx[1]);
3667                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3668                                     ext_phy_addr, MDIO_PMA_DEVAD,
3669                                     MDIO_PMA_REG_8726_TX_CTRL1,
3670                                     params->xgxs_config_tx[0]);
3671
3672                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3673                                     ext_phy_addr, MDIO_PMA_DEVAD,
3674                                     MDIO_PMA_REG_8726_TX_CTRL2,
3675                                     params->xgxs_config_tx[1]);
3676                         }
3677                         break;
3678                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
3679                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
3680                         if (ext_phy_type ==
3681                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
3682                                 rx_alarm_ctrl_val = 0x400;
3683                                 lasi_ctrl_val = 0x0004;
3684                         } else {
3685                                 rx_alarm_ctrl_val = (1<<2);
3686                                 lasi_ctrl_val = 0x0004;
3687                         }
3688
3689                         /* Enable LASI. */
3690                         bxe_cl45_write(sc, params->port, ext_phy_type,
3691                             ext_phy_addr, MDIO_PMA_DEVAD,
3692                             MDIO_PMA_REG_RX_ALARM_CTRL, rx_alarm_ctrl_val);
3693
3694                         bxe_cl45_write(sc, params->port, ext_phy_type,
3695                             ext_phy_addr, MDIO_PMA_DEVAD,
3696                             MDIO_PMA_REG_LASI_CTRL, lasi_ctrl_val);
3697
3698                         bxe_8073_set_pause_cl37(params, vars);
3699
3700                         if (ext_phy_type ==
3701                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072)
3702                                 bxe_bcm8072_external_rom_boot(params);
3703                         else {
3704                                 /*
3705                                  * In case of 8073 with long xaui lines,
3706                                  * don't set the 8073 xaui low power.
3707                                  */
3708                                 bxe_bcm8073_set_xaui_low_power_mode(params);
3709                         }
3710                         bxe_cl45_read(sc, params->port, ext_phy_type,
3711                             ext_phy_addr, MDIO_PMA_DEVAD,
3712                             MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
3713
3714                         bxe_cl45_read(sc, params->port, ext_phy_type,
3715                             ext_phy_addr, MDIO_PMA_DEVAD,
3716                             MDIO_PMA_REG_RX_ALARM, &tmp1);
3717
3718                         DBPRINT(sc, BXE_VERBOSE_PHY,
3719                             "Before rom RX_ALARM(port1):0x%x\n", tmp1);
3720
3721                         /*
3722                          * If this is forced speed, set to KR or KX
3723                          * (all other are not supported).
3724                          */
3725                         if (params->loopback_mode == LOOPBACK_EXT) {
3726                                 bxe_bcm807x_force_10G(params);
3727                                 DBPRINT(sc, BXE_VERBOSE_PHY,
3728                                     "Forced speed 10G on 807X\n");
3729                                 break;
3730                         } else {
3731                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3732                                     ext_phy_addr, MDIO_PMA_DEVAD,
3733                                     MDIO_PMA_REG_BCM_CTRL, 0x0002);
3734                         }
3735                         if (params->req_line_speed != SPEED_AUTO_NEG) {
3736                                 if (params->req_line_speed == SPEED_10000)
3737                                         val = (1 << 7);
3738                                 else if (params->req_line_speed ==
3739                                            SPEED_2500) {
3740                                         val = (1 << 5);
3741                                         /*
3742                                          * Note that 2.5G works only
3743                                          * when used with 1G advertisment.
3744                                          */
3745                                 } else
3746                                         val = (1 << 5);
3747                         } else {
3748                                 val = 0;
3749                                 if (params->speed_cap_mask &
3750                                     PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
3751                                         val |= (1 << 7);
3752
3753                                 /*
3754                                  * Note that 2.5G works only when
3755                                  * used with 1G advertisment.
3756                                  */
3757                                 if (params->speed_cap_mask &
3758                                     (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
3759                                     PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
3760                                         val |= (1 << 5);
3761                                 DBPRINT(sc, BXE_VERBOSE_PHY,
3762                                     "807x autoneg val = 0x%x\n", val);
3763                         }
3764
3765                         bxe_cl45_write(sc, params->port, ext_phy_type,
3766                             ext_phy_addr, MDIO_AN_DEVAD, MDIO_AN_REG_ADV, val);
3767                         if (ext_phy_type ==
3768                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
3769                                 bxe_cl45_read(sc, params->port, ext_phy_type,
3770                                     ext_phy_addr, MDIO_AN_DEVAD,
3771                                     MDIO_AN_REG_8073_2_5G, &tmp1);
3772
3773                                 if (((params->speed_cap_mask &
3774                                     PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
3775                                     (params->req_line_speed ==
3776                                     SPEED_AUTO_NEG)) ||
3777                                     (params->req_line_speed == SPEED_2500)) {
3778                                         /* Allow 2.5G for A1 and above. */
3779                                         bxe_cl45_read(sc, params->port,
3780                                           PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
3781                                             ext_phy_addr, MDIO_PMA_DEVAD,
3782                                             MDIO_PMA_REG_8073_CHIP_REV,
3783                                             &phy_ver);
3784                                         DBPRINT(sc, BXE_VERBOSE_PHY,
3785                                             "Add 2.5G\n");
3786                                         if (phy_ver > 0)
3787                                                 tmp1 |= 1;
3788                                         else
3789                                                 tmp1 &= 0xfffe;
3790                                 } else {
3791                                         DBPRINT(sc, BXE_VERBOSE_PHY,
3792                                             "Disable 2.5G\n");
3793                                         tmp1 &= 0xfffe;
3794                                 }
3795
3796                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3797                                     ext_phy_addr, MDIO_AN_DEVAD,
3798                                     MDIO_AN_REG_8073_2_5G, tmp1);
3799                         }
3800
3801                         /* Add support for CL37 (passive mode) II. */
3802                         bxe_cl45_read(sc, params->port, ext_phy_type,
3803                             ext_phy_addr, MDIO_AN_DEVAD,
3804                             MDIO_AN_REG_CL37_FC_LD, &tmp1);
3805
3806                         bxe_cl45_write(sc, params->port, ext_phy_type,
3807                             ext_phy_addr, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD,
3808                             (tmp1 | ((params->req_duplex == DUPLEX_FULL) ?
3809                             0x20 : 0x40)));
3810
3811                         /* Add support for CL37 (passive mode) III. */
3812                         bxe_cl45_write(sc, params->port, ext_phy_type,
3813                             ext_phy_addr, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN,
3814                             0x1000);
3815
3816                         if (ext_phy_type ==
3817                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
3818                                 /*
3819                                  * The SNR will improve about 2db by changing
3820                                  * BW and FEE main tap. Rest commands are
3821                                  * executed after link is up.
3822                                  */
3823                                 /*
3824                                  * Change FFE main cursor to 5 in EDC register.
3825                                  */
3826                                 if (bxe_8073_is_snr_needed(params))
3827                                         bxe_cl45_write(sc, params->port,
3828                                             ext_phy_type, ext_phy_addr,
3829                                             MDIO_PMA_DEVAD,
3830                                             MDIO_PMA_REG_EDC_FFE_MAIN, 0xFB0C);
3831
3832                                 /*
3833                                  * Enable FEC (Forware Error Correction)
3834                                  * Request in the AN.
3835                                  */
3836                                 bxe_cl45_read(sc, params->port, ext_phy_type,
3837                                     ext_phy_addr, MDIO_AN_DEVAD,
3838                                     MDIO_AN_REG_ADV2, &tmp1);
3839                                 tmp1 |= (1 << 15);
3840                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3841                                     ext_phy_addr, MDIO_AN_DEVAD,
3842                                     MDIO_AN_REG_ADV2, tmp1);
3843                         }
3844
3845                         bxe_ext_phy_set_pause(params, vars);
3846
3847                         /* Restart autoneg. */
3848                         msleep(500);
3849                         bxe_cl45_write(sc, params->port, ext_phy_type,
3850                             ext_phy_addr, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
3851                             0x1200);
3852                         DBPRINT(sc, BXE_VERBOSE_PHY, "807x Autoneg Restart: "
3853                             "Advertise 1G=%x, 10G=%x\n",
3854                             ((val & (1 << 5)) > 0), ((val & (1 << 7)) > 0));
3855                         break;
3856                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
3857                         /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm. */
3858                         rx_alarm_ctrl_val = (1 << 2) | (1 << 5);
3859                         lasi_ctrl_val = 0x0004;
3860
3861                         DBPRINT(sc, BXE_VERBOSE_PHY, "Initializing BCM8727\n");
3862                         /* Enable LASI. */
3863                         bxe_cl45_write(sc, params->port, ext_phy_type,
3864                             ext_phy_addr, MDIO_PMA_DEVAD,
3865                             MDIO_PMA_REG_RX_ALARM_CTRL, rx_alarm_ctrl_val);
3866
3867                         bxe_cl45_write(sc, params->port, ext_phy_type,
3868                             ext_phy_addr, MDIO_PMA_DEVAD,
3869                             MDIO_PMA_REG_LASI_CTRL, lasi_ctrl_val);
3870
3871                         /*
3872                          * Initially configure  MOD_ABS to interrupt when
3873                          * module is presence( bit 8).
3874                          */
3875                         bxe_cl45_read(sc, params->port, ext_phy_type,
3876                             ext_phy_addr, MDIO_PMA_DEVAD,
3877                             MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
3878                         /*
3879                          * Set EDC off by setting OPTXLOS signal input to low
3880                          * (bit 9). When the EDC is off it locks onto a
3881                          * reference clock and avoids becoming 'lost'.
3882                          */
3883                         mod_abs &= ~((1 << 8) | (1 << 9));
3884                         bxe_cl45_write(sc, params->port, ext_phy_type,
3885                             ext_phy_addr, MDIO_PMA_DEVAD,
3886                             MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
3887
3888                         /* Make MOD_ABS give interrupt on change. */
3889                         bxe_cl45_read(sc, params->port, ext_phy_type,
3890                             ext_phy_addr, MDIO_PMA_DEVAD,
3891                             MDIO_PMA_REG_8727_PCS_OPT_CTRL, &val);
3892                         val |= (1 << 12);
3893                         bxe_cl45_write(sc, params->port, ext_phy_type,
3894                             ext_phy_addr, MDIO_PMA_DEVAD,
3895                             MDIO_PMA_REG_8727_PCS_OPT_CTRL, val);
3896
3897                         /*
3898                          * Set 8727 GPIOs to input to allow reading from the
3899                          * 8727 GPIO0 status which reflect SFP+ module
3900                          * over-current.
3901                          */
3902                         bxe_cl45_read(sc, params->port,
3903                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727, ext_phy_addr,
3904                             MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL,
3905                             &val);
3906                         val &= 0xff8f; /* Reset bits 4-6 */
3907                         bxe_cl45_write(sc, params->port,
3908                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727, ext_phy_addr,
3909                             MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL,
3910                             val);
3911
3912                         bxe_8727_power_module(sc, params, ext_phy_addr, 1);
3913                         bxe_bcm8073_set_xaui_low_power_mode(params);
3914
3915                         bxe_cl45_read(sc, params->port, ext_phy_type,
3916                             ext_phy_addr, MDIO_PMA_DEVAD,
3917                             MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
3918
3919                         bxe_cl45_read(sc, params->port, ext_phy_type,
3920                             ext_phy_addr, MDIO_PMA_DEVAD,
3921                             MDIO_PMA_REG_RX_ALARM, &tmp1);
3922
3923                         /* Set option 1G speed. */
3924                         if (params->req_line_speed == SPEED_1000) {
3925                                 DBPRINT(sc, BXE_VERBOSE_PHY,
3926                                     "Setting 1G force\n");
3927                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3928                                     ext_phy_addr, MDIO_PMA_DEVAD,
3929                                     MDIO_PMA_REG_CTRL, 0x40);
3930                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3931                                     ext_phy_addr, MDIO_PMA_DEVAD,
3932                                     MDIO_PMA_REG_10G_CTRL2, 0xD);
3933                                 bxe_cl45_read(sc, params->port, ext_phy_type,
3934                                     ext_phy_addr, MDIO_PMA_DEVAD,
3935                                     MDIO_PMA_REG_10G_CTRL2, &tmp1);
3936                                 DBPRINT(sc, BXE_VERBOSE_PHY, "1.7 = 0x%x \n",
3937                                     tmp1);
3938                         } else if ((params->req_line_speed == SPEED_AUTO_NEG) &&
3939                             ((params->speed_cap_mask &
3940                             PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))) {
3941                                 DBPRINT(sc, BXE_VERBOSE_PHY,
3942                                     "Setting 1G clause37 \n");
3943                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3944                                     ext_phy_addr, MDIO_AN_DEVAD,
3945                                     MDIO_PMA_REG_8727_MISC_CTRL, 0);
3946                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3947                                     ext_phy_addr, MDIO_AN_DEVAD,
3948                                     MDIO_AN_REG_CL37_AN, 0x1300);
3949                         } else {
3950                                 /*
3951                                  * Since the 8727 has only single reset pin,
3952                                  * need to set the 10G registers although it
3953                                  * is default.
3954                                  */
3955                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3956                                     ext_phy_addr, MDIO_AN_DEVAD,
3957                                     MDIO_AN_REG_CTRL, 0x0020);
3958                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3959                                     ext_phy_addr, MDIO_AN_DEVAD,
3960                                     0x7, 0x0100);
3961                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3962                                     ext_phy_addr, MDIO_PMA_DEVAD,
3963                                     MDIO_PMA_REG_CTRL, 0x2040);
3964                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3965                                     ext_phy_addr, MDIO_PMA_DEVAD,
3966                                     MDIO_PMA_REG_10G_CTRL2, 0x0008);
3967                         }
3968
3969                         /*
3970                          * Set 2-wire transfer rate to 400Khz since 100Khz
3971                          * is not operational.
3972                          */
3973                         bxe_cl45_write(sc, params->port, ext_phy_type,
3974                             ext_phy_addr, MDIO_PMA_DEVAD,
3975                             MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR, 0xa101);
3976
3977                         /* Set TX PreEmphasis if needed. */
3978                         if ((params->feature_config_flags &
3979                             FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
3980                                 DBPRINT(sc, BXE_VERBOSE_PHY,
3981                                     "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x\n",
3982                                     params->xgxs_config_tx[0],
3983                                     params->xgxs_config_tx[1]);
3984                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3985                                     ext_phy_addr, MDIO_PMA_DEVAD,
3986                                     MDIO_PMA_REG_8727_TX_CTRL1,
3987                                     params->xgxs_config_tx[0]);
3988
3989                                 bxe_cl45_write(sc, params->port, ext_phy_type,
3990                                     ext_phy_addr, MDIO_PMA_DEVAD,
3991                                     MDIO_PMA_REG_8727_TX_CTRL2,
3992                                     params->xgxs_config_tx[1]);
3993                         }
3994                         break;
3995                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3996                         DBPRINT(sc, BXE_VERBOSE_PHY,
3997                             "Setting the SFX7101 LASI indication\n");
3998
3999                         bxe_cl45_write(sc, params->port, ext_phy_type,
4000                             ext_phy_addr, MDIO_PMA_DEVAD,
4001                             MDIO_PMA_REG_LASI_CTRL, 0x1);
4002                         DBPRINT(sc, BXE_VERBOSE_PHY,
4003                             "Setting the SFX7101 LED to blink on traffic\n");
4004                         bxe_cl45_write(sc, params->port, ext_phy_type,
4005                             ext_phy_addr, MDIO_PMA_DEVAD,
4006                             MDIO_PMA_REG_7107_LED_CNTL, (1 << 3));
4007
4008                         bxe_ext_phy_set_pause(params, vars);
4009                         /* Restart autoneg. */
4010                         bxe_cl45_read(sc, params->port, ext_phy_type,
4011                             ext_phy_addr, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
4012                             &val);
4013                         val |= 0x200;
4014                         bxe_cl45_write(sc, params->port, ext_phy_type,
4015                             ext_phy_addr, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, val);
4016
4017                         /* Save spirom version. */
4018                         bxe_cl45_read(sc, params->port, ext_phy_type,
4019                             ext_phy_addr, MDIO_PMA_DEVAD,
4020                             MDIO_PMA_REG_7101_VER1, &fw_ver1);
4021
4022                         bxe_cl45_read(sc, params->port, ext_phy_type,
4023                             ext_phy_addr, MDIO_PMA_DEVAD,
4024                             MDIO_PMA_REG_7101_VER2, &fw_ver2);
4025
4026                         bxe_save_spirom_version(params->sc, params->port,
4027                             params->shmem_base,
4028                             (uint32_t)(fw_ver1 << 16 | fw_ver2));
4029                         break;
4030                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
4031                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
4032                         /*
4033                          * This phy uses the NIG latch mechanism since link
4034                          * indication arrives through its LED4 and not via
4035                          * its LASI signal, so we get steady signal
4036                          * instead of clear on read.
4037                          */
4038                         bxe_bits_en(sc, NIG_REG_LATCH_BC_0 + params->port * 4,
4039                             1 << NIG_LATCH_BC_ENABLE_MI_INT);
4040                         bxe_cl45_write(sc, params->port,
4041                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481, ext_phy_addr,
4042                             MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0000);
4043
4044                         bxe_8481_set_led4(params, ext_phy_type, ext_phy_addr);
4045                         if (params->req_line_speed == SPEED_AUTO_NEG) {
4046                                 /* Set 1000 speed advertisement. */
4047                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4048                                     ext_phy_addr, MDIO_AN_DEVAD,
4049                                     MDIO_AN_REG_8481_1000T_CTRL, &an_1000_val);
4050
4051                                 bxe_ext_phy_set_pause(params, vars);
4052                                 if (params->speed_cap_mask &
4053                                     PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) {
4054                                         an_1000_val |= (1 << 8);
4055                                         if (params->req_duplex == DUPLEX_FULL)
4056                                                 an_1000_val |= (1 << 9);
4057                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4058                                             "Advertising 1G\n");
4059                                 } else
4060                                         an_1000_val &= ~((1 << 8) | (1 << 9));
4061
4062                                 bxe_cl45_write(sc, params->port, ext_phy_type,
4063                                     ext_phy_addr, MDIO_AN_DEVAD,
4064                                     MDIO_AN_REG_8481_1000T_CTRL, an_1000_val);
4065
4066                                 /* Set 100 speed advertisement. */
4067                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4068                                     ext_phy_addr, MDIO_AN_DEVAD,
4069                                     MDIO_AN_REG_8481_LEGACY_AN_ADV,
4070                                     &an_10_100_val);
4071
4072                                 if (params->speed_cap_mask &
4073                                   (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
4074                                   PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) {
4075                                         an_10_100_val |= (1 << 7);
4076                                         if (params->req_duplex == DUPLEX_FULL)
4077                                                 an_10_100_val |= (1 << 8);
4078                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4079                                             "Advertising 100M\n");
4080                                 } else
4081                                         an_10_100_val &= ~((1 << 7) | (1 << 8));
4082
4083                                 /* Set 10 speed advertisement. */
4084                                 if (params->speed_cap_mask &
4085                                     (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
4086                                     PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) {
4087                                         an_10_100_val |= (1 << 5);
4088                                         if (params->req_duplex == DUPLEX_FULL)
4089                                                 an_10_100_val |= (1 << 6);
4090                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4091                                             "Advertising 10M\n");
4092                                 } else
4093                                         an_10_100_val &= ~((1 << 5) | (1 << 6));
4094
4095                                 bxe_cl45_write(sc, params->port, ext_phy_type,
4096                                     ext_phy_addr, MDIO_AN_DEVAD,
4097                                     MDIO_AN_REG_8481_LEGACY_AN_ADV,
4098                                     an_10_100_val);
4099
4100                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4101                                     ext_phy_addr, MDIO_AN_DEVAD,
4102                                     MDIO_AN_REG_8481_LEGACY_MII_CTRL,
4103                                     &autoneg_val);
4104
4105                                 /* Disable forced speed. */
4106                                 autoneg_val &= ~(1 << 6 | 1 << 13);
4107
4108                                 /*
4109                                  * Enable autoneg and restart autoneg
4110                                  * for legacy speeds.
4111                                  */
4112                                 autoneg_val |= (1 << 9 | 1 << 12);
4113
4114                                 if (params->req_duplex == DUPLEX_FULL)
4115                                         autoneg_val |= (1 << 8);
4116                                 else
4117                                         autoneg_val &= ~(1 << 8);
4118
4119                                 bxe_cl45_write(sc, params->port, ext_phy_type,
4120                                     ext_phy_addr, MDIO_AN_DEVAD,
4121                                     MDIO_AN_REG_8481_LEGACY_MII_CTRL,
4122                                     autoneg_val);
4123
4124                                 if (params->speed_cap_mask &
4125                                     PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) {
4126                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4127                                             "Advertising 10G\n");
4128                                         /* Restart autoneg for 10G */
4129                                         bxe_cl45_write(sc, params->port,
4130                                             ext_phy_type, ext_phy_addr,
4131                                             MDIO_AN_DEVAD,
4132                                             MDIO_AN_REG_CTRL, val);
4133                                 }
4134                         } else {
4135                                 /* Force speed */
4136                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4137                                     ext_phy_addr, MDIO_AN_DEVAD,
4138                                     MDIO_AN_REG_8481_LEGACY_MII_CTRL,
4139                                     &autoneg_ctrl);
4140
4141                                 /* Disable autoneg. */
4142                                 autoneg_ctrl &= ~(1 << 12);
4143
4144                                 /* Set 1000 force. */
4145                                 switch (params->req_line_speed) {
4146                                 case SPEED_10000:
4147                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4148                                             "Unable to set 10G force !\n");
4149                                         break;
4150                                 case SPEED_1000:
4151                                         bxe_cl45_read(sc, params->port,
4152                                             ext_phy_type, ext_phy_addr,
4153                                             MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL,
4154                                             &pma_ctrl);
4155                                         autoneg_ctrl &= ~(1 << 13);
4156                                         autoneg_ctrl |= (1 << 6);
4157                                         pma_ctrl &= ~(1 << 13);
4158                                         pma_ctrl |= (1 << 6);
4159                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4160                                             "Setting 1000M force\n");
4161                                         bxe_cl45_write(sc, params->port,
4162                                             ext_phy_type, ext_phy_addr,
4163                                             MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL,
4164                                             pma_ctrl);
4165                                         break;
4166                                 case SPEED_100:
4167                                         autoneg_ctrl |= (1 << 13);
4168                                         autoneg_ctrl &= ~(1 << 6);
4169                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4170                                             "Setting 100M force\n");
4171                                         break;
4172                                 case SPEED_10:
4173                                         autoneg_ctrl &= ~(1 << 13);
4174                                         autoneg_ctrl &= ~(1 << 6);
4175                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4176                                             "Setting 10M force\n");
4177                                         break;
4178                                 }
4179
4180                                 /* Duplex mode */
4181                                 if (params->req_duplex == DUPLEX_FULL) {
4182                                         autoneg_ctrl |= (1 << 8);
4183                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4184                                             "Setting full duplex\n");
4185                                 } else
4186                                         autoneg_ctrl &= ~(1 << 8);
4187
4188                                 /* Update autoneg ctrl and pma ctrl. */
4189                                 bxe_cl45_write(sc, params->port, ext_phy_type,
4190                                     ext_phy_addr, MDIO_AN_DEVAD,
4191                                     MDIO_AN_REG_8481_LEGACY_MII_CTRL,
4192                                     autoneg_ctrl);
4193                         }
4194
4195                         /* Save spirom version. */
4196                         bxe_save_8481_spirom_version(sc, params->port,
4197                             ext_phy_addr, params->shmem_base);
4198                         break;
4199                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
4200                         DBPRINT(sc, BXE_VERBOSE_PHY,
4201                             "XGXS PHY Failure detected 0x%x\n",
4202                             params->ext_phy_config);
4203                         rc = -EINVAL;
4204                         break;
4205                 default:
4206                         DBPRINT(sc, BXE_VERBOSE_PHY,
4207                             "BAD XGXS ext_phy_config 0x%x\n",
4208                             params->ext_phy_config);
4209                         rc = -EINVAL;
4210                         break;
4211                 }
4212
4213         } else { /* SerDes */
4214                 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
4215                 switch (ext_phy_type) {
4216                 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
4217                         DBPRINT(sc, BXE_VERBOSE_PHY, "SerDes Direct\n");
4218                         break;
4219                 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
4220                         DBPRINT(sc, BXE_VERBOSE_PHY, "SerDes 5482\n");
4221                         break;
4222                 default:
4223                         DBPRINT(sc, BXE_VERBOSE_PHY,
4224                             "BAD SerDes ext_phy_config 0x%x\n",
4225                             params->ext_phy_config);
4226                         break;
4227                 }
4228         }
4229         return (rc);
4230 }
4231
4232 static void
4233 bxe_8727_handle_mod_abs(struct link_params *params)
4234 {
4235         struct bxe_softc *sc;
4236         uint32_t val;
4237         uint16_t mod_abs, rx_alarm_status;
4238         uint8_t ext_phy_addr;
4239
4240         sc = params->sc;
4241         ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
4242         val = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region,
4243             dev_info.port_feature_config[params->port].config));
4244
4245         bxe_cl45_read(sc, params->port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
4246             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
4247             &mod_abs);
4248         if (mod_abs & (1 << 8)) {
4249                 /* Module is absent. */
4250                 DBPRINT(sc, BXE_VERBOSE_PHY,
4251                     "MOD_ABS indication show module is absent\n");
4252
4253                 /*
4254                  * 1. Set mod_abs to detect next module presence event
4255                  * 2. Set EDC off by setting OPTXLOS signal input to low
4256                  *    (bit 9).
4257                  *    When the EDC is off it locks onto a reference clock and
4258                  *    avoids becoming 'lost'.
4259                  */
4260                 mod_abs &= ~((1 << 8) | (1 << 9));
4261                 bxe_cl45_write(sc, params->port,
4262                     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727, ext_phy_addr,
4263                     MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
4264
4265                 /*
4266                  * Clear RX alarm since it stays up as long as
4267                  * the mod_abs wasn't changed.
4268                  */
4269                 bxe_cl45_read(sc, params->port,
4270                     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727, ext_phy_addr,
4271                     MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
4272         } else {
4273                 /* Module is present. */
4274                 DBPRINT(sc, BXE_VERBOSE_PHY,
4275                     "MOD_ABS indication show module is present\n");
4276                 /*
4277                  * First thing, disable transmitter, and if the
4278                  * module is ok, the module_detection will enable
4279                  * it. */
4280
4281                 /*
4282                  * 1. Set mod_abs to detect next module absent event ( bit 8)
4283                  * 2. Restore the default polarity of the OPRXLOS signal and
4284                  *    this signal will then correctly indicate the presence or
4285                  *    absence of the Rx signal. (bit 9)
4286                  */
4287                 mod_abs |= ((1 << 8) | (1 << 9));
4288                 bxe_cl45_write(sc, params->port,
4289                     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727, ext_phy_addr,
4290                     MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
4291
4292                 /*
4293                  * Clear RX alarm since it stays up as long as the mod_abs
4294                  * wasn't changed. This is need to be done before calling
4295                  * the module detection, otherwise it will clear the link
4296                  * update alarm.
4297                  */
4298                 bxe_cl45_read(sc, params->port,
4299                     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727, ext_phy_addr,
4300                     MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
4301
4302                 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
4303                     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
4304                         bxe_sfp_set_transmitter(sc, params->port,
4305                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727, ext_phy_addr,
4306                             0);
4307
4308                 if (bxe_wait_for_sfp_module_initialized(params) == 0)
4309                         bxe_sfp_module_detection(params);
4310                 else
4311                         DBPRINT(sc, BXE_VERBOSE_PHY,
4312                             "SFP+ module is not initialized\n");
4313         }
4314
4315         DBPRINT(sc, BXE_VERBOSE_PHY, "8727 RX_ALARM_STATUS 0x%x\n",
4316                  rx_alarm_status);
4317         /* No need to check link status in case of module plugged in/out. */
4318 }
4319
4320 static uint8_t
4321 bxe_ext_phy_is_link_up(struct link_params *params, struct link_vars *vars,
4322     uint8_t is_mi_int)
4323 {
4324         struct bxe_softc *sc;
4325         uint32_t ext_phy_type;
4326         uint16_t val1, val2;
4327         uint16_t rx_sd, pcs_status;
4328         uint16_t link_status;
4329         uint16_t rx_alarm_status;
4330         uint16_t an1000_status;
4331         uint16_t legacy_status, legacy_speed;
4332         uint8_t ext_phy_addr, ext_phy_link_up, port;
4333
4334         sc = params->sc;
4335         val1 = 0;
4336         ext_phy_link_up = 0;
4337         port = params->port;
4338
4339         if (vars->phy_flags & PHY_XGXS_FLAG) {
4340                 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
4341                 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
4342                 switch (ext_phy_type) {
4343                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
4344                         DBPRINT(sc, BXE_VERBOSE_PHY, "XGXS Direct\n");
4345                         ext_phy_link_up = 1;
4346                         break;
4347                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
4348                         DBPRINT(sc, BXE_VERBOSE_PHY, "XGXS 8705\n");
4349                         bxe_cl45_read(sc, params->port, ext_phy_type,
4350                             ext_phy_addr, MDIO_WIS_DEVAD,
4351                             MDIO_WIS_REG_LASI_STATUS, &val1);
4352                         DBPRINT(sc, BXE_VERBOSE_PHY, "8705 LASI status 0x%x\n",
4353                             val1);
4354
4355                         bxe_cl45_read(sc, params->port, ext_phy_type,
4356                             ext_phy_addr, MDIO_WIS_DEVAD,
4357                             MDIO_WIS_REG_LASI_STATUS, &val1);
4358                         DBPRINT(sc, BXE_VERBOSE_PHY,
4359                             "8705 LASI status 0x%x\n", val1);
4360
4361                         bxe_cl45_read(sc, params->port, ext_phy_type,
4362                             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD,
4363                             &rx_sd);
4364
4365                         bxe_cl45_read(sc, params->port, ext_phy_type,
4366                             ext_phy_addr, 1, 0xc809, &val1);
4367                         bxe_cl45_read(sc, params->port, ext_phy_type,
4368                             ext_phy_addr, 1, 0xc809, &val1);
4369
4370                         DBPRINT(sc, BXE_VERBOSE_PHY, "8705 1.c809 val=0x%x\n",
4371                             val1);
4372                         ext_phy_link_up = ((rx_sd & 0x1) && (val1 & (1 << 9)) &&
4373                             ((val1 & (1 << 8)) == 0));
4374                         if (ext_phy_link_up)
4375                                 vars->line_speed = SPEED_10000;
4376                         break;
4377                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
4378                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
4379                         DBPRINT(sc, BXE_VERBOSE_PHY, "XGXS 8706/8726\n");
4380                         /* Clear RX Alarm. */
4381                         bxe_cl45_read(sc, params->port, ext_phy_type,
4382                             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM,
4383                             &val2);
4384                         /* Clear LASI indication. */
4385                         bxe_cl45_read(sc, params->port, ext_phy_type,
4386                             ext_phy_addr, MDIO_PMA_DEVAD,
4387                             MDIO_PMA_REG_LASI_STATUS, &val1);
4388                         bxe_cl45_read(sc, params->port, ext_phy_type,
4389                             ext_phy_addr, MDIO_PMA_DEVAD,
4390                             MDIO_PMA_REG_LASI_STATUS, &val2);
4391                         DBPRINT(sc, BXE_VERBOSE_PHY,
4392                             "8706/8726 LASI status 0x%x-->0x%x\n", val1, val2);
4393
4394                         bxe_cl45_read(sc, params->port, ext_phy_type,
4395                             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD,
4396                             &rx_sd);
4397                         bxe_cl45_read(sc, params->port, ext_phy_type,
4398                             ext_phy_addr, MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS,
4399                             &pcs_status);
4400                         bxe_cl45_read(sc, params->port, ext_phy_type,
4401                             ext_phy_addr, MDIO_AN_DEVAD,
4402                             MDIO_AN_REG_LINK_STATUS, &val2);
4403                         bxe_cl45_read(sc, params->port, ext_phy_type,
4404                             ext_phy_addr, MDIO_AN_DEVAD,
4405                             MDIO_AN_REG_LINK_STATUS, &val2);
4406
4407                         DBPRINT(sc, BXE_VERBOSE_PHY, "8706/8726 rx_sd 0x%x "
4408                             "pcs_status 0x%x 1Gbps link_status 0x%x\n",
4409                             rx_sd, pcs_status, val2);
4410                         /*
4411                          * Link is up if both bit 0 of pmd_rx_sd and bit 0
4412                          * of pcs_status are set, or if the autoneg bit 1
4413                          * is set.
4414                          */
4415                         ext_phy_link_up = ((rx_sd & pcs_status & 0x1) ||
4416                             (val2 & (1 << 1)));
4417                         if (ext_phy_link_up) {
4418                                 if (ext_phy_type ==
4419                                      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) {
4420                                         /*
4421                                          * If transmitter is disabled,
4422                                          * ignore false link up indication.
4423                                          */
4424                                         bxe_cl45_read(sc, params->port,
4425                                             ext_phy_type, ext_phy_addr,
4426                                             MDIO_PMA_DEVAD,
4427                                             MDIO_PMA_REG_PHY_IDENTIFIER,
4428                                             &val1);
4429                                         if (val1 & (1<<15)) {
4430                                                 DBPRINT(sc, BXE_VERBOSE_PHY,
4431                                                     "Tx is disabled\n");
4432                                                 ext_phy_link_up = 0;
4433                                                 break;
4434                                         }
4435                                 }
4436                                 if (val2 & (1 << 1))
4437                                         vars->line_speed = SPEED_1000;
4438                                 else
4439                                         vars->line_speed = SPEED_10000;
4440                         }
4441                         break;
4442                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
4443                         link_status = 0;
4444                         /* Check the LASI. */
4445                         bxe_cl45_read(sc, params->port, ext_phy_type,
4446                             ext_phy_addr, MDIO_PMA_DEVAD,
4447                             MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
4448
4449                         DBPRINT(sc, BXE_VERBOSE_PHY,
4450                             "8727 RX_ALARM_STATUS 0x%x\n", rx_alarm_status);
4451
4452                         bxe_cl45_read(sc, params->port, ext_phy_type,
4453                             ext_phy_addr, MDIO_PMA_DEVAD,
4454                             MDIO_PMA_REG_LASI_STATUS, &val1);
4455
4456                         DBPRINT(sc, BXE_VERBOSE_PHY, "8727 LASI status 0x%x\n",
4457                             val1);
4458
4459                         /* Clear MSG-OUT */
4460                         bxe_cl45_read(sc, params->port, ext_phy_type,
4461                             ext_phy_addr, MDIO_PMA_DEVAD,
4462                             MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
4463
4464                         /*
4465                          * If a module is present and there is need to check
4466                          * for over current.
4467                          */
4468                         if (!(params->feature_config_flags &
4469                             FEATURE_CONFIG_BCM8727_NOC) &&
4470                             !(rx_alarm_status & (1<<5))) {
4471                                 /* Check over-current using 8727 GPIO0 input. */
4472                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4473                                     ext_phy_addr, MDIO_PMA_DEVAD,
4474                                     MDIO_PMA_REG_8727_GPIO_CTRL, &val1);
4475
4476                                 if ((val1 & (1 << 8)) == 0) {
4477                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4478                         "8727 Power fault has been detected on port %d\n",
4479                                             params->port);
4480                                         printf(
4481                         "Error: Power fault on %s Port %d has been detected "
4482                         "and the power to that SFP+ module has been removed "
4483                         "to prevent failure of the card. Please remove the "
4484                         "SFP+ module and restart the system to clear this "
4485                         "error.\n",
4486                                             sc->name, params->port);
4487                                         /*
4488                                          * Disable all RX_ALARMs except for
4489                                          * mod_abs.
4490                                          */
4491                                         bxe_cl45_write(sc, params->port,
4492                                             ext_phy_type, ext_phy_addr,
4493                                             MDIO_PMA_DEVAD,
4494                                             MDIO_PMA_REG_RX_ALARM_CTRL,
4495                                             (1 << 5));
4496
4497                                         bxe_cl45_read(sc, params->port,
4498                                             ext_phy_type, ext_phy_addr,
4499                                             MDIO_PMA_DEVAD,
4500                                             MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
4501                                         /* Wait for module_absent_event. */
4502                                         val1 |= (1 << 8);
4503                                         bxe_cl45_write(sc, params->port,
4504                                             ext_phy_type, ext_phy_addr,
4505                                             MDIO_PMA_DEVAD,
4506                                             MDIO_PMA_REG_PHY_IDENTIFIER, val1);
4507                                         /* Clear RX alarm. */
4508                                         bxe_cl45_read(sc, params->port,
4509                                             ext_phy_type, ext_phy_addr,
4510                                             MDIO_PMA_DEVAD,
4511                                             MDIO_PMA_REG_RX_ALARM,
4512                                             &rx_alarm_status);
4513                                         break;
4514                                 }
4515                         } /* Over current check */
4516
4517                         /* When module absent bit is set, check module. */
4518                         if (rx_alarm_status & (1 << 5)) {
4519                                 bxe_8727_handle_mod_abs(params);
4520                                 /*
4521                                  * Enable all mod_abs and link detection bits.
4522                                  */
4523                                 bxe_cl45_write(sc, params->port, ext_phy_type,
4524                                     ext_phy_addr, MDIO_PMA_DEVAD,
4525                                     MDIO_PMA_REG_RX_ALARM_CTRL,
4526                                     ((1 << 5) | (1 << 2)));
4527                         }
4528
4529                         /*
4530                          * If transmitter is disabled, ignore false link
4531                          * up indication.
4532                          */
4533                         bxe_cl45_read(sc, params->port, ext_phy_type,
4534                             ext_phy_addr, MDIO_PMA_DEVAD,
4535                             MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
4536                         if (val1 & (1 << 15)) {
4537                                 DBPRINT(sc, BXE_VERBOSE_PHY,
4538                                     "Tx is disabled\n");
4539                                 ext_phy_link_up = 0;
4540                                 break;
4541                         }
4542
4543                         bxe_cl45_read(sc, params->port, ext_phy_type,
4544                             ext_phy_addr, MDIO_PMA_DEVAD,
4545                             MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &link_status);
4546
4547                         /*
4548                          * Bits 0..2 --> speed detected,
4549                          * bits 13..15--> link is down
4550                          */
4551                         if ((link_status & (1 << 2)) &&
4552                             (!(link_status & (1 << 15)))) {
4553                                 ext_phy_link_up = 1;
4554                                 vars->line_speed = SPEED_10000;
4555                         } else if ((link_status & (1 << 0)) &&
4556                             (!(link_status & (1 << 13)))) {
4557                                 ext_phy_link_up = 1;
4558                                 vars->line_speed = SPEED_1000;
4559                                 DBPRINT(sc, BXE_VERBOSE_PHY,
4560                                     "port %x: External link up in 1G\n",
4561                                     params->port);
4562                         } else {
4563                                 ext_phy_link_up = 0;
4564                                 DBPRINT(sc, BXE_VERBOSE_PHY,
4565                                     "port %x: External link is down\n",
4566                                     params->port);
4567                         }
4568                         break;
4569                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
4570                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
4571                         link_status = 0;
4572                         an1000_status = 0;
4573                         if (ext_phy_type ==
4574                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
4575                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4576                                     ext_phy_addr, MDIO_PCS_DEVAD,
4577                                     MDIO_PCS_REG_LASI_STATUS, &val1);
4578                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4579                                     ext_phy_addr, MDIO_PCS_DEVAD,
4580                                     MDIO_PCS_REG_LASI_STATUS, &val2);
4581                                 DBPRINT(sc, BXE_VERBOSE_PHY,
4582                                     "870x LASI status 0x%x->0x%x\n", val1,
4583                                     val2);
4584                         } else {
4585                                 /*
4586                                  * In 8073, port1 is directed through emac0 and
4587                                  * port0 is directed through emac1.
4588                                  */
4589                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4590                                     ext_phy_addr, MDIO_PMA_DEVAD,
4591                                     MDIO_PMA_REG_LASI_STATUS, &val1);
4592
4593                                 DBPRINT(sc, BXE_VERBOSE_PHY,
4594                                     "8703 LASI status 0x%x\n", val1);
4595                         }
4596
4597                         /* Clear the interrupt LASI status register. */
4598                         bxe_cl45_read(sc, params->port, ext_phy_type,
4599                             ext_phy_addr, MDIO_PCS_DEVAD,
4600                             MDIO_PCS_REG_STATUS, &val2);
4601                         bxe_cl45_read(sc, params->port, ext_phy_type,
4602                             ext_phy_addr, MDIO_PCS_DEVAD,
4603                             MDIO_PCS_REG_STATUS, &val1);
4604                         DBPRINT(sc, BXE_VERBOSE_PHY,
4605                             "807x PCS status 0x%x->0x%x\n", val2, val1);
4606                         /* Clear MSG-OUT. */
4607                         bxe_cl45_read(sc, params->port, ext_phy_type,
4608                             ext_phy_addr, MDIO_PMA_DEVAD,
4609                             MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
4610
4611                         /* Check the LASI. */
4612                         bxe_cl45_read(sc, params->port, ext_phy_type,
4613                             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM,
4614                             &val2);
4615
4616                         DBPRINT(sc, BXE_VERBOSE_PHY, "KR 0x9003 0x%x\n", val2);
4617
4618                         /* Check the link status. */
4619                         bxe_cl45_read(sc, params->port, ext_phy_type,
4620                             ext_phy_addr, MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS,
4621                             &val2);
4622                         DBPRINT(sc, BXE_VERBOSE_PHY, "KR PCS status 0x%x\n",
4623                             val2);
4624
4625                         bxe_cl45_read(sc, params->port, ext_phy_type,
4626                             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS,
4627                             &val2);
4628                         bxe_cl45_read(sc, params->port, ext_phy_type,
4629                             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS,
4630                             &val1);
4631                         ext_phy_link_up = ((val1 & 4) == 4);
4632                         DBPRINT(sc, BXE_VERBOSE_PHY, "PMA_REG_STATUS=0x%x\n",
4633                             val1);
4634                         if (ext_phy_type ==
4635                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
4636                                 if (ext_phy_link_up &&
4637                                     ((params->req_line_speed != SPEED_10000))) {
4638                                         if (bxe_bcm8073_xaui_wa(params) != 0) {
4639                                                 ext_phy_link_up = 0;
4640                                                 break;
4641                                         }
4642                                 }
4643                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4644                                     ext_phy_addr, MDIO_AN_DEVAD,
4645                                     MDIO_AN_REG_LINK_STATUS, &an1000_status);
4646                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4647                                     ext_phy_addr, MDIO_AN_DEVAD,
4648                                     MDIO_AN_REG_LINK_STATUS, &an1000_status);
4649
4650                                 /* Check the link status on 1.1.2. */
4651                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4652                                     ext_phy_addr, MDIO_PMA_DEVAD,
4653                                     MDIO_PMA_REG_STATUS, &val2);
4654                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4655                                     ext_phy_addr, MDIO_PMA_DEVAD,
4656                                     MDIO_PMA_REG_STATUS, &val1);
4657                                 DBPRINT(sc, BXE_VERBOSE_PHY,
4658                         "KR PMA status 0x%x->0x%x, an_link_status=0x%x\n",
4659                                     val2, val1, an1000_status);
4660
4661                                 ext_phy_link_up = (((val1 & 4) == 4) ||
4662                                     (an1000_status & (1 << 1)));
4663                                 if (ext_phy_link_up &&
4664                                     bxe_8073_is_snr_needed(params)) {
4665                                         /*
4666                                          * The SNR will improve about 2dbby
4667                                          * changing the BW and FEE main tap.
4668                                          *
4669                                          * The 1st write to change FFE main
4670                                          * tap is set before restart AN.
4671                                          * Change PLL Bandwidth in EDC
4672                                          * register.
4673                                          */
4674                                         bxe_cl45_write(sc, port, ext_phy_type,
4675                                             ext_phy_addr, MDIO_PMA_DEVAD,
4676                                             MDIO_PMA_REG_PLL_BANDWIDTH, 0x26BC);
4677
4678                                         /*
4679                                          * Change CDR Bandwidth in EDC register.
4680                                           */
4681                                         bxe_cl45_write(sc, port, ext_phy_type,
4682                                             ext_phy_addr, MDIO_PMA_DEVAD,
4683                                             MDIO_PMA_REG_CDR_BANDWIDTH, 0x0333);
4684                                 }
4685                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4686                                     ext_phy_addr, MDIO_PMA_DEVAD,
4687                                     MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
4688                                     &link_status);
4689
4690                                 /*
4691                                  * Bits 0..2 --> speed detected,
4692                                  * bits 13..15--> link is down
4693                                  */
4694                                 if ((link_status & (1<<2)) &&
4695                                     (!(link_status & (1<<15)))) {
4696                                         ext_phy_link_up = 1;
4697                                         vars->line_speed = SPEED_10000;
4698                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4699                                 "port %x: External link up in 10G\n",
4700                                             params->port);
4701                                 } else if ((link_status & (1<<1)) &&
4702                                     (!(link_status & (1<<14)))) {
4703                                         ext_phy_link_up = 1;
4704                                         vars->line_speed = SPEED_2500;
4705                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4706                                 "port %x: External link up in 2.5G\n",
4707                                             params->port);
4708                                 } else if ((link_status & (1<<0)) &&
4709                                     (!(link_status & (1<<13)))) {
4710                                         ext_phy_link_up = 1;
4711                                         vars->line_speed = SPEED_1000;
4712                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4713                                 "port %x: External link up in 1G\n",
4714                                             params->port);
4715                                 } else {
4716                                         ext_phy_link_up = 0;
4717                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4718                                 "port %x: External link is down\n",
4719                                             params->port);
4720                                 }
4721                         } else {
4722                                 /* See if 1G link is up for the 8072. */
4723                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4724                                     ext_phy_addr, MDIO_AN_DEVAD,
4725                                     MDIO_AN_REG_LINK_STATUS, &an1000_status);
4726                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4727                                     ext_phy_addr, MDIO_AN_DEVAD,
4728                                     MDIO_AN_REG_LINK_STATUS, &an1000_status);
4729                                 if (an1000_status & (1 << 1)) {
4730                                         ext_phy_link_up = 1;
4731                                         vars->line_speed = SPEED_1000;
4732                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4733                                 "port %x: External link up in 1G\n",
4734                                             params->port);
4735                                 } else if (ext_phy_link_up) {
4736                                         ext_phy_link_up = 1;
4737                                         vars->line_speed = SPEED_10000;
4738                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4739                                 "port %x: External link up in 10G\n",
4740                                             params->port);
4741                                 }
4742                         }
4743                         break;
4744                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
4745                         bxe_cl45_read(sc, params->port, ext_phy_type,
4746                             ext_phy_addr, MDIO_PMA_DEVAD,
4747                             MDIO_PMA_REG_LASI_STATUS, &val2);
4748                         bxe_cl45_read(sc, params->port, ext_phy_type,
4749                             ext_phy_addr, MDIO_PMA_DEVAD,
4750                             MDIO_PMA_REG_LASI_STATUS, &val1);
4751                         DBPRINT(sc, BXE_VERBOSE_PHY,
4752                             "10G-base-T LASI status 0x%x->0x%x\n", val2, val1);
4753                         bxe_cl45_read(sc, params->port, ext_phy_type,
4754                             ext_phy_addr, MDIO_PMA_DEVAD,
4755                             MDIO_PMA_REG_STATUS, &val2);
4756                         bxe_cl45_read(sc, params->port, ext_phy_type,
4757                             ext_phy_addr, MDIO_PMA_DEVAD,
4758                             MDIO_PMA_REG_STATUS, &val1);
4759                         DBPRINT(sc, BXE_VERBOSE_PHY,
4760                             "10G-base-T PMA status 0x%x->0x%x\n", val2, val1);
4761                         ext_phy_link_up = ((val1 & 4) == 4);
4762                         /*
4763                          * if link is up print the AN outcome of the
4764                          * SFX7101 PHY.
4765                          */
4766                         if (ext_phy_link_up) {
4767                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4768                                     ext_phy_addr, MDIO_AN_DEVAD,
4769                                     MDIO_AN_REG_MASTER_STATUS, &val2);
4770                                 vars->line_speed = SPEED_10000;
4771                                 DBPRINT(sc, BXE_VERBOSE_PHY,
4772                                     "SFX7101 AN status 0x%x->Master=%x\n",
4773                                     val2, (val2 & (1 << 14)));
4774                         }
4775                         break;
4776                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
4777                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
4778                         /* Check 10G-BaseT link status. */
4779                         /* Check PMD signal ok. */
4780                         bxe_cl45_read(sc, params->port, ext_phy_type,
4781                             ext_phy_addr, MDIO_AN_DEVAD, 0xFFFA, &val1);
4782                         bxe_cl45_read(sc, params->port, ext_phy_type,
4783                             ext_phy_addr, MDIO_PMA_DEVAD,
4784                             MDIO_PMA_REG_8481_PMD_SIGNAL, &val2);
4785                         DBPRINT(sc, BXE_VERBOSE_PHY,
4786                             "PMD_SIGNAL 1.a811 = 0x%x\n", val2);
4787
4788                         /* Check link 10G. */
4789                         if (val2 & (1 << 11)) {
4790                                 vars->line_speed = SPEED_10000;
4791                                 ext_phy_link_up = 1;
4792                                 bxe_8481_set_10G_led_mode(params, ext_phy_type,
4793                                     ext_phy_addr);
4794                         } else { /* Check Legacy speed link */
4795                                 /*
4796                                  * Enable expansion register 0x42
4797                                  * (Operation mode status).
4798                                  */
4799                                 bxe_cl45_write(sc, params->port, ext_phy_type,
4800                                     ext_phy_addr, MDIO_AN_DEVAD,
4801                                     MDIO_AN_REG_8481_EXPANSION_REG_ACCESS,
4802                                     0xf42);
4803
4804                                 /* Get legacy speed operation status. */
4805                                 bxe_cl45_read(sc, params->port, ext_phy_type,
4806                                     ext_phy_addr, MDIO_AN_DEVAD,
4807                                     MDIO_AN_REG_8481_EXPANSION_REG_RD_RW,
4808                                     &legacy_status);
4809
4810                                 DBPRINT(sc, BXE_VERBOSE_PHY,
4811                                     "Legacy speed status = 0x%x\n",
4812                                     legacy_status);
4813                                 ext_phy_link_up = ((legacy_status &
4814                                     (1 << 11)) == (1<<11));
4815                                 if (ext_phy_link_up) {
4816                                         legacy_speed = (legacy_status &
4817                                             (3 << 9));
4818                                         if (legacy_speed == (0 << 9))
4819                                                 vars->line_speed = SPEED_10;
4820                                         else if (legacy_speed == (1 << 9))
4821                                                 vars->line_speed = SPEED_100;
4822                                         else if (legacy_speed == (2 << 9))
4823                                                 vars->line_speed = SPEED_1000;
4824                                         else /* Should not happen */
4825                                                 vars->line_speed = 0;
4826                                         if (legacy_status & (1 << 8))
4827                                                 vars->duplex = DUPLEX_FULL;
4828                                         else
4829                                                 vars->duplex = DUPLEX_HALF;
4830
4831                                         DBPRINT(sc, BXE_VERBOSE_PHY,
4832                                 "Link is up in %dMbps, is_duplex_full = %d\n",
4833                                             vars->line_speed,
4834                                             (vars->duplex == DUPLEX_FULL));
4835                                         bxe_8481_set_legacy_led_mode(params,
4836                                             ext_phy_type, ext_phy_addr);
4837                                 }
4838                         }
4839                         break;
4840                 default:
4841                         DBPRINT(sc, BXE_VERBOSE_PHY,
4842                             "BAD XGXS ext_phy_config 0x%x\n",
4843                             params->ext_phy_config);
4844                         ext_phy_link_up = 0;
4845                         break;
4846                 }
4847                 /* Set SGMII mode for external phy */
4848                 if (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
4849                         if (vars->line_speed < SPEED_1000)
4850                                 vars->phy_flags |= PHY_SGMII_FLAG;
4851                         else
4852                                 vars->phy_flags &= ~PHY_SGMII_FLAG;
4853                 }
4854
4855         } else { /* SerDes */
4856                 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
4857                 switch (ext_phy_type) {
4858                 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
4859                         DBPRINT(sc, BXE_VERBOSE_PHY, "SerDes Direct\n");
4860                         ext_phy_link_up = 1;
4861                         break;
4862                 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
4863                         DBPRINT(sc, BXE_VERBOSE_PHY, "SerDes 5482\n");
4864                         ext_phy_link_up = 1;
4865                         break;
4866                 default:
4867                         DBPRINT(sc, BXE_VERBOSE_PHY,
4868                             "BAD SerDes ext_phy_config 0x%x\n",
4869                             params->ext_phy_config);
4870                         ext_phy_link_up = 0;
4871                         break;
4872                 }
4873         }
4874
4875         return (ext_phy_link_up);
4876 }
4877
4878 static void
4879 bxe_link_int_enable(struct link_params *params)
4880 {
4881         struct bxe_softc *sc;
4882         uint32_t ext_phy_type, mask;
4883         uint8_t port;
4884
4885         sc = params->sc;
4886         port = params->port;
4887
4888         /* Setting the status to report on link up for either XGXS or SerDes. */
4889
4890         if (params->switch_cfg == SWITCH_CFG_10G) {
4891                 mask = (NIG_MASK_XGXS0_LINK10G | NIG_MASK_XGXS0_LINK_STATUS);
4892                 DBPRINT(sc, BXE_VERBOSE_PHY, "enabled XGXS interrupt\n");
4893                 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
4894                 if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
4895                     (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
4896                     (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) {
4897                         mask |= NIG_MASK_MI_INT;
4898                         DBPRINT(sc, BXE_VERBOSE_PHY,
4899                             "enabled external phy int\n");
4900                 }
4901         } else { /* SerDes */
4902                 mask = NIG_MASK_SERDES0_LINK_STATUS;
4903                 DBPRINT(sc, BXE_VERBOSE_PHY, "enabled SerDes interrupt\n");
4904                 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
4905                 if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
4906                     (ext_phy_type !=
4907                     PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN)) {
4908                         mask |= NIG_MASK_MI_INT;
4909                         DBPRINT(sc, BXE_VERBOSE_PHY,
4910                             "enabled external phy int\n");
4911                 }
4912         }
4913         bxe_bits_en(sc, NIG_REG_MASK_INTERRUPT_PORT0 + port * 4, mask);
4914
4915         DBPRINT(sc, BXE_VERBOSE_PHY, "port %x, is_xgxs %x, int_status 0x%x\n",
4916             port, (params->switch_cfg == SWITCH_CFG_10G), REG_RD(sc,
4917             NIG_REG_STATUS_INTERRUPT_PORT0 + port * 4));
4918         DBPRINT(sc, BXE_VERBOSE_PHY, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n",
4919             REG_RD(sc, NIG_REG_MASK_INTERRUPT_PORT0 + port * 4),
4920             REG_RD(sc, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port * 0x18),
4921             REG_RD(sc, NIG_REG_SERDES0_STATUS_LINK_STATUS + port * 0x3c));
4922         DBPRINT(sc, BXE_VERBOSE_PHY, " 10G %x, XGXS_LINK %x\n",
4923             REG_RD(sc, NIG_REG_XGXS0_STATUS_LINK10G + port * 0x68),
4924             REG_RD(sc, NIG_REG_XGXS0_STATUS_LINK_STATUS + port * 0x68));
4925 }
4926
4927 static void
4928 bxe_8481_rearm_latch_signal(struct bxe_softc *sc, uint8_t port,
4929 uint8_t is_mi_int)
4930 {
4931         uint32_t latch_status, is_mi_int_status;
4932
4933         latch_status = 0;
4934
4935         /*
4936          * Disable the MI INT ( external phy int )
4937          * by writing 1 to the status register. Link down indication
4938          * is high-active-signal, so in this case we need to write
4939          * the status to clear the XOR.
4940          */
4941         /* Read Latched signals. */
4942         latch_status = REG_RD(sc, NIG_REG_LATCH_STATUS_0 + port * 8);
4943         is_mi_int_status = REG_RD(sc, NIG_REG_STATUS_INTERRUPT_PORT0 +
4944             port * 4);
4945         DBPRINT(sc, BXE_VERBOSE_PHY,
4946             "original_signal = 0x%x, nig_status = 0x%x, latch_status = 0x%x\n",
4947             is_mi_int, is_mi_int_status, latch_status);
4948         /* Handle only those with latched-signal=up. */
4949         if (latch_status & 1) {
4950                 /* For all latched-signal=up,Write original_signal to status. */
4951                 if (is_mi_int)
4952                         bxe_bits_en(sc, NIG_REG_STATUS_INTERRUPT_PORT0 +
4953                             port * 4, NIG_STATUS_EMAC0_MI_INT);
4954                 else
4955                         bxe_bits_dis(sc, NIG_REG_STATUS_INTERRUPT_PORT0 +
4956                             port * 4, NIG_STATUS_EMAC0_MI_INT);
4957                 /* For all latched-signal=up : Re-Arm Latch signals. */
4958                 REG_WR(sc, NIG_REG_LATCH_STATUS_0 + port * 8,
4959                     (latch_status & 0xfffe) | (latch_status & 1));
4960         }
4961 }
4962
4963 /*
4964  * Link management
4965  */
4966 static void
4967 bxe_link_int_ack(struct link_params *params, struct link_vars *vars,
4968     uint8_t is_10g, uint8_t is_mi_int)
4969 {
4970         struct bxe_softc *sc;
4971         uint32_t ser_lane;
4972         uint8_t port;
4973
4974         sc = params->sc;
4975         port = params->port;
4976
4977         /*
4978          * First reset all status, we assume only one line will be
4979          * change at a time.
4980          */
4981         bxe_bits_dis(sc, NIG_REG_STATUS_INTERRUPT_PORT0 + port * 4,
4982             (NIG_STATUS_XGXS0_LINK10G | NIG_STATUS_XGXS0_LINK_STATUS |
4983              NIG_STATUS_SERDES0_LINK_STATUS));
4984         if ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
4985             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481) ||
4986             (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
4987             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823))
4988                 bxe_8481_rearm_latch_signal(sc, port, is_mi_int);
4989         if (vars->phy_link_up) {
4990                 if (is_10g) {
4991                         /*
4992                          * Disable the 10G link interrupt by writing 1 to
4993                          * the status register.
4994                          */
4995                         DBPRINT(sc, BXE_VERBOSE_PHY, "10G XGXS phy link up\n");
4996                         bxe_bits_en(sc, NIG_REG_STATUS_INTERRUPT_PORT0 +
4997                             port * 4, NIG_STATUS_XGXS0_LINK10G);
4998                 } else if (params->switch_cfg == SWITCH_CFG_10G) {
4999                         /*
5000                          * Disable the link interrupt by writing 1 to
5001                          * the relevant lane in the status register.
5002                          */
5003                         ser_lane = ((params->lane_config &
5004                             PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
5005                             PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
5006
5007                         DBPRINT(sc, BXE_VERBOSE_PHY,
5008                             "%d speed XGXS phy link up\n", vars->line_speed);
5009                         bxe_bits_en(sc, NIG_REG_STATUS_INTERRUPT_PORT0 +
5010                             port * 4, ((1 << ser_lane) <<
5011                             NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
5012                 } else { /* SerDes */
5013                         DBPRINT(sc, BXE_VERBOSE_PHY, "SerDes phy link up\n");
5014                         /*
5015                          * Disable the link interrupt by writing 1 to
5016                          * the status register.
5017                          */
5018                         bxe_bits_en(sc, NIG_REG_STATUS_INTERRUPT_PORT0 +
5019                             port * 4, NIG_STATUS_SERDES0_LINK_STATUS);
5020                 }
5021
5022         } else { /* link_down */
5023         }
5024 }
5025
5026 static uint8_t
5027 bxe_format_ver(uint32_t num, uint8_t *str, uint16_t len)
5028 {
5029         uint32_t mask;
5030         uint8_t *str_ptr;
5031         uint8_t digit, shift;
5032
5033         str_ptr = str;
5034         mask = 0xf0000000;
5035         shift = 8 * 4;
5036         if (len < 10) {
5037                 /* Need more than 10 chars for this format. */
5038                 *str_ptr = '\0';
5039                 return (-EINVAL);
5040         }
5041         while (shift > 0) {
5042                 shift -= 4;
5043                 digit = ((num & mask) >> shift);
5044                 if (digit < 0xa)
5045                         *str_ptr = digit + '0';
5046                 else
5047                         *str_ptr = digit - 0xa + 'a';
5048                 str_ptr++;
5049                 mask = mask >> 4;
5050                 if (shift == 4*4) {
5051                         *str_ptr = ':';
5052                         str_ptr++;
5053                 }
5054         }
5055         *str_ptr = '\0';
5056         return (0);
5057 }
5058
5059 uint8_t
5060 bxe_get_ext_phy_fw_version(struct link_params *params, uint8_t driver_loaded,
5061     uint8_t *version, uint16_t len)
5062 {
5063         struct bxe_softc *sc;
5064         uint32_t ext_phy_type, spirom_ver;
5065         uint8_t status;
5066
5067         sc = params->sc;
5068         if (version == NULL || params == NULL)
5069                 return (-EINVAL);
5070
5071         spirom_ver = REG_RD(sc, params->shmem_base +
5072             offsetof(struct shmem_region,
5073             port_mb[params->port].ext_phy_fw_version));
5074
5075         status = 0;
5076         /* Reset the returned value to zero. */
5077         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
5078         switch (ext_phy_type) {
5079         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
5080                 if (len < 5)
5081                         return (-EINVAL);
5082                 version[0] = (spirom_ver & 0xFF);
5083                 version[1] = (spirom_ver & 0xFF00) >> 8;
5084                 version[2] = (spirom_ver & 0xFF0000) >> 16;
5085                 version[3] = (spirom_ver & 0xFF000000) >> 24;
5086                 version[4] = '\0';
5087                 break;
5088         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
5089         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
5090         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
5091         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
5092         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
5093                 status = bxe_format_ver(spirom_ver, version, len);
5094                 break;
5095         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
5096         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
5097                 spirom_ver = ((spirom_ver & 0xF80) >> 7) << 16 |
5098                     (spirom_ver & 0x7F);
5099                 status = bxe_format_ver(spirom_ver, version, len);
5100                 break;
5101         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
5102         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
5103                 version[0] = '\0';
5104                 break;
5105         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
5106                 DBPRINT(sc, BXE_VERBOSE_PHY,
5107                     "bxe_get_ext_phy_fw_version: type is FAILURE!\n");
5108                 status = -EINVAL;
5109                 break;
5110         default:
5111                 break;
5112         }
5113         return (status);
5114 }
5115
5116 static void
5117 bxe_set_xgxs_loopback(struct link_params *params, struct link_vars *vars,
5118     uint8_t is_10g)
5119 {
5120         struct bxe_softc *sc;
5121         uint32_t md_devad;
5122         uint16_t mii_control;
5123         uint8_t port;
5124
5125         sc = params->sc;
5126         port = params->port;
5127
5128         if (is_10g) {
5129                 DBPRINT(sc, BXE_VERBOSE_PHY, "XGXS 10G loopback enable\n");
5130
5131                 /* Change the uni_phy_addr in the nig. */
5132                 md_devad = REG_RD(sc, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
5133                     port * 0x18));
5134
5135                 REG_WR(sc, NIG_REG_XGXS0_CTRL_MD_DEVAD + port * 0x18, 0x5);
5136
5137                 bxe_cl45_write(sc, port, 0, params->phy_addr, 5,
5138                     (MDIO_REG_BANK_AER_BLOCK + (MDIO_AER_BLOCK_AER_REG & 0xf)),
5139                     0x2800);
5140
5141                 bxe_cl45_write(sc, port, 0, params->phy_addr, 5,
5142                     (MDIO_REG_BANK_CL73_IEEEB0 +
5143                      (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)), 0x6041);
5144                 msleep(200);
5145                 /* Set aer mmd back. */
5146                 bxe_set_aer_mmd(params, vars);
5147
5148                 /* and md_devad */
5149                 REG_WR(sc, NIG_REG_XGXS0_CTRL_MD_DEVAD + port * 0x18, md_devad);
5150         } else {
5151                 DBPRINT(sc, BXE_VERBOSE_PHY, "XGXS 1G loopback enable\n");
5152
5153                 CL45_RD_OVER_CL22(sc, port, params->phy_addr,
5154                     MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL,
5155                     &mii_control);
5156
5157                 CL45_WR_OVER_CL22(sc, port, params->phy_addr,
5158                     MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL,
5159                     (mii_control | MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK));
5160         }
5161 }
5162
5163 static void
5164 bxe_ext_phy_loopback(struct link_params *params)
5165 {
5166         struct bxe_softc *sc;
5167         uint8_t ext_phy_addr;
5168         uint32_t ext_phy_type;
5169
5170         sc = params->sc;
5171         if (params->switch_cfg == SWITCH_CFG_10G) {
5172                 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
5173                 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
5174                 /* CL37 Autoneg Enabled */
5175                 switch (ext_phy_type) {
5176                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
5177                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
5178                         DBPRINT(sc, BXE_VERBOSE_PHY,
5179                             "ext_phy_loopback: We should not get here\n");
5180                         break;
5181                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
5182                         DBPRINT(sc, BXE_VERBOSE_PHY,
5183                             "ext_phy_loopback: 8705\n");
5184                         break;
5185                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
5186                         DBPRINT(sc, BXE_VERBOSE_PHY,
5187                             "ext_phy_loopback: 8706\n");
5188                         break;
5189                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
5190                         DBPRINT(sc, BXE_VERBOSE_PHY,
5191                             "PMA/PMD ext_phy_loopback: 8726\n");
5192                         bxe_cl45_write(sc, params->port, ext_phy_type,
5193                             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL,
5194                             0x0001);
5195                         break;
5196                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
5197                         /* SFX7101_XGXS_TEST1 */
5198                         bxe_cl45_write(sc, params->port, ext_phy_type,
5199                             ext_phy_addr, MDIO_XS_DEVAD,
5200                             MDIO_XS_SFX7101_XGXS_TEST1, 0x100);
5201                         DBPRINT(sc, BXE_VERBOSE_PHY,
5202                             "ext_phy_loopback: set ext phy loopback\n");
5203                         break;
5204                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
5205                         break;
5206                 } /* switch external PHY type */
5207         } else {
5208                 /* serdes */
5209                 ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
5210                 ext_phy_addr = (params->ext_phy_config &
5211                     PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK) >>
5212                     PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT;
5213         }
5214 }
5215
5216 /* Override the led value of the requsted led. */
5217 uint8_t bxe_override_led_value(struct bxe_softc *sc, uint8_t port,
5218     uint32_t led_idx, uint32_t value)
5219 {
5220         uint32_t reg_val;
5221         uint32_t emac_base;
5222
5223         /* If port 0 then use EMAC0, else use EMAC1. */
5224         emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
5225
5226         DBPRINT(sc, BXE_VERBOSE_PHY,
5227             "bxe_override_led_value() port %x led_idx %d value %d\n", port,
5228             led_idx, value);
5229
5230         switch (led_idx) {
5231         case 0: /* 10MB led */
5232                 /*
5233                  * Read the current value of the LED register in the EMAC block.
5234                  */
5235                 reg_val = REG_RD(sc, emac_base + EMAC_REG_EMAC_LED);
5236                 /* Set the OVERRIDE bit to 1. */
5237                 reg_val |= EMAC_LED_OVERRIDE;
5238                 /*
5239                  * If value is 1, set the 10M_OVERRIDE bit, otherwise reset it.
5240                  */
5241                 reg_val = (value == 1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) :
5242                     (reg_val & ~EMAC_LED_10MB_OVERRIDE);
5243                 REG_WR(sc, emac_base + EMAC_REG_EMAC_LED, reg_val);
5244                 break;
5245         case 1: /*100MB led    */
5246                 /*
5247                  * Read the current value of the LED register in the EMAC block.
5248                  */
5249                 reg_val = REG_RD(sc, emac_base + EMAC_REG_EMAC_LED);
5250                 /* Set the OVERRIDE bit to 1. */
5251                 reg_val |= EMAC_LED_OVERRIDE;
5252                 /*
5253                  * If value is 1, set the 100M_OVERRIDE bit, otherwise reset it.
5254                  */
5255                 reg_val = (value == 1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) :
5256                     (reg_val & ~EMAC_LED_100MB_OVERRIDE);
5257                 REG_WR(sc, emac_base + EMAC_REG_EMAC_LED, reg_val);
5258                 break;
5259         case 2: /* 1000MB led */
5260                 /*
5261                  * Read the current value of the LED register in the EMAC block.
5262                  */
5263                 reg_val = REG_RD(sc, emac_base + EMAC_REG_EMAC_LED);
5264                 /* Set the OVERRIDE bit to 1. */
5265                 reg_val |= EMAC_LED_OVERRIDE;
5266                 /*
5267                  * If value is 1, set the 1000M_OVERRIDE bit, otherwise reset
5268                  * it.
5269                  */
5270                 reg_val = (value == 1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) :
5271                     (reg_val & ~EMAC_LED_1000MB_OVERRIDE);
5272                 REG_WR(sc, emac_base + EMAC_REG_EMAC_LED, reg_val);
5273                 break;
5274         case 3: /* 2500MB led */
5275                 /*
5276                  * Read the current value of the LED register in the EMAC block.
5277                  */
5278                 reg_val = REG_RD(sc, emac_base + EMAC_REG_EMAC_LED);
5279                 /* Set the OVERRIDE bit to 1. */
5280                 reg_val |= EMAC_LED_OVERRIDE;
5281                 /*
5282                  * If value is 1, set the 2500M_OVERRIDE bit, otherwise reset
5283                  * it.
5284                  */
5285                 reg_val = (value == 1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) :
5286                     (reg_val & ~EMAC_LED_2500MB_OVERRIDE);
5287                 REG_WR(sc, emac_base + EMAC_REG_EMAC_LED, reg_val);
5288                 break;
5289         case 4: /*10G led */
5290                 if (port == 0)
5291                         REG_WR(sc, NIG_REG_LED_10G_P0, value);
5292                 else
5293                         REG_WR(sc, NIG_REG_LED_10G_P1, value);
5294                 break;
5295         case 5: /* TRAFFIC led */
5296                 /* Find if the traffic control is via BMAC or EMAC. */
5297                 if (port == 0)
5298                         reg_val = REG_RD(sc, NIG_REG_NIG_EMAC0_EN);
5299                 else
5300                         reg_val = REG_RD(sc, NIG_REG_NIG_EMAC1_EN);
5301
5302                 /*  Override the traffic led in the EMAC. */
5303                 if (reg_val == 1) {
5304                         /*
5305                          * Read the current value of the LED register in
5306                          * the EMAC block.
5307                          */
5308                         reg_val = REG_RD(sc, emac_base + EMAC_REG_EMAC_LED);
5309                         /* Set the TRAFFIC_OVERRIDE bit to 1. */
5310                         reg_val |= EMAC_LED_OVERRIDE;
5311                         /*
5312                          * If value is 1, set the TRAFFIC bit, otherwise reset
5313                          * it.
5314                          */
5315                         reg_val = (value == 1) ? (reg_val | EMAC_LED_TRAFFIC) :
5316                             (reg_val & ~EMAC_LED_TRAFFIC);
5317                         REG_WR(sc, emac_base + EMAC_REG_EMAC_LED, reg_val);
5318                 } else {
5319                         /* Override the traffic led in the BMAC. */
5320                         REG_WR(sc, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
5321                             port * 4, 1);
5322                         REG_WR(sc, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port * 4,
5323                             value);
5324                 }
5325                 break;
5326         default:
5327                 DBPRINT(sc, BXE_VERBOSE_PHY,
5328         "bxe_override_led_value() unknown led index %d (should be 0-5)\n",
5329                     led_idx);
5330                 return (-EINVAL);
5331         }
5332
5333         return (0);
5334 }
5335
5336 uint8_t
5337 bxe_set_led(struct link_params *params, uint8_t mode, uint32_t speed)
5338 {
5339         struct bxe_softc *sc;
5340         uint32_t emac_base, ext_phy_type, tmp;
5341         uint16_t hw_led_mode;
5342         uint8_t port, rc;
5343
5344         sc = params->sc;
5345         port = params->port;
5346         hw_led_mode = params->hw_led_mode;
5347         rc = 0;
5348         emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
5349         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
5350
5351         switch (mode) {
5352         case LED_MODE_OFF:
5353                 REG_WR(sc, NIG_REG_LED_10G_P0 + port * 4, 0);
5354                 REG_WR(sc, NIG_REG_LED_MODE_P0 + port * 4,
5355                     SHARED_HW_CFG_LED_MAC1);
5356                 tmp = EMAC_RD(sc, EMAC_REG_EMAC_LED);
5357                 EMAC_WR(sc, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE));
5358                 break;
5359         case LED_MODE_OPER:
5360                 if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
5361                         REG_WR(sc, NIG_REG_LED_MODE_P0 + port * 4, 0);
5362                         REG_WR(sc, NIG_REG_LED_10G_P0 + port * 4, 1);
5363                 } else
5364                         REG_WR(sc, NIG_REG_LED_MODE_P0 + port * 4, hw_led_mode);
5365                 REG_WR(sc, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + port * 4,
5366                     0);
5367                 /* Set blinking rate to ~15.9Hz. */
5368                 REG_WR(sc, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port * 4,
5369                     LED_BLINK_RATE_VAL);
5370                 REG_WR(sc, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 + port * 4, 1);
5371                 tmp = EMAC_RD(sc, EMAC_REG_EMAC_LED);
5372                 EMAC_WR(sc, EMAC_REG_EMAC_LED, (tmp & (~EMAC_LED_OVERRIDE)));
5373
5374                 if (CHIP_IS_E1(sc) && ((speed == SPEED_2500) ||
5375                     (speed == SPEED_1000) || (speed == SPEED_100) ||
5376                     (speed == SPEED_10))) {
5377                         /*
5378                          * On Everest 1 Ax chip versions for speeds less than
5379                          * 10G LED scheme is different.
5380                          */
5381                         REG_WR(sc, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
5382                             port * 4, 1);
5383                         REG_WR(sc, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port * 4,
5384                             0);
5385                         REG_WR(sc, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
5386                             port * 4, 1);
5387                 }
5388                 break;
5389         default:
5390                 rc = -EINVAL;
5391                 DBPRINT(sc, BXE_VERBOSE_PHY,
5392                     "%s(): Invalid led mode (%d)!\n", __FUNCTION__, mode);
5393                 break;
5394         }
5395         return (rc);
5396 }
5397
5398 uint8_t
5399 bxe_test_link(struct link_params *params, struct link_vars *vars)
5400 {
5401         struct bxe_softc *sc;
5402         uint16_t gp_status;
5403
5404         sc = params->sc;
5405         gp_status = 0;
5406         CL45_RD_OVER_CL22(sc, params->port, params->phy_addr,
5407             MDIO_REG_BANK_GP_STATUS, MDIO_GP_STATUS_TOP_AN_STATUS1, &gp_status);
5408         /* Link is up only if both local phy and external phy are up. */
5409         if ((gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) &&
5410             bxe_ext_phy_is_link_up(params, vars, 1))
5411                 return (0);
5412
5413         return (-EINVAL);
5414 }
5415
5416 static uint8_t
5417 bxe_link_initialize(struct link_params *params, struct link_vars *vars)
5418 {
5419         struct bxe_softc *sc;
5420         uint32_t ext_phy_type;
5421         uint8_t port, rc;
5422         uint8_t non_ext_phy;
5423
5424         sc = params->sc;
5425         port = params->port;
5426         rc = 0;
5427         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
5428
5429         /* Activate the external PHY. */
5430         bxe_ext_phy_reset(params, vars);
5431
5432         bxe_set_aer_mmd(params, vars);
5433
5434         if (vars->phy_flags & PHY_XGXS_FLAG)
5435                 bxe_set_master_ln(params);
5436
5437         rc = bxe_reset_unicore(params);
5438         /* Reset the SerDes and wait for reset bit return low. */
5439         if (rc != 0)
5440                 return (rc);
5441
5442         bxe_set_aer_mmd(params, vars);
5443
5444         /* Setting the masterLn_def again after the reset. */
5445         if (vars->phy_flags & PHY_XGXS_FLAG) {
5446                 bxe_set_master_ln(params);
5447                 bxe_set_swap_lanes(params);
5448         }
5449
5450         if (vars->phy_flags & PHY_XGXS_FLAG) {
5451                 if ((params->req_line_speed &&
5452                     ((params->req_line_speed == SPEED_100) ||
5453                     (params->req_line_speed == SPEED_10))) ||
5454                     (!params->req_line_speed &&
5455                     (params->speed_cap_mask >=
5456                     PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
5457                     (params->speed_cap_mask <
5458                     PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)))
5459                         vars->phy_flags |= PHY_SGMII_FLAG;
5460                 else
5461                         vars->phy_flags &= ~PHY_SGMII_FLAG;
5462         }
5463         /*
5464          * In case of external phy existance, the line speed would be the
5465          * line speed linked up by the external phy. In case it is direct
5466          * only, then the line_speed during initialization will be equal
5467          * to the req_line_speed.
5468          */
5469         vars->line_speed = params->req_line_speed;
5470
5471         bxe_calc_ieee_aneg_adv(params, &vars->ieee_fc);
5472
5473         /* Init ext phy and enable link state int. */
5474         non_ext_phy = ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
5475             (params->loopback_mode == LOOPBACK_XGXS_10));
5476
5477         if (non_ext_phy ||
5478             (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) ||
5479             (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) ||
5480             (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) ||
5481             (params->loopback_mode == LOOPBACK_EXT_PHY)) {
5482                 if (params->req_line_speed == SPEED_AUTO_NEG)
5483                         bxe_set_parallel_detection(params, vars->phy_flags);
5484                 bxe_init_internal_phy(params, vars, 0);
5485         }
5486
5487         if (!non_ext_phy)
5488                 rc |= bxe_ext_phy_init(params, vars);
5489
5490         bxe_bits_dis(sc, NIG_REG_STATUS_INTERRUPT_PORT0 + port * 4,
5491             (NIG_STATUS_XGXS0_LINK10G | NIG_STATUS_XGXS0_LINK_STATUS |
5492             NIG_STATUS_SERDES0_LINK_STATUS));
5493
5494         return (rc);
5495 }
5496
5497 uint8_t
5498 bxe_phy_init(struct link_params *params, struct link_vars *vars)
5499 {
5500         struct bxe_softc *sc;
5501         uint32_t val;
5502
5503         sc = params->sc;
5504         DBPRINT(sc, BXE_VERBOSE_PHY, "Phy Initialization started\n");
5505         DBPRINT(sc, BXE_VERBOSE_PHY, "req_speed %d, req_flowctrl %d\n",
5506             params->req_line_speed, params->req_flow_ctrl);
5507         vars->link_status = 0;
5508         vars->phy_link_up = 0;
5509         vars->link_up = 0;
5510         vars->line_speed = 0;
5511         vars->duplex = DUPLEX_FULL;
5512         vars->flow_ctrl = FLOW_CTRL_NONE;
5513         vars->mac_type = MAC_TYPE_NONE;
5514
5515         if (params->switch_cfg ==  SWITCH_CFG_1G)
5516                 vars->phy_flags = PHY_SERDES_FLAG;
5517         else
5518                 vars->phy_flags = PHY_XGXS_FLAG;
5519
5520         /* disable attentions */
5521         bxe_bits_dis(sc, NIG_REG_MASK_INTERRUPT_PORT0 + params->port * 4,
5522             (NIG_MASK_XGXS0_LINK_STATUS | NIG_MASK_XGXS0_LINK10G |
5523             NIG_MASK_SERDES0_LINK_STATUS | NIG_MASK_MI_INT));
5524
5525         bxe_emac_init(params, vars);
5526
5527         if (params->loopback_mode == LOOPBACK_BMAC) {
5528                 vars->link_up = 1;
5529                 vars->line_speed = SPEED_10000;
5530                 vars->duplex = DUPLEX_FULL;
5531                 vars->flow_ctrl = FLOW_CTRL_NONE;
5532                 vars->mac_type = MAC_TYPE_BMAC;
5533
5534                 vars->phy_flags = PHY_XGXS_FLAG;
5535
5536                 bxe_phy_deassert(params, vars->phy_flags);
5537                 /* Set bmac loopback. */
5538                 bxe_bmac_enable(params, vars, 1);
5539
5540                 REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0);
5541         } else if (params->loopback_mode == LOOPBACK_EMAC) {
5542                 vars->link_up = 1;
5543                 vars->line_speed = SPEED_1000;
5544                 vars->duplex = DUPLEX_FULL;
5545                 vars->flow_ctrl = FLOW_CTRL_NONE;
5546                 vars->mac_type = MAC_TYPE_EMAC;
5547
5548                 vars->phy_flags = PHY_XGXS_FLAG;
5549
5550                 bxe_phy_deassert(params, vars->phy_flags);
5551                 /* Set bmac loopback. */
5552                 bxe_emac_enable(params, vars, 1);
5553                 bxe_emac_program(params, vars->line_speed, vars->duplex);
5554                 REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0);
5555         } else if ((params->loopback_mode == LOOPBACK_XGXS_10) ||
5556             (params->loopback_mode == LOOPBACK_EXT_PHY)) {
5557                 vars->link_up = 1;
5558                 vars->line_speed = SPEED_10000;
5559                 vars->duplex = DUPLEX_FULL;
5560                 vars->flow_ctrl = FLOW_CTRL_NONE;
5561
5562                 vars->phy_flags = PHY_XGXS_FLAG;
5563
5564                 val = REG_RD(sc, NIG_REG_XGXS0_CTRL_PHY_ADDR +
5565                     params->port * 0x18);
5566                 params->phy_addr = (uint8_t)val;
5567
5568                 bxe_phy_deassert(params, vars->phy_flags);
5569                 bxe_link_initialize(params, vars);
5570
5571                 vars->mac_type = MAC_TYPE_BMAC;
5572
5573                 bxe_bmac_enable(params, vars, 0);
5574
5575                 if (params->loopback_mode == LOOPBACK_XGXS_10) {
5576                         /* Set 10G XGXS loopback. */
5577                         bxe_set_xgxs_loopback(params, vars, 1);
5578                 } else {
5579                         /* Set external phy loopback. */
5580                         bxe_ext_phy_loopback(params);
5581                 }
5582                 REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0);
5583                 bxe_set_led(params, LED_MODE_OPER, vars->line_speed);
5584         } else {
5585                 /* No loopback. */
5586                 bxe_phy_deassert(params, vars->phy_flags);
5587                 switch (params->switch_cfg) {
5588                 case SWITCH_CFG_1G:
5589                         vars->phy_flags |= PHY_SERDES_FLAG;
5590                         if ((params->ext_phy_config &
5591                             PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK) ==
5592                             PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482) {
5593                                 vars->phy_flags |= PHY_SGMII_FLAG;
5594                         }
5595
5596                         val = REG_RD(sc, NIG_REG_SERDES0_CTRL_PHY_ADDR +
5597                             params->port * 0x10);
5598                         params->phy_addr = (uint8_t)val;
5599                         break;
5600                 case SWITCH_CFG_10G:
5601                         vars->phy_flags |= PHY_XGXS_FLAG;
5602                         val = REG_RD(sc, NIG_REG_XGXS0_CTRL_PHY_ADDR +
5603                             params->port * 0x18);
5604                         params->phy_addr = (uint8_t)val;
5605                         break;
5606                 default:
5607                         DBPRINT(sc, BXE_VERBOSE_PHY, "Invalid switch_cfg\n");
5608                         return (-EINVAL);
5609                 }
5610                 DBPRINT(sc, BXE_VERBOSE_PHY, "Phy address = 0x%x\n",
5611                     params->phy_addr);
5612
5613                 bxe_link_initialize(params, vars);
5614                 msleep(30);
5615                 bxe_link_int_enable(params);
5616         }
5617         return (0);
5618 }
5619
5620 static void
5621 bxe_8726_reset_phy(struct bxe_softc *sc, uint8_t port, uint8_t ext_phy_addr)
5622 {
5623
5624         DBPRINT(sc, BXE_VERBOSE_PHY, "bxe_8726_reset_phy port %d\n", port);
5625
5626         /* Set serial boot control for external load. */
5627         bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
5628             ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x0001);
5629 }
5630
5631 uint8_t
5632 bxe_link_reset(struct link_params *params, struct link_vars *vars,
5633     uint8_t reset_ext_phy)
5634 {
5635         struct bxe_softc *sc;
5636         uint32_t ext_phy_config, ext_phy_type, val;
5637         uint8_t ext_phy_addr, port;
5638
5639         sc = params->sc;
5640         ext_phy_config = params->ext_phy_config;
5641         port = params->port;
5642         ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
5643         val = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region,
5644             dev_info.port_feature_config[params->port].config));
5645
5646         DBPRINT(sc, BXE_INFO, "%s(): Resetting port %d link.\n",
5647             __FUNCTION__, port);
5648
5649         /* Disable attentions. */
5650         vars->link_status = 0;
5651         bxe_update_mng(params, vars->link_status);
5652         bxe_bits_dis(sc, NIG_REG_MASK_INTERRUPT_PORT0 + port * 4,
5653             (NIG_MASK_XGXS0_LINK_STATUS | NIG_MASK_XGXS0_LINK10G |
5654             NIG_MASK_SERDES0_LINK_STATUS | NIG_MASK_MI_INT));
5655
5656         /* Activate nig drain. */
5657         REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + port * 4, 1);
5658
5659         /* Disable nig egress interface. */
5660         REG_WR(sc, NIG_REG_BMAC0_OUT_EN + port * 4, 0);
5661         REG_WR(sc, NIG_REG_EGRESS_EMAC0_OUT_EN + port * 4, 0);
5662
5663         /* Stop BigMac rx. */
5664         bxe_bmac_rx_disable(sc, params->chip_id, port);
5665
5666         /* Disable emac. */
5667         REG_WR(sc, NIG_REG_NIG_EMAC0_EN + port * 4, 0);
5668
5669         msleep(10);
5670         /* The PHY reset is controled by GPIO 1 Hold it as vars low. */
5671          /* Clear link led. */
5672         bxe_set_led(params, LED_MODE_OFF, 0);
5673         if (reset_ext_phy) {
5674                 switch (ext_phy_type) {
5675                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
5676                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
5677                         break;
5678                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
5679                         /* Disable Transmitter */
5680                         ext_phy_addr =
5681                             XGXS_EXT_PHY_ADDR(params->ext_phy_config);
5682                         if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
5683                             PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
5684                                 bxe_sfp_set_transmitter(sc, port,
5685                                     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
5686                                     ext_phy_addr, 0);
5687                         break;
5688                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
5689                         DBPRINT(sc, BXE_VERBOSE_PHY,
5690                             "Setting 8073 port %d into low power mode\n",
5691                             port);
5692                         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_2,
5693                             MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
5694                         break;
5695                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
5696                         ext_phy_addr =
5697                             XGXS_EXT_PHY_ADDR(params->ext_phy_config);
5698                         /* Set soft reset. */
5699                         bxe_8726_reset_phy(sc, params->port, ext_phy_addr);
5700                         break;
5701                 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
5702                         ext_phy_addr =
5703                             XGXS_EXT_PHY_ADDR(params->ext_phy_config);
5704                         bxe_cl45_write(sc, port,
5705                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481, ext_phy_addr,
5706                             MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
5707                         bxe_cl45_write(sc, port,
5708                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481, ext_phy_addr,
5709                             MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1);
5710                         break;
5711                 default:
5712                         /* HW reset */
5713                         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_1,
5714                             MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
5715                         bxe_set_gpio(sc, MISC_REGISTERS_GPIO_2,
5716                             MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
5717                         DBPRINT(sc, BXE_VERBOSE_PHY, "reset external PHY\n");
5718                 }
5719         }
5720         /* Reset the SerDes/XGXS. */
5721         REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
5722             (0x1ff << (port * 16)));
5723
5724         /* Reset BigMac. */
5725         REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
5726             (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
5727
5728         /* Disable nig ingress interface. */
5729         REG_WR(sc, NIG_REG_BMAC0_IN_EN + port * 4, 0);
5730         REG_WR(sc, NIG_REG_EMAC0_IN_EN + port * 4, 0);
5731         REG_WR(sc, NIG_REG_BMAC0_OUT_EN + port * 4, 0);
5732         REG_WR(sc, NIG_REG_EGRESS_EMAC0_OUT_EN + port * 4, 0);
5733         vars->link_up = 0;
5734         return (0);
5735 }
5736
5737 static uint8_t
5738 bxe_update_link_down(struct link_params *params, struct link_vars *vars)
5739 {
5740         struct bxe_softc *sc;
5741         uint8_t port;
5742
5743         sc = params->sc;
5744         port = params->port;
5745
5746         DBPRINT(sc, BXE_INFO, "Port %x: Link is down\n", port);
5747         bxe_set_led(params, LED_MODE_OFF, 0);
5748
5749         /* Indicate no mac active. */
5750         vars->mac_type = MAC_TYPE_NONE;
5751
5752         /* Update shared memory. */
5753         vars->link_status = 0;
5754         vars->line_speed = 0;
5755         bxe_update_mng(params, vars->link_status);
5756
5757         /* Activate nig drain. */
5758         REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + port * 4, 1);
5759
5760         /* Disable emac. */
5761         REG_WR(sc, NIG_REG_NIG_EMAC0_EN + port * 4, 0);
5762
5763         msleep(10);
5764
5765         /* Reset BigMac. */
5766         bxe_bmac_rx_disable(sc, params->chip_id, params->port);
5767         REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
5768             (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
5769         return (0);
5770 }
5771
5772 static uint8_t
5773 bxe_update_link_up(struct link_params *params, struct link_vars *vars,
5774     uint8_t link_10g, uint32_t gp_status)
5775 {
5776         struct bxe_softc *sc;
5777         uint8_t port, rc;
5778
5779         sc = params->sc;
5780         port = params->port;
5781         rc = 0;
5782
5783         vars->link_status |= LINK_STATUS_LINK_UP;
5784         if (link_10g) {
5785                 bxe_bmac_enable(params, vars, 0);
5786                 bxe_set_led(params, LED_MODE_OPER, SPEED_10000);
5787         } else {
5788                 rc = bxe_emac_program(params, vars->line_speed, vars->duplex);
5789                 bxe_emac_enable(params, vars, 0);
5790                 /* AN complete? */
5791                 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
5792                         if (!(vars->phy_flags & PHY_SGMII_FLAG))
5793                                 bxe_set_gmii_tx_driver(params);
5794                 }
5795         }
5796
5797         /* PBF - link up */
5798         rc |= bxe_pbf_update(params, vars->flow_ctrl, vars->line_speed);
5799
5800         /* Disable drain. */
5801         REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + port * 4, 0);
5802
5803         /* Update shared memory. */
5804         bxe_update_mng(params, vars->link_status);
5805         msleep(20);
5806         return (rc);
5807 }
5808
5809 /*
5810  * This function should called upon link interrupt.
5811  * In case vars->link_up, driver needs to
5812  *      1. Update the pbf
5813  *      2. Disable drain
5814  *      3. Update the shared memory
5815  *      4. Indicate link up
5816  *      5. Set LEDs
5817  *  Otherwise,
5818  *      1. Update shared memory
5819  *      2. Reset BigMac
5820  *      3. Report link down
5821  *      4. Unset LEDs
5822  */
5823 uint8_t
5824 bxe_link_update(struct link_params *params, struct link_vars *vars)
5825 {
5826         struct bxe_softc *sc;
5827         uint32_t ext_phy_type;
5828         uint16_t gp_status;
5829         uint8_t link_10g, port;
5830         uint8_t ext_phy_link_up, rc;
5831         uint8_t is_mi_int;
5832
5833         sc = params->sc;
5834         port = params->port;
5835         rc = 0;
5836         is_mi_int = 0;
5837
5838         DBPRINT(sc, BXE_VERBOSE_PHY, "port %x, XGXS?%x, int_status 0x%x\n",
5839             port, (vars->phy_flags & PHY_XGXS_FLAG), REG_RD(sc,
5840             NIG_REG_STATUS_INTERRUPT_PORT0 + port * 4));
5841
5842         is_mi_int = (uint8_t)(REG_RD(sc, NIG_REG_EMAC0_STATUS_MISC_MI_INT +
5843             port * 0x18) > 0);
5844         DBPRINT(sc, BXE_VERBOSE_PHY,
5845             "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n", REG_RD(sc,
5846             NIG_REG_MASK_INTERRUPT_PORT0 + port * 4), is_mi_int, REG_RD(sc,
5847             NIG_REG_SERDES0_STATUS_LINK_STATUS + port * 0x3c));
5848
5849         DBPRINT(sc, BXE_VERBOSE_PHY, " 10G %x, XGXS_LINK %x\n",
5850             REG_RD(sc, NIG_REG_XGXS0_STATUS_LINK10G + port * 0x68),
5851             REG_RD(sc, NIG_REG_XGXS0_STATUS_LINK_STATUS + port * 0x68));
5852
5853         /* Disable emac. */
5854         REG_WR(sc, NIG_REG_NIG_EMAC0_EN + port * 4, 0);
5855
5856         ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
5857
5858         /* Check external link change only for non-direct. */
5859         ext_phy_link_up = bxe_ext_phy_is_link_up(params, vars, is_mi_int);
5860
5861         /* Read gp_status. */
5862         CL45_RD_OVER_CL22(sc, port, params->phy_addr, MDIO_REG_BANK_GP_STATUS,
5863             MDIO_GP_STATUS_TOP_AN_STATUS1, &gp_status);
5864
5865         rc = bxe_link_settings_status(params, vars, gp_status, ext_phy_link_up);
5866         if (rc != 0)
5867                 return (rc);
5868
5869         /* Anything 10 and over uses the bmac. */
5870         link_10g = ((vars->line_speed == SPEED_10000) ||
5871             (vars->line_speed == SPEED_12000) ||
5872             (vars->line_speed == SPEED_12500) ||
5873             (vars->line_speed == SPEED_13000) ||
5874             (vars->line_speed == SPEED_15000) ||
5875             (vars->line_speed == SPEED_16000));
5876
5877         bxe_link_int_ack(params, vars, link_10g, is_mi_int);
5878
5879         /*
5880          * In case external phy link is up, and internal link is down,
5881          * not initialized yet probably after link initialization, it
5882          * needs to be initialized.
5883          * Note that after link down-up as result of cable plug,
5884          * the xgxs link would probably become up again without the need
5885          * to initialize it.
5886          */
5887         if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
5888             (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) &&
5889             (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) &&
5890             (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) &&
5891             (ext_phy_link_up && !vars->phy_link_up)) {
5892                         bxe_init_internal_phy(params, vars, 0);
5893         }
5894
5895         /* Link is up only if both local phy and external phy are up. */
5896         vars->link_up = (ext_phy_link_up && vars->phy_link_up);
5897         if (vars->link_up)
5898                 rc = bxe_update_link_up(params, vars, link_10g, gp_status);
5899         else
5900                 rc = bxe_update_link_down(params, vars);
5901
5902         return (rc);
5903 }
5904
5905 static uint8_t
5906 bxe_8073_common_init_phy(struct bxe_softc *sc, uint32_t shmem_base)
5907 {
5908         uint32_t ext_phy_config;
5909         uint16_t fw_ver1, val;
5910         uint8_t ext_phy_addr[PORT_MAX];
5911         int port;
5912
5913         /* PART1 - Reset both phys. */
5914         for (port = PORT_MAX - 1; port >= PORT_0; port--) {
5915                 /* Extract the ext phy address for the port. */
5916                 ext_phy_config = REG_RD(sc, shmem_base +
5917                     offsetof(struct shmem_region,
5918                     dev_info.port_hw_config[port].external_phy_config));
5919
5920                 /* Disable attentions. */
5921                 bxe_bits_dis(sc, NIG_REG_MASK_INTERRUPT_PORT0 + port * 4,
5922                     (NIG_MASK_XGXS0_LINK_STATUS | NIG_MASK_XGXS0_LINK10G |
5923                     NIG_MASK_SERDES0_LINK_STATUS | NIG_MASK_MI_INT));
5924
5925                 ext_phy_addr[port] = XGXS_EXT_PHY_ADDR(ext_phy_config);
5926
5927                 /*
5928                  * Need to take the phy out of low power mode in order
5929                  * to write to access its registers.
5930                  */
5931                 bxe_set_gpio(sc, MISC_REGISTERS_GPIO_2,
5932                     MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
5933
5934                 /* Reset the phy. */
5935                 bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
5936                     ext_phy_addr[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL,
5937                     1 << 15);
5938         }
5939
5940         /* Add delay of 150ms after reset. */
5941         msleep(150);
5942
5943         /* PART2 - Download firmware to both phys. */
5944         for (port = PORT_MAX - 1; port >= PORT_0; port--) {
5945                 bxe_bcm8073_external_rom_boot(sc, port, ext_phy_addr[port],
5946                     shmem_base);
5947                 bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
5948                     ext_phy_addr[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1,
5949                     &fw_ver1);
5950                 if (fw_ver1 == 0 || fw_ver1 == 0x4321) {
5951                         DBPRINT(sc, BXE_VERBOSE_PHY,
5952                             "bxe_8073_common_init_phy port %x:"
5953                             "Download failed. fw version = 0x%x\n", port,
5954                             fw_ver1);
5955                         return (-EINVAL);
5956                 }
5957
5958                 /* Only set bit 10 = 1 (Tx power down). */
5959                 bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
5960                     ext_phy_addr[port], MDIO_PMA_DEVAD,
5961                     MDIO_PMA_REG_TX_POWER_DOWN, &val);
5962
5963                 /* Phase1 of TX_POWER_DOWN reset. */
5964                 bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
5965                     ext_phy_addr[port], MDIO_PMA_DEVAD,
5966                     MDIO_PMA_REG_TX_POWER_DOWN, (val | 1 << 10));
5967         }
5968
5969         /*
5970          * Toggle Transmitter: Power down and then up with 600ms
5971          * delay between.
5972          */
5973         msleep(600);
5974
5975         /* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low. */
5976         for (port = PORT_MAX - 1; port >= PORT_0; port--) {
5977                 /* Phase2 of POWER_DOWN_RESET */
5978                 /* Release bit 10 (Release Tx power down). */
5979                 bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
5980                     ext_phy_addr[port], MDIO_PMA_DEVAD,
5981                     MDIO_PMA_REG_TX_POWER_DOWN, &val);
5982
5983                 bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
5984                     ext_phy_addr[port], MDIO_PMA_DEVAD,
5985                     MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1 << 10))));
5986                 msleep(15);
5987
5988                 /* Read modify write the SPI-ROM version select register. */
5989                 bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
5990                     ext_phy_addr[port], MDIO_PMA_DEVAD,
5991                     MDIO_PMA_REG_EDC_FFE_MAIN, &val);
5992                 bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
5993                     ext_phy_addr[port], MDIO_PMA_DEVAD,
5994                     MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1 << 12)));
5995
5996                 /* Set GPIO2 back to LOW. */
5997                 bxe_set_gpio(sc, MISC_REGISTERS_GPIO_2,
5998                      MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
5999         }
6000         return (0);
6001 }
6002
6003 static uint8_t
6004 bxe_8727_common_init_phy(struct bxe_softc *sc, uint32_t shmem_base)
6005 {
6006         uint32_t swap_val, swap_override;
6007         uint32_t ext_phy_config;
6008         uint16_t fw_ver1;
6009         uint8_t ext_phy_addr[PORT_MAX];
6010         uint8_t port, first_port, i;
6011
6012         DBPRINT(sc, BXE_VERBOSE_PHY, "Executing BCM8727 common init\n");
6013         swap_val = REG_RD(sc,  NIG_REG_PORT_SWAP);
6014         swap_override = REG_RD(sc,  NIG_REG_STRAP_OVERRIDE);
6015
6016         bxe_ext_phy_hw_reset(sc, 1 ^ (swap_val && swap_override));
6017         msleep(5);
6018
6019         if (swap_val && swap_override)
6020                 first_port = PORT_0;
6021         else
6022                 first_port = PORT_1;
6023         /* PART1 - Reset both phys. */
6024         for (i = 0, port = first_port; i < PORT_MAX; i++, port = !port) {
6025                 /* Extract the ext phy address for the port. */
6026                 ext_phy_config = REG_RD(sc, shmem_base +
6027                     offsetof(struct shmem_region,
6028                     dev_info.port_hw_config[port].external_phy_config));
6029
6030                 /* Disable attentions. */
6031                 bxe_bits_dis(sc, NIG_REG_MASK_INTERRUPT_PORT0 + port * 4,
6032                     (NIG_MASK_XGXS0_LINK_STATUS | NIG_MASK_XGXS0_LINK10G |
6033                     NIG_MASK_SERDES0_LINK_STATUS | NIG_MASK_MI_INT));
6034
6035                 ext_phy_addr[port] = XGXS_EXT_PHY_ADDR(ext_phy_config);
6036
6037                 /* Reset the phy. */
6038                 bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
6039                     ext_phy_addr[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL,
6040                     1 << 15);
6041         }
6042
6043         /* Add delay of 150ms after reset. */
6044         msleep(150);
6045
6046         /* PART2 - Download firmware to both phys. */
6047         for (i = 0, port = first_port; i < PORT_MAX; i++, port = !port) {
6048                 bxe_bcm8727_external_rom_boot(sc, port, ext_phy_addr[port],
6049                     shmem_base);
6050                 bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
6051                     ext_phy_addr[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1,
6052                     &fw_ver1);
6053                 if (fw_ver1 == 0 || fw_ver1 == 0x4321) {
6054                         DBPRINT(sc, 1/*BXE_VERBOSE_PHY*/,
6055                             "bxe_8727_common_init_phy port %x:"
6056                             "Download failed. fw version = 0x%x\n", port,
6057                             fw_ver1);
6058                         return (-EINVAL);
6059                 }
6060         }
6061
6062         return (0);
6063 }
6064
6065 static uint8_t
6066 bxe_8726_common_init_phy(struct bxe_softc *sc, uint32_t shmem_base)
6067 {
6068         uint32_t ext_phy_config, val;
6069         uint8_t ext_phy_addr;
6070         uint8_t port;
6071
6072         /* Use port1 because of the static port-swap. */
6073         /* Enable the module detection interrupt. */
6074         val = REG_RD(sc, MISC_REG_GPIO_EVENT_EN);
6075         val |= ((1 << MISC_REGISTERS_GPIO_3) | (1 << (MISC_REGISTERS_GPIO_3 +
6076             MISC_REGISTERS_GPIO_PORT_SHIFT)));
6077         REG_WR(sc, MISC_REG_GPIO_EVENT_EN, val);
6078
6079         bxe_ext_phy_hw_reset(sc, 1);
6080         msleep(5);
6081         for (port = 0; port < PORT_MAX; port++) {
6082                 /* Extract the ext phy address for the port. */
6083                 ext_phy_config = REG_RD(sc, shmem_base +
6084                     offsetof(struct shmem_region,
6085                     dev_info.port_hw_config[port].external_phy_config));
6086
6087                 ext_phy_addr = XGXS_EXT_PHY_ADDR(ext_phy_config);
6088                 DBPRINT(sc, BXE_VERBOSE_PHY,
6089                     "8726_common_init : ext_phy_addr = 0x%x\n", ext_phy_addr);
6090
6091                 bxe_8726_reset_phy(sc, port, ext_phy_addr);
6092
6093                 /* Set fault module detected LED on. */
6094                 bxe_set_gpio(sc, MISC_REGISTERS_GPIO_0,
6095                     MISC_REGISTERS_GPIO_HIGH, port);
6096         }
6097
6098         return (0);
6099 }
6100
6101 static uint8_t
6102 bxe_84823_common_init_phy(struct bxe_softc *sc, uint32_t shmem_base)
6103 {
6104
6105         bxe_ext_phy_hw_reset(sc, 1);
6106         return (0);
6107 }
6108
6109 uint8_t
6110 bxe_common_init_phy(struct bxe_softc *sc, uint32_t shmem_base)
6111 {
6112         uint32_t ext_phy_type;
6113         uint8_t rc;
6114
6115         DBPRINT(sc, BXE_VERBOSE_PHY, "Begin common phy init\n");
6116
6117         rc = 0;
6118         ext_phy_type = 0;
6119         /* Read the ext_phy_type for arbitrary port(0) */
6120         ext_phy_type = XGXS_EXT_PHY_TYPE( REG_RD(sc, shmem_base +
6121             offsetof(struct shmem_region,
6122             dev_info.port_hw_config[0].external_phy_config)));
6123
6124         switch (ext_phy_type) {
6125         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
6126                 rc = bxe_8073_common_init_phy(sc, shmem_base);
6127                 break;
6128         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
6129         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
6130                 rc = bxe_8727_common_init_phy(sc, shmem_base);
6131                 break;
6132         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
6133                 /*
6134                  * GPIO1 affects both ports, so there's need to pull
6135                  * it for single port alone.
6136                  */
6137                 rc = bxe_8726_common_init_phy(sc, shmem_base);
6138                 break;
6139         case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
6140                 rc = bxe_84823_common_init_phy(sc, shmem_base);
6141                 break;
6142         default:
6143                 DBPRINT(sc, BXE_VERBOSE_PHY,
6144                     "bxe_common_init_phy: ext_phy 0x%x not required\n",
6145                     ext_phy_type);
6146                 break;
6147         }
6148
6149         return (rc);
6150 }
6151
6152 void
6153 bxe_sfx7101_sp_sw_reset(struct bxe_softc *sc, uint8_t port, uint8_t phy_addr)
6154 {
6155         uint16_t val, cnt;
6156
6157         bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101, phy_addr,
6158             MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_RESET, &val);
6159
6160         for (cnt = 0; cnt < 10; cnt++) {
6161                 msleep(50);
6162                 /* Writes a self-clearing reset. */
6163                 bxe_cl45_write(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
6164                     phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_RESET,
6165                     (val | (1 << 15)));
6166                 /* Wait for clear. */
6167                 bxe_cl45_read(sc, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
6168                     phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_RESET, &val);
6169                 if ((val & (1 << 15)) == 0)
6170                         break;
6171         }
6172 }