1 #ifdef __LINUX
2 #include <linux/kernel.h>
3 #include <linux/types.h>
4 #include <asm/byteorder.h>
5 #endif
6 #ifdef USER_LINUX
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
13 #include <sys/ioctl.h>
14 #include <net/if.h>
15 #include <linux/sockios.h>
16 #include <string.h>
17 #include <malloc.h>
18 #endif
19 #ifdef __FreeBSD__
20 #include <sys/types.h>
21 #endif
22 #include "bcmtype.h"
23 #ifdef EDEBUG
24 #include "edebug_types.h"
25 #endif
26 #include "clc.h"
27 #include "grc_addr.h"
28 #include "bigmac_addresses.h"
29 #include "emac_reg_driver.h"
30 #include "misc_bits.h"
31 #include "57712_reg.h"
32 #include "clc_reg.h"
33 #include "dev_info.h"
34 #include "license.h"
35 #include "shmem.h"
36 #include "aeu_inputs.h"
37
38 typedef elink_status_t (*read_sfp_module_eeprom_func_p)(struct elink_phy *phy,
39 struct elink_params *params,
40 u8 dev_addr, u16 addr, u8 byte_cnt,
41 u8 *o_buf, u8);
42 /********************************************************/
43 #define ELINK_ETH_HLEN 14
44 /* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
45 #define ELINK_ETH_OVREHEAD (ELINK_ETH_HLEN + 8 + 8)
46 #define ELINK_ETH_MIN_PACKET_SIZE 60
47 #define ELINK_ETH_MAX_PACKET_SIZE 1500
48 #define ELINK_ETH_MAX_JUMBO_PACKET_SIZE 9600
49 #define ELINK_MDIO_ACCESS_TIMEOUT 1000
50 #define WC_LANE_MAX 4
51 #define I2C_SWITCH_WIDTH 2
52 #define I2C_BSC0 0
53 #define I2C_BSC1 1
54 #define I2C_WA_RETRY_CNT 3
55 #define I2C_WA_PWR_ITER (I2C_WA_RETRY_CNT - 1)
56 #define MCPR_IMC_COMMAND_READ_OP 1
57 #define MCPR_IMC_COMMAND_WRITE_OP 2
58
59 /* LED Blink rate that will achieve ~15.9Hz */
60 #define LED_BLINK_RATE_VAL_E3 354
61 #define LED_BLINK_RATE_VAL_E1X_E2 480
62 /***********************************************************/
63 /* Macros */
64 /***********************************************************/
65 #define MSLEEP(cb, ms) elink_cb_udelay(cb, 1000*ms)
66 #define USLEEP(cb, us) elink_cb_udelay(cb, us)
67 #define REG_RD(cb, reg) elink_cb_reg_read(cb, reg)
68 #define REG_WR(cb, reg, val) elink_cb_reg_write(cb, reg, val)
69 #define EMAC_RD(cb, reg) REG_RD(cb, emac_base + reg)
70 #define EMAC_WR(cb, reg, val) REG_WR(cb, emac_base + reg, val)
71 #define REG_WR_DMAE(cb, offset, wb_data, len) \
72 elink_cb_reg_wb_write(cb, offset, wb_data, len)
73 #define REG_RD_DMAE(cb, offset, wb_data, len) \
74 elink_cb_reg_wb_read(cb, offset, wb_data, len)
75 #define PATH_ID(cb) elink_cb_path_id(cb)
76
77 #define ELINK_SET_GPIO elink_cb_gpio_write
78 #define ELINK_SET_MULT_GPIO elink_cb_gpio_mult_write
79 #define ELINK_GET_GPIO elink_cb_gpio_read
80 #define ELINK_SET_GPIO_INT elink_cb_gpio_int_write
81
82 #ifndef OFFSETOF
83 #define OFFSETOF(_s, _m) ((u32) ((u8 *)(&((_s *) 0)->_m) - \
84 (u8 *)((u8 *) 0)))
85 #endif
86
87 #define CHIP_REV_SHIFT 12
88 #define CHIP_REV_MASK (0xF<<CHIP_REV_SHIFT)
89 #define CHIP_REV(_chip_id) ((_chip_id) & CHIP_REV_MASK)
90
91 #define CHIP_REV_Ax (0x0<<CHIP_REV_SHIFT)
92 #define CHIP_REV_Bx (0x1<<CHIP_REV_SHIFT)
93 #define CHIP_REV_IS_SLOW(_chip_id) \
94 (CHIP_REV(_chip_id) > 0x00005000)
95 #define CHIP_REV_IS_FPGA(_chip_id) \
96 (CHIP_REV_IS_SLOW(_chip_id)&& \
97 (CHIP_REV(_chip_id) & 0x00001000))
98 #define CHIP_REV_IS_EMUL(_chip_id) \
99 (CHIP_REV_IS_SLOW(_chip_id)&& \
100 !(CHIP_REV(_chip_id) & 0x00001000))
101
102 #define CHIP_NUM(_chip_id) (_chip_id >> 16)
103 #define CHIP_NUM_57710 0x164e
104 #define CHIP_NUM_57711 0x164f
105 #define CHIP_NUM_57711E 0x1650
106 #define CHIP_NUM_57712 0x1662
107 #define CHIP_NUM_57712E 0x1663
108 #define CHIP_NUM_57713 0x1651
109 #define CHIP_NUM_57713E 0x1652
110 #define CHIP_NUM_57840_OBSOLETE 0x168d
111 #define CHIP_NUM_57840_4_10 0x16a1
112 #define CHIP_NUM_57840_2_20 0x16a2
113 #define CHIP_NUM_57810 0x168e
114 #define CHIP_NUM_57800 0x168a
115 #define CHIP_NUM_57811 0x163d
116 #define CHIP_NUM_57811_MF 0x163e
117 #define CHIP_IS_E1(_chip_id) (CHIP_NUM(_chip_id) == \
118 CHIP_NUM_57710)
119 #define CHIP_IS_E1X(_chip_id) ((CHIP_NUM(_chip_id) == \
120 CHIP_NUM_57710) || \
121 (CHIP_NUM(_chip_id) == \
122 CHIP_NUM_57711) || \
123 (CHIP_NUM(_chip_id) == \
124 CHIP_NUM_57711E))
125
126 #define CHIP_IS_E2(_chip_id) ((CHIP_NUM(_chip_id) == \
127 CHIP_NUM_57712) || \
128 (CHIP_NUM(_chip_id) == \
129 CHIP_NUM_57712E) || \
130 (CHIP_NUM(_chip_id) == \
131 CHIP_NUM_57713) || \
132 (CHIP_NUM(_chip_id) == \
133 CHIP_NUM_57713E))
134
135 #define CHIP_IS_57711(_chip_id) (CHIP_NUM(_chip_id) == \
136 CHIP_NUM_57711)
137 #define CHIP_IS_57711E(_chip_id) (CHIP_NUM(_chip_id) == \
138 CHIP_NUM_57711E)
139 #define DO_CHIP_IS_E3(_chip_family) ((_chip_family == 0x1630) || \
140 (_chip_family == 0x1680) || \
141 (_chip_family == 0x16a0))
142 #define CHIP_IS_E3(_chip_id) (DO_CHIP_IS_E3(((CHIP_NUM(_chip_id)) & 0xfff0)))
143
144
145 /* For EMUL: Ax=0xE, Bx=0xC, Cx=0xA. For FPGA: Ax=0xF, Bx=0xD,
146 * Cx=0xB.
147 */
148 #define CHIP_REV_SIM(_p) (((0xF - (CHIP_REV(_p) >> CHIP_REV_SHIFT)) \
149 >>1) << CHIP_REV_SHIFT)
150
151 #define CHIP_IS_E3B0(_p) (CHIP_IS_E3(_p) && \
152 ((CHIP_REV(_p) == CHIP_REV_Bx) || \
153 (CHIP_REV_SIM(_p) == CHIP_REV_Bx)))
154
155 #define CHIP_IS_E3A0(_p) (CHIP_IS_E3(_p) && \
156 ((CHIP_REV(_p) == CHIP_REV_Ax) || \
157 (CHIP_REV_SIM(_p) == CHIP_REV_Ax)))
158
159 #define ELINK_USES_WARPCORE(_chip_id) (CHIP_IS_E3(_chip_id))
160
161 #define SHMEM2_RD(cb, shmem2_base, _field) \
162 REG_RD(cb, shmem2_base + \
163 OFFSETOF(struct shmem2_region, \
164 _field))
165
166 #define SHMEM2_HAS(cb, shmem2_base, field) (shmem2_base && \
167 (SHMEM2_RD(cb, shmem2_base, size) > \
168 OFFSETOF(struct shmem2_region, field)))
169 #ifndef NULL
170 #define NULL ((void *) 0)
171 #endif
172
173 /***********************************************************/
174 /* Shortcut definitions */
175 /***********************************************************/
176
177 #define ELINK_NIG_LATCH_BC_ENABLE_MI_INT 0
178
179 #define ELINK_NIG_STATUS_EMAC0_MI_INT \
180 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_INT
181 #define ELINK_NIG_STATUS_XGXS0_LINK10G \
182 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G
183 #define ELINK_NIG_STATUS_XGXS0_LINK_STATUS \
184 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS
185 #define ELINK_NIG_STATUS_XGXS0_LINK_STATUS_SIZE \
186 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE
187 #define ELINK_NIG_STATUS_SERDES0_LINK_STATUS \
188 NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS
189 #define ELINK_NIG_MASK_MI_INT \
190 NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT
191 #define ELINK_NIG_MASK_XGXS0_LINK10G \
192 NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G
193 #define ELINK_NIG_MASK_XGXS0_LINK_STATUS \
194 NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK_STATUS
195 #define ELINK_NIG_MASK_SERDES0_LINK_STATUS \
196 NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS
197
198 #define ELINK_MDIO_AN_CL73_OR_37_COMPLETE \
199 (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | \
200 MDIO_GP_STATUS_TOP_AN_STATUS1_CL37_AUTONEG_COMPLETE)
201
202 #define ELINK_XGXS_RESET_BITS \
203 (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW | \
204 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_IDDQ | \
205 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN | \
206 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN_SD | \
207 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB)
208
209 #define ELINK_SERDES_RESET_BITS \
210 (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_RSTB_HW | \
211 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ | \
212 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN | \
213 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN_SD)
214
215 #define ELINK_AUTONEG_CL37 SHARED_HW_CFG_AN_ENABLE_CL37
216 #define ELINK_AUTONEG_CL73 SHARED_HW_CFG_AN_ENABLE_CL73
217 #define ELINK_AUTONEG_BAM SHARED_HW_CFG_AN_ENABLE_BAM
218 #define ELINK_AUTONEG_PARALLEL \
219 SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
220 #define ELINK_AUTONEG_SGMII_FIBER_AUTODET \
221 SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT
222 #define ELINK_AUTONEG_REMOTE_PHY SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY
223
224 #define ELINK_GP_STATUS_PAUSE_RSOLUTION_TXSIDE \
225 MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE
226 #define ELINK_GP_STATUS_PAUSE_RSOLUTION_RXSIDE \
227 MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_RXSIDE
228 #define ELINK_GP_STATUS_SPEED_MASK \
229 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_MASK
230 #define ELINK_GP_STATUS_10M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10M
231 #define ELINK_GP_STATUS_100M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_100M
232 #define ELINK_GP_STATUS_1G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G
233 #define ELINK_GP_STATUS_2_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_2_5G
234 #define ELINK_GP_STATUS_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_5G
235 #define ELINK_GP_STATUS_6G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_6G
236 #define ELINK_GP_STATUS_10G_HIG \
237 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG
238 #define ELINK_GP_STATUS_10G_CX4 \
239 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4
240 #define ELINK_GP_STATUS_1G_KX MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX
241 #define ELINK_GP_STATUS_10G_KX4 \
242 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
243 #define ELINK_GP_STATUS_10G_KR MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KR
244 #define ELINK_GP_STATUS_10G_XFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI
245 #define ELINK_GP_STATUS_20G_DXGXS MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS
246 #define ELINK_GP_STATUS_10G_SFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI
247 #define ELINK_GP_STATUS_20G_KR2 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_KR2
248 #define ELINK_LINK_10THD LINK_STATUS_SPEED_AND_DUPLEX_10THD
249 #define ELINK_LINK_10TFD LINK_STATUS_SPEED_AND_DUPLEX_10TFD
250 #define ELINK_LINK_100TXHD LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
251 #define ELINK_LINK_100T4 LINK_STATUS_SPEED_AND_DUPLEX_100T4
252 #define ELINK_LINK_100TXFD LINK_STATUS_SPEED_AND_DUPLEX_100TXFD
253 #define ELINK_LINK_1000THD LINK_STATUS_SPEED_AND_DUPLEX_1000THD
254 #define ELINK_LINK_1000TFD LINK_STATUS_SPEED_AND_DUPLEX_1000TFD
255 #define ELINK_LINK_1000XFD LINK_STATUS_SPEED_AND_DUPLEX_1000XFD
256 #define ELINK_LINK_2500THD LINK_STATUS_SPEED_AND_DUPLEX_2500THD
257 #define ELINK_LINK_2500TFD LINK_STATUS_SPEED_AND_DUPLEX_2500TFD
258 #define ELINK_LINK_2500XFD LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
259 #define ELINK_LINK_10GTFD LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
260 #define ELINK_LINK_10GXFD LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
261 #define ELINK_LINK_20GTFD LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
262 #define ELINK_LINK_20GXFD LINK_STATUS_SPEED_AND_DUPLEX_20GXFD
263
264 #define ELINK_LINK_UPDATE_MASK \
265 (LINK_STATUS_SPEED_AND_DUPLEX_MASK | \
266 LINK_STATUS_LINK_UP | \
267 LINK_STATUS_PHYSICAL_LINK_FLAG | \
268 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | \
269 LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | \
270 LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | \
271 LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | \
272 LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \
273 LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)
274
275 #define ELINK_SFP_EEPROM_CON_TYPE_ADDR 0x2
276 #define ELINK_SFP_EEPROM_CON_TYPE_VAL_UNKNOWN 0x0
277 #define ELINK_SFP_EEPROM_CON_TYPE_VAL_LC 0x7
278 #define ELINK_SFP_EEPROM_CON_TYPE_VAL_COPPER 0x21
279 #define ELINK_SFP_EEPROM_CON_TYPE_VAL_RJ45 0x22
280
281
282 #define ELINK_SFP_EEPROM_10G_COMP_CODE_ADDR 0x3
283 #define ELINK_SFP_EEPROM_10G_COMP_CODE_SR_MASK (1<<4)
284 #define ELINK_SFP_EEPROM_10G_COMP_CODE_LR_MASK (1<<5)
285 #define ELINK_SFP_EEPROM_10G_COMP_CODE_LRM_MASK (1<<6)
286
287 #define ELINK_SFP_EEPROM_1G_COMP_CODE_ADDR 0x6
288 #define ELINK_SFP_EEPROM_1G_COMP_CODE_SX (1<<0)
289 #define ELINK_SFP_EEPROM_1G_COMP_CODE_LX (1<<1)
290 #define ELINK_SFP_EEPROM_1G_COMP_CODE_CX (1<<2)
291 #define ELINK_SFP_EEPROM_1G_COMP_CODE_BASE_T (1<<3)
292
293 #define ELINK_SFP_EEPROM_FC_TX_TECH_ADDR 0x8
294 #define ELINK_SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE 0x4
295 #define ELINK_SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE 0x8
296
297 #define ELINK_SFP_EEPROM_OPTIONS_ADDR 0x40
298 #define ELINK_SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK 0x1
299 #define ELINK_SFP_EEPROM_OPTIONS_SIZE 2
300
301 #define ELINK_EDC_MODE_LINEAR 0x0022
302 #define ELINK_EDC_MODE_LIMITING 0x0044
303 #define ELINK_EDC_MODE_PASSIVE_DAC 0x0055
304 #define ELINK_EDC_MODE_ACTIVE_DAC 0x0066
305
306 /* ETS defines*/
307 #define DCBX_INVALID_COS (0xFF)
308
309 #define ELINK_ETS_BW_LIMIT_CREDIT_UPPER_BOUND (0x5000)
310 #define ELINK_ETS_BW_LIMIT_CREDIT_WEIGHT (0x5000)
311 #define ELINK_ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS (1360)
312 #define ELINK_ETS_E3B0_NIG_MIN_W_VAL_20GBPS (2720)
313 #define ELINK_ETS_E3B0_PBF_MIN_W_VAL (10000)
314
315 #define ELINK_MAX_PACKET_SIZE (9700)
316 #ifdef INCLUDE_WARPCORE_UC_LOAD
317 #define ELINK_WC_UC_TIMEOUT 1000
318 #define ELINK_WC_RDY_TIMEOUT_MSEC 100
319 #endif
320 #define MAX_KR_LINK_RETRY 4
321
322 /**********************************************************/
323 /* INTERFACE */
324 /**********************************************************/
325
326 #define CL22_WR_OVER_CL45(_cb, _phy, _bank, _addr, _val) \
327 elink_cl45_write(_cb, _phy, \
328 (_phy)->def_md_devad, \
329 (_bank + (_addr & 0xf)), \
330 _val)
331
332 #define CL22_RD_OVER_CL45(_cb, _phy, _bank, _addr, _val) \
333 elink_cl45_read(_cb, _phy, \
334 (_phy)->def_md_devad, \
335 (_bank + (_addr & 0xf)), \
336 _val)
337
338 #ifdef BNX2X_ADD /* BNX2X_ADD */
339 static int elink_check_half_open_conn(struct elink_params *params,
340 struct elink_vars *vars, u8 notify);
341 static int elink_sfp_module_detection(struct elink_phy *phy,
342 struct elink_params *params);
343 #endif
344
elink_bits_en(struct elink_dev * cb,u32 reg,u32 bits)345 static u32 elink_bits_en(struct elink_dev *cb, u32 reg, u32 bits)
346 {
347 u32 val = REG_RD(cb, reg);
348
349 val |= bits;
350 REG_WR(cb, reg, val);
351 return val;
352 }
353
elink_bits_dis(struct elink_dev * cb,u32 reg,u32 bits)354 static u32 elink_bits_dis(struct elink_dev *cb, u32 reg, u32 bits)
355 {
356 u32 val = REG_RD(cb, reg);
357
358 val &= ~bits;
359 REG_WR(cb, reg, val);
360 return val;
361 }
362
363 /*
364 * elink_check_lfa - This function checks if link reinitialization is required,
365 * or link flap can be avoided.
366 *
367 * @params: link parameters
368 * Returns 0 if Link Flap Avoidance conditions are met otherwise, the failed
369 * condition code.
370 */
371 #ifndef EXCLUDE_NON_COMMON_INIT
elink_check_lfa(struct elink_params * params)372 static int elink_check_lfa(struct elink_params *params)
373 {
374 u32 link_status, cfg_idx, lfa_mask, cfg_size;
375 u32 cur_speed_cap_mask, cur_req_fc_auto_adv, additional_config;
376 u32 saved_val, req_val, eee_status;
377 struct elink_dev *cb = params->cb;
378
379 additional_config =
380 REG_RD(cb, params->lfa_base +
381 OFFSETOF(struct shmem_lfa, additional_config));
382
383 /* NOTE: must be first condition checked -
384 * to verify DCC bit is cleared in any case!
385 */
386 if (additional_config & NO_LFA_DUE_TO_DCC_MASK) {
387 ELINK_DEBUG_P0(cb, "No LFA due to DCC flap after clp exit\n");
388 REG_WR(cb, params->lfa_base +
389 OFFSETOF(struct shmem_lfa, additional_config),
390 additional_config & ~NO_LFA_DUE_TO_DCC_MASK);
391 return LFA_DCC_LFA_DISABLED;
392 }
393
394 /* Verify that link is up */
395 link_status = REG_RD(cb, params->shmem_base +
396 OFFSETOF(struct shmem_region,
397 port_mb[params->port].link_status));
398 if (!(link_status & LINK_STATUS_LINK_UP))
399 return LFA_LINK_DOWN;
400
401 /* if loaded after BOOT from SAN, don't flap the link in any case and
402 * rely on link set by preboot driver
403 */
404 if (params->feature_config_flags & ELINK_FEATURE_CONFIG_BOOT_FROM_SAN)
405 return 0;
406
407 /* Verify that loopback mode is not set */
408 if (params->loopback_mode)
409 return LFA_LOOPBACK_ENABLED;
410
411 /* Verify that MFW supports LFA */
412 if (!params->lfa_base)
413 return LFA_MFW_IS_TOO_OLD;
414
415 if (params->num_phys == 3) {
416 cfg_size = 2;
417 lfa_mask = 0xffffffff;
418 } else {
419 cfg_size = 1;
420 lfa_mask = 0xffff;
421 }
422
423 /* Compare Duplex */
424 saved_val = REG_RD(cb, params->lfa_base +
425 OFFSETOF(struct shmem_lfa, req_duplex));
426 req_val = params->req_duplex[0] | (params->req_duplex[1] << 16);
427 if ((saved_val & lfa_mask) != (req_val & lfa_mask)) {
428 ELINK_DEBUG_P2(cb, "Duplex mismatch %x vs. %x\n",
429 (saved_val & lfa_mask), (req_val & lfa_mask));
430 return LFA_DUPLEX_MISMATCH;
431 }
432 /* Compare Flow Control */
433 saved_val = REG_RD(cb, params->lfa_base +
434 OFFSETOF(struct shmem_lfa, req_flow_ctrl));
435 req_val = params->req_flow_ctrl[0] | (params->req_flow_ctrl[1] << 16);
436 if ((saved_val & lfa_mask) != (req_val & lfa_mask)) {
437 ELINK_DEBUG_P2(cb, "Flow control mismatch %x vs. %x\n",
438 (saved_val & lfa_mask), (req_val & lfa_mask));
439 return LFA_FLOW_CTRL_MISMATCH;
440 }
441 /* Compare Link Speed */
442 saved_val = REG_RD(cb, params->lfa_base +
443 OFFSETOF(struct shmem_lfa, req_line_speed));
444 req_val = params->req_line_speed[0] | (params->req_line_speed[1] << 16);
445 if ((saved_val & lfa_mask) != (req_val & lfa_mask)) {
446 ELINK_DEBUG_P2(cb, "Link speed mismatch %x vs. %x\n",
447 (saved_val & lfa_mask), (req_val & lfa_mask));
448 return LFA_LINK_SPEED_MISMATCH;
449 }
450
451 for (cfg_idx = 0; cfg_idx < cfg_size; cfg_idx++) {
452 cur_speed_cap_mask = REG_RD(cb, params->lfa_base +
453 OFFSETOF(struct shmem_lfa,
454 speed_cap_mask[cfg_idx]));
455
456 if (cur_speed_cap_mask != params->speed_cap_mask[cfg_idx]) {
457 ELINK_DEBUG_P2(cb, "Speed Cap mismatch %x vs. %x\n",
458 cur_speed_cap_mask,
459 params->speed_cap_mask[cfg_idx]);
460 return LFA_SPEED_CAP_MISMATCH;
461 }
462 }
463
464 cur_req_fc_auto_adv =
465 REG_RD(cb, params->lfa_base +
466 OFFSETOF(struct shmem_lfa, additional_config)) &
467 REQ_FC_AUTO_ADV_MASK;
468
469 if ((u16)cur_req_fc_auto_adv != params->req_fc_auto_adv) {
470 ELINK_DEBUG_P2(cb, "Flow Ctrl AN mismatch %x vs. %x\n",
471 cur_req_fc_auto_adv, params->req_fc_auto_adv);
472 return LFA_FLOW_CTRL_MISMATCH;
473 }
474
475 eee_status = REG_RD(cb, params->shmem2_base +
476 OFFSETOF(struct shmem2_region,
477 eee_status[params->port]));
478
479 if (((eee_status & SHMEM_EEE_LPI_REQUESTED_BIT) ^
480 (params->eee_mode & ELINK_EEE_MODE_ENABLE_LPI)) ||
481 ((eee_status & SHMEM_EEE_REQUESTED_BIT) ^
482 (params->eee_mode & ELINK_EEE_MODE_ADV_LPI))) {
483 ELINK_DEBUG_P2(cb, "EEE mismatch %x vs. %x\n", params->eee_mode,
484 eee_status);
485 return LFA_EEE_MISMATCH;
486 }
487
488 /* LFA conditions are met */
489 return 0;
490 }
491 #endif
492 /******************************************************************/
493 /* EPIO/GPIO section */
494 /******************************************************************/
495 #if (!defined EXCLUDE_WARPCORE)
elink_get_epio(struct elink_dev * cb,u32 epio_pin,u32 * en)496 static void elink_get_epio(struct elink_dev *cb, u32 epio_pin, u32 *en)
497 {
498 u32 epio_mask, gp_oenable;
499 *en = 0;
500 /* Sanity check */
501 if (epio_pin > 31) {
502 ELINK_DEBUG_P1(cb, "Invalid EPIO pin %d to get\n", epio_pin);
503 return;
504 }
505
506 epio_mask = 1 << epio_pin;
507 /* Set this EPIO to output */
508 gp_oenable = REG_RD(cb, MCP_REG_MCPR_GP_OENABLE);
509 REG_WR(cb, MCP_REG_MCPR_GP_OENABLE, gp_oenable & ~epio_mask);
510
511 *en = (REG_RD(cb, MCP_REG_MCPR_GP_INPUTS) & epio_mask) >> epio_pin;
512 }
elink_set_epio(struct elink_dev * cb,u32 epio_pin,u32 en)513 static void elink_set_epio(struct elink_dev *cb, u32 epio_pin, u32 en)
514 {
515 u32 epio_mask, gp_output, gp_oenable;
516
517 /* Sanity check */
518 if (epio_pin > 31) {
519 ELINK_DEBUG_P1(cb, "Invalid EPIO pin %d to set\n", epio_pin);
520 return;
521 }
522 ELINK_DEBUG_P2(cb, "Setting EPIO pin %d to %d\n", epio_pin, en);
523 epio_mask = 1 << epio_pin;
524 /* Set this EPIO to output */
525 gp_output = REG_RD(cb, MCP_REG_MCPR_GP_OUTPUTS);
526 if (en)
527 gp_output |= epio_mask;
528 else
529 gp_output &= ~epio_mask;
530
531 REG_WR(cb, MCP_REG_MCPR_GP_OUTPUTS, gp_output);
532
533 /* Set the value for this EPIO */
534 gp_oenable = REG_RD(cb, MCP_REG_MCPR_GP_OENABLE);
535 REG_WR(cb, MCP_REG_MCPR_GP_OENABLE, gp_oenable | epio_mask);
536 }
537
elink_set_cfg_pin(struct elink_dev * cb,u32 pin_cfg,u32 val)538 static void elink_set_cfg_pin(struct elink_dev *cb, u32 pin_cfg, u32 val)
539 {
540 if (pin_cfg == PIN_CFG_NA)
541 return;
542 if (pin_cfg >= PIN_CFG_EPIO0) {
543 elink_set_epio(cb, pin_cfg - PIN_CFG_EPIO0, val);
544 } else {
545 u8 gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3;
546 u8 gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2;
547 ELINK_SET_GPIO(cb, gpio_num, (u8)val, gpio_port);
548 }
549 }
550
elink_get_cfg_pin(struct elink_dev * cb,u32 pin_cfg,u32 * val)551 static u32 elink_get_cfg_pin(struct elink_dev *cb, u32 pin_cfg, u32 *val)
552 {
553 if (pin_cfg == PIN_CFG_NA)
554 return ELINK_STATUS_ERROR;
555 if (pin_cfg >= PIN_CFG_EPIO0) {
556 elink_get_epio(cb, pin_cfg - PIN_CFG_EPIO0, val);
557 } else {
558 u8 gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3;
559 u8 gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2;
560 *val = ELINK_GET_GPIO(cb, gpio_num, gpio_port);
561 }
562 return ELINK_STATUS_OK;
563
564 }
565 #endif /* (!defined EXCLUDE_WARPCORE) */
566 /******************************************************************/
567 /* ETS section */
568 /******************************************************************/
569 #ifdef ELINK_ENHANCEMENTS
elink_ets_e2e3a0_disabled(struct elink_params * params)570 static void elink_ets_e2e3a0_disabled(struct elink_params *params)
571 {
572 /* ETS disabled configuration*/
573 struct elink_dev *cb = params->cb;
574
575 ELINK_DEBUG_P0(cb, "ETS E2E3 disabled configuration\n");
576
577 /* mapping between entry priority to client number (0,1,2 -debug and
578 * management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
579 * 3bits client num.
580 * PRI4 | PRI3 | PRI2 | PRI1 | PRI0
581 * cos1-100 cos0-011 dbg1-010 dbg0-001 MCP-000
582 */
583
584 REG_WR(cb, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, 0x4688);
585 /* Bitmap of 5bits length. Each bit specifies whether the entry behaves
586 * as strict. Bits 0,1,2 - debug and management entries, 3 -
587 * COS0 entry, 4 - COS1 entry.
588 * COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
589 * bit4 bit3 bit2 bit1 bit0
590 * MCP and debug are strict
591 */
592
593 REG_WR(cb, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
594 /* defines which entries (clients) are subjected to WFQ arbitration */
595 REG_WR(cb, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
596 /* For strict priority entries defines the number of consecutive
597 * slots for the highest priority.
598 */
599 REG_WR(cb, NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
600 /* mapping between the CREDIT_WEIGHT registers and actual client
601 * numbers
602 */
603 REG_WR(cb, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP, 0);
604 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, 0);
605 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, 0);
606
607 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0, 0);
608 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1, 0);
609 REG_WR(cb, PBF_REG_HIGH_PRIORITY_COS_NUM, 0);
610 /* ETS mode disable */
611 REG_WR(cb, PBF_REG_ETS_ENABLED, 0);
612 /* If ETS mode is enabled (there is no strict priority) defines a WFQ
613 * weight for COS0/COS1.
614 */
615 REG_WR(cb, PBF_REG_COS0_WEIGHT, 0x2710);
616 REG_WR(cb, PBF_REG_COS1_WEIGHT, 0x2710);
617 /* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter */
618 REG_WR(cb, PBF_REG_COS0_UPPER_BOUND, 0x989680);
619 REG_WR(cb, PBF_REG_COS1_UPPER_BOUND, 0x989680);
620 /* Defines the number of consecutive slots for the strict priority */
621 REG_WR(cb, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
622 }
623 /******************************************************************************
624 * Description:
625 * Getting min_w_val will be set according to line speed .
626 *.
627 ******************************************************************************/
elink_ets_get_min_w_val_nig(const struct elink_vars * vars)628 static u32 elink_ets_get_min_w_val_nig(const struct elink_vars *vars)
629 {
630 u32 min_w_val = 0;
631 /* Calculate min_w_val.*/
632 if (vars->link_up) {
633 if (vars->line_speed == ELINK_SPEED_20000)
634 min_w_val = ELINK_ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
635 else
636 min_w_val = ELINK_ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS;
637 } else
638 min_w_val = ELINK_ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
639 /* If the link isn't up (static configuration for example ) The
640 * link will be according to 20GBPS.
641 */
642 return min_w_val;
643 }
644 /******************************************************************************
645 * Description:
646 * Getting credit upper bound form min_w_val.
647 *.
648 ******************************************************************************/
elink_ets_get_credit_upper_bound(const u32 min_w_val)649 static u32 elink_ets_get_credit_upper_bound(const u32 min_w_val)
650 {
651 const u32 credit_upper_bound = (u32)ELINK_MAXVAL((150 * min_w_val),
652 ELINK_MAX_PACKET_SIZE);
653 return credit_upper_bound;
654 }
655 /******************************************************************************
656 * Description:
657 * Set credit upper bound for NIG.
658 *.
659 ******************************************************************************/
elink_ets_e3b0_set_credit_upper_bound_nig(const struct elink_params * params,const u32 min_w_val)660 static void elink_ets_e3b0_set_credit_upper_bound_nig(
661 const struct elink_params *params,
662 const u32 min_w_val)
663 {
664 struct elink_dev *cb = params->cb;
665 const u8 port = params->port;
666 const u32 credit_upper_bound =
667 elink_ets_get_credit_upper_bound(min_w_val);
668
669 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_0 :
670 NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0, credit_upper_bound);
671 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_1 :
672 NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1, credit_upper_bound);
673 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_2 :
674 NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_2, credit_upper_bound);
675 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_3 :
676 NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_3, credit_upper_bound);
677 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_4 :
678 NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_4, credit_upper_bound);
679 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_5 :
680 NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_5, credit_upper_bound);
681
682 if (!port) {
683 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_6,
684 credit_upper_bound);
685 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_7,
686 credit_upper_bound);
687 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_8,
688 credit_upper_bound);
689 }
690 }
691 /******************************************************************************
692 * Description:
693 * Will return the NIG ETS registers to init values.Except
694 * credit_upper_bound.
695 * That isn't used in this configuration (No WFQ is enabled) and will be
696 * configured acording to spec
697 *.
698 ******************************************************************************/
elink_ets_e3b0_nig_disabled(const struct elink_params * params,const struct elink_vars * vars)699 static void elink_ets_e3b0_nig_disabled(const struct elink_params *params,
700 const struct elink_vars *vars)
701 {
702 struct elink_dev *cb = params->cb;
703 const u8 port = params->port;
704 const u32 min_w_val = elink_ets_get_min_w_val_nig(vars);
705 /* Mapping between entry priority to client number (0,1,2 -debug and
706 * management clients, 3 - COS0 client, 4 - COS1, ... 8 -
707 * COS5)(HIGHEST) 4bits client num.TODO_ETS - Should be done by
708 * reset value or init tool
709 */
710 if (port) {
711 REG_WR(cb, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB, 0x543210);
712 REG_WR(cb, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB, 0x0);
713 } else {
714 REG_WR(cb, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB, 0x76543210);
715 REG_WR(cb, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB, 0x8);
716 }
717 /* For strict priority entries defines the number of consecutive
718 * slots for the highest priority.
719 */
720 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS :
721 NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
722 /* Mapping between the CREDIT_WEIGHT registers and actual client
723 * numbers
724 */
725 if (port) {
726 /*Port 1 has 6 COS*/
727 REG_WR(cb, NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_LSB, 0x210543);
728 REG_WR(cb, NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_MSB, 0x0);
729 } else {
730 /*Port 0 has 9 COS*/
731 REG_WR(cb, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_LSB,
732 0x43210876);
733 REG_WR(cb, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_MSB, 0x5);
734 }
735
736 /* Bitmap of 5bits length. Each bit specifies whether the entry behaves
737 * as strict. Bits 0,1,2 - debug and management entries, 3 -
738 * COS0 entry, 4 - COS1 entry.
739 * COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
740 * bit4 bit3 bit2 bit1 bit0
741 * MCP and debug are strict
742 */
743 if (port)
744 REG_WR(cb, NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT, 0x3f);
745 else
746 REG_WR(cb, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x1ff);
747 /* defines which entries (clients) are subjected to WFQ arbitration */
748 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ :
749 NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
750
751 /* Please notice the register address are note continuous and a
752 * for here is note appropriate.In 2 port mode port0 only COS0-5
753 * can be used. DEBUG1,DEBUG1,MGMT are never used for WFQ* In 4
754 * port mode port1 only COS0-2 can be used. DEBUG1,DEBUG1,MGMT
755 * are never used for WFQ
756 */
757 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
758 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, 0x0);
759 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
760 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, 0x0);
761 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
762 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2, 0x0);
763 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_3 :
764 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3, 0x0);
765 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_4 :
766 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4, 0x0);
767 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_5 :
768 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5, 0x0);
769 if (!port) {
770 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_6, 0x0);
771 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_7, 0x0);
772 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_8, 0x0);
773 }
774
775 elink_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val);
776 }
777 /******************************************************************************
778 * Description:
779 * Set credit upper bound for PBF.
780 *.
781 ******************************************************************************/
elink_ets_e3b0_set_credit_upper_bound_pbf(const struct elink_params * params,const u32 min_w_val)782 static void elink_ets_e3b0_set_credit_upper_bound_pbf(
783 const struct elink_params *params,
784 const u32 min_w_val)
785 {
786 struct elink_dev *cb = params->cb;
787 const u32 credit_upper_bound =
788 elink_ets_get_credit_upper_bound(min_w_val);
789 const u8 port = params->port;
790 u32 base_upper_bound = 0;
791 u8 max_cos = 0;
792 u8 i = 0;
793 /* In 2 port mode port0 has COS0-5 that can be used for WFQ.In 4
794 * port mode port1 has COS0-2 that can be used for WFQ.
795 */
796 if (!port) {
797 base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P0;
798 max_cos = ELINK_DCBX_E3B0_MAX_NUM_COS_PORT0;
799 } else {
800 base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P1;
801 max_cos = ELINK_DCBX_E3B0_MAX_NUM_COS_PORT1;
802 }
803
804 for (i = 0; i < max_cos; i++)
805 REG_WR(cb, base_upper_bound + (i << 2), credit_upper_bound);
806 }
807
808 /******************************************************************************
809 * Description:
810 * Will return the PBF ETS registers to init values.Except
811 * credit_upper_bound.
812 * That isn't used in this configuration (No WFQ is enabled) and will be
813 * configured acording to spec
814 *.
815 ******************************************************************************/
elink_ets_e3b0_pbf_disabled(const struct elink_params * params)816 static void elink_ets_e3b0_pbf_disabled(const struct elink_params *params)
817 {
818 struct elink_dev *cb = params->cb;
819 const u8 port = params->port;
820 const u32 min_w_val_pbf = ELINK_ETS_E3B0_PBF_MIN_W_VAL;
821 u8 i = 0;
822 u32 base_weight = 0;
823 u8 max_cos = 0;
824
825 /* Mapping between entry priority to client number 0 - COS0
826 * client, 2 - COS1, ... 5 - COS5)(HIGHEST) 4bits client num.
827 * TODO_ETS - Should be done by reset value or init tool
828 */
829 if (port)
830 /* 0x688 (|011|0 10|00 1|000) */
831 REG_WR(cb, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 , 0x688);
832 else
833 /* (10 1|100 |011|0 10|00 1|000) */
834 REG_WR(cb, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 , 0x2C688);
835
836 /* TODO_ETS - Should be done by reset value or init tool */
837 if (port)
838 /* 0x688 (|011|0 10|00 1|000)*/
839 REG_WR(cb, PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P1, 0x688);
840 else
841 /* 0x2C688 (10 1|100 |011|0 10|00 1|000) */
842 REG_WR(cb, PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P0, 0x2C688);
843
844 REG_WR(cb, (port) ? PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P1 :
845 PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P0 , 0x100);
846
847
848 REG_WR(cb, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 :
849 PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 , 0);
850
851 REG_WR(cb, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 :
852 PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0 , 0);
853 /* In 2 port mode port0 has COS0-5 that can be used for WFQ.
854 * In 4 port mode port1 has COS0-2 that can be used for WFQ.
855 */
856 if (!port) {
857 base_weight = PBF_REG_COS0_WEIGHT_P0;
858 max_cos = ELINK_DCBX_E3B0_MAX_NUM_COS_PORT0;
859 } else {
860 base_weight = PBF_REG_COS0_WEIGHT_P1;
861 max_cos = ELINK_DCBX_E3B0_MAX_NUM_COS_PORT1;
862 }
863
864 for (i = 0; i < max_cos; i++)
865 REG_WR(cb, base_weight + (0x4 * i), 0);
866
867 elink_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
868 }
869 /******************************************************************************
870 * Description:
871 * E3B0 disable will return basicly the values to init values.
872 *.
873 ******************************************************************************/
elink_ets_e3b0_disabled(const struct elink_params * params,const struct elink_vars * vars)874 static elink_status_t elink_ets_e3b0_disabled(const struct elink_params *params,
875 const struct elink_vars *vars)
876 {
877 struct elink_dev *cb = params->cb;
878
879 if (!CHIP_IS_E3B0(params->chip_id)) {
880 ELINK_DEBUG_P0(cb,
881 "elink_ets_e3b0_disabled the chip isn't E3B0\n");
882 return ELINK_STATUS_ERROR;
883 }
884
885 elink_ets_e3b0_nig_disabled(params, vars);
886
887 elink_ets_e3b0_pbf_disabled(params);
888
889 return ELINK_STATUS_OK;
890 }
891
892 /******************************************************************************
893 * Description:
894 * Disable will return basicly the values to init values.
895 *
896 ******************************************************************************/
elink_ets_disabled(struct elink_params * params,struct elink_vars * vars)897 elink_status_t elink_ets_disabled(struct elink_params *params,
898 struct elink_vars *vars)
899 {
900 struct elink_dev *cb = params->cb;
901 elink_status_t elink_status = ELINK_STATUS_OK;
902
903 if ((CHIP_IS_E2(params->chip_id)) || (CHIP_IS_E3A0(params->chip_id)))
904 elink_ets_e2e3a0_disabled(params);
905 else if (CHIP_IS_E3B0(params->chip_id))
906 elink_status = elink_ets_e3b0_disabled(params, vars);
907 else {
908 ELINK_DEBUG_P0(cb, "elink_ets_disabled - chip not supported\n");
909 return ELINK_STATUS_ERROR;
910 }
911
912 return elink_status;
913 }
914
915 /******************************************************************************
916 * Description
917 * Set the COS mappimg to SP and BW until this point all the COS are not
918 * set as SP or BW.
919 ******************************************************************************/
elink_ets_e3b0_cli_map(const struct elink_params * params,const struct elink_ets_params * ets_params,const u8 cos_sp_bitmap,const u8 cos_bw_bitmap)920 static elink_status_t elink_ets_e3b0_cli_map(const struct elink_params *params,
921 const struct elink_ets_params *ets_params,
922 const u8 cos_sp_bitmap,
923 const u8 cos_bw_bitmap)
924 {
925 struct elink_dev *cb = params->cb;
926 const u8 port = params->port;
927 const u8 nig_cli_sp_bitmap = 0x7 | (cos_sp_bitmap << 3);
928 const u8 pbf_cli_sp_bitmap = cos_sp_bitmap;
929 const u8 nig_cli_subject2wfq_bitmap = cos_bw_bitmap << 3;
930 const u8 pbf_cli_subject2wfq_bitmap = cos_bw_bitmap;
931
932 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT :
933 NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, nig_cli_sp_bitmap);
934
935 REG_WR(cb, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 :
936 PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 , pbf_cli_sp_bitmap);
937
938 REG_WR(cb, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ :
939 NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ,
940 nig_cli_subject2wfq_bitmap);
941
942 REG_WR(cb, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 :
943 PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0,
944 pbf_cli_subject2wfq_bitmap);
945
946 return ELINK_STATUS_OK;
947 }
948
949 /******************************************************************************
950 * Description:
951 * This function is needed because NIG ARB_CREDIT_WEIGHT_X are
952 * not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
953 ******************************************************************************/
elink_ets_e3b0_set_cos_bw(struct elink_dev * cb,const u8 cos_entry,const u32 min_w_val_nig,const u32 min_w_val_pbf,const u16 total_bw,const u8 bw,const u8 port)954 static elink_status_t elink_ets_e3b0_set_cos_bw(struct elink_dev *cb,
955 const u8 cos_entry,
956 const u32 min_w_val_nig,
957 const u32 min_w_val_pbf,
958 const u16 total_bw,
959 const u8 bw,
960 const u8 port)
961 {
962 u32 nig_reg_adress_crd_weight = 0;
963 u32 pbf_reg_adress_crd_weight = 0;
964 /* Calculate and set BW for this COS - use 1 instead of 0 for BW */
965 const u32 cos_bw_nig = ((bw ? bw : 1) * min_w_val_nig) / total_bw;
966 const u32 cos_bw_pbf = ((bw ? bw : 1) * min_w_val_pbf) / total_bw;
967
968 switch (cos_entry) {
969 case 0:
970 nig_reg_adress_crd_weight =
971 (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
972 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0;
973 pbf_reg_adress_crd_weight = (port) ?
974 PBF_REG_COS0_WEIGHT_P1 : PBF_REG_COS0_WEIGHT_P0;
975 break;
976 case 1:
977 nig_reg_adress_crd_weight = (port) ?
978 NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
979 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1;
980 pbf_reg_adress_crd_weight = (port) ?
981 PBF_REG_COS1_WEIGHT_P1 : PBF_REG_COS1_WEIGHT_P0;
982 break;
983 case 2:
984 nig_reg_adress_crd_weight = (port) ?
985 NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
986 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2;
987
988 pbf_reg_adress_crd_weight = (port) ?
989 PBF_REG_COS2_WEIGHT_P1 : PBF_REG_COS2_WEIGHT_P0;
990 break;
991 case 3:
992 if (port)
993 return ELINK_STATUS_ERROR;
994 nig_reg_adress_crd_weight =
995 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3;
996 pbf_reg_adress_crd_weight =
997 PBF_REG_COS3_WEIGHT_P0;
998 break;
999 case 4:
1000 if (port)
1001 return ELINK_STATUS_ERROR;
1002 nig_reg_adress_crd_weight =
1003 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4;
1004 pbf_reg_adress_crd_weight = PBF_REG_COS4_WEIGHT_P0;
1005 break;
1006 case 5:
1007 if (port)
1008 return ELINK_STATUS_ERROR;
1009 nig_reg_adress_crd_weight =
1010 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5;
1011 pbf_reg_adress_crd_weight = PBF_REG_COS5_WEIGHT_P0;
1012 break;
1013 }
1014
1015 REG_WR(cb, nig_reg_adress_crd_weight, cos_bw_nig);
1016
1017 REG_WR(cb, pbf_reg_adress_crd_weight, cos_bw_pbf);
1018
1019 return ELINK_STATUS_OK;
1020 }
1021 /******************************************************************************
1022 * Description:
1023 * Calculate the total BW.A value of 0 isn't legal.
1024 *
1025 ******************************************************************************/
elink_ets_e3b0_get_total_bw(const struct elink_params * params,struct elink_ets_params * ets_params,u16 * total_bw)1026 static elink_status_t elink_ets_e3b0_get_total_bw(
1027 const struct elink_params *params,
1028 struct elink_ets_params *ets_params,
1029 u16 *total_bw)
1030 {
1031 struct elink_dev *cb = params->cb;
1032 u8 cos_idx = 0;
1033 u8 is_bw_cos_exist = 0;
1034
1035 *total_bw = 0 ;
1036 /* Calculate total BW requested */
1037 for (cos_idx = 0; cos_idx < ets_params->num_of_cos; cos_idx++) {
1038 if (ets_params->cos[cos_idx].state == elink_cos_state_bw) {
1039 is_bw_cos_exist = 1;
1040 if (!ets_params->cos[cos_idx].params.bw_params.bw) {
1041 ELINK_DEBUG_P0(cb, "elink_ets_E3B0_config BW"
1042 "was set to 0\n");
1043 /* This is to prevent a state when ramrods
1044 * can't be sent
1045 */
1046 ets_params->cos[cos_idx].params.bw_params.bw
1047 = 1;
1048 }
1049 *total_bw +=
1050 ets_params->cos[cos_idx].params.bw_params.bw;
1051 }
1052 }
1053
1054 /* Check total BW is valid */
1055 if ((is_bw_cos_exist == 1) && (*total_bw != 100)) {
1056 if (*total_bw == 0) {
1057 ELINK_DEBUG_P0(cb,
1058 "elink_ets_E3B0_config total BW shouldn't be 0\n");
1059 return ELINK_STATUS_ERROR;
1060 }
1061 ELINK_DEBUG_P0(cb,
1062 "elink_ets_E3B0_config total BW should be 100\n");
1063 /* We can handle a case whre the BW isn't 100 this can happen
1064 * if the TC are joined.
1065 */
1066 }
1067 return ELINK_STATUS_OK;
1068 }
1069
1070 /******************************************************************************
1071 * Description:
1072 * Invalidate all the sp_pri_to_cos.
1073 *
1074 ******************************************************************************/
elink_ets_e3b0_sp_pri_to_cos_init(u8 * sp_pri_to_cos)1075 static void elink_ets_e3b0_sp_pri_to_cos_init(u8 *sp_pri_to_cos)
1076 {
1077 u8 pri = 0;
1078 for (pri = 0; pri < ELINK_DCBX_MAX_NUM_COS; pri++)
1079 sp_pri_to_cos[pri] = DCBX_INVALID_COS;
1080 }
1081 /******************************************************************************
1082 * Description:
1083 * Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
1084 * according to sp_pri_to_cos.
1085 *
1086 ******************************************************************************/
elink_ets_e3b0_sp_pri_to_cos_set(const struct elink_params * params,u8 * sp_pri_to_cos,const u8 pri,const u8 cos_entry)1087 static elink_status_t elink_ets_e3b0_sp_pri_to_cos_set(const struct elink_params *params,
1088 u8 *sp_pri_to_cos, const u8 pri,
1089 const u8 cos_entry)
1090 {
1091 struct elink_dev *cb = params->cb;
1092 const u8 port = params->port;
1093 const u8 max_num_of_cos = (port) ? ELINK_DCBX_E3B0_MAX_NUM_COS_PORT1 :
1094 ELINK_DCBX_E3B0_MAX_NUM_COS_PORT0;
1095
1096 if (pri >= max_num_of_cos) {
1097 ELINK_DEBUG_P0(cb, "elink_ets_e3b0_sp_pri_to_cos_set invalid "
1098 "parameter Illegal strict priority\n");
1099 return ELINK_STATUS_ERROR;
1100 }
1101
1102 if (sp_pri_to_cos[pri] != DCBX_INVALID_COS) {
1103 ELINK_DEBUG_P0(cb, "elink_ets_e3b0_sp_pri_to_cos_set invalid "
1104 "parameter There can't be two COS's with "
1105 "the same strict pri\n");
1106 return ELINK_STATUS_ERROR;
1107 }
1108
1109 sp_pri_to_cos[pri] = cos_entry;
1110 return ELINK_STATUS_OK;
1111
1112 }
1113
1114 /******************************************************************************
1115 * Description:
1116 * Returns the correct value according to COS and priority in
1117 * the sp_pri_cli register.
1118 *
1119 ******************************************************************************/
elink_e3b0_sp_get_pri_cli_reg(const u8 cos,const u8 cos_offset,const u8 pri_set,const u8 pri_offset,const u8 entry_size)1120 static u64 elink_e3b0_sp_get_pri_cli_reg(const u8 cos, const u8 cos_offset,
1121 const u8 pri_set,
1122 const u8 pri_offset,
1123 const u8 entry_size)
1124 {
1125 u64 pri_cli_nig = 0;
1126 pri_cli_nig = ((u64)(cos + cos_offset)) << (entry_size *
1127 (pri_set + pri_offset));
1128
1129 return pri_cli_nig;
1130 }
1131 /******************************************************************************
1132 * Description:
1133 * Returns the correct value according to COS and priority in the
1134 * sp_pri_cli register for NIG.
1135 *
1136 ******************************************************************************/
elink_e3b0_sp_get_pri_cli_reg_nig(const u8 cos,const u8 pri_set)1137 static u64 elink_e3b0_sp_get_pri_cli_reg_nig(const u8 cos, const u8 pri_set)
1138 {
1139 /* MCP Dbg0 and dbg1 are always with higher strict pri*/
1140 const u8 nig_cos_offset = 3;
1141 const u8 nig_pri_offset = 3;
1142
1143 return elink_e3b0_sp_get_pri_cli_reg(cos, nig_cos_offset, pri_set,
1144 nig_pri_offset, 4);
1145
1146 }
1147 /******************************************************************************
1148 * Description:
1149 * Returns the correct value according to COS and priority in the
1150 * sp_pri_cli register for PBF.
1151 *
1152 ******************************************************************************/
elink_e3b0_sp_get_pri_cli_reg_pbf(const u8 cos,const u8 pri_set)1153 static u64 elink_e3b0_sp_get_pri_cli_reg_pbf(const u8 cos, const u8 pri_set)
1154 {
1155 const u8 pbf_cos_offset = 0;
1156 const u8 pbf_pri_offset = 0;
1157
1158 return elink_e3b0_sp_get_pri_cli_reg(cos, pbf_cos_offset, pri_set,
1159 pbf_pri_offset, 3);
1160
1161 }
1162
1163 /******************************************************************************
1164 * Description:
1165 * Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
1166 * according to sp_pri_to_cos.(which COS has higher priority)
1167 *
1168 ******************************************************************************/
elink_ets_e3b0_sp_set_pri_cli_reg(const struct elink_params * params,u8 * sp_pri_to_cos)1169 static elink_status_t elink_ets_e3b0_sp_set_pri_cli_reg(const struct elink_params *params,
1170 u8 *sp_pri_to_cos)
1171 {
1172 struct elink_dev *cb = params->cb;
1173 u8 i = 0;
1174 const u8 port = params->port;
1175 /* MCP Dbg0 and dbg1 are always with higher strict pri*/
1176 u64 pri_cli_nig = 0x210;
1177 u32 pri_cli_pbf = 0x0;
1178 u8 pri_set = 0;
1179 u8 pri_bitmask = 0;
1180 const u8 max_num_of_cos = (port) ? ELINK_DCBX_E3B0_MAX_NUM_COS_PORT1 :
1181 ELINK_DCBX_E3B0_MAX_NUM_COS_PORT0;
1182
1183 u8 cos_bit_to_set = (1 << max_num_of_cos) - 1;
1184
1185 /* Set all the strict priority first */
1186 for (i = 0; i < max_num_of_cos; i++) {
1187 if (sp_pri_to_cos[i] != DCBX_INVALID_COS) {
1188 if (sp_pri_to_cos[i] >= ELINK_DCBX_MAX_NUM_COS) {
1189 ELINK_DEBUG_P0(cb,
1190 "elink_ets_e3b0_sp_set_pri_cli_reg "
1191 "invalid cos entry\n");
1192 return ELINK_STATUS_ERROR;
1193 }
1194
1195 pri_cli_nig |= elink_e3b0_sp_get_pri_cli_reg_nig(
1196 sp_pri_to_cos[i], pri_set);
1197
1198 pri_cli_pbf |= elink_e3b0_sp_get_pri_cli_reg_pbf(
1199 sp_pri_to_cos[i], pri_set);
1200 pri_bitmask = 1 << sp_pri_to_cos[i];
1201 /* COS is used remove it from bitmap.*/
1202 if (!(pri_bitmask & cos_bit_to_set)) {
1203 ELINK_DEBUG_P0(cb,
1204 "elink_ets_e3b0_sp_set_pri_cli_reg "
1205 "invalid There can't be two COS's with"
1206 " the same strict pri\n");
1207 return ELINK_STATUS_ERROR;
1208 }
1209 cos_bit_to_set &= ~pri_bitmask;
1210 pri_set++;
1211 }
1212 }
1213
1214 /* Set all the Non strict priority i= COS*/
1215 for (i = 0; i < max_num_of_cos; i++) {
1216 pri_bitmask = 1 << i;
1217 /* Check if COS was already used for SP */
1218 if (pri_bitmask & cos_bit_to_set) {
1219 /* COS wasn't used for SP */
1220 pri_cli_nig |= elink_e3b0_sp_get_pri_cli_reg_nig(
1221 i, pri_set);
1222
1223 pri_cli_pbf |= elink_e3b0_sp_get_pri_cli_reg_pbf(
1224 i, pri_set);
1225 /* COS is used remove it from bitmap.*/
1226 cos_bit_to_set &= ~pri_bitmask;
1227 pri_set++;
1228 }
1229 }
1230
1231 if (pri_set != max_num_of_cos) {
1232 ELINK_DEBUG_P0(cb, "elink_ets_e3b0_sp_set_pri_cli_reg not all "
1233 "entries were set\n");
1234 return ELINK_STATUS_ERROR;
1235 }
1236
1237 if (port) {
1238 /* Only 6 usable clients*/
1239 REG_WR(cb, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB,
1240 (u32)pri_cli_nig);
1241
1242 REG_WR(cb, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 , pri_cli_pbf);
1243 } else {
1244 /* Only 9 usable clients*/
1245 const u32 pri_cli_nig_lsb = (u32) (pri_cli_nig);
1246 const u32 pri_cli_nig_msb = (u32) ((pri_cli_nig >> 32) & 0xF);
1247
1248 REG_WR(cb, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB,
1249 pri_cli_nig_lsb);
1250 REG_WR(cb, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB,
1251 pri_cli_nig_msb);
1252
1253 REG_WR(cb, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 , pri_cli_pbf);
1254 }
1255 return ELINK_STATUS_OK;
1256 }
1257
1258 /******************************************************************************
1259 * Description:
1260 * Configure the COS to ETS according to BW and SP settings.
1261 ******************************************************************************/
elink_ets_e3b0_config(const struct elink_params * params,const struct elink_vars * vars,struct elink_ets_params * ets_params)1262 elink_status_t elink_ets_e3b0_config(const struct elink_params *params,
1263 const struct elink_vars *vars,
1264 struct elink_ets_params *ets_params)
1265 {
1266 struct elink_dev *cb = params->cb;
1267 elink_status_t elink_status = ELINK_STATUS_OK;
1268 const u8 port = params->port;
1269 u16 total_bw = 0;
1270 const u32 min_w_val_nig = elink_ets_get_min_w_val_nig(vars);
1271 const u32 min_w_val_pbf = ELINK_ETS_E3B0_PBF_MIN_W_VAL;
1272 u8 cos_bw_bitmap = 0;
1273 u8 cos_sp_bitmap = 0;
1274 u8 sp_pri_to_cos[ELINK_DCBX_MAX_NUM_COS] = {0};
1275 const u8 max_num_of_cos = (port) ? ELINK_DCBX_E3B0_MAX_NUM_COS_PORT1 :
1276 ELINK_DCBX_E3B0_MAX_NUM_COS_PORT0;
1277 u8 cos_entry = 0;
1278
1279 if (!CHIP_IS_E3B0(params->chip_id)) {
1280 ELINK_DEBUG_P0(cb,
1281 "elink_ets_e3b0_disabled the chip isn't E3B0\n");
1282 return ELINK_STATUS_ERROR;
1283 }
1284
1285 if ((ets_params->num_of_cos > max_num_of_cos)) {
1286 ELINK_DEBUG_P0(cb, "elink_ets_E3B0_config the number of COS "
1287 "isn't supported\n");
1288 return ELINK_STATUS_ERROR;
1289 }
1290
1291 /* Prepare sp strict priority parameters*/
1292 elink_ets_e3b0_sp_pri_to_cos_init(sp_pri_to_cos);
1293
1294 /* Prepare BW parameters*/
1295 elink_status = elink_ets_e3b0_get_total_bw(params, ets_params,
1296 &total_bw);
1297 if (elink_status != ELINK_STATUS_OK) {
1298 ELINK_DEBUG_P0(cb,
1299 "elink_ets_E3B0_config get_total_bw failed\n");
1300 return ELINK_STATUS_ERROR;
1301 }
1302
1303 /* Upper bound is set according to current link speed (min_w_val
1304 * should be the same for upper bound and COS credit val).
1305 */
1306 elink_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val_nig);
1307 elink_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
1308
1309
1310 for (cos_entry = 0; cos_entry < ets_params->num_of_cos; cos_entry++) {
1311 if (elink_cos_state_bw == ets_params->cos[cos_entry].state) {
1312 cos_bw_bitmap |= (1 << cos_entry);
1313 /* The function also sets the BW in HW(not the mappin
1314 * yet)
1315 */
1316 elink_status = elink_ets_e3b0_set_cos_bw(
1317 cb, cos_entry, min_w_val_nig, min_w_val_pbf,
1318 total_bw,
1319 ets_params->cos[cos_entry].params.bw_params.bw,
1320 port);
1321 } else if (elink_cos_state_strict ==
1322 ets_params->cos[cos_entry].state){
1323 cos_sp_bitmap |= (1 << cos_entry);
1324
1325 elink_status = elink_ets_e3b0_sp_pri_to_cos_set(
1326 params,
1327 sp_pri_to_cos,
1328 ets_params->cos[cos_entry].params.sp_params.pri,
1329 cos_entry);
1330
1331 } else {
1332 ELINK_DEBUG_P0(cb,
1333 "elink_ets_e3b0_config cos state not valid\n");
1334 return ELINK_STATUS_ERROR;
1335 }
1336 if (elink_status != ELINK_STATUS_OK) {
1337 ELINK_DEBUG_P0(cb,
1338 "elink_ets_e3b0_config set cos bw failed\n");
1339 return elink_status;
1340 }
1341 }
1342
1343 /* Set SP register (which COS has higher priority) */
1344 elink_status = elink_ets_e3b0_sp_set_pri_cli_reg(params,
1345 sp_pri_to_cos);
1346
1347 if (elink_status != ELINK_STATUS_OK) {
1348 ELINK_DEBUG_P0(cb,
1349 "elink_ets_E3B0_config set_pri_cli_reg failed\n");
1350 return elink_status;
1351 }
1352
1353 /* Set client mapping of BW and strict */
1354 elink_status = elink_ets_e3b0_cli_map(params, ets_params,
1355 cos_sp_bitmap,
1356 cos_bw_bitmap);
1357
1358 if (elink_status != ELINK_STATUS_OK) {
1359 ELINK_DEBUG_P0(cb, "elink_ets_E3B0_config SP failed\n");
1360 return elink_status;
1361 }
1362 return ELINK_STATUS_OK;
1363 }
elink_ets_bw_limit_common(const struct elink_params * params)1364 static void elink_ets_bw_limit_common(const struct elink_params *params)
1365 {
1366 /* ETS disabled configuration */
1367 struct elink_dev *cb = params->cb;
1368 ELINK_DEBUG_P0(cb, "ETS enabled BW limit configuration\n");
1369 /* Defines which entries (clients) are subjected to WFQ arbitration
1370 * COS0 0x8
1371 * COS1 0x10
1372 */
1373 REG_WR(cb, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0x18);
1374 /* Mapping between the ARB_CREDIT_WEIGHT registers and actual
1375 * client numbers (WEIGHT_0 does not actually have to represent
1376 * client 0)
1377 * PRI4 | PRI3 | PRI2 | PRI1 | PRI0
1378 * cos1-001 cos0-000 dbg1-100 dbg0-011 MCP-010
1379 */
1380 REG_WR(cb, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP, 0x111A);
1381
1382 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0,
1383 ELINK_ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
1384 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1,
1385 ELINK_ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
1386
1387 /* ETS mode enabled*/
1388 REG_WR(cb, PBF_REG_ETS_ENABLED, 1);
1389
1390 /* Defines the number of consecutive slots for the strict priority */
1391 REG_WR(cb, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
1392 /* Bitmap of 5bits length. Each bit specifies whether the entry behaves
1393 * as strict. Bits 0,1,2 - debug and management entries, 3 - COS0
1394 * entry, 4 - COS1 entry.
1395 * COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
1396 * bit4 bit3 bit2 bit1 bit0
1397 * MCP and debug are strict
1398 */
1399 REG_WR(cb, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
1400
1401 /* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter.*/
1402 REG_WR(cb, PBF_REG_COS0_UPPER_BOUND,
1403 ELINK_ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
1404 REG_WR(cb, PBF_REG_COS1_UPPER_BOUND,
1405 ELINK_ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
1406 }
1407
elink_ets_bw_limit(const struct elink_params * params,const u32 cos0_bw,const u32 cos1_bw)1408 void elink_ets_bw_limit(const struct elink_params *params, const u32 cos0_bw,
1409 const u32 cos1_bw)
1410 {
1411 /* ETS disabled configuration*/
1412 struct elink_dev *cb = params->cb;
1413 const u32 total_bw = cos0_bw + cos1_bw;
1414 u32 cos0_credit_weight = 0;
1415 u32 cos1_credit_weight = 0;
1416
1417 ELINK_DEBUG_P0(cb, "ETS enabled BW limit configuration\n");
1418
1419 if ((!total_bw) ||
1420 (!cos0_bw) ||
1421 (!cos1_bw)) {
1422 ELINK_DEBUG_P0(cb, "Total BW can't be zero\n");
1423 return;
1424 }
1425
1426 cos0_credit_weight = (cos0_bw * ELINK_ETS_BW_LIMIT_CREDIT_WEIGHT)/
1427 total_bw;
1428 cos1_credit_weight = (cos1_bw * ELINK_ETS_BW_LIMIT_CREDIT_WEIGHT)/
1429 total_bw;
1430
1431 elink_ets_bw_limit_common(params);
1432
1433 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, cos0_credit_weight);
1434 REG_WR(cb, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, cos1_credit_weight);
1435
1436 REG_WR(cb, PBF_REG_COS0_WEIGHT, cos0_credit_weight);
1437 REG_WR(cb, PBF_REG_COS1_WEIGHT, cos1_credit_weight);
1438 }
1439
elink_ets_strict(const struct elink_params * params,const u8 strict_cos)1440 elink_status_t elink_ets_strict(const struct elink_params *params, const u8 strict_cos)
1441 {
1442 /* ETS disabled configuration*/
1443 struct elink_dev *cb = params->cb;
1444 u32 val = 0;
1445
1446 ELINK_DEBUG_P0(cb, "ETS enabled strict configuration\n");
1447 /* Bitmap of 5bits length. Each bit specifies whether the entry behaves
1448 * as strict. Bits 0,1,2 - debug and management entries,
1449 * 3 - COS0 entry, 4 - COS1 entry.
1450 * COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
1451 * bit4 bit3 bit2 bit1 bit0
1452 * MCP and debug are strict
1453 */
1454 REG_WR(cb, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x1F);
1455 /* For strict priority entries defines the number of consecutive slots
1456 * for the highest priority.
1457 */
1458 REG_WR(cb, NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
1459 /* ETS mode disable */
1460 REG_WR(cb, PBF_REG_ETS_ENABLED, 0);
1461 /* Defines the number of consecutive slots for the strict priority */
1462 REG_WR(cb, PBF_REG_NUM_STRICT_ARB_SLOTS, 0x100);
1463
1464 /* Defines the number of consecutive slots for the strict priority */
1465 REG_WR(cb, PBF_REG_HIGH_PRIORITY_COS_NUM, strict_cos);
1466
1467 /* Mapping between entry priority to client number (0,1,2 -debug and
1468 * management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
1469 * 3bits client num.
1470 * PRI4 | PRI3 | PRI2 | PRI1 | PRI0
1471 * dbg0-010 dbg1-001 cos1-100 cos0-011 MCP-000
1472 * dbg0-010 dbg1-001 cos0-011 cos1-100 MCP-000
1473 */
1474 val = (!strict_cos) ? 0x2318 : 0x22E0;
1475 REG_WR(cb, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, val);
1476
1477 return ELINK_STATUS_OK;
1478 }
1479 #endif /* ELINK_ENHANCEMENTS */
1480
1481 /******************************************************************/
1482 /* PFC section */
1483 /******************************************************************/
1484 #ifndef EXCLUDE_NON_COMMON_INIT
1485 #ifndef EXCLUDE_WARPCORE
elink_update_pfc_xmac(struct elink_params * params,struct elink_vars * vars,u8 is_lb)1486 static void elink_update_pfc_xmac(struct elink_params *params,
1487 struct elink_vars *vars,
1488 u8 is_lb)
1489 {
1490 struct elink_dev *cb = params->cb;
1491 u32 xmac_base;
1492 u32 pause_val, pfc0_val, pfc1_val;
1493
1494 /* XMAC base adrr */
1495 xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
1496
1497 /* Initialize pause and pfc registers */
1498 pause_val = 0x18000;
1499 pfc0_val = 0xFFFF8000;
1500 pfc1_val = 0x2;
1501
1502 /* No PFC support */
1503 if (!(params->feature_config_flags &
1504 ELINK_FEATURE_CONFIG_PFC_ENABLED)) {
1505
1506 /* RX flow control - Process pause frame in receive direction
1507 */
1508 if (vars->flow_ctrl & ELINK_FLOW_CTRL_RX)
1509 pause_val |= XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN;
1510
1511 /* TX flow control - Send pause packet when buffer is full */
1512 if (vars->flow_ctrl & ELINK_FLOW_CTRL_TX)
1513 pause_val |= XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN;
1514 } else {/* PFC support */
1515 pfc1_val |= XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN |
1516 XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN |
1517 XMAC_PFC_CTRL_HI_REG_RX_PFC_EN |
1518 XMAC_PFC_CTRL_HI_REG_TX_PFC_EN |
1519 XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON;
1520 /* Write pause and PFC registers */
1521 REG_WR(cb, xmac_base + XMAC_REG_PAUSE_CTRL, pause_val);
1522 REG_WR(cb, xmac_base + XMAC_REG_PFC_CTRL, pfc0_val);
1523 REG_WR(cb, xmac_base + XMAC_REG_PFC_CTRL_HI, pfc1_val);
1524 pfc1_val &= ~XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON;
1525
1526 }
1527
1528 /* Write pause and PFC registers */
1529 REG_WR(cb, xmac_base + XMAC_REG_PAUSE_CTRL, pause_val);
1530 REG_WR(cb, xmac_base + XMAC_REG_PFC_CTRL, pfc0_val);
1531 REG_WR(cb, xmac_base + XMAC_REG_PFC_CTRL_HI, pfc1_val);
1532
1533
1534 /* Set MAC address for source TX Pause/PFC frames */
1535 REG_WR(cb, xmac_base + XMAC_REG_CTRL_SA_LO,
1536 ((params->mac_addr[2] << 24) |
1537 (params->mac_addr[3] << 16) |
1538 (params->mac_addr[4] << 8) |
1539 (params->mac_addr[5])));
1540 REG_WR(cb, xmac_base + XMAC_REG_CTRL_SA_HI,
1541 ((params->mac_addr[0] << 8) |
1542 (params->mac_addr[1])));
1543
1544 USLEEP(cb, 30);
1545 }
1546
1547 #endif // EXCLUDE_WARPCORE
1548 #endif // #ifndef EXCLUDE_NON_COMMON_INIT
1549 #ifdef ELINK_ENHANCEMENTS
1550 #ifndef BNX2X_UPSTREAM /* ! BNX2X_UPSTREAM */
elink_emac_get_pfc_stat(struct elink_params * params,u32 pfc_frames_sent[2],u32 pfc_frames_received[2])1551 static void elink_emac_get_pfc_stat(struct elink_params *params,
1552 u32 pfc_frames_sent[2],
1553 u32 pfc_frames_received[2])
1554 {
1555 /* Read pfc statistic */
1556 struct elink_dev *cb = params->cb;
1557 u32 emac_base = params->port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
1558 u32 val_xon = 0;
1559 u32 val_xoff = 0;
1560
1561 ELINK_DEBUG_P0(cb, "pfc statistic read from EMAC\n");
1562
1563 /* PFC received frames */
1564 val_xoff = REG_RD(cb, emac_base +
1565 EMAC_REG_RX_PFC_STATS_XOFF_RCVD);
1566 val_xoff &= EMAC_REG_RX_PFC_STATS_XOFF_RCVD_COUNT;
1567 val_xon = REG_RD(cb, emac_base + EMAC_REG_RX_PFC_STATS_XON_RCVD);
1568 val_xon &= EMAC_REG_RX_PFC_STATS_XON_RCVD_COUNT;
1569
1570 pfc_frames_received[0] = val_xon + val_xoff;
1571
1572 /* PFC received sent */
1573 val_xoff = REG_RD(cb, emac_base +
1574 EMAC_REG_RX_PFC_STATS_XOFF_SENT);
1575 val_xoff &= EMAC_REG_RX_PFC_STATS_XOFF_SENT_COUNT;
1576 val_xon = REG_RD(cb, emac_base + EMAC_REG_RX_PFC_STATS_XON_SENT);
1577 val_xon &= EMAC_REG_RX_PFC_STATS_XON_SENT_COUNT;
1578
1579 pfc_frames_sent[0] = val_xon + val_xoff;
1580 }
1581
1582 /* Read pfc statistic*/
elink_pfc_statistic(struct elink_params * params,struct elink_vars * vars,u32 pfc_frames_sent[2],u32 pfc_frames_received[2])1583 void elink_pfc_statistic(struct elink_params *params, struct elink_vars *vars,
1584 u32 pfc_frames_sent[2],
1585 u32 pfc_frames_received[2])
1586 {
1587 /* Read pfc statistic */
1588 struct elink_dev *cb = params->cb;
1589
1590 ELINK_DEBUG_P0(cb, "pfc statistic\n");
1591
1592 if (!vars->link_up)
1593 return;
1594
1595 if (vars->mac_type == ELINK_MAC_TYPE_EMAC) {
1596 ELINK_DEBUG_P0(cb, "About to read PFC stats from EMAC\n");
1597 elink_emac_get_pfc_stat(params, pfc_frames_sent,
1598 pfc_frames_received);
1599 }
1600 }
1601 #endif /* ! BNX2X_UPSTREAM */
1602 #endif /* ELINK_ENHANCEMENTS */
1603 /******************************************************************/
1604 /* MAC/PBF section */
1605 /******************************************************************/
elink_set_mdio_clk(struct elink_dev * cb,u32 chip_id,u32 emac_base)1606 static void elink_set_mdio_clk(struct elink_dev *cb, u32 chip_id,
1607 u32 emac_base)
1608 {
1609 u32 new_mode, cur_mode;
1610 u32 clc_cnt;
1611 /* Set clause 45 mode, slow down the MDIO clock to 2.5MHz
1612 * (a value of 49==0x31) and make sure that the AUTO poll is off
1613 */
1614 cur_mode = REG_RD(cb, emac_base + EMAC_REG_EMAC_MDIO_MODE);
1615
1616 if (ELINK_USES_WARPCORE(chip_id))
1617 clc_cnt = 74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT;
1618 else
1619 clc_cnt = 49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT;
1620
1621 if (((cur_mode & EMAC_MDIO_MODE_CLOCK_CNT) == clc_cnt) &&
1622 (cur_mode & (EMAC_MDIO_MODE_CLAUSE_45)))
1623 return;
1624
1625 new_mode = cur_mode &
1626 ~(EMAC_MDIO_MODE_AUTO_POLL | EMAC_MDIO_MODE_CLOCK_CNT);
1627 new_mode |= clc_cnt;
1628 new_mode |= (EMAC_MDIO_MODE_CLAUSE_45);
1629
1630 ELINK_DEBUG_P2(cb, "Changing emac_mode from 0x%x to 0x%x\n",
1631 cur_mode, new_mode);
1632 REG_WR(cb, emac_base + EMAC_REG_EMAC_MDIO_MODE, new_mode);
1633 USLEEP(cb, 40);
1634 }
1635
1636 #ifndef EXCLUDE_WARPCORE
elink_is_4_port_mode(struct elink_dev * cb)1637 static u8 elink_is_4_port_mode(struct elink_dev *cb)
1638 {
1639 u32 port4mode_ovwr_val;
1640 /* Check 4-port override enabled */
1641 port4mode_ovwr_val = REG_RD(cb, MISC_REG_PORT4MODE_EN_OVWR);
1642 if (port4mode_ovwr_val & (1<<0)) {
1643 /* Return 4-port mode override value */
1644 return ((port4mode_ovwr_val & (1<<1)) == (1<<1));
1645 }
1646 /* Return 4-port mode from input pin */
1647 return (u8)REG_RD(cb, MISC_REG_PORT4MODE_EN);
1648 }
1649 #endif
1650
1651 #ifndef EXCLUDE_NON_COMMON_INIT
elink_set_mdio_emac_per_phy(struct elink_dev * cb,struct elink_params * params)1652 static void elink_set_mdio_emac_per_phy(struct elink_dev *cb,
1653 struct elink_params *params)
1654 {
1655 u8 phy_index;
1656
1657 /* Set mdio clock per phy */
1658 for (phy_index = ELINK_INT_PHY; phy_index < params->num_phys;
1659 phy_index++)
1660 elink_set_mdio_clk(cb, params->chip_id,
1661 params->phy[phy_index].mdio_ctrl);
1662 }
1663
elink_emac_init(struct elink_params * params,struct elink_vars * vars)1664 static void elink_emac_init(struct elink_params *params,
1665 struct elink_vars *vars)
1666 {
1667 /* reset and unreset the emac core */
1668 struct elink_dev *cb = params->cb;
1669 u8 port = params->port;
1670 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
1671 u32 val;
1672 u16 timeout;
1673
1674 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
1675 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
1676 USLEEP(cb, 5);
1677 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
1678 (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
1679
1680 /* init emac - use read-modify-write */
1681 /* self clear reset */
1682 val = REG_RD(cb, emac_base + EMAC_REG_EMAC_MODE);
1683 EMAC_WR(cb, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET));
1684
1685 timeout = 200;
1686 do {
1687 val = REG_RD(cb, emac_base + EMAC_REG_EMAC_MODE);
1688 ELINK_DEBUG_P1(cb, "EMAC reset reg is %u\n", val);
1689 if (!timeout) {
1690 ELINK_DEBUG_P0(cb, "EMAC timeout!\n");
1691 return;
1692 }
1693 timeout--;
1694 } while (val & EMAC_MODE_RESET);
1695
1696 elink_set_mdio_emac_per_phy(cb, params);
1697 /* Set mac address */
1698 val = ((params->mac_addr[0] << 8) |
1699 params->mac_addr[1]);
1700 EMAC_WR(cb, EMAC_REG_EMAC_MAC_MATCH, val);
1701
1702 val = ((params->mac_addr[2] << 24) |
1703 (params->mac_addr[3] << 16) |
1704 (params->mac_addr[4] << 8) |
1705 params->mac_addr[5]);
1706 EMAC_WR(cb, EMAC_REG_EMAC_MAC_MATCH + 4, val);
1707 }
1708
1709 #ifndef EXCLUDE_WARPCORE
elink_set_xumac_nig(struct elink_params * params,u16 tx_pause_en,u8 enable)1710 static void elink_set_xumac_nig(struct elink_params *params,
1711 u16 tx_pause_en,
1712 u8 enable)
1713 {
1714 struct elink_dev *cb = params->cb;
1715
1716 REG_WR(cb, params->port ? NIG_REG_P1_MAC_IN_EN : NIG_REG_P0_MAC_IN_EN,
1717 enable);
1718 REG_WR(cb, params->port ? NIG_REG_P1_MAC_OUT_EN : NIG_REG_P0_MAC_OUT_EN,
1719 enable);
1720 REG_WR(cb, params->port ? NIG_REG_P1_MAC_PAUSE_OUT_EN :
1721 NIG_REG_P0_MAC_PAUSE_OUT_EN, tx_pause_en);
1722 }
1723
elink_set_umac_rxtx(struct elink_params * params,u8 en)1724 static void elink_set_umac_rxtx(struct elink_params *params, u8 en)
1725 {
1726 u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
1727 u32 val;
1728 struct elink_dev *cb = params->cb;
1729 if (!(REG_RD(cb, MISC_REG_RESET_REG_2) &
1730 (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port)))
1731 return;
1732 val = REG_RD(cb, umac_base + UMAC_REG_COMMAND_CONFIG);
1733 if (en)
1734 val |= (UMAC_COMMAND_CONFIG_REG_TX_ENA |
1735 UMAC_COMMAND_CONFIG_REG_RX_ENA);
1736 else
1737 val &= ~(UMAC_COMMAND_CONFIG_REG_TX_ENA |
1738 UMAC_COMMAND_CONFIG_REG_RX_ENA);
1739 /* Disable RX and TX */
1740 REG_WR(cb, umac_base + UMAC_REG_COMMAND_CONFIG, val);
1741 }
1742
elink_umac_enable(struct elink_params * params,struct elink_vars * vars,u8 lb)1743 static void elink_umac_enable(struct elink_params *params,
1744 struct elink_vars *vars, u8 lb)
1745 {
1746 u32 val;
1747 u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
1748 struct elink_dev *cb = params->cb;
1749 /* Reset UMAC */
1750 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
1751 (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port));
1752 MSLEEP(cb, 1);
1753
1754 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
1755 (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port));
1756
1757 ELINK_DEBUG_P0(cb, "enabling UMAC\n");
1758
1759 /* This register opens the gate for the UMAC despite its name */
1760 REG_WR(cb, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
1761
1762 val = UMAC_COMMAND_CONFIG_REG_PROMIS_EN |
1763 UMAC_COMMAND_CONFIG_REG_PAD_EN |
1764 UMAC_COMMAND_CONFIG_REG_SW_RESET |
1765 UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK;
1766 switch (vars->line_speed) {
1767 case ELINK_SPEED_10:
1768 val |= (0<<2);
1769 break;
1770 case ELINK_SPEED_100:
1771 val |= (1<<2);
1772 break;
1773 case ELINK_SPEED_1000:
1774 val |= (2<<2);
1775 break;
1776 case ELINK_SPEED_2500:
1777 val |= (3<<2);
1778 break;
1779 default:
1780 ELINK_DEBUG_P1(cb, "Invalid speed for UMAC %d\n",
1781 vars->line_speed);
1782 break;
1783 }
1784 if (!(vars->flow_ctrl & ELINK_FLOW_CTRL_TX))
1785 val |= UMAC_COMMAND_CONFIG_REG_IGNORE_TX_PAUSE;
1786
1787 if (!(vars->flow_ctrl & ELINK_FLOW_CTRL_RX))
1788 val |= UMAC_COMMAND_CONFIG_REG_PAUSE_IGNORE;
1789
1790 if (vars->duplex == DUPLEX_HALF)
1791 val |= UMAC_COMMAND_CONFIG_REG_HD_ENA;
1792
1793 REG_WR(cb, umac_base + UMAC_REG_COMMAND_CONFIG, val);
1794 USLEEP(cb, 50);
1795
1796 /* Configure UMAC for EEE */
1797 if (vars->eee_status & SHMEM_EEE_ADV_STATUS_MASK) {
1798 ELINK_DEBUG_P0(cb, "configured UMAC for EEE\n");
1799 REG_WR(cb, umac_base + UMAC_REG_UMAC_EEE_CTRL,
1800 UMAC_UMAC_EEE_CTRL_REG_EEE_EN);
1801 REG_WR(cb, umac_base + UMAC_REG_EEE_WAKE_TIMER, 0x11);
1802 } else {
1803 REG_WR(cb, umac_base + UMAC_REG_UMAC_EEE_CTRL, 0x0);
1804 }
1805
1806 /* Set MAC address for source TX Pause/PFC frames (under SW reset) */
1807 REG_WR(cb, umac_base + UMAC_REG_MAC_ADDR0,
1808 ((params->mac_addr[2] << 24) |
1809 (params->mac_addr[3] << 16) |
1810 (params->mac_addr[4] << 8) |
1811 (params->mac_addr[5])));
1812 REG_WR(cb, umac_base + UMAC_REG_MAC_ADDR1,
1813 ((params->mac_addr[0] << 8) |
1814 (params->mac_addr[1])));
1815
1816 /* Enable RX and TX */
1817 val &= ~UMAC_COMMAND_CONFIG_REG_PAD_EN;
1818 val |= UMAC_COMMAND_CONFIG_REG_TX_ENA |
1819 UMAC_COMMAND_CONFIG_REG_RX_ENA;
1820 REG_WR(cb, umac_base + UMAC_REG_COMMAND_CONFIG, val);
1821 USLEEP(cb, 50);
1822
1823 /* Remove SW Reset */
1824 val &= ~UMAC_COMMAND_CONFIG_REG_SW_RESET;
1825
1826 /* Check loopback mode */
1827 if (lb)
1828 val |= UMAC_COMMAND_CONFIG_REG_LOOP_ENA;
1829 REG_WR(cb, umac_base + UMAC_REG_COMMAND_CONFIG, val);
1830
1831 /* Maximum Frame Length (RW). Defines a 14-Bit maximum frame
1832 * length used by the MAC receive logic to check frames.
1833 */
1834 REG_WR(cb, umac_base + UMAC_REG_MAXFR, 0x2710);
1835 elink_set_xumac_nig(params,
1836 ((vars->flow_ctrl & ELINK_FLOW_CTRL_TX) != 0), 1);
1837 vars->mac_type = ELINK_MAC_TYPE_UMAC;
1838
1839 }
1840
1841 /* Define the XMAC mode */
elink_xmac_init(struct elink_params * params,u32 max_speed)1842 static void elink_xmac_init(struct elink_params *params, u32 max_speed)
1843 {
1844 struct elink_dev *cb = params->cb;
1845 u32 is_port4mode = elink_is_4_port_mode(cb);
1846
1847 /* In 4-port mode, need to set the mode only once, so if XMAC is
1848 * already out of reset, it means the mode has already been set,
1849 * and it must not* reset the XMAC again, since it controls both
1850 * ports of the path
1851 */
1852
1853 if (((CHIP_NUM(params->chip_id) == CHIP_NUM_57840_4_10) ||
1854 (CHIP_NUM(params->chip_id) == CHIP_NUM_57840_2_20) ||
1855 (CHIP_NUM(params->chip_id) == CHIP_NUM_57840_OBSOLETE)) &&
1856 is_port4mode &&
1857 (REG_RD(cb, MISC_REG_RESET_REG_2) &
1858 MISC_REGISTERS_RESET_REG_2_XMAC)) {
1859 ELINK_DEBUG_P0(cb,
1860 "XMAC already out of reset in 4-port mode\n");
1861 return;
1862 }
1863
1864 /* Hard reset */
1865 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
1866 MISC_REGISTERS_RESET_REG_2_XMAC);
1867 MSLEEP(cb, 1);
1868
1869 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
1870 MISC_REGISTERS_RESET_REG_2_XMAC);
1871 if (is_port4mode) {
1872 ELINK_DEBUG_P0(cb, "Init XMAC to 2 ports x 10G per path\n");
1873
1874 /* Set the number of ports on the system side to up to 2 */
1875 REG_WR(cb, MISC_REG_XMAC_CORE_PORT_MODE, 1);
1876
1877 /* Set the number of ports on the Warp Core to 10G */
1878 REG_WR(cb, MISC_REG_XMAC_PHY_PORT_MODE, 3);
1879 } else {
1880 /* Set the number of ports on the system side to 1 */
1881 REG_WR(cb, MISC_REG_XMAC_CORE_PORT_MODE, 0);
1882 if (max_speed == ELINK_SPEED_10000) {
1883 ELINK_DEBUG_P0(cb,
1884 "Init XMAC to 10G x 1 port per path\n");
1885 /* Set the number of ports on the Warp Core to 10G */
1886 REG_WR(cb, MISC_REG_XMAC_PHY_PORT_MODE, 3);
1887 } else {
1888 ELINK_DEBUG_P0(cb,
1889 "Init XMAC to 20G x 2 ports per path\n");
1890 /* Set the number of ports on the Warp Core to 20G */
1891 REG_WR(cb, MISC_REG_XMAC_PHY_PORT_MODE, 1);
1892 }
1893 }
1894 /* Soft reset */
1895 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
1896 MISC_REGISTERS_RESET_REG_2_XMAC_SOFT);
1897 MSLEEP(cb, 1);
1898
1899 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
1900 MISC_REGISTERS_RESET_REG_2_XMAC_SOFT);
1901
1902 }
1903
elink_set_xmac_rxtx(struct elink_params * params,u8 en)1904 static void elink_set_xmac_rxtx(struct elink_params *params, u8 en)
1905 {
1906 u8 port = params->port;
1907 struct elink_dev *cb = params->cb;
1908 u32 pfc_ctrl, xmac_base = (port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
1909 u32 val;
1910
1911 if (REG_RD(cb, MISC_REG_RESET_REG_2) &
1912 MISC_REGISTERS_RESET_REG_2_XMAC) {
1913 /* Send an indication to change the state in the NIG back to XON
1914 * Clearing this bit enables the next set of this bit to get
1915 * rising edge
1916 */
1917 pfc_ctrl = REG_RD(cb, xmac_base + XMAC_REG_PFC_CTRL_HI);
1918 REG_WR(cb, xmac_base + XMAC_REG_PFC_CTRL_HI,
1919 (pfc_ctrl & ~(1<<1)));
1920 REG_WR(cb, xmac_base + XMAC_REG_PFC_CTRL_HI,
1921 (pfc_ctrl | (1<<1)));
1922 ELINK_DEBUG_P1(cb, "Disable XMAC on port %x\n", port);
1923 val = REG_RD(cb, xmac_base + XMAC_REG_CTRL);
1924 if (en)
1925 val |= (XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN);
1926 else
1927 val &= ~(XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN);
1928 REG_WR(cb, xmac_base + XMAC_REG_CTRL, val);
1929 }
1930 }
1931
elink_xmac_enable(struct elink_params * params,struct elink_vars * vars,u8 lb)1932 static elink_status_t elink_xmac_enable(struct elink_params *params,
1933 struct elink_vars *vars, u8 lb)
1934 {
1935 u32 val, xmac_base;
1936 struct elink_dev *cb = params->cb;
1937 ELINK_DEBUG_P0(cb, "enabling XMAC\n");
1938
1939 xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
1940
1941 elink_xmac_init(params, vars->line_speed);
1942
1943 /* This register determines on which events the MAC will assert
1944 * error on the i/f to the NIG along w/ EOP.
1945 */
1946
1947 /* This register tells the NIG whether to send traffic to UMAC
1948 * or XMAC
1949 */
1950 REG_WR(cb, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 0);
1951
1952 /* When XMAC is in XLGMII mode, disable sending idles for fault
1953 * detection.
1954 */
1955 if (!(params->phy[ELINK_INT_PHY].flags & ELINK_FLAGS_TX_ERROR_CHECK)) {
1956 REG_WR(cb, xmac_base + XMAC_REG_RX_LSS_CTRL,
1957 (XMAC_RX_LSS_CTRL_REG_LOCAL_FAULT_DISABLE |
1958 XMAC_RX_LSS_CTRL_REG_REMOTE_FAULT_DISABLE));
1959 REG_WR(cb, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0);
1960 REG_WR(cb, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS,
1961 XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS |
1962 XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS);
1963 }
1964 /* Set Max packet size */
1965 REG_WR(cb, xmac_base + XMAC_REG_RX_MAX_SIZE, 0x2710);
1966
1967 /* CRC append for Tx packets */
1968 REG_WR(cb, xmac_base + XMAC_REG_TX_CTRL, 0xC800);
1969
1970 /* update PFC */
1971 elink_update_pfc_xmac(params, vars, 0);
1972
1973 if (vars->eee_status & SHMEM_EEE_ADV_STATUS_MASK) {
1974 ELINK_DEBUG_P0(cb, "Setting XMAC for EEE\n");
1975 REG_WR(cb, xmac_base + XMAC_REG_EEE_TIMERS_HI, 0x1380008);
1976 REG_WR(cb, xmac_base + XMAC_REG_EEE_CTRL, 0x1);
1977 } else {
1978 REG_WR(cb, xmac_base + XMAC_REG_EEE_CTRL, 0x0);
1979 }
1980
1981 /* Enable TX and RX */
1982 val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN;
1983
1984 /* Set MAC in XLGMII mode for dual-mode */
1985 if ((vars->line_speed == ELINK_SPEED_20000) &&
1986 (params->phy[ELINK_INT_PHY].supported &
1987 ELINK_SUPPORTED_20000baseKR2_Full))
1988 val |= XMAC_CTRL_REG_XLGMII_ALIGN_ENB;
1989
1990 /* Check loopback mode */
1991 if (lb)
1992 val |= XMAC_CTRL_REG_LINE_LOCAL_LPBK;
1993 REG_WR(cb, xmac_base + XMAC_REG_CTRL, val);
1994 elink_set_xumac_nig(params,
1995 ((vars->flow_ctrl & ELINK_FLOW_CTRL_TX) != 0), 1);
1996
1997 vars->mac_type = ELINK_MAC_TYPE_XMAC;
1998
1999 return ELINK_STATUS_OK;
2000 }
2001 #endif // EXCLUDE_WARPCORE
2002
2003 #ifndef EXCLUDE_EMAC
elink_emac_enable(struct elink_params * params,struct elink_vars * vars,u8 lb)2004 static elink_status_t elink_emac_enable(struct elink_params *params,
2005 struct elink_vars *vars, u8 lb)
2006 {
2007 struct elink_dev *cb = params->cb;
2008 u8 port = params->port;
2009 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
2010 u32 val;
2011
2012 ELINK_DEBUG_P0(cb, "enabling EMAC\n");
2013
2014 /* Disable BMAC */
2015 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
2016 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
2017
2018 /* enable emac and not bmac */
2019 REG_WR(cb, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
2020
2021 #ifdef ELINK_INCLUDE_EMUL
2022 /* for paladium */
2023 if (CHIP_REV_IS_EMUL(params->chip_id)) {
2024 /* Use lane 1 (of lanes 0-3) */
2025 REG_WR(cb, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
2026 REG_WR(cb, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
2027 }
2028 /* for fpga */
2029 else
2030 #endif
2031 #ifdef ELINK_INCLUDE_FPGA
2032 if (CHIP_REV_IS_FPGA(params->chip_id)) {
2033 /* Use lane 1 (of lanes 0-3) */
2034 ELINK_DEBUG_P0(cb, "elink_emac_enable: Setting FPGA\n");
2035
2036 REG_WR(cb, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
2037 REG_WR(cb, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0);
2038 } else
2039 #endif
2040 /* ASIC */
2041 if (vars->phy_flags & PHY_XGXS_FLAG) {
2042 u32 ser_lane = ((params->lane_config &
2043 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
2044 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
2045
2046 ELINK_DEBUG_P0(cb, "XGXS\n");
2047 /* select the master lanes (out of 0-3) */
2048 REG_WR(cb, NIG_REG_XGXS_LANE_SEL_P0 + port*4, ser_lane);
2049 /* select XGXS */
2050 REG_WR(cb, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
2051
2052 } else { /* SerDes */
2053 ELINK_DEBUG_P0(cb, "SerDes\n");
2054 /* select SerDes */
2055 REG_WR(cb, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0);
2056 }
2057
2058 elink_bits_en(cb, emac_base + EMAC_REG_EMAC_RX_MODE,
2059 EMAC_RX_MODE_RESET);
2060 elink_bits_en(cb, emac_base + EMAC_REG_EMAC_TX_MODE,
2061 EMAC_TX_MODE_RESET);
2062
2063 #if defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA)
2064 if (CHIP_REV_IS_SLOW(params->chip_id)) {
2065 /* config GMII mode */
2066 val = REG_RD(cb, emac_base + EMAC_REG_EMAC_MODE);
2067 EMAC_WR(cb, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_PORT_GMII));
2068 } else { /* ASIC */
2069 #endif /* defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA)*/
2070 /* pause enable/disable */
2071 elink_bits_dis(cb, emac_base + EMAC_REG_EMAC_RX_MODE,
2072 EMAC_RX_MODE_FLOW_EN);
2073
2074 elink_bits_dis(cb, emac_base + EMAC_REG_EMAC_TX_MODE,
2075 (EMAC_TX_MODE_EXT_PAUSE_EN |
2076 EMAC_TX_MODE_FLOW_EN));
2077 if (!(params->feature_config_flags &
2078 ELINK_FEATURE_CONFIG_PFC_ENABLED)) {
2079 if (vars->flow_ctrl & ELINK_FLOW_CTRL_RX)
2080 elink_bits_en(cb, emac_base +
2081 EMAC_REG_EMAC_RX_MODE,
2082 EMAC_RX_MODE_FLOW_EN);
2083
2084 if (vars->flow_ctrl & ELINK_FLOW_CTRL_TX)
2085 elink_bits_en(cb, emac_base +
2086 EMAC_REG_EMAC_TX_MODE,
2087 (EMAC_TX_MODE_EXT_PAUSE_EN |
2088 EMAC_TX_MODE_FLOW_EN));
2089 } else
2090 elink_bits_en(cb, emac_base + EMAC_REG_EMAC_TX_MODE,
2091 EMAC_TX_MODE_FLOW_EN);
2092 #if defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA)
2093 }
2094 #endif /* defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA) */
2095
2096 /* KEEP_VLAN_TAG, promiscuous */
2097 val = REG_RD(cb, emac_base + EMAC_REG_EMAC_RX_MODE);
2098 val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
2099
2100 /* Setting this bit causes MAC control frames (except for pause
2101 * frames) to be passed on for processing. This setting has no
2102 * affect on the operation of the pause frames. This bit effects
2103 * all packets regardless of RX Parser packet sorting logic.
2104 * Turn the PFC off to make sure we are in Xon state before
2105 * enabling it.
2106 */
2107 EMAC_WR(cb, EMAC_REG_RX_PFC_MODE, 0);
2108 if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) {
2109 ELINK_DEBUG_P0(cb, "PFC is enabled\n");
2110 /* Enable PFC again */
2111 EMAC_WR(cb, EMAC_REG_RX_PFC_MODE,
2112 EMAC_REG_RX_PFC_MODE_RX_EN |
2113 EMAC_REG_RX_PFC_MODE_TX_EN |
2114 EMAC_REG_RX_PFC_MODE_PRIORITIES);
2115
2116 EMAC_WR(cb, EMAC_REG_RX_PFC_PARAM,
2117 ((0x0101 <<
2118 EMAC_REG_RX_PFC_PARAM_OPCODE_BITSHIFT) |
2119 (0x00ff <<
2120 EMAC_REG_RX_PFC_PARAM_PRIORITY_EN_BITSHIFT)));
2121 val |= EMAC_RX_MODE_KEEP_MAC_CONTROL;
2122 }
2123 EMAC_WR(cb, EMAC_REG_EMAC_RX_MODE, val);
2124
2125 /* Set Loopback */
2126 val = REG_RD(cb, emac_base + EMAC_REG_EMAC_MODE);
2127 if (lb)
2128 val |= 0x810;
2129 else
2130 val &= ~0x810;
2131 EMAC_WR(cb, EMAC_REG_EMAC_MODE, val);
2132
2133 /* Enable emac */
2134 REG_WR(cb, NIG_REG_NIG_EMAC0_EN + port*4, 1);
2135
2136 #ifndef ELINK_AUX_POWER
2137 /* Enable emac for jumbo packets */
2138 EMAC_WR(cb, EMAC_REG_EMAC_RX_MTU_SIZE,
2139 (EMAC_RX_MTU_SIZE_JUMBO_ENA |
2140 (ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD)));
2141 #endif
2142
2143 /* Strip CRC */
2144 REG_WR(cb, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1);
2145
2146 /* Disable the NIG in/out to the bmac */
2147 REG_WR(cb, NIG_REG_BMAC0_IN_EN + port*4, 0x0);
2148 REG_WR(cb, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, 0x0);
2149 REG_WR(cb, NIG_REG_BMAC0_OUT_EN + port*4, 0x0);
2150
2151 /* Enable the NIG in/out to the emac */
2152 REG_WR(cb, NIG_REG_EMAC0_IN_EN + port*4, 0x1);
2153 val = 0;
2154 if ((params->feature_config_flags &
2155 ELINK_FEATURE_CONFIG_PFC_ENABLED) ||
2156 (vars->flow_ctrl & ELINK_FLOW_CTRL_TX))
2157 val = 1;
2158
2159 REG_WR(cb, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
2160 REG_WR(cb, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x1);
2161
2162 #ifdef ELINK_INCLUDE_EMUL
2163 if (CHIP_REV_IS_EMUL(params->chip_id)) {
2164 /* Take the BigMac out of reset */
2165 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
2166 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
2167
2168 /* Enable access for bmac registers */
2169 REG_WR(cb, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
2170 } else
2171 #endif /* ELINK_INCLUDE_EMUL */
2172 REG_WR(cb, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x0);
2173
2174 vars->mac_type = ELINK_MAC_TYPE_EMAC;
2175 return ELINK_STATUS_OK;
2176 }
2177
2178 #endif //EXCLUDE_EMAC
2179 #ifndef EXCLUDE_BMAC1
elink_update_pfc_bmac1(struct elink_params * params,struct elink_vars * vars)2180 static void elink_update_pfc_bmac1(struct elink_params *params,
2181 struct elink_vars *vars)
2182 {
2183 u32 wb_data[2];
2184 struct elink_dev *cb = params->cb;
2185 u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
2186 NIG_REG_INGRESS_BMAC0_MEM;
2187
2188 u32 val = 0x14;
2189 if ((!(params->feature_config_flags &
2190 ELINK_FEATURE_CONFIG_PFC_ENABLED)) &&
2191 (vars->flow_ctrl & ELINK_FLOW_CTRL_RX))
2192 /* Enable BigMAC to react on received Pause packets */
2193 val |= (1<<5);
2194 wb_data[0] = val;
2195 wb_data[1] = 0;
2196 REG_WR_DMAE(cb, bmac_addr + BIGMAC_REGISTER_RX_CONTROL, wb_data, 2);
2197
2198 /* TX control */
2199 val = 0xc0;
2200 if (!(params->feature_config_flags &
2201 ELINK_FEATURE_CONFIG_PFC_ENABLED) &&
2202 (vars->flow_ctrl & ELINK_FLOW_CTRL_TX))
2203 val |= 0x800000;
2204 wb_data[0] = val;
2205 wb_data[1] = 0;
2206 REG_WR_DMAE(cb, bmac_addr + BIGMAC_REGISTER_TX_CONTROL, wb_data, 2);
2207 }
2208 #endif // EXCLUDE_BMAC1
2209
2210 #ifndef EXCLUDE_BMAC2
elink_update_pfc_bmac2(struct elink_params * params,struct elink_vars * vars,u8 is_lb)2211 static void elink_update_pfc_bmac2(struct elink_params *params,
2212 struct elink_vars *vars,
2213 u8 is_lb)
2214 {
2215 /* Set rx control: Strip CRC and enable BigMAC to relay
2216 * control packets to the system as well
2217 */
2218 u32 wb_data[2];
2219 struct elink_dev *cb = params->cb;
2220 u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
2221 NIG_REG_INGRESS_BMAC0_MEM;
2222 u32 val = 0x14;
2223
2224 if ((!(params->feature_config_flags &
2225 ELINK_FEATURE_CONFIG_PFC_ENABLED)) &&
2226 (vars->flow_ctrl & ELINK_FLOW_CTRL_RX))
2227 /* Enable BigMAC to react on received Pause packets */
2228 val |= (1<<5);
2229 wb_data[0] = val;
2230 wb_data[1] = 0;
2231 REG_WR_DMAE(cb, bmac_addr + BIGMAC2_REGISTER_RX_CONTROL, wb_data, 2);
2232 USLEEP(cb, 30);
2233
2234 /* Tx control */
2235 val = 0xc0;
2236 if (!(params->feature_config_flags &
2237 ELINK_FEATURE_CONFIG_PFC_ENABLED) &&
2238 (vars->flow_ctrl & ELINK_FLOW_CTRL_TX))
2239 val |= 0x800000;
2240 wb_data[0] = val;
2241 wb_data[1] = 0;
2242 REG_WR_DMAE(cb, bmac_addr + BIGMAC2_REGISTER_TX_CONTROL, wb_data, 2);
2243
2244 if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) {
2245 ELINK_DEBUG_P0(cb, "PFC is enabled\n");
2246 /* Enable PFC RX & TX & STATS and set 8 COS */
2247 wb_data[0] = 0x0;
2248 wb_data[0] |= (1<<0); /* RX */
2249 wb_data[0] |= (1<<1); /* TX */
2250 wb_data[0] |= (1<<2); /* Force initial Xon */
2251 wb_data[0] |= (1<<3); /* 8 cos */
2252 wb_data[0] |= (1<<5); /* STATS */
2253 wb_data[1] = 0;
2254 REG_WR_DMAE(cb, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL,
2255 wb_data, 2);
2256 /* Clear the force Xon */
2257 wb_data[0] &= ~(1<<2);
2258 } else {
2259 ELINK_DEBUG_P0(cb, "PFC is disabled\n");
2260 /* Disable PFC RX & TX & STATS and set 8 COS */
2261 wb_data[0] = 0x8;
2262 wb_data[1] = 0;
2263 }
2264
2265 REG_WR_DMAE(cb, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL, wb_data, 2);
2266
2267 /* Set Time (based unit is 512 bit time) between automatic
2268 * re-sending of PP packets amd enable automatic re-send of
2269 * Per-Priroity Packet as long as pp_gen is asserted and
2270 * pp_disable is low.
2271 */
2272 val = 0x8000;
2273 if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED)
2274 val |= (1<<16); /* enable automatic re-send */
2275
2276 wb_data[0] = val;
2277 wb_data[1] = 0;
2278 REG_WR_DMAE(cb, bmac_addr + BIGMAC2_REGISTER_TX_PAUSE_CONTROL,
2279 wb_data, 2);
2280
2281 /* mac control */
2282 val = 0x3; /* Enable RX and TX */
2283 if (is_lb) {
2284 val |= 0x4; /* Local loopback */
2285 ELINK_DEBUG_P0(cb, "enable bmac loopback\n");
2286 }
2287 /* When PFC enabled, Pass pause frames towards the NIG. */
2288 if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED)
2289 val |= ((1<<6)|(1<<5));
2290
2291 wb_data[0] = val;
2292 wb_data[1] = 0;
2293 REG_WR_DMAE(cb, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
2294 }
2295 #endif // EXCLUDE_BMAC2
2296 #endif // EXCLUDE_NON_COMMON_INIT
2297 #ifdef ELINK_ENHANCEMENTS
2298
2299 /******************************************************************************
2300 * Description:
2301 * This function is needed because NIG ARB_CREDIT_WEIGHT_X are
2302 * not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
2303 ******************************************************************************/
elink_pfc_nig_rx_priority_mask(struct elink_dev * cb,u8 cos_entry,u32 priority_mask,u8 port)2304 static elink_status_t elink_pfc_nig_rx_priority_mask(struct elink_dev *cb,
2305 u8 cos_entry,
2306 u32 priority_mask, u8 port)
2307 {
2308 u32 nig_reg_rx_priority_mask_add = 0;
2309
2310 switch (cos_entry) {
2311 case 0:
2312 nig_reg_rx_priority_mask_add = (port) ?
2313 NIG_REG_P1_RX_COS0_PRIORITY_MASK :
2314 NIG_REG_P0_RX_COS0_PRIORITY_MASK;
2315 break;
2316 case 1:
2317 nig_reg_rx_priority_mask_add = (port) ?
2318 NIG_REG_P1_RX_COS1_PRIORITY_MASK :
2319 NIG_REG_P0_RX_COS1_PRIORITY_MASK;
2320 break;
2321 case 2:
2322 nig_reg_rx_priority_mask_add = (port) ?
2323 NIG_REG_P1_RX_COS2_PRIORITY_MASK :
2324 NIG_REG_P0_RX_COS2_PRIORITY_MASK;
2325 break;
2326 case 3:
2327 if (port)
2328 return ELINK_STATUS_ERROR;
2329 nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS3_PRIORITY_MASK;
2330 break;
2331 case 4:
2332 if (port)
2333 return ELINK_STATUS_ERROR;
2334 nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS4_PRIORITY_MASK;
2335 break;
2336 case 5:
2337 if (port)
2338 return ELINK_STATUS_ERROR;
2339 nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS5_PRIORITY_MASK;
2340 break;
2341 }
2342
2343 REG_WR(cb, nig_reg_rx_priority_mask_add, priority_mask);
2344
2345 return ELINK_STATUS_OK;
2346 }
2347 #endif // ELINK_ENHANCEMENTS
2348 #ifndef EXCLUDE_NON_COMMON_INIT
elink_update_mng(struct elink_params * params,u32 link_status)2349 static void elink_update_mng(struct elink_params *params, u32 link_status)
2350 {
2351 struct elink_dev *cb = params->cb;
2352
2353 REG_WR(cb, params->shmem_base +
2354 OFFSETOF(struct shmem_region,
2355 port_mb[params->port].link_status), link_status);
2356 }
2357
2358 #ifdef ELINK_ENHANCEMENTS
elink_update_pfc_nig(struct elink_params * params,struct elink_vars * vars,struct elink_nig_brb_pfc_port_params * nig_params)2359 static void elink_update_pfc_nig(struct elink_params *params,
2360 struct elink_vars *vars,
2361 struct elink_nig_brb_pfc_port_params *nig_params)
2362 {
2363 u32 xcm_mask = 0, ppp_enable = 0, pause_enable = 0, llfc_out_en = 0;
2364 u32 llfc_enable = 0, xcm_out_en = 0, hwpfc_enable = 0;
2365 u32 pkt_priority_to_cos = 0;
2366 struct elink_dev *cb = params->cb;
2367 u8 port = params->port;
2368
2369 int set_pfc = params->feature_config_flags &
2370 ELINK_FEATURE_CONFIG_PFC_ENABLED;
2371 ELINK_DEBUG_P0(cb, "updating pfc nig parameters\n");
2372
2373 /* When NIG_LLH0_XCM_MASK_REG_LLHX_XCM_MASK_BCN bit is set
2374 * MAC control frames (that are not pause packets)
2375 * will be forwarded to the XCM.
2376 */
2377 xcm_mask = REG_RD(cb, port ? NIG_REG_LLH1_XCM_MASK :
2378 NIG_REG_LLH0_XCM_MASK);
2379 /* NIG params will override non PFC params, since it's possible to
2380 * do transition from PFC to SAFC
2381 */
2382 if (set_pfc) {
2383 pause_enable = 0;
2384 llfc_out_en = 0;
2385 llfc_enable = 0;
2386 if (CHIP_IS_E3(params->chip_id))
2387 ppp_enable = 0;
2388 else
2389 ppp_enable = 1;
2390 xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
2391 NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
2392 xcm_out_en = 0;
2393 hwpfc_enable = 1;
2394 } else {
2395 if (nig_params) {
2396 llfc_out_en = nig_params->llfc_out_en;
2397 llfc_enable = nig_params->llfc_enable;
2398 pause_enable = nig_params->pause_enable;
2399 } else /* Default non PFC mode - PAUSE */
2400 pause_enable = 1;
2401
2402 xcm_mask |= (port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
2403 NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
2404 xcm_out_en = 1;
2405 }
2406
2407 if (CHIP_IS_E3(params->chip_id))
2408 REG_WR(cb, port ? NIG_REG_BRB1_PAUSE_IN_EN :
2409 NIG_REG_BRB0_PAUSE_IN_EN, pause_enable);
2410 REG_WR(cb, port ? NIG_REG_LLFC_OUT_EN_1 :
2411 NIG_REG_LLFC_OUT_EN_0, llfc_out_en);
2412 REG_WR(cb, port ? NIG_REG_LLFC_ENABLE_1 :
2413 NIG_REG_LLFC_ENABLE_0, llfc_enable);
2414 REG_WR(cb, port ? NIG_REG_PAUSE_ENABLE_1 :
2415 NIG_REG_PAUSE_ENABLE_0, pause_enable);
2416
2417 REG_WR(cb, port ? NIG_REG_PPP_ENABLE_1 :
2418 NIG_REG_PPP_ENABLE_0, ppp_enable);
2419
2420 REG_WR(cb, port ? NIG_REG_LLH1_XCM_MASK :
2421 NIG_REG_LLH0_XCM_MASK, xcm_mask);
2422
2423 REG_WR(cb, port ? NIG_REG_LLFC_EGRESS_SRC_ENABLE_1 :
2424 NIG_REG_LLFC_EGRESS_SRC_ENABLE_0, 0x7);
2425
2426 /* Output enable for RX_XCM # IF */
2427 REG_WR(cb, port ? NIG_REG_XCM1_OUT_EN :
2428 NIG_REG_XCM0_OUT_EN, xcm_out_en);
2429
2430 /* HW PFC TX enable */
2431 REG_WR(cb, port ? NIG_REG_P1_HWPFC_ENABLE :
2432 NIG_REG_P0_HWPFC_ENABLE, hwpfc_enable);
2433
2434 if (nig_params) {
2435 u8 i = 0;
2436 pkt_priority_to_cos = nig_params->pkt_priority_to_cos;
2437
2438 for (i = 0; i < nig_params->num_of_rx_cos_priority_mask; i++)
2439 elink_pfc_nig_rx_priority_mask(cb, i,
2440 nig_params->rx_cos_priority_mask[i], port);
2441
2442 REG_WR(cb, port ? NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_1 :
2443 NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_0,
2444 nig_params->llfc_high_priority_classes);
2445
2446 REG_WR(cb, port ? NIG_REG_LLFC_LOW_PRIORITY_CLASSES_1 :
2447 NIG_REG_LLFC_LOW_PRIORITY_CLASSES_0,
2448 nig_params->llfc_low_priority_classes);
2449 }
2450 REG_WR(cb, port ? NIG_REG_P1_PKT_PRIORITY_TO_COS :
2451 NIG_REG_P0_PKT_PRIORITY_TO_COS,
2452 pkt_priority_to_cos);
2453 }
2454
elink_update_pfc(struct elink_params * params,struct elink_vars * vars,struct elink_nig_brb_pfc_port_params * pfc_params)2455 elink_status_t elink_update_pfc(struct elink_params *params,
2456 struct elink_vars *vars,
2457 struct elink_nig_brb_pfc_port_params *pfc_params)
2458 {
2459 /* The PFC and pause are orthogonal to one another, meaning when
2460 * PFC is enabled, the pause are disabled, and when PFC is
2461 * disabled, pause are set according to the pause result.
2462 */
2463 u32 val;
2464 struct elink_dev *cb = params->cb;
2465 u8 bmac_loopback = (params->loopback_mode == ELINK_LOOPBACK_BMAC);
2466
2467 if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED)
2468 vars->link_status |= LINK_STATUS_PFC_ENABLED;
2469 else
2470 vars->link_status &= ~LINK_STATUS_PFC_ENABLED;
2471
2472 elink_update_mng(params, vars->link_status);
2473
2474 /* Update NIG params */
2475 elink_update_pfc_nig(params, vars, pfc_params);
2476
2477 if (!vars->link_up)
2478 return ELINK_STATUS_OK;
2479
2480 ELINK_DEBUG_P0(cb, "About to update PFC in BMAC\n");
2481
2482 if (CHIP_IS_E3(params->chip_id)) {
2483 if (vars->mac_type == ELINK_MAC_TYPE_XMAC)
2484 elink_update_pfc_xmac(params, vars, 0);
2485 } else {
2486 val = REG_RD(cb, MISC_REG_RESET_REG_2);
2487 if ((val &
2488 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
2489 == 0) {
2490 ELINK_DEBUG_P0(cb, "About to update PFC in EMAC\n");
2491 elink_emac_enable(params, vars, 0);
2492 return ELINK_STATUS_OK;
2493 }
2494 if (CHIP_IS_E2(params->chip_id))
2495 elink_update_pfc_bmac2(params, vars, bmac_loopback);
2496 else
2497 elink_update_pfc_bmac1(params, vars);
2498
2499 val = 0;
2500 if ((params->feature_config_flags &
2501 ELINK_FEATURE_CONFIG_PFC_ENABLED) ||
2502 (vars->flow_ctrl & ELINK_FLOW_CTRL_TX))
2503 val = 1;
2504 REG_WR(cb, NIG_REG_BMAC0_PAUSE_OUT_EN + params->port*4, val);
2505 }
2506 return ELINK_STATUS_OK;
2507 }
2508
2509 #endif /* ELINK_ENHANCEMENTS */
2510 #ifndef EXCLUDE_BMAC1
elink_bmac1_enable(struct elink_params * params,struct elink_vars * vars,u8 is_lb)2511 static elink_status_t elink_bmac1_enable(struct elink_params *params,
2512 struct elink_vars *vars,
2513 u8 is_lb)
2514 {
2515 struct elink_dev *cb = params->cb;
2516 u8 port = params->port;
2517 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
2518 NIG_REG_INGRESS_BMAC0_MEM;
2519 u32 wb_data[2];
2520 u32 val;
2521
2522 ELINK_DEBUG_P0(cb, "Enabling BigMAC1\n");
2523
2524 /* XGXS control */
2525 wb_data[0] = 0x3c;
2526 wb_data[1] = 0;
2527 REG_WR_DMAE(cb, bmac_addr + BIGMAC_REGISTER_BMAC_XGXS_CONTROL,
2528 wb_data, 2);
2529
2530 /* TX MAC SA */
2531 wb_data[0] = ((params->mac_addr[2] << 24) |
2532 (params->mac_addr[3] << 16) |
2533 (params->mac_addr[4] << 8) |
2534 params->mac_addr[5]);
2535 wb_data[1] = ((params->mac_addr[0] << 8) |
2536 params->mac_addr[1]);
2537 REG_WR_DMAE(cb, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR, wb_data, 2);
2538
2539 /* MAC control */
2540 val = 0x3;
2541 if (is_lb) {
2542 val |= 0x4;
2543 ELINK_DEBUG_P0(cb, "enable bmac loopback\n");
2544 }
2545 wb_data[0] = val;
2546 wb_data[1] = 0;
2547 REG_WR_DMAE(cb, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL, wb_data, 2);
2548
2549 /* Set rx mtu */
2550 wb_data[0] = ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD;
2551 wb_data[1] = 0;
2552 REG_WR_DMAE(cb, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE, wb_data, 2);
2553
2554 elink_update_pfc_bmac1(params, vars);
2555
2556 /* Set tx mtu */
2557 wb_data[0] = ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD;
2558 wb_data[1] = 0;
2559 REG_WR_DMAE(cb, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE, wb_data, 2);
2560
2561 /* Set cnt max size */
2562 wb_data[0] = ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD;
2563 wb_data[1] = 0;
2564 REG_WR_DMAE(cb, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE, wb_data, 2);
2565
2566 /* Configure SAFC */
2567 wb_data[0] = 0x1000200;
2568 wb_data[1] = 0;
2569 REG_WR_DMAE(cb, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
2570 wb_data, 2);
2571 #ifdef ELINK_INCLUDE_EMUL
2572 /* Fix for emulation */
2573 if (CHIP_REV_IS_EMUL(params->chip_id)) {
2574 wb_data[0] = 0xf000;
2575 wb_data[1] = 0;
2576 REG_WR_DMAE(cb, bmac_addr + BIGMAC_REGISTER_TX_PAUSE_THRESHOLD,
2577 wb_data, 2);
2578 }
2579 #endif /* ELINK_INCLUDE_EMUL */
2580
2581 return ELINK_STATUS_OK;
2582 }
2583 #endif /* EXCLUDE_BMAC1 */
2584
2585 #ifndef EXCLUDE_BMAC2
elink_bmac2_enable(struct elink_params * params,struct elink_vars * vars,u8 is_lb)2586 static elink_status_t elink_bmac2_enable(struct elink_params *params,
2587 struct elink_vars *vars,
2588 u8 is_lb)
2589 {
2590 struct elink_dev *cb = params->cb;
2591 u8 port = params->port;
2592 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
2593 NIG_REG_INGRESS_BMAC0_MEM;
2594 u32 wb_data[2];
2595
2596 ELINK_DEBUG_P0(cb, "Enabling BigMAC2\n");
2597
2598 wb_data[0] = 0;
2599 wb_data[1] = 0;
2600 REG_WR_DMAE(cb, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
2601 USLEEP(cb, 30);
2602
2603 /* XGXS control: Reset phy HW, MDIO registers, PHY PLL and BMAC */
2604 wb_data[0] = 0x3c;
2605 wb_data[1] = 0;
2606 REG_WR_DMAE(cb, bmac_addr + BIGMAC2_REGISTER_BMAC_XGXS_CONTROL,
2607 wb_data, 2);
2608
2609 USLEEP(cb, 30);
2610
2611 /* TX MAC SA */
2612 wb_data[0] = ((params->mac_addr[2] << 24) |
2613 (params->mac_addr[3] << 16) |
2614 (params->mac_addr[4] << 8) |
2615 params->mac_addr[5]);
2616 wb_data[1] = ((params->mac_addr[0] << 8) |
2617 params->mac_addr[1]);
2618 REG_WR_DMAE(cb, bmac_addr + BIGMAC2_REGISTER_TX_SOURCE_ADDR,
2619 wb_data, 2);
2620
2621 USLEEP(cb, 30);
2622
2623 /* Configure SAFC */
2624 wb_data[0] = 0x1000200;
2625 wb_data[1] = 0;
2626 REG_WR_DMAE(cb, bmac_addr + BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS,
2627 wb_data, 2);
2628 USLEEP(cb, 30);
2629
2630 /* Set RX MTU */
2631 wb_data[0] = ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD;
2632 wb_data[1] = 0;
2633 REG_WR_DMAE(cb, bmac_addr + BIGMAC2_REGISTER_RX_MAX_SIZE, wb_data, 2);
2634 USLEEP(cb, 30);
2635
2636 /* Set TX MTU */
2637 wb_data[0] = ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD;
2638 wb_data[1] = 0;
2639 REG_WR_DMAE(cb, bmac_addr + BIGMAC2_REGISTER_TX_MAX_SIZE, wb_data, 2);
2640 USLEEP(cb, 30);
2641 /* Set cnt max size */
2642 wb_data[0] = ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD - 2;
2643 wb_data[1] = 0;
2644 REG_WR_DMAE(cb, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE, wb_data, 2);
2645 USLEEP(cb, 30);
2646 elink_update_pfc_bmac2(params, vars, is_lb);
2647
2648 return ELINK_STATUS_OK;
2649 }
2650 #endif /* EXCLUDE_BMAC2 */
2651
2652 #if !defined(EXCLUDE_BMAC2)
elink_bmac_enable(struct elink_params * params,struct elink_vars * vars,u8 is_lb,u8 reset_bmac)2653 static elink_status_t elink_bmac_enable(struct elink_params *params,
2654 struct elink_vars *vars,
2655 u8 is_lb, u8 reset_bmac)
2656 {
2657 elink_status_t rc = ELINK_STATUS_OK;
2658 u8 port = params->port;
2659 struct elink_dev *cb = params->cb;
2660 u32 val;
2661 /* Reset and unreset the BigMac */
2662 if (reset_bmac) {
2663 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
2664 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
2665 MSLEEP(cb, 1);
2666 }
2667
2668 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
2669 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
2670
2671 /* Enable access for bmac registers */
2672 REG_WR(cb, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
2673
2674 /* Enable BMAC according to BMAC type*/
2675 #ifdef ELINK_ENHANCEMENTS
2676 if (CHIP_IS_E2(params->chip_id))
2677 #endif
2678 #ifndef EXCLUDE_BMAC2
2679 rc = elink_bmac2_enable(params, vars, is_lb);
2680 #endif
2681 #ifdef ELINK_ENHANCEMENTS
2682 else
2683 #endif
2684 #ifndef EXCLUDE_BMAC1
2685 rc = elink_bmac1_enable(params, vars, is_lb);
2686 #endif
2687 REG_WR(cb, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
2688 REG_WR(cb, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
2689 REG_WR(cb, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
2690 val = 0;
2691 if ((params->feature_config_flags &
2692 ELINK_FEATURE_CONFIG_PFC_ENABLED) ||
2693 (vars->flow_ctrl & ELINK_FLOW_CTRL_TX))
2694 val = 1;
2695 REG_WR(cb, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
2696 REG_WR(cb, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
2697 REG_WR(cb, NIG_REG_EMAC0_IN_EN + port*4, 0x0);
2698 REG_WR(cb, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, 0x0);
2699 REG_WR(cb, NIG_REG_BMAC0_IN_EN + port*4, 0x1);
2700 REG_WR(cb, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);
2701
2702 vars->mac_type = ELINK_MAC_TYPE_BMAC;
2703 return rc;
2704 }
2705 #endif /* #if !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1) */
2706
2707 #if !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1)
elink_set_bmac_rx(struct elink_dev * cb,u32 chip_id,u8 port,u8 en)2708 static void elink_set_bmac_rx(struct elink_dev *cb, u32 chip_id, u8 port, u8 en)
2709 {
2710 u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
2711 NIG_REG_INGRESS_BMAC0_MEM;
2712 u32 wb_data[2];
2713 u32 nig_bmac_enable = REG_RD(cb, NIG_REG_BMAC0_REGS_OUT_EN + port*4);
2714
2715 if (CHIP_IS_E2(chip_id))
2716 bmac_addr += BIGMAC2_REGISTER_BMAC_CONTROL;
2717 else
2718 bmac_addr += BIGMAC_REGISTER_BMAC_CONTROL;
2719 /* Only if the bmac is out of reset */
2720 if (REG_RD(cb, MISC_REG_RESET_REG_2) &
2721 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) &&
2722 nig_bmac_enable) {
2723 /* Clear Rx Enable bit in BMAC_CONTROL register */
2724 REG_RD_DMAE(cb, bmac_addr, wb_data, 2);
2725 if (en)
2726 wb_data[0] |= ELINK_BMAC_CONTROL_RX_ENABLE;
2727 else
2728 wb_data[0] &= ~ELINK_BMAC_CONTROL_RX_ENABLE;
2729 REG_WR_DMAE(cb, bmac_addr, wb_data, 2);
2730 MSLEEP(cb, 1);
2731 }
2732 }
2733 #endif /* !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1) */
2734 #endif // EXCLUDE_NON_COMMON_INIT
2735
2736 #ifndef ELINK_AUX_POWER
elink_pbf_update(struct elink_params * params,u32 flow_ctrl,u32 line_speed)2737 static elink_status_t elink_pbf_update(struct elink_params *params, u32 flow_ctrl,
2738 u32 line_speed)
2739 {
2740 struct elink_dev *cb = params->cb;
2741 u8 port = params->port;
2742 u32 init_crd, crd;
2743 u32 count = 1000;
2744
2745 /* Disable port */
2746 REG_WR(cb, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1);
2747
2748 /* Wait for init credit */
2749 init_crd = REG_RD(cb, PBF_REG_P0_INIT_CRD + port*4);
2750 crd = REG_RD(cb, PBF_REG_P0_CREDIT + port*8);
2751 ELINK_DEBUG_P2(cb, "init_crd 0x%x crd 0x%x\n", init_crd, crd);
2752
2753 while ((init_crd != crd) && count) {
2754 MSLEEP(cb, 5);
2755 crd = REG_RD(cb, PBF_REG_P0_CREDIT + port*8);
2756 count--;
2757 }
2758 crd = REG_RD(cb, PBF_REG_P0_CREDIT + port*8);
2759 if (init_crd != crd) {
2760 ELINK_DEBUG_P2(cb, "BUG! init_crd 0x%x != crd 0x%x\n",
2761 init_crd, crd);
2762 return ELINK_STATUS_ERROR;
2763 }
2764
2765 if (flow_ctrl & ELINK_FLOW_CTRL_RX ||
2766 line_speed == ELINK_SPEED_10 ||
2767 line_speed == ELINK_SPEED_100 ||
2768 line_speed == ELINK_SPEED_1000 ||
2769 line_speed == ELINK_SPEED_2500) {
2770 REG_WR(cb, PBF_REG_P0_PAUSE_ENABLE + port*4, 1);
2771 /* Update threshold */
2772 REG_WR(cb, PBF_REG_P0_ARB_THRSH + port*4, 0);
2773 /* Update init credit */
2774 init_crd = 778; /* (800-18-4) */
2775
2776 } else {
2777 u32 thresh = (ELINK_ETH_MAX_JUMBO_PACKET_SIZE +
2778 ELINK_ETH_OVREHEAD)/16;
2779 REG_WR(cb, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
2780 /* Update threshold */
2781 REG_WR(cb, PBF_REG_P0_ARB_THRSH + port*4, thresh);
2782 /* Update init credit */
2783 switch (line_speed) {
2784 case ELINK_SPEED_10000:
2785 init_crd = thresh + 553 - 22;
2786 break;
2787 default:
2788 ELINK_DEBUG_P1(cb, "Invalid line_speed 0x%x\n",
2789 line_speed);
2790 return ELINK_STATUS_ERROR;
2791 }
2792 }
2793 REG_WR(cb, PBF_REG_P0_INIT_CRD + port*4, init_crd);
2794 ELINK_DEBUG_P2(cb, "PBF updated to speed %d credit %d\n",
2795 line_speed, init_crd);
2796
2797 /* Probe the credit changes */
2798 REG_WR(cb, PBF_REG_INIT_P0 + port*4, 0x1);
2799 MSLEEP(cb, 5);
2800 REG_WR(cb, PBF_REG_INIT_P0 + port*4, 0x0);
2801
2802 /* Enable port */
2803 REG_WR(cb, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x0);
2804 return ELINK_STATUS_OK;
2805 }
2806 #endif /* ELINK_AUX_POWER */
2807
2808 #ifndef EXCLUDE_COMMON_INIT
2809 /**
2810 * elink_get_emac_base - retrive emac base address
2811 *
2812 * @bp: driver handle
2813 * @mdc_mdio_access: access type
2814 * @port: port id
2815 *
2816 * This function selects the MDC/MDIO access (through emac0 or
2817 * emac1) depend on the mdc_mdio_access, port, port swapped. Each
2818 * phy has a default access mode, which could also be overridden
2819 * by nvram configuration. This parameter, whether this is the
2820 * default phy configuration, or the nvram overrun
2821 * configuration, is passed here as mdc_mdio_access and selects
2822 * the emac_base for the CL45 read/writes operations
2823 */
elink_get_emac_base(struct elink_dev * cb,u32 mdc_mdio_access,u8 port)2824 static u32 elink_get_emac_base(struct elink_dev *cb,
2825 u32 mdc_mdio_access, u8 port)
2826 {
2827 u32 emac_base = 0;
2828 switch (mdc_mdio_access) {
2829 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE:
2830 break;
2831 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0:
2832 if (REG_RD(cb, NIG_REG_PORT_SWAP))
2833 emac_base = GRCBASE_EMAC1;
2834 else
2835 emac_base = GRCBASE_EMAC0;
2836 break;
2837 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1:
2838 if (REG_RD(cb, NIG_REG_PORT_SWAP))
2839 emac_base = GRCBASE_EMAC0;
2840 else
2841 emac_base = GRCBASE_EMAC1;
2842 break;
2843 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH:
2844 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
2845 break;
2846 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED:
2847 emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
2848 break;
2849 default:
2850 break;
2851 }
2852 return emac_base;
2853
2854 }
2855 #endif /* EXCLUDE_COMMON_INIT */
2856
2857 /******************************************************************/
2858 /* CL22 access functions */
2859 /******************************************************************/
2860 #ifndef EXCLUDE_NON_COMMON_INIT
2861 #ifndef EXCLUDE_BCM54618SE
elink_cl22_write(struct elink_dev * cb,struct elink_phy * phy,u16 reg,u16 val)2862 static elink_status_t elink_cl22_write(struct elink_dev *cb,
2863 struct elink_phy *phy,
2864 u16 reg, u16 val)
2865 {
2866 u32 tmp, mode;
2867 u8 i;
2868 elink_status_t rc = ELINK_STATUS_OK;
2869 /* Switch to CL22 */
2870 mode = REG_RD(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
2871 REG_WR(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE,
2872 mode & ~EMAC_MDIO_MODE_CLAUSE_45);
2873
2874 /* Address */
2875 tmp = ((phy->addr << 21) | (reg << 16) | val |
2876 EMAC_MDIO_COMM_COMMAND_WRITE_22 |
2877 EMAC_MDIO_COMM_START_BUSY);
2878 REG_WR(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
2879
2880 for (i = 0; i < 50; i++) {
2881 USLEEP(cb, 10);
2882
2883 tmp = REG_RD(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
2884 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
2885 USLEEP(cb, 5);
2886 break;
2887 }
2888 }
2889 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
2890 ELINK_DEBUG_P0(cb, "write phy register failed\n");
2891 rc = ELINK_STATUS_TIMEOUT;
2892 }
2893 REG_WR(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode);
2894 return rc;
2895 }
2896
elink_cl22_read(struct elink_dev * cb,struct elink_phy * phy,u16 reg,u16 * ret_val)2897 static elink_status_t elink_cl22_read(struct elink_dev *cb,
2898 struct elink_phy *phy,
2899 u16 reg, u16 *ret_val)
2900 {
2901 u32 val, mode;
2902 u16 i;
2903 elink_status_t rc = ELINK_STATUS_OK;
2904
2905 /* Switch to CL22 */
2906 mode = REG_RD(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
2907 REG_WR(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE,
2908 mode & ~EMAC_MDIO_MODE_CLAUSE_45);
2909
2910 /* Address */
2911 val = ((phy->addr << 21) | (reg << 16) |
2912 EMAC_MDIO_COMM_COMMAND_READ_22 |
2913 EMAC_MDIO_COMM_START_BUSY);
2914 REG_WR(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
2915
2916 for (i = 0; i < 50; i++) {
2917 USLEEP(cb, 10);
2918
2919 val = REG_RD(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
2920 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
2921 *ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
2922 USLEEP(cb, 5);
2923 break;
2924 }
2925 }
2926 if (val & EMAC_MDIO_COMM_START_BUSY) {
2927 ELINK_DEBUG_P0(cb, "read phy register failed\n");
2928
2929 *ret_val = 0;
2930 rc = ELINK_STATUS_TIMEOUT;
2931 }
2932 REG_WR(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode);
2933 return rc;
2934 }
2935 #endif
2936 #endif /* EXCLUDE_NON_COMMON_INIT */
2937
2938 /******************************************************************/
2939 /* CL45 access functions */
2940 /******************************************************************/
elink_cl45_read(struct elink_dev * cb,struct elink_phy * phy,u8 devad,u16 reg,u16 * ret_val)2941 static elink_status_t elink_cl45_read(struct elink_dev *cb, struct elink_phy *phy,
2942 u8 devad, u16 reg, u16 *ret_val)
2943 {
2944 u32 val;
2945 u16 i;
2946 elink_status_t rc = ELINK_STATUS_OK;
2947 #ifndef ELINK_AUX_POWER
2948 u32 chip_id;
2949 if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA_G) {
2950 chip_id = (REG_RD(cb, MISC_REG_CHIP_NUM) << 16) |
2951 ((REG_RD(cb, MISC_REG_CHIP_REV) & 0xf) << 12);
2952 elink_set_mdio_clk(cb, chip_id, phy->mdio_ctrl);
2953 }
2954 #endif /* ELINK_AUX_POWER */
2955
2956 if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA_B0)
2957 elink_bits_en(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
2958 EMAC_MDIO_STATUS_10MB);
2959 /* Address */
2960 val = ((phy->addr << 21) | (devad << 16) | reg |
2961 EMAC_MDIO_COMM_COMMAND_ADDRESS |
2962 EMAC_MDIO_COMM_START_BUSY);
2963 REG_WR(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
2964
2965 for (i = 0; i < 50; i++) {
2966 USLEEP(cb, 10);
2967
2968 val = REG_RD(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
2969 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
2970 USLEEP(cb, 5);
2971 break;
2972 }
2973 }
2974 if (val & EMAC_MDIO_COMM_START_BUSY) {
2975 ELINK_DEBUG_P0(cb, "read phy register failed\n");
2976 elink_cb_event_log(cb, ELINK_LOG_ID_MDIO_ACCESS_TIMEOUT); // "MDC/MDIO access timeout\n"
2977
2978 *ret_val = 0;
2979 rc = ELINK_STATUS_TIMEOUT;
2980 } else {
2981 /* Data */
2982 val = ((phy->addr << 21) | (devad << 16) |
2983 EMAC_MDIO_COMM_COMMAND_READ_45 |
2984 EMAC_MDIO_COMM_START_BUSY);
2985 REG_WR(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
2986
2987 for (i = 0; i < 50; i++) {
2988 USLEEP(cb, 10);
2989
2990 val = REG_RD(cb, phy->mdio_ctrl +
2991 EMAC_REG_EMAC_MDIO_COMM);
2992 if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
2993 *ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
2994 break;
2995 }
2996 }
2997 if (val & EMAC_MDIO_COMM_START_BUSY) {
2998 ELINK_DEBUG_P0(cb, "read phy register failed\n");
2999 elink_cb_event_log(cb, ELINK_LOG_ID_MDIO_ACCESS_TIMEOUT); // "MDC/MDIO access timeout\n"
3000
3001 *ret_val = 0;
3002 rc = ELINK_STATUS_TIMEOUT;
3003 }
3004 }
3005 /* Work around for E3 A0 */
3006 if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA) {
3007 phy->flags ^= ELINK_FLAGS_DUMMY_READ;
3008 if (phy->flags & ELINK_FLAGS_DUMMY_READ) {
3009 u16 temp_val;
3010 elink_cl45_read(cb, phy, devad, 0xf, &temp_val);
3011 }
3012 }
3013
3014 if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA_B0)
3015 elink_bits_dis(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
3016 EMAC_MDIO_STATUS_10MB);
3017 return rc;
3018 }
3019
elink_cl45_write(struct elink_dev * cb,struct elink_phy * phy,u8 devad,u16 reg,u16 val)3020 static elink_status_t elink_cl45_write(struct elink_dev *cb, struct elink_phy *phy,
3021 u8 devad, u16 reg, u16 val)
3022 {
3023 u32 tmp;
3024 u8 i;
3025 elink_status_t rc = ELINK_STATUS_OK;
3026 #ifndef ELINK_AUX_POWER
3027 u32 chip_id;
3028 if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA_G) {
3029 chip_id = (REG_RD(cb, MISC_REG_CHIP_NUM) << 16) |
3030 ((REG_RD(cb, MISC_REG_CHIP_REV) & 0xf) << 12);
3031 elink_set_mdio_clk(cb, chip_id, phy->mdio_ctrl);
3032 }
3033 #endif /* ELINK_AUX_POWER */
3034
3035 if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA_B0)
3036 elink_bits_en(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
3037 EMAC_MDIO_STATUS_10MB);
3038
3039 /* Address */
3040 tmp = ((phy->addr << 21) | (devad << 16) | reg |
3041 EMAC_MDIO_COMM_COMMAND_ADDRESS |
3042 EMAC_MDIO_COMM_START_BUSY);
3043 REG_WR(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
3044
3045 for (i = 0; i < 50; i++) {
3046 USLEEP(cb, 10);
3047
3048 tmp = REG_RD(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
3049 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
3050 USLEEP(cb, 5);
3051 break;
3052 }
3053 }
3054 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
3055 ELINK_DEBUG_P0(cb, "write phy register failed\n");
3056 elink_cb_event_log(cb, ELINK_LOG_ID_MDIO_ACCESS_TIMEOUT); // "MDC/MDIO access timeout\n"
3057
3058 rc = ELINK_STATUS_TIMEOUT;
3059 } else {
3060 /* Data */
3061 tmp = ((phy->addr << 21) | (devad << 16) | val |
3062 EMAC_MDIO_COMM_COMMAND_WRITE_45 |
3063 EMAC_MDIO_COMM_START_BUSY);
3064 REG_WR(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
3065
3066 for (i = 0; i < 50; i++) {
3067 USLEEP(cb, 10);
3068
3069 tmp = REG_RD(cb, phy->mdio_ctrl +
3070 EMAC_REG_EMAC_MDIO_COMM);
3071 if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
3072 USLEEP(cb, 5);
3073 break;
3074 }
3075 }
3076 if (tmp & EMAC_MDIO_COMM_START_BUSY) {
3077 ELINK_DEBUG_P0(cb, "write phy register failed\n");
3078 elink_cb_event_log(cb, ELINK_LOG_ID_MDIO_ACCESS_TIMEOUT); // "MDC/MDIO access timeout\n"
3079
3080 rc = ELINK_STATUS_TIMEOUT;
3081 }
3082 }
3083 /* Work around for E3 A0 */
3084 if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA) {
3085 phy->flags ^= ELINK_FLAGS_DUMMY_READ;
3086 if (phy->flags & ELINK_FLAGS_DUMMY_READ) {
3087 u16 temp_val;
3088 elink_cl45_read(cb, phy, devad, 0xf, &temp_val);
3089 }
3090 }
3091 if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA_B0)
3092 elink_bits_dis(cb, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
3093 EMAC_MDIO_STATUS_10MB);
3094 return rc;
3095 }
3096
3097 /******************************************************************/
3098 /* EEE section */
3099 /******************************************************************/
3100 #ifndef EXCLUDE_NON_COMMON_INIT
3101 #ifndef EXCLUDE_WARPCORE
elink_eee_has_cap(struct elink_params * params)3102 static u8 elink_eee_has_cap(struct elink_params *params)
3103 {
3104 struct elink_dev *cb = params->cb;
3105
3106 if (REG_RD(cb, params->shmem2_base) <=
3107 OFFSETOF(struct shmem2_region, eee_status[params->port]))
3108 return 0;
3109
3110 return 1;
3111 }
3112
elink_eee_nvram_to_time(u32 nvram_mode,u32 * idle_timer)3113 static elink_status_t elink_eee_nvram_to_time(u32 nvram_mode, u32 *idle_timer)
3114 {
3115 switch (nvram_mode) {
3116 case PORT_FEAT_CFG_EEE_POWER_MODE_BALANCED:
3117 *idle_timer = ELINK_EEE_MODE_NVRAM_BALANCED_TIME;
3118 break;
3119 case PORT_FEAT_CFG_EEE_POWER_MODE_AGGRESSIVE:
3120 *idle_timer = ELINK_EEE_MODE_NVRAM_AGGRESSIVE_TIME;
3121 break;
3122 case PORT_FEAT_CFG_EEE_POWER_MODE_LOW_LATENCY:
3123 *idle_timer = ELINK_EEE_MODE_NVRAM_LATENCY_TIME;
3124 break;
3125 default:
3126 *idle_timer = 0;
3127 break;
3128 }
3129
3130 return ELINK_STATUS_OK;
3131 }
3132
elink_eee_time_to_nvram(u32 idle_timer,u32 * nvram_mode)3133 static elink_status_t elink_eee_time_to_nvram(u32 idle_timer, u32 *nvram_mode)
3134 {
3135 switch (idle_timer) {
3136 case ELINK_EEE_MODE_NVRAM_BALANCED_TIME:
3137 *nvram_mode = PORT_FEAT_CFG_EEE_POWER_MODE_BALANCED;
3138 break;
3139 case ELINK_EEE_MODE_NVRAM_AGGRESSIVE_TIME:
3140 *nvram_mode = PORT_FEAT_CFG_EEE_POWER_MODE_AGGRESSIVE;
3141 break;
3142 case ELINK_EEE_MODE_NVRAM_LATENCY_TIME:
3143 *nvram_mode = PORT_FEAT_CFG_EEE_POWER_MODE_LOW_LATENCY;
3144 break;
3145 default:
3146 *nvram_mode = PORT_FEAT_CFG_EEE_POWER_MODE_DISABLED;
3147 break;
3148 }
3149
3150 return ELINK_STATUS_OK;
3151 }
3152
elink_eee_calc_timer(struct elink_params * params)3153 static u32 elink_eee_calc_timer(struct elink_params *params)
3154 {
3155 u32 eee_mode, eee_idle;
3156 struct elink_dev *cb = params->cb;
3157
3158 if (params->eee_mode & ELINK_EEE_MODE_OVERRIDE_NVRAM) {
3159 if (params->eee_mode & ELINK_EEE_MODE_OUTPUT_TIME) {
3160 /* time value in eee_mode --> used directly*/
3161 eee_idle = params->eee_mode & ELINK_EEE_MODE_TIMER_MASK;
3162 } else {
3163 /* hsi value in eee_mode --> time */
3164 if (elink_eee_nvram_to_time(params->eee_mode &
3165 ELINK_EEE_MODE_NVRAM_MASK,
3166 &eee_idle))
3167 return 0;
3168 }
3169 } else {
3170 /* hsi values in nvram --> time*/
3171 eee_mode = ((REG_RD(cb, params->shmem_base +
3172 OFFSETOF(struct shmem_region, dev_info.
3173 port_feature_config[params->port].
3174 eee_power_mode)) &
3175 PORT_FEAT_CFG_EEE_POWER_MODE_MASK) >>
3176 PORT_FEAT_CFG_EEE_POWER_MODE_SHIFT);
3177
3178 if (elink_eee_nvram_to_time(eee_mode, &eee_idle))
3179 return 0;
3180 }
3181
3182 return eee_idle;
3183 }
3184
elink_eee_set_timers(struct elink_params * params,struct elink_vars * vars)3185 static elink_status_t elink_eee_set_timers(struct elink_params *params,
3186 struct elink_vars *vars)
3187 {
3188 u32 eee_idle = 0, eee_mode;
3189 struct elink_dev *cb = params->cb;
3190
3191 eee_idle = elink_eee_calc_timer(params);
3192
3193 if (eee_idle) {
3194 REG_WR(cb, MISC_REG_CPMU_LP_IDLE_THR_P0 + (params->port << 2),
3195 eee_idle);
3196 } else if ((params->eee_mode & ELINK_EEE_MODE_ENABLE_LPI) &&
3197 (params->eee_mode & ELINK_EEE_MODE_OVERRIDE_NVRAM) &&
3198 (params->eee_mode & ELINK_EEE_MODE_OUTPUT_TIME)) {
3199 ELINK_DEBUG_P0(cb, "Error: Tx LPI is enabled with timer 0\n");
3200 return ELINK_STATUS_ERROR;
3201 }
3202
3203 vars->eee_status &= ~(SHMEM_EEE_TIMER_MASK | SHMEM_EEE_TIME_OUTPUT_BIT);
3204 if (params->eee_mode & ELINK_EEE_MODE_OUTPUT_TIME) {
3205 /* eee_idle in 1u --> eee_status in 16u */
3206 eee_idle >>= 4;
3207 vars->eee_status |= (eee_idle & SHMEM_EEE_TIMER_MASK) |
3208 SHMEM_EEE_TIME_OUTPUT_BIT;
3209 } else {
3210 if (elink_eee_time_to_nvram(eee_idle, &eee_mode))
3211 return ELINK_STATUS_ERROR;
3212 vars->eee_status |= eee_mode;
3213 }
3214
3215 return ELINK_STATUS_OK;
3216 }
3217
elink_eee_initial_config(struct elink_params * params,struct elink_vars * vars,u8 mode)3218 static elink_status_t elink_eee_initial_config(struct elink_params *params,
3219 struct elink_vars *vars, u8 mode)
3220 {
3221 vars->eee_status |= ((u32) mode) << SHMEM_EEE_SUPPORTED_SHIFT;
3222
3223 /* Propogate params' bits --> vars (for migration exposure) */
3224 if (params->eee_mode & ELINK_EEE_MODE_ENABLE_LPI)
3225 vars->eee_status |= SHMEM_EEE_LPI_REQUESTED_BIT;
3226 else
3227 vars->eee_status &= ~SHMEM_EEE_LPI_REQUESTED_BIT;
3228
3229 if (params->eee_mode & ELINK_EEE_MODE_ADV_LPI)
3230 vars->eee_status |= SHMEM_EEE_REQUESTED_BIT;
3231 else
3232 vars->eee_status &= ~SHMEM_EEE_REQUESTED_BIT;
3233
3234 return elink_eee_set_timers(params, vars);
3235 }
3236
elink_eee_disable(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)3237 static elink_status_t elink_eee_disable(struct elink_phy *phy,
3238 struct elink_params *params,
3239 struct elink_vars *vars)
3240 {
3241 struct elink_dev *cb = params->cb;
3242
3243 /* Make Certain LPI is disabled */
3244 REG_WR(cb, MISC_REG_CPMU_LP_FW_ENABLE_P0 + (params->port << 2), 0);
3245
3246 elink_cl45_write(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_EEE_ADV, 0x0);
3247
3248 vars->eee_status &= ~SHMEM_EEE_ADV_STATUS_MASK;
3249
3250 return ELINK_STATUS_OK;
3251 }
3252
elink_eee_advertise(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars,u8 modes)3253 static elink_status_t elink_eee_advertise(struct elink_phy *phy,
3254 struct elink_params *params,
3255 struct elink_vars *vars, u8 modes)
3256 {
3257 struct elink_dev *cb = params->cb;
3258 u16 val = 0;
3259
3260 /* Mask events preventing LPI generation */
3261 REG_WR(cb, MISC_REG_CPMU_LP_MASK_EXT_P0 + (params->port << 2), 0xfc20);
3262
3263 if (modes & SHMEM_EEE_10G_ADV) {
3264 ELINK_DEBUG_P0(cb, "Advertise 10GBase-T EEE\n");
3265 val |= 0x8;
3266 }
3267 if (modes & SHMEM_EEE_1G_ADV) {
3268 ELINK_DEBUG_P0(cb, "Advertise 1GBase-T EEE\n");
3269 val |= 0x4;
3270 }
3271
3272 elink_cl45_write(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_EEE_ADV, val);
3273
3274 vars->eee_status &= ~SHMEM_EEE_ADV_STATUS_MASK;
3275 vars->eee_status |= (modes << SHMEM_EEE_ADV_STATUS_SHIFT);
3276
3277 return ELINK_STATUS_OK;
3278 }
3279
elink_update_mng_eee(struct elink_params * params,u32 eee_status)3280 static void elink_update_mng_eee(struct elink_params *params, u32 eee_status)
3281 {
3282 struct elink_dev *cb = params->cb;
3283
3284 if (elink_eee_has_cap(params))
3285 REG_WR(cb, params->shmem2_base +
3286 OFFSETOF(struct shmem2_region,
3287 eee_status[params->port]), eee_status);
3288 }
3289
elink_eee_an_resolve(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)3290 static void elink_eee_an_resolve(struct elink_phy *phy,
3291 struct elink_params *params,
3292 struct elink_vars *vars)
3293 {
3294 struct elink_dev *cb = params->cb;
3295 u16 adv = 0, lp = 0;
3296 u32 lp_adv = 0;
3297 u8 neg = 0;
3298
3299 elink_cl45_read(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_EEE_ADV, &adv);
3300 elink_cl45_read(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_LP_EEE_ADV, &lp);
3301
3302 if (lp & 0x2) {
3303 lp_adv |= SHMEM_EEE_100M_ADV;
3304 if (adv & 0x2) {
3305 if (vars->line_speed == ELINK_SPEED_100)
3306 neg = 1;
3307 ELINK_DEBUG_P0(cb, "EEE negotiated - 100M\n");
3308 }
3309 }
3310 if (lp & 0x14) {
3311 lp_adv |= SHMEM_EEE_1G_ADV;
3312 if (adv & 0x14) {
3313 if (vars->line_speed == ELINK_SPEED_1000)
3314 neg = 1;
3315 ELINK_DEBUG_P0(cb, "EEE negotiated - 1G\n");
3316 }
3317 }
3318 if (lp & 0x68) {
3319 lp_adv |= SHMEM_EEE_10G_ADV;
3320 if (adv & 0x68) {
3321 if (vars->line_speed == ELINK_SPEED_10000)
3322 neg = 1;
3323 ELINK_DEBUG_P0(cb, "EEE negotiated - 10G\n");
3324 }
3325 }
3326
3327 vars->eee_status &= ~SHMEM_EEE_LP_ADV_STATUS_MASK;
3328 vars->eee_status |= (lp_adv << SHMEM_EEE_LP_ADV_STATUS_SHIFT);
3329
3330 if (neg) {
3331 ELINK_DEBUG_P0(cb, "EEE is active\n");
3332 vars->eee_status |= SHMEM_EEE_ACTIVE_BIT;
3333 }
3334 }
3335
3336 /******************************************************************/
3337 /* BSC access functions from E3 */
3338 /******************************************************************/
elink_bsc_module_sel(struct elink_params * params)3339 static void elink_bsc_module_sel(struct elink_params *params)
3340 {
3341 int idx;
3342 u32 board_cfg, sfp_ctrl;
3343 u32 i2c_pins[I2C_SWITCH_WIDTH], i2c_val[I2C_SWITCH_WIDTH];
3344 struct elink_dev *cb = params->cb;
3345 u8 port = params->port;
3346 /* Read I2C output PINs */
3347 board_cfg = REG_RD(cb, params->shmem_base +
3348 OFFSETOF(struct shmem_region,
3349 dev_info.shared_hw_config.board));
3350 i2c_pins[I2C_BSC0] = board_cfg & SHARED_HW_CFG_E3_I2C_MUX0_MASK;
3351 i2c_pins[I2C_BSC1] = (board_cfg & SHARED_HW_CFG_E3_I2C_MUX1_MASK) >>
3352 SHARED_HW_CFG_E3_I2C_MUX1_SHIFT;
3353
3354 /* Read I2C output value */
3355 sfp_ctrl = REG_RD(cb, params->shmem_base +
3356 OFFSETOF(struct shmem_region,
3357 dev_info.port_hw_config[port].e3_cmn_pin_cfg));
3358 i2c_val[I2C_BSC0] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX0_MASK) > 0;
3359 i2c_val[I2C_BSC1] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX1_MASK) > 0;
3360 ELINK_DEBUG_P0(cb, "Setting BSC switch\n");
3361 for (idx = 0; idx < I2C_SWITCH_WIDTH; idx++)
3362 elink_set_cfg_pin(cb, i2c_pins[idx], i2c_val[idx]);
3363 }
3364
elink_bsc_read(struct elink_params * params,struct elink_dev * cb,u8 sl_devid,u16 sl_addr,u8 lc_addr,u8 xfer_cnt,u32 * data_array)3365 static elink_status_t elink_bsc_read(struct elink_params *params,
3366 struct elink_dev *cb,
3367 u8 sl_devid,
3368 u16 sl_addr,
3369 u8 lc_addr,
3370 u8 xfer_cnt,
3371 u32 *data_array)
3372 {
3373 u32 val, i;
3374 elink_status_t rc = ELINK_STATUS_OK;
3375
3376 if (xfer_cnt > 16) {
3377 ELINK_DEBUG_P1(cb, "invalid xfer_cnt %d. Max is 16 bytes\n",
3378 xfer_cnt);
3379 return ELINK_STATUS_ERROR;
3380 }
3381 if (params)
3382 elink_bsc_module_sel(params);
3383
3384 xfer_cnt = 16 - lc_addr;
3385
3386 /* Enable the engine */
3387 val = REG_RD(cb, MCP_REG_MCPR_IMC_COMMAND);
3388 val |= MCPR_IMC_COMMAND_ENABLE;
3389 REG_WR(cb, MCP_REG_MCPR_IMC_COMMAND, val);
3390
3391 /* Program slave device ID */
3392 val = (sl_devid << 16) | sl_addr;
3393 REG_WR(cb, MCP_REG_MCPR_IMC_SLAVE_CONTROL, val);
3394
3395 /* Start xfer with 0 byte to update the address pointer ???*/
3396 val = (MCPR_IMC_COMMAND_ENABLE) |
3397 (MCPR_IMC_COMMAND_WRITE_OP <<
3398 MCPR_IMC_COMMAND_OPERATION_BITSHIFT) |
3399 (lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) | (0);
3400 REG_WR(cb, MCP_REG_MCPR_IMC_COMMAND, val);
3401
3402 /* Poll for completion */
3403 i = 0;
3404 val = REG_RD(cb, MCP_REG_MCPR_IMC_COMMAND);
3405 while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) {
3406 USLEEP(cb, 10);
3407 val = REG_RD(cb, MCP_REG_MCPR_IMC_COMMAND);
3408 if (i++ > 1000) {
3409 ELINK_DEBUG_P1(cb, "wr 0 byte timed out after %d try\n",
3410 i);
3411 rc = ELINK_STATUS_TIMEOUT;
3412 break;
3413 }
3414 }
3415 if (rc == ELINK_STATUS_TIMEOUT)
3416 return rc;
3417
3418 /* Start xfer with read op */
3419 val = (MCPR_IMC_COMMAND_ENABLE) |
3420 (MCPR_IMC_COMMAND_READ_OP <<
3421 MCPR_IMC_COMMAND_OPERATION_BITSHIFT) |
3422 (lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) |
3423 (xfer_cnt);
3424 REG_WR(cb, MCP_REG_MCPR_IMC_COMMAND, val);
3425
3426 /* Poll for completion */
3427 i = 0;
3428 val = REG_RD(cb, MCP_REG_MCPR_IMC_COMMAND);
3429 while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) {
3430 USLEEP(cb, 10);
3431 val = REG_RD(cb, MCP_REG_MCPR_IMC_COMMAND);
3432 if (i++ > 1000) {
3433 ELINK_DEBUG_P1(cb, "rd op timed out after %d try\n", i);
3434 rc = ELINK_STATUS_TIMEOUT;
3435 break;
3436 }
3437 }
3438 if (rc == ELINK_STATUS_TIMEOUT)
3439 return rc;
3440
3441 for (i = (lc_addr >> 2); i < 4; i++) {
3442 data_array[i] = REG_RD(cb, (MCP_REG_MCPR_IMC_DATAREG0 + i*4));
3443 #ifdef BIG_ENDIAN
3444 data_array[i] = ((data_array[i] & 0x000000ff) << 24) |
3445 ((data_array[i] & 0x0000ff00) << 8) |
3446 ((data_array[i] & 0x00ff0000) >> 8) |
3447 ((data_array[i] & 0xff000000) >> 24);
3448 #endif
3449 }
3450 return rc;
3451 }
3452
3453 #endif /* EXCLUDE_WARPCORE */
3454 #endif /* EXCLUDE_NON_COMMON_INIT */
3455 #if !defined(EXCLUDE_NON_COMMON_INIT) || defined(INCLUDE_WARPCORE_UC_LOAD)
elink_cl45_read_or_write(struct elink_dev * cb,struct elink_phy * phy,u8 devad,u16 reg,u16 or_val)3456 static void elink_cl45_read_or_write(struct elink_dev *cb, struct elink_phy *phy,
3457 u8 devad, u16 reg, u16 or_val)
3458 {
3459 u16 val;
3460 elink_cl45_read(cb, phy, devad, reg, &val);
3461 elink_cl45_write(cb, phy, devad, reg, val | or_val);
3462 }
3463
elink_cl45_read_and_write(struct elink_dev * cb,struct elink_phy * phy,u8 devad,u16 reg,u16 and_val)3464 static void elink_cl45_read_and_write(struct elink_dev *cb,
3465 struct elink_phy *phy,
3466 u8 devad, u16 reg, u16 and_val)
3467 {
3468 u16 val;
3469 elink_cl45_read(cb, phy, devad, reg, &val);
3470 elink_cl45_write(cb, phy, devad, reg, val & and_val);
3471 }
3472 #endif
3473
3474 #ifdef ELINK_ENHANCEMENTS
elink_phy_read(struct elink_params * params,u8 phy_addr,u8 devad,u16 reg,u16 * ret_val)3475 elink_status_t elink_phy_read(struct elink_params *params, u8 phy_addr,
3476 u8 devad, u16 reg, u16 *ret_val)
3477 {
3478 u8 phy_index;
3479 /* Probe for the phy according to the given phy_addr, and execute
3480 * the read request on it
3481 */
3482 for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
3483 if (params->phy[phy_index].addr == phy_addr) {
3484 return elink_cl45_read(params->cb,
3485 ¶ms->phy[phy_index], devad,
3486 reg, ret_val);
3487 }
3488 }
3489 return ELINK_STATUS_ERROR;
3490 }
3491
elink_phy_write(struct elink_params * params,u8 phy_addr,u8 devad,u16 reg,u16 val)3492 elink_status_t elink_phy_write(struct elink_params *params, u8 phy_addr,
3493 u8 devad, u16 reg, u16 val)
3494 {
3495 u8 phy_index;
3496 /* Probe for the phy according to the given phy_addr, and execute
3497 * the write request on it
3498 */
3499 for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
3500 if (params->phy[phy_index].addr == phy_addr) {
3501 return elink_cl45_write(params->cb,
3502 ¶ms->phy[phy_index], devad,
3503 reg, val);
3504 }
3505 }
3506 return ELINK_STATUS_ERROR;
3507 }
3508 #endif // ELINK_ENHANCEMENTS
3509
3510 #if (!defined EXCLUDE_NON_COMMON_INIT) || (!defined EXCLUDE_WARPCORE)
elink_get_warpcore_lane(struct elink_phy * phy,struct elink_params * params)3511 static u8 elink_get_warpcore_lane(struct elink_phy *phy,
3512 struct elink_params *params)
3513 {
3514 u8 lane = 0;
3515 #ifndef EXCLUDE_WARPCORE
3516 struct elink_dev *cb = params->cb;
3517 u32 path_swap, path_swap_ovr;
3518 u8 path, port;
3519
3520 path = PATH_ID(cb);
3521 port = params->port;
3522
3523 if (elink_is_4_port_mode(cb)) {
3524 u32 port_swap, port_swap_ovr;
3525
3526 /* Figure out path swap value */
3527 path_swap_ovr = REG_RD(cb, MISC_REG_FOUR_PORT_PATH_SWAP_OVWR);
3528 if (path_swap_ovr & 0x1)
3529 path_swap = (path_swap_ovr & 0x2);
3530 else
3531 path_swap = REG_RD(cb, MISC_REG_FOUR_PORT_PATH_SWAP);
3532
3533 if (path_swap)
3534 path = path ^ 1;
3535
3536 /* Figure out port swap value */
3537 port_swap_ovr = REG_RD(cb, MISC_REG_FOUR_PORT_PORT_SWAP_OVWR);
3538 if (port_swap_ovr & 0x1)
3539 port_swap = (port_swap_ovr & 0x2);
3540 else
3541 port_swap = REG_RD(cb, MISC_REG_FOUR_PORT_PORT_SWAP);
3542
3543 if (port_swap)
3544 port = port ^ 1;
3545
3546 lane = (port<<1) + path;
3547 } else { /* Two port mode - no port swap */
3548
3549 /* Figure out path swap value */
3550 path_swap_ovr =
3551 REG_RD(cb, MISC_REG_TWO_PORT_PATH_SWAP_OVWR);
3552 if (path_swap_ovr & 0x1) {
3553 path_swap = (path_swap_ovr & 0x2);
3554 } else {
3555 path_swap =
3556 REG_RD(cb, MISC_REG_TWO_PORT_PATH_SWAP);
3557 }
3558 if (path_swap)
3559 path = path ^ 1;
3560
3561 lane = path << 1 ;
3562 }
3563 #endif /* #ifndef EXCLUDE_WARPCORE */
3564 return lane;
3565 }
3566
3567
elink_set_aer_mmd(struct elink_params * params,struct elink_phy * phy)3568 static void elink_set_aer_mmd(struct elink_params *params,
3569 struct elink_phy *phy)
3570 {
3571 u32 ser_lane;
3572 u16 offset, aer_val;
3573 struct elink_dev *cb = params->cb;
3574 ser_lane = ((params->lane_config &
3575 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
3576 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
3577
3578 offset = (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ?
3579 (phy->addr + ser_lane) : 0;
3580
3581 if (ELINK_USES_WARPCORE(params->chip_id)) {
3582 aer_val = elink_get_warpcore_lane(phy, params);
3583 /* In Dual-lane mode, two lanes are joined together,
3584 * so in order to configure them, the AER broadcast method is
3585 * used here.
3586 * 0x200 is the broadcast address for lanes 0,1
3587 * 0x201 is the broadcast address for lanes 2,3
3588 */
3589 if (phy->flags & ELINK_FLAGS_WC_DUAL_MODE)
3590 aer_val = (aer_val >> 1) | 0x200;
3591 } else if (CHIP_IS_E2(params->chip_id))
3592 aer_val = 0x3800 + offset - 1;
3593 else
3594 aer_val = 0x3800 + offset;
3595
3596 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
3597 MDIO_AER_BLOCK_AER_REG, aer_val);
3598
3599 }
3600 #endif
3601 #ifndef EXCLUDE_SERDES
3602
3603 /******************************************************************/
3604 /* Internal phy section */
3605 /******************************************************************/
3606
elink_set_serdes_access(struct elink_dev * cb,u8 port)3607 static void elink_set_serdes_access(struct elink_dev *cb, u8 port)
3608 {
3609 u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
3610
3611 /* Set Clause 22 */
3612 REG_WR(cb, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 1);
3613 REG_WR(cb, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000);
3614 USLEEP(cb, 500);
3615 REG_WR(cb, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f);
3616 USLEEP(cb, 500);
3617 /* Set Clause 45 */
3618 REG_WR(cb, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 0);
3619 }
3620
elink_serdes_deassert(struct elink_dev * cb,u8 port)3621 static void elink_serdes_deassert(struct elink_dev *cb, u8 port)
3622 {
3623 u32 val;
3624
3625 ELINK_DEBUG_P0(cb, "elink_serdes_deassert\n");
3626
3627 val = ELINK_SERDES_RESET_BITS << (port*16);
3628
3629 /* Reset and unreset the SerDes/XGXS */
3630 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
3631 USLEEP(cb, 500);
3632 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
3633
3634 elink_set_serdes_access(cb, port);
3635
3636 REG_WR(cb, NIG_REG_SERDES0_CTRL_MD_DEVAD + port*0x10,
3637 ELINK_DEFAULT_PHY_DEV_ADDR);
3638 }
3639 #endif /* #ifndef EXCLUDE_SERDES */
3640
3641 #ifndef EXCLUDE_NON_COMMON_INIT
3642 #ifndef EXCLUDE_XGXS
elink_xgxs_specific_func(struct elink_phy * phy,struct elink_params * params,u32 action)3643 static void elink_xgxs_specific_func(struct elink_phy *phy,
3644 struct elink_params *params,
3645 u32 action)
3646 {
3647 struct elink_dev *cb = params->cb;
3648 switch (action) {
3649 case ELINK_PHY_INIT:
3650 /* Set correct devad */
3651 REG_WR(cb, NIG_REG_XGXS0_CTRL_MD_ST + params->port*0x18, 0);
3652 REG_WR(cb, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
3653 phy->def_md_devad);
3654 break;
3655 }
3656 }
3657
elink_xgxs_deassert(struct elink_params * params)3658 static void elink_xgxs_deassert(struct elink_params *params)
3659 {
3660 struct elink_dev *cb = params->cb;
3661 u8 port;
3662 u32 val;
3663 ELINK_DEBUG_P0(cb, "elink_xgxs_deassert\n");
3664 port = params->port;
3665
3666 val = ELINK_XGXS_RESET_BITS << (port*16);
3667
3668 /* Reset and unreset the SerDes/XGXS */
3669 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
3670 USLEEP(cb, 500);
3671 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
3672 elink_xgxs_specific_func(¶ms->phy[ELINK_INT_PHY], params,
3673 ELINK_PHY_INIT);
3674 }
3675 #endif // EXCLUDE_XGXS
3676
elink_calc_ieee_aneg_adv(struct elink_phy * phy,struct elink_params * params,u16 * ieee_fc)3677 static void elink_calc_ieee_aneg_adv(struct elink_phy *phy,
3678 struct elink_params *params, u16 *ieee_fc)
3679 {
3680 #ifdef ELINK_DEBUG
3681 struct elink_dev *cb = params->cb;
3682 #endif
3683 *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
3684 /* Resolve pause mode and advertisement Please refer to Table
3685 * 28B-3 of the 802.3ab-1999 spec
3686 */
3687
3688 switch (phy->req_flow_ctrl) {
3689 case ELINK_FLOW_CTRL_AUTO:
3690 switch (params->req_fc_auto_adv) {
3691 case ELINK_FLOW_CTRL_BOTH:
3692 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
3693 break;
3694 case ELINK_FLOW_CTRL_RX:
3695 case ELINK_FLOW_CTRL_TX:
3696 *ieee_fc |=
3697 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
3698 break;
3699 default:
3700 break;
3701 }
3702 break;
3703 case ELINK_FLOW_CTRL_TX:
3704 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
3705 break;
3706
3707 case ELINK_FLOW_CTRL_RX:
3708 case ELINK_FLOW_CTRL_BOTH:
3709 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
3710 break;
3711
3712 case ELINK_FLOW_CTRL_NONE:
3713 default:
3714 *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
3715 break;
3716 }
3717 ELINK_DEBUG_P1(cb, "ieee_fc = 0x%x\n", *ieee_fc);
3718 }
3719 #endif /* #ifndef EXCLUDE_NON_COMMON_INIT */
3720
set_phy_vars(struct elink_params * params,struct elink_vars * vars)3721 static void set_phy_vars(struct elink_params *params,
3722 struct elink_vars *vars)
3723 {
3724 #ifdef ELINK_DEBUG
3725 struct elink_dev *cb = params->cb;
3726 #endif
3727 u8 actual_phy_idx, phy_index, link_cfg_idx;
3728 u8 phy_config_swapped = params->multi_phy_config &
3729 PORT_HW_CFG_PHY_SWAPPED_ENABLED;
3730 for (phy_index = ELINK_INT_PHY; phy_index < params->num_phys;
3731 phy_index++) {
3732 link_cfg_idx = ELINK_LINK_CONFIG_IDX(phy_index);
3733 actual_phy_idx = phy_index;
3734 if (phy_config_swapped) {
3735 if (phy_index == ELINK_EXT_PHY1)
3736 actual_phy_idx = ELINK_EXT_PHY2;
3737 else if (phy_index == ELINK_EXT_PHY2)
3738 actual_phy_idx = ELINK_EXT_PHY1;
3739 }
3740 params->phy[actual_phy_idx].req_flow_ctrl =
3741 params->req_flow_ctrl[link_cfg_idx];
3742
3743 params->phy[actual_phy_idx].req_line_speed =
3744 params->req_line_speed[link_cfg_idx];
3745
3746 params->phy[actual_phy_idx].speed_cap_mask =
3747 params->speed_cap_mask[link_cfg_idx];
3748
3749 params->phy[actual_phy_idx].req_duplex =
3750 params->req_duplex[link_cfg_idx];
3751
3752 if (params->req_line_speed[link_cfg_idx] ==
3753 ELINK_SPEED_AUTO_NEG)
3754 vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
3755
3756 ELINK_DEBUG_P3(cb, "req_flow_ctrl %x, req_line_speed %x,"
3757 " speed_cap_mask %x\n",
3758 params->phy[actual_phy_idx].req_flow_ctrl,
3759 params->phy[actual_phy_idx].req_line_speed,
3760 params->phy[actual_phy_idx].speed_cap_mask);
3761 }
3762 }
3763
3764 #ifndef EXCLUDE_NON_COMMON_INIT
elink_ext_phy_set_pause(struct elink_params * params,struct elink_phy * phy,struct elink_vars * vars)3765 static void elink_ext_phy_set_pause(struct elink_params *params,
3766 struct elink_phy *phy,
3767 struct elink_vars *vars)
3768 {
3769 u16 val;
3770 struct elink_dev *cb = params->cb;
3771 /* Read modify write pause advertizing */
3772 elink_cl45_read(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val);
3773
3774 val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
3775
3776 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
3777 elink_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
3778 if ((vars->ieee_fc &
3779 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
3780 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
3781 val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
3782 }
3783 if ((vars->ieee_fc &
3784 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
3785 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
3786 val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
3787 }
3788 ELINK_DEBUG_P1(cb, "Ext phy AN advertize 0x%x\n", val);
3789 elink_cl45_write(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val);
3790 }
3791
elink_pause_resolve(struct elink_vars * vars,u32 pause_result)3792 static void elink_pause_resolve(struct elink_vars *vars, u32 pause_result)
3793 { /* LD LP */
3794 switch (pause_result) { /* ASYM P ASYM P */
3795 case 0xb: /* 1 0 1 1 */
3796 vars->flow_ctrl = ELINK_FLOW_CTRL_TX;
3797 break;
3798
3799 case 0xe: /* 1 1 1 0 */
3800 vars->flow_ctrl = ELINK_FLOW_CTRL_RX;
3801 break;
3802
3803 case 0x5: /* 0 1 0 1 */
3804 case 0x7: /* 0 1 1 1 */
3805 case 0xd: /* 1 1 0 1 */
3806 case 0xf: /* 1 1 1 1 */
3807 vars->flow_ctrl = ELINK_FLOW_CTRL_BOTH;
3808 break;
3809
3810 default:
3811 break;
3812 }
3813 if (pause_result & (1<<0))
3814 vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
3815 if (pause_result & (1<<1))
3816 vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
3817
3818 }
3819
elink_ext_phy_update_adv_fc(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)3820 static void elink_ext_phy_update_adv_fc(struct elink_phy *phy,
3821 struct elink_params *params,
3822 struct elink_vars *vars)
3823 {
3824 u16 ld_pause; /* local */
3825 u16 lp_pause; /* link partner */
3826 u16 pause_result;
3827 struct elink_dev *cb = params->cb;
3828 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) {
3829 #ifndef EXCLUDE_BCM54618SE
3830 elink_cl22_read(cb, phy, 0x4, &ld_pause);
3831 elink_cl22_read(cb, phy, 0x5, &lp_pause);
3832 #endif
3833 } else if (CHIP_IS_E3(params->chip_id) &&
3834 ELINK_SINGLE_MEDIA_DIRECT(params)) {
3835 u8 lane = elink_get_warpcore_lane(phy, params);
3836 u16 gp_status, gp_mask;
3837 elink_cl45_read(cb, phy,
3838 MDIO_AN_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_4,
3839 &gp_status);
3840 gp_mask = (MDIO_WC_REG_GP2_STATUS_GP_2_4_CL73_AN_CMPL |
3841 MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_LP_AN_CAP) <<
3842 lane;
3843 if ((gp_status & gp_mask) == gp_mask) {
3844 elink_cl45_read(cb, phy, MDIO_AN_DEVAD,
3845 MDIO_AN_REG_ADV_PAUSE, &ld_pause);
3846 elink_cl45_read(cb, phy, MDIO_AN_DEVAD,
3847 MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
3848 } else {
3849 elink_cl45_read(cb, phy, MDIO_AN_DEVAD,
3850 MDIO_AN_REG_CL37_FC_LD, &ld_pause);
3851 elink_cl45_read(cb, phy, MDIO_AN_DEVAD,
3852 MDIO_AN_REG_CL37_FC_LP, &lp_pause);
3853 ld_pause = ((ld_pause &
3854 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
3855 << 3);
3856 lp_pause = ((lp_pause &
3857 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
3858 << 3);
3859 }
3860 } else {
3861 elink_cl45_read(cb, phy,
3862 MDIO_AN_DEVAD,
3863 MDIO_AN_REG_ADV_PAUSE, &ld_pause);
3864 elink_cl45_read(cb, phy,
3865 MDIO_AN_DEVAD,
3866 MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
3867 }
3868 pause_result = (ld_pause &
3869 MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
3870 pause_result |= (lp_pause &
3871 MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
3872 ELINK_DEBUG_P1(cb, "Ext PHY pause result 0x%x\n", pause_result);
3873 elink_pause_resolve(vars, pause_result);
3874
3875 }
3876
elink_ext_phy_resolve_fc(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)3877 static u8 elink_ext_phy_resolve_fc(struct elink_phy *phy,
3878 struct elink_params *params,
3879 struct elink_vars *vars)
3880 {
3881 u8 ret = 0;
3882 vars->flow_ctrl = ELINK_FLOW_CTRL_NONE;
3883 if (phy->req_flow_ctrl != ELINK_FLOW_CTRL_AUTO) {
3884 /* Update the advertised flow-controled of LD/LP in AN */
3885 if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG)
3886 elink_ext_phy_update_adv_fc(phy, params, vars);
3887 /* But set the flow-control result as the requested one */
3888 vars->flow_ctrl = phy->req_flow_ctrl;
3889 } else if (phy->req_line_speed != ELINK_SPEED_AUTO_NEG)
3890 vars->flow_ctrl = params->req_fc_auto_adv;
3891 else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
3892 ret = 1;
3893 elink_ext_phy_update_adv_fc(phy, params, vars);
3894 }
3895 return ret;
3896 }
3897 #endif // EXCLUDE_NON_COMMON_INIT
3898 /******************************************************************/
3899 /* Warpcore section */
3900 /******************************************************************/
3901 /* The init_internal_warpcore should mirror the xgxs,
3902 * i.e. reset the lane (if needed), set aer for the
3903 * init configuration, and set/clear SGMII flag. Internal
3904 * phy init is done purely in phy_init stage.
3905 */
3906 #define WC_TX_DRIVER(post2, idriver, ipre) \
3907 ((post2 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) | \
3908 (idriver << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) | \
3909 (ipre << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET))
3910
3911 #define WC_TX_FIR(post, main, pre) \
3912 ((post << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) | \
3913 (main << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) | \
3914 (pre << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET))
3915
3916 #ifndef EXCLUDE_WARPCORE
3917 #ifndef EXCLUDE_NON_COMMON_INIT
elink_update_link_attr(struct elink_params * params,u32 link_attr)3918 static void elink_update_link_attr(struct elink_params *params, u32 link_attr)
3919 {
3920 struct elink_dev *cb = params->cb;
3921
3922 if (SHMEM2_HAS(cb, params->shmem2_base, link_attr_sync))
3923 REG_WR(cb, params->shmem2_base +
3924 OFFSETOF(struct shmem2_region,
3925 link_attr_sync[params->port]), link_attr);
3926 }
3927
elink_warpcore_enable_AN_KR2(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)3928 static void elink_warpcore_enable_AN_KR2(struct elink_phy *phy,
3929 struct elink_params *params,
3930 struct elink_vars *vars)
3931 {
3932 struct elink_dev *cb = params->cb;
3933 u16 i;
3934 static struct elink_reg_set reg_set[] = {
3935 /* Step 1 - Program the TX/RX alignment markers */
3936 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0xa157},
3937 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xcbe2},
3938 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0x7537},
3939 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0xa157},
3940 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xcbe2},
3941 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0x7537},
3942 /* Step 2 - Configure the NP registers */
3943 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000a},
3944 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6400},
3945 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0620},
3946 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0157},
3947 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x6464},
3948 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x3150},
3949 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x3150},
3950 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0157},
3951 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0620}
3952 };
3953 ELINK_DEBUG_P0(cb, "Enabling 20G-KR2\n");
3954
3955 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
3956 MDIO_WC_REG_CL49_USERB0_CTRL, (3<<6));
3957
3958 for (i = 0; i < ARRAY_SIZE(reg_set); i++)
3959 elink_cl45_write(cb, phy, reg_set[i].devad, reg_set[i].reg,
3960 reg_set[i].val);
3961
3962 /* Start KR2 work-around timer which handles BCM8073 link-parner */
3963 params->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE;
3964 elink_update_link_attr(params, params->link_attr_sync);
3965 }
3966
elink_disable_kr2(struct elink_params * params,struct elink_vars * vars,struct elink_phy * phy)3967 static void elink_disable_kr2(struct elink_params *params,
3968 struct elink_vars *vars,
3969 struct elink_phy *phy)
3970 {
3971 struct elink_dev *cb = params->cb;
3972 int i;
3973 static struct elink_reg_set reg_set[] = {
3974 /* Step 1 - Program the TX/RX alignment markers */
3975 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0x7690},
3976 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xe647},
3977 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0xc4f0},
3978 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0x7690},
3979 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xe647},
3980 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0xc4f0},
3981 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000c},
3982 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6000},
3983 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0000},
3984 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0002},
3985 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x0000},
3986 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x0af7},
3987 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x0af7},
3988 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0002},
3989 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0000}
3990 };
3991 ELINK_DEBUG_P0(cb, "Disabling 20G-KR2\n");
3992
3993 for (i = 0; i < ARRAY_SIZE(reg_set); i++)
3994 elink_cl45_write(cb, phy, reg_set[i].devad, reg_set[i].reg,
3995 reg_set[i].val);
3996 params->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
3997 elink_update_link_attr(params, params->link_attr_sync);
3998
3999 vars->check_kr2_recovery_cnt = ELINK_CHECK_KR2_RECOVERY_CNT;
4000 }
4001
elink_warpcore_set_lpi_passthrough(struct elink_phy * phy,struct elink_params * params)4002 static void elink_warpcore_set_lpi_passthrough(struct elink_phy *phy,
4003 struct elink_params *params)
4004 {
4005 struct elink_dev *cb = params->cb;
4006
4007 ELINK_DEBUG_P0(cb, "Configure WC for LPI pass through\n");
4008 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4009 MDIO_WC_REG_EEE_COMBO_CONTROL0, 0x7c);
4010 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4011 MDIO_WC_REG_DIGITAL4_MISC5, 0xc000);
4012 }
4013
elink_warpcore_restart_AN_KR(struct elink_phy * phy,struct elink_params * params)4014 static void elink_warpcore_restart_AN_KR(struct elink_phy *phy,
4015 struct elink_params *params)
4016 {
4017 /* Restart autoneg on the leading lane only */
4018 struct elink_dev *cb = params->cb;
4019 u16 lane = elink_get_warpcore_lane(phy, params);
4020 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
4021 MDIO_AER_BLOCK_AER_REG, lane);
4022 elink_cl45_write(cb, phy, MDIO_AN_DEVAD,
4023 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
4024
4025 /* Restore AER */
4026 elink_set_aer_mmd(params, phy);
4027 }
4028
elink_warpcore_enable_AN_KR(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)4029 static void elink_warpcore_enable_AN_KR(struct elink_phy *phy,
4030 struct elink_params *params,
4031 struct elink_vars *vars) {
4032 u16 lane, i, cl72_ctrl, an_adv = 0, val;
4033 u32 wc_lane_config;
4034 struct elink_dev *cb = params->cb;
4035 static struct elink_reg_set reg_set[] = {
4036 {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
4037 {MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0},
4038 {MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},
4039 {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190},
4040 /* Disable Autoneg: re-enable it after adv is done. */
4041 {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0},
4042 {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2},
4043 {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0},
4044 };
4045 ELINK_DEBUG_P0(cb, "Enable Auto Negotiation for KR\n");
4046 /* Set to default registers that may be overriden by 10G force */
4047 for (i = 0; i < ARRAY_SIZE(reg_set); i++)
4048 elink_cl45_write(cb, phy, reg_set[i].devad, reg_set[i].reg,
4049 reg_set[i].val);
4050
4051 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4052 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl);
4053 cl72_ctrl &= 0x08ff;
4054 cl72_ctrl |= 0x3800;
4055 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4056 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl);
4057
4058 /* Check adding advertisement for 1G KX */
4059 if (((vars->line_speed == ELINK_SPEED_AUTO_NEG) &&
4060 (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
4061 (vars->line_speed == ELINK_SPEED_1000)) {
4062 u16 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2;
4063 an_adv |= (1<<5);
4064
4065 /* Enable CL37 1G Parallel Detect */
4066 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD, addr, 0x1);
4067 ELINK_DEBUG_P0(cb, "Advertize 1G\n");
4068 }
4069 if (((vars->line_speed == ELINK_SPEED_AUTO_NEG) &&
4070 (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
4071 (vars->line_speed == ELINK_SPEED_10000)) {
4072 /* Check adding advertisement for 10G KR */
4073 an_adv |= (1<<7);
4074 /* Enable 10G Parallel Detect */
4075 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
4076 MDIO_AER_BLOCK_AER_REG, 0);
4077
4078 elink_cl45_write(cb, phy, MDIO_AN_DEVAD,
4079 MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
4080 elink_set_aer_mmd(params, phy);
4081 ELINK_DEBUG_P0(cb, "Advertize 10G\n");
4082 }
4083
4084 /* Set Transmit PMD settings */
4085 lane = elink_get_warpcore_lane(phy, params);
4086 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4087 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
4088 WC_TX_DRIVER(0x02, 0x06, 0x09));
4089 /* Configure the next lane if dual mode */
4090 if (phy->flags & ELINK_FLAGS_WC_DUAL_MODE)
4091 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4092 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*(lane+1),
4093 WC_TX_DRIVER(0x02, 0x06, 0x09));
4094 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4095 MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL,
4096 0x03f0);
4097 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4098 MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL,
4099 0x03f0);
4100
4101 /* Advertised speeds */
4102 elink_cl45_write(cb, phy, MDIO_AN_DEVAD,
4103 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv);
4104
4105 /* Advertised and set FEC (Forward Error Correction) */
4106 elink_cl45_write(cb, phy, MDIO_AN_DEVAD,
4107 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT2,
4108 (MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_ABILITY |
4109 MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_REQ));
4110
4111 /* Enable CL37 BAM */
4112 if (REG_RD(cb, params->shmem_base +
4113 OFFSETOF(struct shmem_region, dev_info.
4114 port_hw_config[params->port].default_cfg)) &
4115 PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED) {
4116 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4117 MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL,
4118 1);
4119 ELINK_DEBUG_P0(cb, "Enable CL37 BAM on KR\n");
4120 }
4121
4122 /* Advertise pause */
4123 elink_ext_phy_set_pause(params, phy, vars);
4124 vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
4125 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4126 MDIO_WC_REG_DIGITAL5_MISC7, 0x100);
4127
4128 /* Over 1G - AN local device user page 1 */
4129 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4130 MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
4131
4132 if (((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) &&
4133 (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) ||
4134 (phy->req_line_speed == ELINK_SPEED_20000)) {
4135
4136 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
4137 MDIO_AER_BLOCK_AER_REG, lane);
4138
4139 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4140 MDIO_WC_REG_RX1_PCI_CTRL + (0x10*lane),
4141 (1<<11));
4142
4143 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4144 MDIO_WC_REG_XGXS_X2_CONTROL3, 0x7);
4145 elink_set_aer_mmd(params, phy);
4146
4147 elink_warpcore_enable_AN_KR2(phy, params, vars);
4148 } else {
4149 /* Enable Auto-Detect to support 1G over CL37 as well */
4150 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4151 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0x10);
4152 wc_lane_config = REG_RD(cb, params->shmem_base +
4153 OFFSETOF(struct shmem_region, dev_info.
4154 shared_hw_config.wc_lane_config));
4155 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4156 MDIO_WC_REG_RX0_PCI_CTRL + (lane << 4), &val);
4157 /* Force cl48 sync_status LOW to avoid getting stuck in CL73
4158 * parallel-detect loop when CL73 and CL37 are enabled.
4159 */
4160 val |= 1 << 11;
4161
4162 /* Restore Polarity settings in case it was run over by
4163 * previous link owner
4164 */
4165 if (wc_lane_config &
4166 (SHARED_HW_CFG_RX_LANE0_POL_FLIP_ENABLED << lane))
4167 val |= 3 << 2;
4168 else
4169 val &= ~(3 << 2);
4170 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4171 MDIO_WC_REG_RX0_PCI_CTRL + (lane << 4),
4172 val);
4173
4174 elink_disable_kr2(params, vars, phy);
4175 }
4176
4177 /* Enable Autoneg: only on the main lane */
4178 elink_warpcore_restart_AN_KR(phy, params);
4179 }
4180
elink_warpcore_set_10G_KR(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)4181 static void elink_warpcore_set_10G_KR(struct elink_phy *phy,
4182 struct elink_params *params,
4183 struct elink_vars *vars)
4184 {
4185 struct elink_dev *cb = params->cb;
4186 u16 val16, i, lane;
4187 static struct elink_reg_set reg_set[] = {
4188 /* Disable Autoneg */
4189 {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
4190 {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
4191 0x3f00},
4192 {MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0},
4193 {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0},
4194 {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},
4195 {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa},
4196 /* Leave cl72 training enable, needed for KR */
4197 {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2}
4198 };
4199
4200 for (i = 0; i < ARRAY_SIZE(reg_set); i++)
4201 elink_cl45_write(cb, phy, reg_set[i].devad, reg_set[i].reg,
4202 reg_set[i].val);
4203
4204 lane = elink_get_warpcore_lane(phy, params);
4205 /* Global registers */
4206 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
4207 MDIO_AER_BLOCK_AER_REG, 0);
4208 /* Disable CL36 PCS Tx */
4209 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4210 MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
4211 val16 &= ~(0x0011 << lane);
4212 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4213 MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
4214
4215 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4216 MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
4217 val16 |= (0x0303 << (lane << 1));
4218 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4219 MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
4220 /* Restore AER */
4221 elink_set_aer_mmd(params, phy);
4222 /* Set speed via PMA/PMD register */
4223 elink_cl45_write(cb, phy, MDIO_PMA_DEVAD,
4224 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
4225
4226 elink_cl45_write(cb, phy, MDIO_PMA_DEVAD,
4227 MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0xB);
4228
4229 /* Enable encoded forced speed */
4230 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4231 MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x30);
4232
4233 /* Turn TX scramble payload only the 64/66 scrambler */
4234 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4235 MDIO_WC_REG_TX66_CONTROL, 0x9);
4236
4237 /* Turn RX scramble payload only the 64/66 scrambler */
4238 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4239 MDIO_WC_REG_RX66_CONTROL, 0xF9);
4240
4241 /* Set and clear loopback to cause a reset to 64/66 decoder */
4242 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4243 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x4000);
4244 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4245 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0);
4246
4247 }
4248
elink_warpcore_set_10G_XFI(struct elink_phy * phy,struct elink_params * params,u8 is_xfi)4249 static void elink_warpcore_set_10G_XFI(struct elink_phy *phy,
4250 struct elink_params *params,
4251 u8 is_xfi)
4252 {
4253 struct elink_dev *cb = params->cb;
4254 u16 misc1_val, tap_val, tx_driver_val, lane, val;
4255 u32 cfg_tap_val, tx_drv_brdct, tx_equal;
4256
4257 /* Hold rxSeqStart */
4258 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4259 MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, 0x8000);
4260
4261 /* Hold tx_fifo_reset */
4262 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4263 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, 0x1);
4264
4265 /* Disable CL73 AN */
4266 elink_cl45_write(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
4267
4268 /* Disable 100FX Enable and Auto-Detect */
4269 elink_cl45_read_and_write(cb, phy, MDIO_WC_DEVAD,
4270 MDIO_WC_REG_FX100_CTRL1, 0xFFFA);
4271
4272 /* Disable 100FX Idle detect */
4273 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4274 MDIO_WC_REG_FX100_CTRL3, 0x0080);
4275
4276 /* Set Block address to Remote PHY & Clear forced_speed[5] */
4277 elink_cl45_read_and_write(cb, phy, MDIO_WC_DEVAD,
4278 MDIO_WC_REG_DIGITAL4_MISC3, 0xFF7F);
4279
4280 /* Turn off auto-detect & fiber mode */
4281 elink_cl45_read_and_write(cb, phy, MDIO_WC_DEVAD,
4282 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
4283 0xFFEE);
4284
4285 /* Set filter_force_link, disable_false_link and parallel_detect */
4286 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4287 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &val);
4288 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4289 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
4290 ((val | 0x0006) & 0xFFFE));
4291
4292 /* Set XFI / SFI */
4293 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4294 MDIO_WC_REG_SERDESDIGITAL_MISC1, &misc1_val);
4295
4296 misc1_val &= ~(0x1f);
4297
4298 if (is_xfi) {
4299 misc1_val |= 0x5;
4300 tap_val = WC_TX_FIR(0x08, 0x37, 0x00);
4301 tx_driver_val = WC_TX_DRIVER(0x00, 0x02, 0x03);
4302 } else {
4303 cfg_tap_val = REG_RD(cb, params->shmem_base +
4304 OFFSETOF(struct shmem_region, dev_info.
4305 port_hw_config[params->port].
4306 sfi_tap_values));
4307
4308 tx_equal = cfg_tap_val & PORT_HW_CFG_TX_EQUALIZATION_MASK;
4309
4310 tx_drv_brdct = (cfg_tap_val &
4311 PORT_HW_CFG_TX_DRV_BROADCAST_MASK) >>
4312 PORT_HW_CFG_TX_DRV_BROADCAST_SHIFT;
4313
4314 misc1_val |= 0x9;
4315
4316 /* TAP values are controlled by nvram, if value there isn't 0 */
4317 if (tx_equal)
4318 tap_val = (u16)tx_equal;
4319 else
4320 tap_val = WC_TX_FIR(0x0f, 0x2b, 0x02);
4321
4322 if (tx_drv_brdct)
4323 tx_driver_val = WC_TX_DRIVER(0x03, (u16)tx_drv_brdct,
4324 0x06);
4325 else
4326 tx_driver_val = WC_TX_DRIVER(0x03, 0x02, 0x06);
4327 }
4328 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4329 MDIO_WC_REG_SERDESDIGITAL_MISC1, misc1_val);
4330
4331 /* Set Transmit PMD settings */
4332 lane = elink_get_warpcore_lane(phy, params);
4333 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4334 MDIO_WC_REG_TX_FIR_TAP,
4335 tap_val | MDIO_WC_REG_TX_FIR_TAP_ENABLE);
4336 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4337 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
4338 tx_driver_val);
4339
4340 /* Enable fiber mode, enable and invert sig_det */
4341 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4342 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0xd);
4343
4344 /* Set Block address to Remote PHY & Set forced_speed[5], 40bit mode */
4345 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4346 MDIO_WC_REG_DIGITAL4_MISC3, 0x8080);
4347
4348 elink_warpcore_set_lpi_passthrough(phy, params);
4349
4350 /* 10G XFI Full Duplex */
4351 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4352 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x100);
4353
4354 /* Release tx_fifo_reset */
4355 elink_cl45_read_and_write(cb, phy, MDIO_WC_DEVAD,
4356 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3,
4357 0xFFFE);
4358 /* Release rxSeqStart */
4359 elink_cl45_read_and_write(cb, phy, MDIO_WC_DEVAD,
4360 MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, 0x7FFF);
4361 }
4362 #endif //EXCLUDE_NON_COMMON_INIT
4363
4364 #ifndef ELINK_AUX_POWER
elink_warpcore_set_20G_force_KR2(struct elink_phy * phy,struct elink_params * params)4365 static void elink_warpcore_set_20G_force_KR2(struct elink_phy *phy,
4366 struct elink_params *params)
4367 {
4368 u16 val;
4369 struct elink_dev *cb = params->cb;
4370 /* Set global registers, so set AER lane to 0 */
4371 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
4372 MDIO_AER_BLOCK_AER_REG, 0);
4373
4374 /* Disable sequencer */
4375 elink_cl45_read_and_write(cb, phy, MDIO_WC_DEVAD,
4376 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, ~(1<<13));
4377
4378 elink_set_aer_mmd(params, phy);
4379
4380 elink_cl45_read_and_write(cb, phy, MDIO_PMA_DEVAD,
4381 MDIO_WC_REG_PMD_KR_CONTROL, ~(1<<1));
4382 elink_cl45_write(cb, phy, MDIO_AN_DEVAD,
4383 MDIO_AN_REG_CTRL, 0);
4384 /* Turn off CL73 */
4385 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4386 MDIO_WC_REG_CL73_USERB0_CTRL, &val);
4387 val &= ~(1<<5);
4388 val |= (1<<6);
4389 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4390 MDIO_WC_REG_CL73_USERB0_CTRL, val);
4391
4392 /* Set 20G KR2 force speed */
4393 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4394 MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x1f);
4395
4396 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4397 MDIO_WC_REG_DIGITAL4_MISC3, (1<<7));
4398
4399 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4400 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &val);
4401 val &= ~(3<<14);
4402 val |= (1<<15);
4403 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4404 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, val);
4405 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4406 MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0x835A);
4407
4408 /* Enable sequencer (over lane 0) */
4409 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
4410 MDIO_AER_BLOCK_AER_REG, 0);
4411
4412 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4413 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, (1<<13));
4414
4415 elink_set_aer_mmd(params, phy);
4416 }
4417 #endif
4418
4419 #ifndef EXCLUDE_COMMON_INIT
elink_warpcore_set_20G_DXGXS(struct elink_dev * cb,struct elink_phy * phy,u16 lane)4420 static void elink_warpcore_set_20G_DXGXS(struct elink_dev *cb,
4421 struct elink_phy *phy,
4422 u16 lane)
4423 {
4424 /* Rx0 anaRxControl1G */
4425 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4426 MDIO_WC_REG_RX0_ANARXCONTROL1G, 0x90);
4427
4428 /* Rx2 anaRxControl1G */
4429 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4430 MDIO_WC_REG_RX2_ANARXCONTROL1G, 0x90);
4431
4432 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4433 MDIO_WC_REG_RX66_SCW0, 0xE070);
4434
4435 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4436 MDIO_WC_REG_RX66_SCW1, 0xC0D0);
4437
4438 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4439 MDIO_WC_REG_RX66_SCW2, 0xA0B0);
4440
4441 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4442 MDIO_WC_REG_RX66_SCW3, 0x8090);
4443
4444 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4445 MDIO_WC_REG_RX66_SCW0_MASK, 0xF0F0);
4446
4447 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4448 MDIO_WC_REG_RX66_SCW1_MASK, 0xF0F0);
4449
4450 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4451 MDIO_WC_REG_RX66_SCW2_MASK, 0xF0F0);
4452
4453 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4454 MDIO_WC_REG_RX66_SCW3_MASK, 0xF0F0);
4455
4456 /* Serdes Digital Misc1 */
4457 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4458 MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6008);
4459
4460 /* Serdes Digital4 Misc3 */
4461 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4462 MDIO_WC_REG_DIGITAL4_MISC3, 0x8088);
4463
4464 /* Set Transmit PMD settings */
4465 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4466 MDIO_WC_REG_TX_FIR_TAP,
4467 (WC_TX_FIR(0x12, 0x2d, 0x00) |
4468 MDIO_WC_REG_TX_FIR_TAP_ENABLE));
4469 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4470 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
4471 WC_TX_DRIVER(0x02, 0x02, 0x02));
4472 }
4473 #endif
4474
4475 #ifndef EXCLUDE_NON_COMMON_INIT
elink_warpcore_set_sgmii_speed(struct elink_phy * phy,struct elink_params * params,u8 fiber_mode,u8 always_autoneg)4476 static void elink_warpcore_set_sgmii_speed(struct elink_phy *phy,
4477 struct elink_params *params,
4478 u8 fiber_mode,
4479 u8 always_autoneg)
4480 {
4481 struct elink_dev *cb = params->cb;
4482 u16 val16, digctrl_kx1, digctrl_kx2;
4483
4484 /* Clear XFI clock comp in non-10G single lane mode. */
4485 elink_cl45_read_and_write(cb, phy, MDIO_WC_DEVAD,
4486 MDIO_WC_REG_RX66_CONTROL, ~(3<<13));
4487
4488 elink_warpcore_set_lpi_passthrough(phy, params);
4489
4490 if (always_autoneg || phy->req_line_speed == ELINK_SPEED_AUTO_NEG) {
4491 /* SGMII Autoneg */
4492 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4493 MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
4494 0x1000);
4495 ELINK_DEBUG_P0(cb, "set SGMII AUTONEG\n");
4496 } else {
4497 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4498 MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
4499 val16 &= 0xcebf;
4500 switch (phy->req_line_speed) {
4501 case ELINK_SPEED_10:
4502 break;
4503 case ELINK_SPEED_100:
4504 val16 |= 0x2000;
4505 break;
4506 case ELINK_SPEED_1000:
4507 val16 |= 0x0040;
4508 break;
4509 default:
4510 ELINK_DEBUG_P1(cb,
4511 "Speed not supported: 0x%x\n", phy->req_line_speed);
4512 return;
4513 }
4514
4515 if (phy->req_duplex == DUPLEX_FULL)
4516 val16 |= 0x0100;
4517
4518 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4519 MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16);
4520
4521 ELINK_DEBUG_P1(cb, "set SGMII force speed %d\n",
4522 phy->req_line_speed);
4523 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4524 MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
4525 ELINK_DEBUG_P1(cb, " (readback) %x\n", val16);
4526 }
4527
4528 /* SGMII Slave mode and disable signal detect */
4529 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4530 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &digctrl_kx1);
4531 if (fiber_mode)
4532 digctrl_kx1 = 1;
4533 else
4534 digctrl_kx1 &= 0xff4a;
4535
4536 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4537 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
4538 digctrl_kx1);
4539
4540 /* Turn off parallel detect */
4541 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4542 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &digctrl_kx2);
4543 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4544 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
4545 (digctrl_kx2 & ~(1<<2)));
4546
4547 /* Re-enable parallel detect */
4548 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4549 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
4550 (digctrl_kx2 | (1<<2)));
4551
4552 /* Enable autodet */
4553 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4554 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
4555 (digctrl_kx1 | 0x10));
4556 }
4557
4558 #endif //EXCLUDE_NON_COMMON_INIT
4559
elink_warpcore_reset_lane(struct elink_dev * cb,struct elink_phy * phy,u8 reset)4560 static void elink_warpcore_reset_lane(struct elink_dev *cb,
4561 struct elink_phy *phy,
4562 u8 reset)
4563 {
4564 u16 val;
4565 /* Take lane out of reset after configuration is finished */
4566 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4567 MDIO_WC_REG_DIGITAL5_MISC6, &val);
4568 if (reset)
4569 val |= 0xC000;
4570 else
4571 val &= 0x3FFF;
4572 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4573 MDIO_WC_REG_DIGITAL5_MISC6, val);
4574 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4575 MDIO_WC_REG_DIGITAL5_MISC6, &val);
4576 }
4577
4578 #ifndef EXCLUDE_NON_COMMON_INIT
4579 /* Clear SFI/XFI link settings registers */
elink_warpcore_clear_regs(struct elink_phy * phy,struct elink_params * params,u16 lane)4580 static void elink_warpcore_clear_regs(struct elink_phy *phy,
4581 struct elink_params *params,
4582 u16 lane)
4583 {
4584 struct elink_dev *cb = params->cb;
4585 u16 i;
4586 static struct elink_reg_set wc_regs[] = {
4587 {MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0},
4588 {MDIO_WC_DEVAD, MDIO_WC_REG_FX100_CTRL1, 0x014a},
4589 {MDIO_WC_DEVAD, MDIO_WC_REG_FX100_CTRL3, 0x0800},
4590 {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL4_MISC3, 0x8008},
4591 {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
4592 0x0195},
4593 {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
4594 0x0007},
4595 {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3,
4596 0x0002},
4597 {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6000},
4598 {MDIO_WC_DEVAD, MDIO_WC_REG_TX_FIR_TAP, 0x0000},
4599 {MDIO_WC_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040},
4600 {MDIO_WC_DEVAD, MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0x0140}
4601 };
4602 /* Set XFI clock comp as default. */
4603 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4604 MDIO_WC_REG_RX66_CONTROL, (3<<13));
4605
4606 for (i = 0; i < ARRAY_SIZE(wc_regs); i++)
4607 elink_cl45_write(cb, phy, wc_regs[i].devad, wc_regs[i].reg,
4608 wc_regs[i].val);
4609
4610 lane = elink_get_warpcore_lane(phy, params);
4611 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4612 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane, 0x0990);
4613
4614 }
4615
elink_get_mod_abs_int_cfg(struct elink_dev * cb,u32 chip_id,u32 shmem_base,u8 port,u8 * gpio_num,u8 * gpio_port)4616 static elink_status_t elink_get_mod_abs_int_cfg(struct elink_dev *cb,
4617 u32 chip_id,
4618 u32 shmem_base, u8 port,
4619 u8 *gpio_num, u8 *gpio_port)
4620 {
4621 u32 cfg_pin;
4622 *gpio_num = 0;
4623 *gpio_port = 0;
4624 if (CHIP_IS_E3(chip_id)) {
4625 cfg_pin = (REG_RD(cb, shmem_base +
4626 OFFSETOF(struct shmem_region,
4627 dev_info.port_hw_config[port].e3_sfp_ctrl)) &
4628 PORT_HW_CFG_E3_MOD_ABS_MASK) >>
4629 PORT_HW_CFG_E3_MOD_ABS_SHIFT;
4630
4631 /* Should not happen. This function called upon interrupt
4632 * triggered by GPIO ( since EPIO can only generate interrupts
4633 * to MCP).
4634 * So if this function was called and none of the GPIOs was set,
4635 * it means the shit hit the fan.
4636 */
4637 if ((cfg_pin < PIN_CFG_GPIO0_P0) ||
4638 (cfg_pin > PIN_CFG_GPIO3_P1)) {
4639 ELINK_DEBUG_P1(cb,
4640 "No cfg pin %x for module detect indication\n",
4641 cfg_pin);
4642 return ELINK_STATUS_ERROR;
4643 }
4644
4645 *gpio_num = (cfg_pin - PIN_CFG_GPIO0_P0) & 0x3;
4646 *gpio_port = (cfg_pin - PIN_CFG_GPIO0_P0) >> 2;
4647 } else {
4648 *gpio_num = MISC_REGISTERS_GPIO_3;
4649 *gpio_port = port;
4650 }
4651
4652 return ELINK_STATUS_OK;
4653 }
4654
elink_is_sfp_module_plugged(struct elink_phy * phy,struct elink_params * params)4655 static int elink_is_sfp_module_plugged(struct elink_phy *phy,
4656 struct elink_params *params)
4657 {
4658 struct elink_dev *cb = params->cb;
4659 u8 gpio_num, gpio_port;
4660 u32 gpio_val;
4661 if (elink_get_mod_abs_int_cfg(cb, params->chip_id,
4662 params->shmem_base, params->port,
4663 &gpio_num, &gpio_port) != ELINK_STATUS_OK)
4664 return 0;
4665 gpio_val = ELINK_GET_GPIO(cb, gpio_num, gpio_port);
4666
4667 /* Call the handling function in case module is detected */
4668 if (gpio_val == 0)
4669 return 1;
4670 else
4671 return 0;
4672 }
elink_warpcore_get_sigdet(struct elink_phy * phy,struct elink_params * params)4673 int elink_warpcore_get_sigdet(struct elink_phy *phy,
4674 struct elink_params *params)
4675 {
4676 u16 gp2_status_reg0, lane;
4677 struct elink_dev *cb = params->cb;
4678
4679 lane = elink_get_warpcore_lane(phy, params);
4680
4681 elink_cl45_read(cb, phy, MDIO_WC_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_0,
4682 &gp2_status_reg0);
4683
4684 return (gp2_status_reg0 >> (8+lane)) & 0x1;
4685 }
4686
4687 #ifndef ELINK_AUX_POWER
elink_warpcore_config_runtime(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)4688 static void elink_warpcore_config_runtime(struct elink_phy *phy,
4689 struct elink_params *params,
4690 struct elink_vars *vars)
4691 {
4692 struct elink_dev *cb = params->cb;
4693 u32 serdes_net_if;
4694 u16 gp_status1 = 0, lnkup = 0, lnkup_kr = 0;
4695
4696 vars->turn_to_run_wc_rt = vars->turn_to_run_wc_rt ? 0 : 1;
4697
4698 if (!vars->turn_to_run_wc_rt)
4699 return;
4700
4701 if (vars->rx_tx_asic_rst) {
4702 u16 lane = elink_get_warpcore_lane(phy, params);
4703 serdes_net_if = (REG_RD(cb, params->shmem_base +
4704 OFFSETOF(struct shmem_region, dev_info.
4705 port_hw_config[params->port].default_cfg)) &
4706 PORT_HW_CFG_NET_SERDES_IF_MASK);
4707
4708 switch (serdes_net_if) {
4709 case PORT_HW_CFG_NET_SERDES_IF_KR:
4710 /* Do we get link yet? */
4711 elink_cl45_read(cb, phy, MDIO_WC_DEVAD, 0x81d1,
4712 &gp_status1);
4713 lnkup = (gp_status1 >> (8+lane)) & 0x1;/* 1G */
4714 /*10G KR*/
4715 lnkup_kr = (gp_status1 >> (12+lane)) & 0x1;
4716
4717 if (lnkup_kr || lnkup) {
4718 vars->rx_tx_asic_rst = 0;
4719 } else {
4720 /* Reset the lane to see if link comes up.*/
4721 elink_warpcore_reset_lane(cb, phy, 1);
4722 elink_warpcore_reset_lane(cb, phy, 0);
4723
4724 /* Restart Autoneg */
4725 elink_cl45_write(cb, phy, MDIO_AN_DEVAD,
4726 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
4727
4728 vars->rx_tx_asic_rst--;
4729 ELINK_DEBUG_P1(cb, "0x%x retry left\n",
4730 vars->rx_tx_asic_rst);
4731 }
4732 break;
4733
4734 default:
4735 break;
4736 }
4737
4738 } /*params->rx_tx_asic_rst*/
4739
4740 }
4741 #endif
elink_warpcore_config_sfi(struct elink_phy * phy,struct elink_params * params)4742 static void elink_warpcore_config_sfi(struct elink_phy *phy,
4743 struct elink_params *params)
4744 {
4745 u16 lane = elink_get_warpcore_lane(phy, params);
4746 #ifdef ELINK_DEBUG
4747 struct elink_dev *cb = params->cb;
4748 #endif
4749 elink_warpcore_clear_regs(phy, params, lane);
4750 if ((params->req_line_speed[ELINK_LINK_CONFIG_IDX(ELINK_INT_PHY)] ==
4751 ELINK_SPEED_10000) &&
4752 (phy->media_type != ELINK_ETH_PHY_SFP_1G_FIBER)) {
4753 ELINK_DEBUG_P0(cb, "Setting 10G SFI\n");
4754 elink_warpcore_set_10G_XFI(phy, params, 0);
4755 } else {
4756 ELINK_DEBUG_P0(cb, "Setting 1G Fiber\n");
4757 elink_warpcore_set_sgmii_speed(phy, params, 1, 0);
4758 }
4759 }
4760
elink_sfp_e3_set_transmitter(struct elink_params * params,struct elink_phy * phy,u8 tx_en)4761 static void elink_sfp_e3_set_transmitter(struct elink_params *params,
4762 struct elink_phy *phy,
4763 u8 tx_en)
4764 {
4765 struct elink_dev *cb = params->cb;
4766 u32 cfg_pin;
4767 u8 port = params->port;
4768
4769 cfg_pin = REG_RD(cb, params->shmem_base +
4770 OFFSETOF(struct shmem_region,
4771 dev_info.port_hw_config[port].e3_sfp_ctrl)) &
4772 PORT_HW_CFG_E3_TX_LASER_MASK;
4773 /* Set the !tx_en since this pin is DISABLE_TX_LASER */
4774 ELINK_DEBUG_P1(cb, "Setting WC TX to %d\n", tx_en);
4775
4776 /* For 20G, the expected pin to be used is 3 pins after the current */
4777 elink_set_cfg_pin(cb, cfg_pin, tx_en ^ 1);
4778 if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)
4779 elink_set_cfg_pin(cb, cfg_pin + 3, tx_en ^ 1);
4780 }
4781
elink_warpcore_config_init(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)4782 static void elink_warpcore_config_init(struct elink_phy *phy,
4783 struct elink_params *params,
4784 struct elink_vars *vars)
4785 {
4786 struct elink_dev *cb = params->cb;
4787 u32 serdes_net_if;
4788 u8 fiber_mode;
4789 u16 lane = elink_get_warpcore_lane(phy, params);
4790 serdes_net_if = (REG_RD(cb, params->shmem_base +
4791 OFFSETOF(struct shmem_region, dev_info.
4792 port_hw_config[params->port].default_cfg)) &
4793 PORT_HW_CFG_NET_SERDES_IF_MASK);
4794 ELINK_DEBUG_P2(cb, "Begin Warpcore init, link_speed %d, "
4795 "serdes_net_if = 0x%x\n",
4796 vars->line_speed, serdes_net_if);
4797 elink_set_aer_mmd(params, phy);
4798 elink_warpcore_reset_lane(cb, phy, 1);
4799 vars->phy_flags |= PHY_XGXS_FLAG;
4800 if ((serdes_net_if == PORT_HW_CFG_NET_SERDES_IF_SGMII) ||
4801 (phy->req_line_speed &&
4802 ((phy->req_line_speed == ELINK_SPEED_100) ||
4803 (phy->req_line_speed == ELINK_SPEED_10)))) {
4804 vars->phy_flags |= PHY_SGMII_FLAG;
4805 ELINK_DEBUG_P0(cb, "Setting SGMII mode\n");
4806 elink_warpcore_clear_regs(phy, params, lane);
4807 elink_warpcore_set_sgmii_speed(phy, params, 0, 1);
4808 } else {
4809 switch (serdes_net_if) {
4810 case PORT_HW_CFG_NET_SERDES_IF_KR:
4811 /* Enable KR Auto Neg */
4812 if (params->loopback_mode != ELINK_LOOPBACK_EXT)
4813 elink_warpcore_enable_AN_KR(phy, params, vars);
4814 else {
4815 ELINK_DEBUG_P0(cb, "Setting KR 10G-Force\n");
4816 elink_warpcore_set_10G_KR(phy, params, vars);
4817 }
4818 break;
4819
4820 case PORT_HW_CFG_NET_SERDES_IF_XFI:
4821 elink_warpcore_clear_regs(phy, params, lane);
4822 if (vars->line_speed == ELINK_SPEED_10000) {
4823 ELINK_DEBUG_P0(cb, "Setting 10G XFI\n");
4824 elink_warpcore_set_10G_XFI(phy, params, 1);
4825 } else {
4826 if (ELINK_SINGLE_MEDIA_DIRECT(params)) {
4827 ELINK_DEBUG_P0(cb, "1G Fiber\n");
4828 fiber_mode = 1;
4829 } else {
4830 ELINK_DEBUG_P0(cb, "10/100/1G SGMII\n");
4831 fiber_mode = 0;
4832 }
4833 elink_warpcore_set_sgmii_speed(phy,
4834 params,
4835 fiber_mode,
4836 0);
4837 }
4838
4839 break;
4840
4841 case PORT_HW_CFG_NET_SERDES_IF_SFI:
4842 /* Issue Module detection if module is plugged, or
4843 * enabled transmitter to avoid current leakage in case
4844 * no module is connected
4845 */
4846 if ((params->loopback_mode == ELINK_LOOPBACK_NONE) ||
4847 (params->loopback_mode == ELINK_LOOPBACK_EXT)) {
4848 if (elink_is_sfp_module_plugged(phy, params))
4849 elink_sfp_module_detection(phy, params);
4850 else
4851 elink_sfp_e3_set_transmitter(params,
4852 phy, 1);
4853 }
4854
4855 elink_warpcore_config_sfi(phy, params);
4856 break;
4857
4858 #ifndef ELINK_AUX_POWER
4859 case PORT_HW_CFG_NET_SERDES_IF_DXGXS:
4860 if (vars->line_speed != ELINK_SPEED_20000) {
4861 ELINK_DEBUG_P0(cb, "Speed not supported yet\n");
4862 return;
4863 }
4864 ELINK_DEBUG_P0(cb, "Setting 20G DXGXS\n");
4865 elink_warpcore_set_20G_DXGXS(cb, phy, lane);
4866 /* Issue Module detection */
4867
4868 elink_sfp_module_detection(phy, params);
4869 break;
4870 #endif
4871 case PORT_HW_CFG_NET_SERDES_IF_KR2:
4872 if (!params->loopback_mode) {
4873 elink_warpcore_enable_AN_KR(phy, params, vars);
4874 } else {
4875 #ifndef ELINK_AUX_POWER
4876 ELINK_DEBUG_P0(cb, "Setting KR 20G-Force\n");
4877 elink_warpcore_set_20G_force_KR2(phy, params);
4878 #endif
4879 }
4880 break;
4881 default:
4882 ELINK_DEBUG_P1(cb,
4883 "Unsupported Serdes Net Interface 0x%x\n",
4884 serdes_net_if);
4885 return;
4886 }
4887 }
4888
4889 /* Take lane out of reset after configuration is finished */
4890 elink_warpcore_reset_lane(cb, phy, 0);
4891 ELINK_DEBUG_P0(cb, "Exit config init\n");
4892 }
4893
elink_warpcore_link_reset(struct elink_phy * phy,struct elink_params * params)4894 static void elink_warpcore_link_reset(struct elink_phy *phy,
4895 struct elink_params *params)
4896 {
4897 #ifndef EXCLUDE_LINK_RESET
4898 struct elink_dev *cb = params->cb;
4899 u16 val16, lane;
4900 elink_sfp_e3_set_transmitter(params, phy, 0);
4901 elink_set_mdio_emac_per_phy(cb, params);
4902 elink_set_aer_mmd(params, phy);
4903 /* Global register */
4904 elink_warpcore_reset_lane(cb, phy, 1);
4905
4906 /* Clear loopback settings (if any) */
4907 /* 10G & 20G */
4908 elink_cl45_read_and_write(cb, phy, MDIO_WC_DEVAD,
4909 MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0xBFFF);
4910
4911 elink_cl45_read_and_write(cb, phy, MDIO_WC_DEVAD,
4912 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0xfffe);
4913
4914 /* Update those 1-copy registers */
4915 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
4916 MDIO_AER_BLOCK_AER_REG, 0);
4917 /* Enable 1G MDIO (1-copy) */
4918 elink_cl45_read_and_write(cb, phy, MDIO_WC_DEVAD,
4919 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
4920 ~0x10);
4921
4922 elink_cl45_read_and_write(cb, phy, MDIO_WC_DEVAD,
4923 MDIO_WC_REG_XGXSBLK1_LANECTRL2, 0xff00);
4924 lane = elink_get_warpcore_lane(phy, params);
4925 /* Disable CL36 PCS Tx */
4926 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4927 MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
4928 val16 |= (0x11 << lane);
4929 if (phy->flags & ELINK_FLAGS_WC_DUAL_MODE)
4930 val16 |= (0x22 << lane);
4931 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4932 MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
4933
4934 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4935 MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
4936 val16 &= ~(0x0303 << (lane << 1));
4937 val16 |= (0x0101 << (lane << 1));
4938 if (phy->flags & ELINK_FLAGS_WC_DUAL_MODE) {
4939 val16 &= ~(0x0c0c << (lane << 1));
4940 val16 |= (0x0404 << (lane << 1));
4941 }
4942
4943 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4944 MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
4945 /* Restore AER */
4946 elink_set_aer_mmd(params, phy);
4947 #endif
4948
4949 }
4950
elink_set_warpcore_loopback(struct elink_phy * phy,struct elink_params * params)4951 static void elink_set_warpcore_loopback(struct elink_phy *phy,
4952 struct elink_params *params)
4953 {
4954 #ifdef ELINK_INCLUDE_LOOPBACK
4955 struct elink_dev *cb = params->cb;
4956 u16 val16;
4957 u32 lane;
4958 ELINK_DEBUG_P2(cb, "Setting Warpcore loopback type %x, speed %d\n",
4959 params->loopback_mode, phy->req_line_speed);
4960
4961 if (phy->req_line_speed < ELINK_SPEED_10000 ||
4962 phy->supported & ELINK_SUPPORTED_20000baseKR2_Full) {
4963 /* 10/100/1000/20G-KR2 */
4964
4965 /* Update those 1-copy registers */
4966 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
4967 MDIO_AER_BLOCK_AER_REG, 0);
4968 /* Enable 1G MDIO (1-copy) */
4969 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4970 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
4971 0x10);
4972 /* Set 1G loopback based on lane (1-copy) */
4973 lane = elink_get_warpcore_lane(phy, params);
4974 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
4975 MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
4976 val16 |= (1<<lane);
4977 if (phy->flags & ELINK_FLAGS_WC_DUAL_MODE)
4978 val16 |= (2<<lane);
4979 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
4980 MDIO_WC_REG_XGXSBLK1_LANECTRL2,
4981 val16);
4982
4983 /* Switch back to 4-copy registers */
4984 elink_set_aer_mmd(params, phy);
4985 } else {
4986 /* 10G / 20G-DXGXS */
4987 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4988 MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
4989 0x4000);
4990 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
4991 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1);
4992 }
4993 #endif // #ifdef ELINK_INCLUDE_LOOPBACK
4994 }
4995 #endif // EXCLUDE_NON_COMMON_INIT
4996 #endif // #ifndef EXCLUDE_WARPCORE
4997
4998 #ifdef INCLUDE_WARPCORE_UC_LOAD
elink_warpcore_powerdown_secondport_lanes(struct elink_dev * cb,struct elink_phy * phy)4999 static void elink_warpcore_powerdown_secondport_lanes(struct elink_dev *cb,
5000 struct elink_phy *phy)
5001 {
5002 u16 path_swap_ovr, path_swap, i;
5003 u8 power_down_lanes[4];
5004
5005 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5006 MDIO_WC_REG_XGXSBLK1_LANETEST0, 0);
5007 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5008 MDIO_WC_REG_XGXS_X2_CONTROL2, 0x29FB);
5009
5010 /* Figure out path swap value */
5011 path_swap_ovr = REG_RD(cb, MISC_REG_TWO_PORT_PATH_SWAP_OVWR);
5012 if (path_swap_ovr & 0x1)
5013 path_swap = (path_swap_ovr & 0x2);
5014 else
5015 path_swap = REG_RD(cb, MISC_REG_TWO_PORT_PATH_SWAP);
5016
5017 /* Find which lanes to power down according to path swap value */
5018 if (path_swap) {
5019 power_down_lanes[0] = 1;
5020 power_down_lanes[1] = 1;
5021 power_down_lanes[2] = 0;
5022 power_down_lanes[3] = 1;
5023 } else {
5024 power_down_lanes[0] = 0;
5025 power_down_lanes[1] = 1;
5026 power_down_lanes[2] = 1;
5027 power_down_lanes[3] = 1;
5028 }
5029
5030 /* Go through lanes which should be powered down */
5031 for (i = 0; i < 4; i++) {
5032 if (power_down_lanes[i]) {
5033 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5034 MDIO_WC_REG_XGXSBLK1_LANECTRL3,
5035 (1 << i) | (1 << (4+i)) |
5036 (1 << 11));
5037
5038 elink_cl45_read_and_write(
5039 cb, phy, MDIO_WC_DEVAD,
5040 MDIO_WC_REG_XGXSBLK1_LANECTRL0,
5041 ~((u16)((1 << i) | (1 << (4+i)))));
5042 }
5043 }
5044 }
5045 #endif //INCLUDE_WARPCORE_UC_LOAD
5046
5047 #ifdef INCLUDE_WARPCORE_UC_LOAD
5048 /**
5049 * elink_warpcore_sequencer
5050 *
5051 * @param cb
5052 * @param phy
5053 * @param enable - sequencer
5054 *
5055 * @return u32
5056 *
5057 * Before starting any of the specific speed/protocol flow,
5058 * there's need disable the sequencer and once all
5059 * configurations are made the sequencer will be enabled again.
5060 * That way it is guaranteed that improper link won't be
5061 * established during the init phase.
5062 */
elink_warpcore_sequencer(struct elink_dev * cb,struct elink_phy * phy,u8 enable)5063 static void elink_warpcore_sequencer(struct elink_dev *cb,
5064 struct elink_phy *phy,
5065 u8 enable){
5066
5067 u16 val16;
5068 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
5069 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, &val16);
5070 if(enable)
5071 val16 |= 0x2000;
5072 else
5073 val16 &= 0xDFFF;
5074 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5075 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, val16);
5076 }
5077
elink_warpcore_set_lane_swap(struct elink_dev * cb,struct elink_phy * phy,u32 wc_lane_config)5078 static void elink_warpcore_set_lane_swap(struct elink_dev *cb,
5079 struct elink_phy *phy,
5080 u32 wc_lane_config)
5081 {
5082 u16 rx_lane_swap, tx_lane_swap, val16;
5083 rx_lane_swap = ((wc_lane_config &
5084 SHARED_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
5085 SHARED_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
5086
5087 tx_lane_swap = ((wc_lane_config &
5088 SHARED_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
5089 SHARED_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
5090
5091 /* Rx Lanes */
5092 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
5093 MDIO_WC_REG_XGXS_RX_LN_SWAP1, &val16);
5094 val16 &= 0xFF00;
5095 val16 |= rx_lane_swap;
5096 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5097 MDIO_WC_REG_XGXS_RX_LN_SWAP1, val16);
5098
5099 /* Tx Lanes */
5100 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
5101 MDIO_WC_REG_XGXS_TX_LN_SWAP1, &val16);
5102 val16 &= 0xFF00;
5103 val16 |= tx_lane_swap;
5104 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5105 MDIO_WC_REG_XGXS_TX_LN_SWAP1, val16);
5106 }
5107
elink_warpcore_set_lane_polarity(struct elink_dev * cb,struct elink_phy * phy,u32 wc_lane_config)5108 static void elink_warpcore_set_lane_polarity(struct elink_dev *cb,
5109 struct elink_phy *phy,
5110 u32 wc_lane_config)
5111 {
5112 /* Set RX polarity on all lanes; flip and enable the flip. */
5113 if (wc_lane_config & SHARED_HW_CFG_RX_LANE0_POL_FLIP_ENABLED)
5114 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5115 MDIO_WC_REG_RX0_PCI_CTRL, (3<<2));
5116 if (wc_lane_config & SHARED_HW_CFG_RX_LANE1_POL_FLIP_ENABLED)
5117 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5118 MDIO_WC_REG_RX1_PCI_CTRL, (3<<2));
5119 if (wc_lane_config & SHARED_HW_CFG_RX_LANE2_POL_FLIP_ENABLED)
5120 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5121 MDIO_WC_REG_RX2_PCI_CTRL, (3<<2));
5122 if (wc_lane_config & SHARED_HW_CFG_RX_LANE3_POL_FLIP_ENABLED)
5123 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5124 MDIO_WC_REG_RX3_PCI_CTRL, (3<<2));
5125 /* Set TX polarity on all lanes */
5126 if (wc_lane_config & SHARED_HW_CFG_TX_LANE0_POL_FLIP_ENABLED)
5127 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5128 MDIO_WC_REG_TX0_ANA_CTRL0, (1<<5));
5129 if (wc_lane_config & SHARED_HW_CFG_TX_LANE1_POL_FLIP_ENABLED)
5130 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5131 MDIO_WC_REG_TX1_ANA_CTRL0, (1<<5));
5132 if (wc_lane_config & SHARED_HW_CFG_TX_LANE2_POL_FLIP_ENABLED)
5133 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5134 MDIO_WC_REG_TX2_ANA_CTRL0, (1<<5));
5135 if (wc_lane_config & SHARED_HW_CFG_TX_LANE3_POL_FLIP_ENABLED)
5136 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5137 MDIO_WC_REG_TX3_ANA_CTRL0, (1<<5));
5138 }
5139
elink_reset_warpcore(struct elink_dev * cb)5140 static elink_status_t elink_reset_warpcore(struct elink_dev *cb)
5141 {
5142 u16 time;
5143 u32 pll_lock;
5144 ELINK_DEBUG_P0(cb, "Resetting Warpcore\n");
5145
5146 REG_WR(cb, MISC_REG_WC0_RESET, 0xE);
5147 MSLEEP(cb, 1);
5148 REG_WR(cb, MISC_REG_WC0_RESET, 0xF);
5149
5150 for(time = 0; time < ELINK_MDIO_ACCESS_TIMEOUT; time++) {
5151 MSLEEP(cb, 1);
5152 pll_lock = REG_RD(cb, MISC_REG_WC0_PLL_LOCK);
5153 if (pll_lock & 0x1) {
5154 /* Flush all TX fifo */
5155 REG_WR(cb, MISC_REG_WC0_RESET, 0x3FF);
5156 break;
5157 }
5158 }
5159 if (time == ELINK_MDIO_ACCESS_TIMEOUT) {
5160 ELINK_DEBUG_P0(cb, "BUG! WARPCORE is still in reset!\n");
5161 return ELINK_STATUS_ERROR;
5162 }
5163
5164 return ELINK_STATUS_OK;
5165 }
5166
5167
elink_warpcore_set_quad_mode(struct elink_dev * cb,struct elink_phy * phy)5168 static void elink_warpcore_set_quad_mode(struct elink_dev *cb,
5169 struct elink_phy *phy)
5170 {
5171 u16 lane, val;
5172 /* Need to set lanes 0..3 */
5173 for (lane = 0; lane < WC_LANE_MAX; lane++) {
5174 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
5175 MDIO_AER_BLOCK_AER_REG, lane);
5176 /* Reset Asic lane */
5177 elink_warpcore_reset_lane(cb, phy, 1);
5178 // This access is required only for version 0xd101 of the WC FW
5179 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
5180 MDIO_WC_REG_CL72_USERB0_CL72_MISC4_CONTROL,
5181 &val);
5182 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5183 MDIO_WC_REG_CL72_USERB0_CL72_MISC4_CONTROL,
5184 (val & 0xfe07) | 0x78);
5185
5186 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5187 MDIO_WC_REG_DSC_SMC, 0x8000);
5188
5189 /* Set on clock compensation in WC */
5190 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5191 MDIO_WC_REG_RX66_CONTROL, 0x7415);
5192
5193 /* Set on clock compensation in WC
5194 * For WC/B0 programming register 0x8104 to value 0x8091 insures
5195 * that clock comensation in cl48 modes is enabled during
5196 * multi-port modes, and disabled during single port modes.
5197 */
5198 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5199 MDIO_WC_REG_XGXSBLK2_UNICORE_MODE_10G,
5200 0x8091);
5201 }
5202 }
5203
elink_warpcore_set_dual_mode(struct elink_dev * cb,struct elink_phy * phy,u32 shmem_base)5204 static void elink_warpcore_set_dual_mode(struct elink_dev *cb,
5205 struct elink_phy *phy,
5206 u32 shmem_base)
5207 {
5208 u16 lane, val;
5209 u32 serdes_net_if;
5210 for (lane = 0; lane < WC_LANE_MAX; lane++) {
5211 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
5212 MDIO_AER_BLOCK_AER_REG, lane);
5213
5214 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
5215 MDIO_WC_REG_CL72_USERB0_CL72_MISC4_CONTROL,
5216 &val);
5217 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5218 MDIO_WC_REG_CL72_USERB0_CL72_MISC4_CONTROL,
5219 (val & 0xfe07) | 0x50);
5220 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5221 MDIO_WC_REG_CL49_USERB0_CTRL,
5222 (3<<6));
5223
5224 /* Set on clock compensation in WC
5225 * For WC/B0 programming register 0x8104 to value 0x8091 insures
5226 * that clock comensation in cl48 modes is enabled during
5227 * multi-port modes, and disabled during single port modes.
5228 */
5229 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5230 MDIO_WC_REG_XGXSBLK2_UNICORE_MODE_10G,
5231 0x8091);
5232 /* In dual port mode XFI compensation should be disabled by
5233 * setting 0x83C0[14:13] to 2'b00 for each port.
5234 */
5235 elink_cl45_read_and_write(cb, phy, MDIO_WC_DEVAD,
5236 MDIO_WC_REG_RX66_CONTROL, ~(3<<13));
5237
5238 /* This access is required only for version 0xd101 of the
5239 * WC FW
5240 */
5241 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5242 MDIO_WC_REG_DSC_SMC, 0x8000);
5243 }
5244
5245 serdes_net_if = (REG_RD(cb, shmem_base +
5246 OFFSETOF(struct shmem_region, dev_info.
5247 port_hw_config[0].default_cfg)) &
5248 PORT_HW_CFG_NET_SERDES_IF_MASK);
5249
5250 /* Configure both ports to 20G to enable clock working on both ports */
5251 for (lane = 0x200; lane <= 0x201; lane++) {
5252 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
5253 MDIO_AER_BLOCK_AER_REG, lane);
5254 elink_warpcore_reset_lane(cb, phy, 1);
5255 if (serdes_net_if == PORT_HW_CFG_NET_SERDES_IF_DXGXS)
5256 elink_warpcore_set_20G_DXGXS(cb, phy, lane);
5257 }
5258 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5259 MDIO_WC_REG_RX1_PCI_CTRL, (1<<11));
5260 elink_cl45_read_or_write(cb, phy, MDIO_WC_DEVAD,
5261 MDIO_WC_REG_RX3_PCI_CTRL, (1<<11));
5262 }
5263
elink_warpcore_load_uc(struct elink_dev * cb,struct elink_phy * phy)5264 static elink_status_t elink_warpcore_load_uc(struct elink_dev *cb,
5265 struct elink_phy *phy)
5266 {
5267 u16 val, cnt;
5268 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
5269 MDIO_AER_BLOCK_AER_REG, 0);
5270
5271 /* Enable External memory access */
5272 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5273 MDIO_WC_REG_UC_INFO_B0_DEAD_TRAP, 0x0000);
5274
5275 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5276 MDIO_WC_REG_MICROBLK_CMD3, 0x0407);
5277
5278 /* Initialize ram memory prior to programming it */
5279 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5280 MDIO_WC_REG_MICROBLK_CMD, 0x8000);
5281
5282 /* Wait for completion of memory initialization */
5283 for (cnt = 0; cnt < ELINK_WC_UC_TIMEOUT; cnt++) {
5284 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
5285 MDIO_WC_REG_MICROBLK_DL_STATUS , &val);
5286 if (val & 0x8000)
5287 break;
5288 USLEEP(cb, 1);
5289 }
5290 if (cnt >= ELINK_WC_UC_TIMEOUT)
5291 return ELINK_STATUS_TIMEOUT;
5292
5293 elink_cl45_write(cb, phy, MDIO_WC_DEVAD, MDIO_WC_REG_UC_INFO_B1_CRC, 0);
5294
5295 /* Load Warpcore microcode for E3 and after */
5296 elink_cb_load_warpcore_microcode();
5297
5298 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5299 MDIO_WC_REG_MICROBLK_CMD3, 0x0404);
5300
5301 /* Turn off read_for_cmd bit, check for FW setting this later. */
5302 elink_cl45_read_and_write(cb, phy, MDIO_WC_DEVAD,
5303 MDIO_WC_REG_DSC1B0_UC_CTRL,
5304 ~MDIO_WC_REG_DSC1B0_UC_CTRL_RDY4CMD);
5305
5306 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
5307 MDIO_WC_REG_MICROBLK_CMD, 0x0810);
5308 for (cnt = 0; cnt < ELINK_WC_RDY_TIMEOUT_MSEC; cnt++) {
5309 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
5310 MDIO_WC_REG_DSC1B0_UC_CTRL, &val);
5311 if (val & MDIO_WC_REG_DSC1B0_UC_CTRL_RDY4CMD)
5312 break;
5313 MSLEEP(cb, 1);
5314 }
5315 if (cnt >= ELINK_WC_RDY_TIMEOUT_MSEC)
5316 return ELINK_STATUS_TIMEOUT;
5317
5318 return ELINK_STATUS_OK;
5319 }
5320 #endif /* INCLUDE_WARPCORE_UC_LOAD */
5321
elink_sync_link(struct elink_params * params,struct elink_vars * vars)5322 static void elink_sync_link(struct elink_params *params,
5323 struct elink_vars *vars)
5324 {
5325 #ifdef ELINK_DEBUG
5326 struct elink_dev *cb = params->cb;
5327 #endif
5328 u8 link_10g_plus;
5329 if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
5330 vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
5331 vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
5332 if (vars->link_up) {
5333 ELINK_DEBUG_P0(cb, "phy link up\n");
5334
5335 vars->phy_link_up = 1;
5336 vars->duplex = DUPLEX_FULL;
5337 switch (vars->link_status &
5338 LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
5339 case ELINK_LINK_10THD:
5340 vars->duplex = DUPLEX_HALF;
5341 /* Fall thru */
5342 case ELINK_LINK_10TFD:
5343 vars->line_speed = ELINK_SPEED_10;
5344 break;
5345
5346 case ELINK_LINK_100TXHD:
5347 vars->duplex = DUPLEX_HALF;
5348 /* Fall thru */
5349 case ELINK_LINK_100T4:
5350 case ELINK_LINK_100TXFD:
5351 vars->line_speed = ELINK_SPEED_100;
5352 break;
5353
5354 case ELINK_LINK_1000THD:
5355 vars->duplex = DUPLEX_HALF;
5356 /* Fall thru */
5357 case ELINK_LINK_1000TFD:
5358 vars->line_speed = ELINK_SPEED_1000;
5359 break;
5360
5361 case ELINK_LINK_2500THD:
5362 vars->duplex = DUPLEX_HALF;
5363 /* Fall thru */
5364 case ELINK_LINK_2500TFD:
5365 vars->line_speed = ELINK_SPEED_2500;
5366 break;
5367
5368 case ELINK_LINK_10GTFD:
5369 vars->line_speed = ELINK_SPEED_10000;
5370 break;
5371 case ELINK_LINK_20GTFD:
5372 vars->line_speed = ELINK_SPEED_20000;
5373 break;
5374 default:
5375 break;
5376 }
5377 vars->flow_ctrl = 0;
5378 if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
5379 vars->flow_ctrl |= ELINK_FLOW_CTRL_TX;
5380
5381 if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
5382 vars->flow_ctrl |= ELINK_FLOW_CTRL_RX;
5383
5384 if (!vars->flow_ctrl)
5385 vars->flow_ctrl = ELINK_FLOW_CTRL_NONE;
5386
5387 if (vars->line_speed &&
5388 ((vars->line_speed == ELINK_SPEED_10) ||
5389 (vars->line_speed == ELINK_SPEED_100))) {
5390 vars->phy_flags |= PHY_SGMII_FLAG;
5391 } else {
5392 vars->phy_flags &= ~PHY_SGMII_FLAG;
5393 }
5394 #ifndef EXCLUDE_WARPCORE
5395 if (vars->line_speed &&
5396 ELINK_USES_WARPCORE(params->chip_id) &&
5397 (vars->line_speed == ELINK_SPEED_1000))
5398 vars->phy_flags |= PHY_SGMII_FLAG;
5399 #endif /* #ifndef EXCLUDE_WARPCORE */
5400 /* Anything 10 and over uses the bmac */
5401 link_10g_plus = (vars->line_speed >= ELINK_SPEED_10000);
5402
5403 if (link_10g_plus) {
5404 if (ELINK_USES_WARPCORE(params->chip_id))
5405 vars->mac_type = ELINK_MAC_TYPE_XMAC;
5406 else
5407 vars->mac_type = ELINK_MAC_TYPE_BMAC;
5408 } else {
5409 if (ELINK_USES_WARPCORE(params->chip_id))
5410 vars->mac_type = ELINK_MAC_TYPE_UMAC;
5411 else
5412 vars->mac_type = ELINK_MAC_TYPE_EMAC;
5413 }
5414 } else { /* Link down */
5415 ELINK_DEBUG_P0(cb, "phy link down\n");
5416
5417 vars->phy_link_up = 0;
5418
5419 vars->line_speed = 0;
5420 vars->duplex = DUPLEX_FULL;
5421 vars->flow_ctrl = ELINK_FLOW_CTRL_NONE;
5422
5423 /* Indicate no mac active */
5424 vars->mac_type = ELINK_MAC_TYPE_NONE;
5425 if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
5426 vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
5427 if (vars->link_status & LINK_STATUS_SFP_TX_FAULT)
5428 vars->phy_flags |= PHY_SFP_TX_FAULT_FLAG;
5429 }
5430 }
5431
elink_link_status_update(struct elink_params * params,struct elink_vars * vars)5432 void elink_link_status_update(struct elink_params *params,
5433 struct elink_vars *vars)
5434 {
5435 struct elink_dev *cb = params->cb;
5436 u8 port = params->port;
5437 u32 sync_offset, media_types;
5438 /* Update PHY configuration */
5439 set_phy_vars(params, vars);
5440
5441 vars->link_status = REG_RD(cb, params->shmem_base +
5442 OFFSETOF(struct shmem_region,
5443 port_mb[port].link_status));
5444
5445 /* Force link UP in non LOOPBACK_EXT loopback mode(s) */
5446 if (params->loopback_mode != ELINK_LOOPBACK_NONE &&
5447 params->loopback_mode != ELINK_LOOPBACK_EXT)
5448 vars->link_status |= LINK_STATUS_LINK_UP;
5449
5450 #ifndef EXCLUDE_NON_COMMON_INIT
5451 #ifndef EXCLUDE_WARPCORE
5452 if (elink_eee_has_cap(params))
5453 vars->eee_status = REG_RD(cb, params->shmem2_base +
5454 OFFSETOF(struct shmem2_region,
5455 eee_status[params->port]));
5456 #endif
5457 #endif
5458
5459 vars->phy_flags = PHY_XGXS_FLAG;
5460 elink_sync_link(params, vars);
5461 /* Sync media type */
5462 sync_offset = params->shmem_base +
5463 OFFSETOF(struct shmem_region,
5464 dev_info.port_hw_config[port].media_type);
5465 media_types = REG_RD(cb, sync_offset);
5466
5467 params->phy[ELINK_INT_PHY].media_type =
5468 (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) >>
5469 PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT;
5470 params->phy[ELINK_EXT_PHY1].media_type =
5471 (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK) >>
5472 PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT;
5473 params->phy[ELINK_EXT_PHY2].media_type =
5474 (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK) >>
5475 PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT;
5476 ELINK_DEBUG_P1(cb, "media_types = 0x%x\n", media_types);
5477
5478 /* Sync AEU offset */
5479 sync_offset = params->shmem_base +
5480 OFFSETOF(struct shmem_region,
5481 dev_info.port_hw_config[port].aeu_int_mask);
5482
5483 vars->aeu_int_mask = REG_RD(cb, sync_offset);
5484
5485 /* Sync PFC status */
5486 if (vars->link_status & LINK_STATUS_PFC_ENABLED)
5487 params->feature_config_flags |=
5488 ELINK_FEATURE_CONFIG_PFC_ENABLED;
5489 else
5490 params->feature_config_flags &=
5491 ~ELINK_FEATURE_CONFIG_PFC_ENABLED;
5492
5493 if (SHMEM2_HAS(cb, params->shmem2_base, link_attr_sync))
5494 params->link_attr_sync = SHMEM2_RD(cb, params->shmem2_base,
5495 link_attr_sync[params->port]);
5496
5497 ELINK_DEBUG_P3(cb, "link_status 0x%x phy_link_up %x int_mask 0x%x\n",
5498 vars->link_status, vars->phy_link_up, vars->aeu_int_mask);
5499 ELINK_DEBUG_P3(cb, "line_speed %x duplex %x flow_ctrl 0x%x\n",
5500 vars->line_speed, vars->duplex, vars->flow_ctrl);
5501 }
5502
5503 #ifndef EXCLUDE_NON_COMMON_INIT
5504 #ifndef EXCLUDE_XGXS
elink_set_master_ln(struct elink_params * params,struct elink_phy * phy)5505 static void elink_set_master_ln(struct elink_params *params,
5506 struct elink_phy *phy)
5507 {
5508 struct elink_dev *cb = params->cb;
5509 u16 new_master_ln, ser_lane;
5510 ser_lane = ((params->lane_config &
5511 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
5512 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
5513
5514 /* Set the master_ln for AN */
5515 CL22_RD_OVER_CL45(cb, phy,
5516 MDIO_REG_BANK_XGXS_BLOCK2,
5517 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
5518 &new_master_ln);
5519
5520 CL22_WR_OVER_CL45(cb, phy,
5521 MDIO_REG_BANK_XGXS_BLOCK2 ,
5522 MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
5523 (new_master_ln | ser_lane));
5524 }
5525
elink_reset_unicore(struct elink_params * params,struct elink_phy * phy,u8 set_serdes)5526 static elink_status_t elink_reset_unicore(struct elink_params *params,
5527 struct elink_phy *phy,
5528 u8 set_serdes)
5529 {
5530 struct elink_dev *cb = params->cb;
5531 u16 mii_control;
5532 u16 i;
5533 CL22_RD_OVER_CL45(cb, phy,
5534 MDIO_REG_BANK_COMBO_IEEE0,
5535 MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
5536
5537 /* Reset the unicore */
5538 CL22_WR_OVER_CL45(cb, phy,
5539 MDIO_REG_BANK_COMBO_IEEE0,
5540 MDIO_COMBO_IEEE0_MII_CONTROL,
5541 (mii_control |
5542 MDIO_COMBO_IEEO_MII_CONTROL_RESET));
5543 #ifndef EXCLUDE_SERDES
5544 if (set_serdes)
5545 elink_set_serdes_access(cb, params->port);
5546 #endif /* EXCLUDE_SERDES */
5547
5548 /* Wait for the reset to self clear */
5549 for (i = 0; i < ELINK_MDIO_ACCESS_TIMEOUT; i++) {
5550 USLEEP(cb, 5);
5551
5552 /* The reset erased the previous bank value */
5553 CL22_RD_OVER_CL45(cb, phy,
5554 MDIO_REG_BANK_COMBO_IEEE0,
5555 MDIO_COMBO_IEEE0_MII_CONTROL,
5556 &mii_control);
5557
5558 if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) {
5559 USLEEP(cb, 5);
5560 return ELINK_STATUS_OK;
5561 }
5562 }
5563
5564 elink_cb_event_log(cb, ELINK_LOG_ID_PHY_UNINITIALIZED, params->port); // "Warning: PHY was not initialized,"
5565 // " Port %d\n",
5566
5567 ELINK_DEBUG_P0(cb, "BUG! XGXS is still in reset!\n");
5568 return ELINK_STATUS_ERROR;
5569
5570 }
5571
elink_set_swap_lanes(struct elink_params * params,struct elink_phy * phy)5572 static void elink_set_swap_lanes(struct elink_params *params,
5573 struct elink_phy *phy)
5574 {
5575 struct elink_dev *cb = params->cb;
5576 /* Each two bits represents a lane number:
5577 * No swap is 0123 => 0x1b no need to enable the swap
5578 */
5579 u16 rx_lane_swap, tx_lane_swap;
5580
5581 rx_lane_swap = ((params->lane_config &
5582 PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
5583 PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
5584 tx_lane_swap = ((params->lane_config &
5585 PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
5586 PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
5587
5588 if (rx_lane_swap != 0x1b) {
5589 CL22_WR_OVER_CL45(cb, phy,
5590 MDIO_REG_BANK_XGXS_BLOCK2,
5591 MDIO_XGXS_BLOCK2_RX_LN_SWAP,
5592 (rx_lane_swap |
5593 MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
5594 MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
5595 } else {
5596 CL22_WR_OVER_CL45(cb, phy,
5597 MDIO_REG_BANK_XGXS_BLOCK2,
5598 MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
5599 }
5600
5601 if (tx_lane_swap != 0x1b) {
5602 CL22_WR_OVER_CL45(cb, phy,
5603 MDIO_REG_BANK_XGXS_BLOCK2,
5604 MDIO_XGXS_BLOCK2_TX_LN_SWAP,
5605 (tx_lane_swap |
5606 MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
5607 } else {
5608 CL22_WR_OVER_CL45(cb, phy,
5609 MDIO_REG_BANK_XGXS_BLOCK2,
5610 MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
5611 }
5612 }
5613
elink_set_parallel_detection(struct elink_phy * phy,struct elink_params * params)5614 static void elink_set_parallel_detection(struct elink_phy *phy,
5615 struct elink_params *params)
5616 {
5617 struct elink_dev *cb = params->cb;
5618 u16 control2;
5619 CL22_RD_OVER_CL45(cb, phy,
5620 MDIO_REG_BANK_SERDES_DIGITAL,
5621 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
5622 &control2);
5623 if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
5624 control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
5625 else
5626 control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
5627 ELINK_DEBUG_P2(cb, "phy->speed_cap_mask = 0x%x, control2 = 0x%x\n",
5628 phy->speed_cap_mask, control2);
5629 CL22_WR_OVER_CL45(cb, phy,
5630 MDIO_REG_BANK_SERDES_DIGITAL,
5631 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
5632 control2);
5633
5634 if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
5635 (phy->speed_cap_mask &
5636 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
5637 ELINK_DEBUG_P0(cb, "XGXS\n");
5638
5639 CL22_WR_OVER_CL45(cb, phy,
5640 MDIO_REG_BANK_10G_PARALLEL_DETECT,
5641 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
5642 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
5643
5644 CL22_RD_OVER_CL45(cb, phy,
5645 MDIO_REG_BANK_10G_PARALLEL_DETECT,
5646 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
5647 &control2);
5648
5649
5650 control2 |=
5651 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
5652
5653 CL22_WR_OVER_CL45(cb, phy,
5654 MDIO_REG_BANK_10G_PARALLEL_DETECT,
5655 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
5656 control2);
5657
5658 /* Disable parallel detection of HiG */
5659 CL22_WR_OVER_CL45(cb, phy,
5660 MDIO_REG_BANK_XGXS_BLOCK2,
5661 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
5662 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
5663 MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
5664 }
5665 }
5666
elink_set_autoneg(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars,u8 enable_cl73)5667 static void elink_set_autoneg(struct elink_phy *phy,
5668 struct elink_params *params,
5669 struct elink_vars *vars,
5670 u8 enable_cl73)
5671 {
5672 struct elink_dev *cb = params->cb;
5673 u16 reg_val;
5674
5675 /* CL37 Autoneg */
5676 CL22_RD_OVER_CL45(cb, phy,
5677 MDIO_REG_BANK_COMBO_IEEE0,
5678 MDIO_COMBO_IEEE0_MII_CONTROL, ®_val);
5679
5680 /* CL37 Autoneg Enabled */
5681 if (vars->line_speed == ELINK_SPEED_AUTO_NEG)
5682 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN;
5683 else /* CL37 Autoneg Disabled */
5684 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
5685 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);
5686
5687 CL22_WR_OVER_CL45(cb, phy,
5688 MDIO_REG_BANK_COMBO_IEEE0,
5689 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
5690
5691 /* Enable/Disable Autodetection */
5692
5693 CL22_RD_OVER_CL45(cb, phy,
5694 MDIO_REG_BANK_SERDES_DIGITAL,
5695 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, ®_val);
5696 reg_val &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN |
5697 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT);
5698 reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE;
5699 if (vars->line_speed == ELINK_SPEED_AUTO_NEG)
5700 reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
5701 else
5702 reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
5703
5704 CL22_WR_OVER_CL45(cb, phy,
5705 MDIO_REG_BANK_SERDES_DIGITAL,
5706 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
5707
5708 /* Enable TetonII and BAM autoneg */
5709 CL22_RD_OVER_CL45(cb, phy,
5710 MDIO_REG_BANK_BAM_NEXT_PAGE,
5711 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
5712 ®_val);
5713 if (vars->line_speed == ELINK_SPEED_AUTO_NEG) {
5714 /* Enable BAM aneg Mode and TetonII aneg Mode */
5715 reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
5716 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
5717 } else {
5718 /* TetonII and BAM Autoneg Disabled */
5719 reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
5720 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
5721 }
5722 CL22_WR_OVER_CL45(cb, phy,
5723 MDIO_REG_BANK_BAM_NEXT_PAGE,
5724 MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
5725 reg_val);
5726
5727 if (enable_cl73) {
5728 /* Enable Cl73 FSM status bits */
5729 CL22_WR_OVER_CL45(cb, phy,
5730 MDIO_REG_BANK_CL73_USERB0,
5731 MDIO_CL73_USERB0_CL73_UCTRL,
5732 0xe);
5733
5734 /* Enable BAM Station Manager*/
5735 CL22_WR_OVER_CL45(cb, phy,
5736 MDIO_REG_BANK_CL73_USERB0,
5737 MDIO_CL73_USERB0_CL73_BAM_CTRL1,
5738 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
5739 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN |
5740 MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN);
5741
5742 /* Advertise CL73 link speeds */
5743 CL22_RD_OVER_CL45(cb, phy,
5744 MDIO_REG_BANK_CL73_IEEEB1,
5745 MDIO_CL73_IEEEB1_AN_ADV2,
5746 ®_val);
5747 if (phy->speed_cap_mask &
5748 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
5749 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
5750 if (phy->speed_cap_mask &
5751 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
5752 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
5753
5754 CL22_WR_OVER_CL45(cb, phy,
5755 MDIO_REG_BANK_CL73_IEEEB1,
5756 MDIO_CL73_IEEEB1_AN_ADV2,
5757 reg_val);
5758
5759 /* CL73 Autoneg Enabled */
5760 reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;
5761
5762 } else /* CL73 Autoneg Disabled */
5763 reg_val = 0;
5764
5765 CL22_WR_OVER_CL45(cb, phy,
5766 MDIO_REG_BANK_CL73_IEEEB0,
5767 MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
5768 }
5769
5770 /* Program SerDes, forced speed */
elink_program_serdes(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)5771 static void elink_program_serdes(struct elink_phy *phy,
5772 struct elink_params *params,
5773 struct elink_vars *vars)
5774 {
5775 struct elink_dev *cb = params->cb;
5776 u16 reg_val;
5777
5778 /* Program duplex, disable autoneg and sgmii*/
5779 CL22_RD_OVER_CL45(cb, phy,
5780 MDIO_REG_BANK_COMBO_IEEE0,
5781 MDIO_COMBO_IEEE0_MII_CONTROL, ®_val);
5782 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
5783 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
5784 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK);
5785 if (phy->req_duplex == DUPLEX_FULL)
5786 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
5787 CL22_WR_OVER_CL45(cb, phy,
5788 MDIO_REG_BANK_COMBO_IEEE0,
5789 MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
5790
5791 /* Program speed
5792 * - needed only if the speed is greater than 1G (2.5G or 10G)
5793 */
5794 CL22_RD_OVER_CL45(cb, phy,
5795 MDIO_REG_BANK_SERDES_DIGITAL,
5796 MDIO_SERDES_DIGITAL_MISC1, ®_val);
5797 /* Clearing the speed value before setting the right speed */
5798 ELINK_DEBUG_P1(cb, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x\n", reg_val);
5799
5800 reg_val &= ~(MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK |
5801 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
5802
5803 if (!((vars->line_speed == ELINK_SPEED_1000) ||
5804 (vars->line_speed == ELINK_SPEED_100) ||
5805 (vars->line_speed == ELINK_SPEED_10))) {
5806
5807 reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M |
5808 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
5809 if (vars->line_speed == ELINK_SPEED_10000)
5810 reg_val |=
5811 MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
5812 }
5813
5814 CL22_WR_OVER_CL45(cb, phy,
5815 MDIO_REG_BANK_SERDES_DIGITAL,
5816 MDIO_SERDES_DIGITAL_MISC1, reg_val);
5817
5818 }
5819
elink_set_brcm_cl37_advertisement(struct elink_phy * phy,struct elink_params * params)5820 static void elink_set_brcm_cl37_advertisement(struct elink_phy *phy,
5821 struct elink_params *params)
5822 {
5823 struct elink_dev *cb = params->cb;
5824 u16 val = 0;
5825
5826 /* Set extended capabilities */
5827 if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
5828 val |= MDIO_OVER_1G_UP1_2_5G;
5829 if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
5830 val |= MDIO_OVER_1G_UP1_10G;
5831 CL22_WR_OVER_CL45(cb, phy,
5832 MDIO_REG_BANK_OVER_1G,
5833 MDIO_OVER_1G_UP1, val);
5834
5835 CL22_WR_OVER_CL45(cb, phy,
5836 MDIO_REG_BANK_OVER_1G,
5837 MDIO_OVER_1G_UP3, 0x400);
5838 }
5839
elink_set_ieee_aneg_advertisement(struct elink_phy * phy,struct elink_params * params,u16 ieee_fc)5840 static void elink_set_ieee_aneg_advertisement(struct elink_phy *phy,
5841 struct elink_params *params,
5842 u16 ieee_fc)
5843 {
5844 struct elink_dev *cb = params->cb;
5845 u16 val;
5846 /* For AN, we are always publishing full duplex */
5847
5848 CL22_WR_OVER_CL45(cb, phy,
5849 MDIO_REG_BANK_COMBO_IEEE0,
5850 MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc);
5851 CL22_RD_OVER_CL45(cb, phy,
5852 MDIO_REG_BANK_CL73_IEEEB1,
5853 MDIO_CL73_IEEEB1_AN_ADV1, &val);
5854 val &= ~MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH;
5855 val |= ((ieee_fc<<3) & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK);
5856 CL22_WR_OVER_CL45(cb, phy,
5857 MDIO_REG_BANK_CL73_IEEEB1,
5858 MDIO_CL73_IEEEB1_AN_ADV1, val);
5859 }
5860
elink_restart_autoneg(struct elink_phy * phy,struct elink_params * params,u8 enable_cl73)5861 static void elink_restart_autoneg(struct elink_phy *phy,
5862 struct elink_params *params,
5863 u8 enable_cl73)
5864 {
5865 struct elink_dev *cb = params->cb;
5866 u16 mii_control;
5867
5868 ELINK_DEBUG_P0(cb, "elink_restart_autoneg\n");
5869 /* Enable and restart BAM/CL37 aneg */
5870
5871 if (enable_cl73) {
5872 CL22_RD_OVER_CL45(cb, phy,
5873 MDIO_REG_BANK_CL73_IEEEB0,
5874 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
5875 &mii_control);
5876
5877 CL22_WR_OVER_CL45(cb, phy,
5878 MDIO_REG_BANK_CL73_IEEEB0,
5879 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
5880 (mii_control |
5881 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
5882 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
5883 } else {
5884
5885 CL22_RD_OVER_CL45(cb, phy,
5886 MDIO_REG_BANK_COMBO_IEEE0,
5887 MDIO_COMBO_IEEE0_MII_CONTROL,
5888 &mii_control);
5889 ELINK_DEBUG_P1(cb,
5890 "elink_restart_autoneg mii_control before = 0x%x\n",
5891 mii_control);
5892 CL22_WR_OVER_CL45(cb, phy,
5893 MDIO_REG_BANK_COMBO_IEEE0,
5894 MDIO_COMBO_IEEE0_MII_CONTROL,
5895 (mii_control |
5896 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
5897 MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
5898 }
5899 }
5900
elink_initialize_sgmii_process(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)5901 static void elink_initialize_sgmii_process(struct elink_phy *phy,
5902 struct elink_params *params,
5903 struct elink_vars *vars)
5904 {
5905 struct elink_dev *cb = params->cb;
5906 u16 control1;
5907
5908 /* In SGMII mode, the unicore is always slave */
5909
5910 CL22_RD_OVER_CL45(cb, phy,
5911 MDIO_REG_BANK_SERDES_DIGITAL,
5912 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
5913 &control1);
5914 control1 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT;
5915 /* Set sgmii mode (and not fiber) */
5916 control1 &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE |
5917 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET |
5918 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE);
5919 CL22_WR_OVER_CL45(cb, phy,
5920 MDIO_REG_BANK_SERDES_DIGITAL,
5921 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
5922 control1);
5923
5924 /* If forced speed */
5925 if (!(vars->line_speed == ELINK_SPEED_AUTO_NEG)) {
5926 /* Set speed, disable autoneg */
5927 u16 mii_control;
5928
5929 CL22_RD_OVER_CL45(cb, phy,
5930 MDIO_REG_BANK_COMBO_IEEE0,
5931 MDIO_COMBO_IEEE0_MII_CONTROL,
5932 &mii_control);
5933 mii_control &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
5934 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK|
5935 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX);
5936
5937 switch (vars->line_speed) {
5938 case ELINK_SPEED_100:
5939 mii_control |=
5940 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100;
5941 break;
5942 case ELINK_SPEED_1000:
5943 mii_control |=
5944 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_1000;
5945 break;
5946 case ELINK_SPEED_10:
5947 /* There is nothing to set for 10M */
5948 break;
5949 default:
5950 /* Invalid speed for SGMII */
5951 ELINK_DEBUG_P1(cb, "Invalid line_speed 0x%x\n",
5952 vars->line_speed);
5953 break;
5954 }
5955
5956 /* Setting the full duplex */
5957 if (phy->req_duplex == DUPLEX_FULL)
5958 mii_control |=
5959 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
5960 CL22_WR_OVER_CL45(cb, phy,
5961 MDIO_REG_BANK_COMBO_IEEE0,
5962 MDIO_COMBO_IEEE0_MII_CONTROL,
5963 mii_control);
5964
5965 } else { /* AN mode */
5966 /* Enable and restart AN */
5967 elink_restart_autoneg(phy, params, 0);
5968 }
5969 }
5970
5971 /* Link management
5972 */
elink_direct_parallel_detect_used(struct elink_phy * phy,struct elink_params * params)5973 static elink_status_t elink_direct_parallel_detect_used(struct elink_phy *phy,
5974 struct elink_params *params)
5975 {
5976 struct elink_dev *cb = params->cb;
5977 u16 pd_10g, status2_1000x;
5978 if (phy->req_line_speed != ELINK_SPEED_AUTO_NEG)
5979 return ELINK_STATUS_OK;
5980 CL22_RD_OVER_CL45(cb, phy,
5981 MDIO_REG_BANK_SERDES_DIGITAL,
5982 MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
5983 &status2_1000x);
5984 CL22_RD_OVER_CL45(cb, phy,
5985 MDIO_REG_BANK_SERDES_DIGITAL,
5986 MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
5987 &status2_1000x);
5988 if (status2_1000x & MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED) {
5989 ELINK_DEBUG_P1(cb, "1G parallel detect link on port %d\n",
5990 params->port);
5991 return 1;
5992 }
5993
5994 CL22_RD_OVER_CL45(cb, phy,
5995 MDIO_REG_BANK_10G_PARALLEL_DETECT,
5996 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS,
5997 &pd_10g);
5998
5999 if (pd_10g & MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK) {
6000 ELINK_DEBUG_P1(cb, "10G parallel detect link on port %d\n",
6001 params->port);
6002 return 1;
6003 }
6004 return ELINK_STATUS_OK;
6005 }
6006
elink_update_adv_fc(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars,u32 gp_status)6007 static void elink_update_adv_fc(struct elink_phy *phy,
6008 struct elink_params *params,
6009 struct elink_vars *vars,
6010 u32 gp_status)
6011 {
6012 u16 ld_pause; /* local driver */
6013 u16 lp_pause; /* link partner */
6014 u16 pause_result;
6015 struct elink_dev *cb = params->cb;
6016 if ((gp_status &
6017 (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
6018 MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) ==
6019 (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
6020 MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {
6021
6022 CL22_RD_OVER_CL45(cb, phy,
6023 MDIO_REG_BANK_CL73_IEEEB1,
6024 MDIO_CL73_IEEEB1_AN_ADV1,
6025 &ld_pause);
6026 CL22_RD_OVER_CL45(cb, phy,
6027 MDIO_REG_BANK_CL73_IEEEB1,
6028 MDIO_CL73_IEEEB1_AN_LP_ADV1,
6029 &lp_pause);
6030 pause_result = (ld_pause &
6031 MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK) >> 8;
6032 pause_result |= (lp_pause &
6033 MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK) >> 10;
6034 ELINK_DEBUG_P1(cb, "pause_result CL73 0x%x\n", pause_result);
6035 } else {
6036 CL22_RD_OVER_CL45(cb, phy,
6037 MDIO_REG_BANK_COMBO_IEEE0,
6038 MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
6039 &ld_pause);
6040 CL22_RD_OVER_CL45(cb, phy,
6041 MDIO_REG_BANK_COMBO_IEEE0,
6042 MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
6043 &lp_pause);
6044 pause_result = (ld_pause &
6045 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
6046 pause_result |= (lp_pause &
6047 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
6048 ELINK_DEBUG_P1(cb, "pause_result CL37 0x%x\n", pause_result);
6049 }
6050 elink_pause_resolve(vars, pause_result);
6051
6052 }
6053
elink_flow_ctrl_resolve(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars,u32 gp_status)6054 static void elink_flow_ctrl_resolve(struct elink_phy *phy,
6055 struct elink_params *params,
6056 struct elink_vars *vars,
6057 u32 gp_status)
6058 {
6059 #ifdef ELINK_DEBUG
6060 struct elink_dev *cb = params->cb;
6061 #endif
6062 vars->flow_ctrl = ELINK_FLOW_CTRL_NONE;
6063
6064 /* Resolve from gp_status in case of AN complete and not sgmii */
6065 if (phy->req_flow_ctrl != ELINK_FLOW_CTRL_AUTO) {
6066 /* Update the advertised flow-controled of LD/LP in AN */
6067 if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG)
6068 elink_update_adv_fc(phy, params, vars, gp_status);
6069 /* But set the flow-control result as the requested one */
6070 vars->flow_ctrl = phy->req_flow_ctrl;
6071 } else if (phy->req_line_speed != ELINK_SPEED_AUTO_NEG)
6072 vars->flow_ctrl = params->req_fc_auto_adv;
6073 else if ((gp_status & ELINK_MDIO_AN_CL73_OR_37_COMPLETE) &&
6074 (!(vars->phy_flags & PHY_SGMII_FLAG))) {
6075 if (elink_direct_parallel_detect_used(phy, params)) {
6076 vars->flow_ctrl = params->req_fc_auto_adv;
6077 return;
6078 }
6079 elink_update_adv_fc(phy, params, vars, gp_status);
6080 }
6081 ELINK_DEBUG_P1(cb, "flow_ctrl 0x%x\n", vars->flow_ctrl);
6082 }
6083
elink_check_fallback_to_cl37(struct elink_phy * phy,struct elink_params * params)6084 static void elink_check_fallback_to_cl37(struct elink_phy *phy,
6085 struct elink_params *params)
6086 {
6087 struct elink_dev *cb = params->cb;
6088 u16 rx_status, ustat_val, cl37_fsm_received;
6089 ELINK_DEBUG_P0(cb, "elink_check_fallback_to_cl37\n");
6090 /* Step 1: Make sure signal is detected */
6091 CL22_RD_OVER_CL45(cb, phy,
6092 MDIO_REG_BANK_RX0,
6093 MDIO_RX0_RX_STATUS,
6094 &rx_status);
6095 if ((rx_status & MDIO_RX0_RX_STATUS_SIGDET) !=
6096 (MDIO_RX0_RX_STATUS_SIGDET)) {
6097 ELINK_DEBUG_P1(cb, "Signal is not detected. Restoring CL73."
6098 "rx_status(0x80b0) = 0x%x\n", rx_status);
6099 CL22_WR_OVER_CL45(cb, phy,
6100 MDIO_REG_BANK_CL73_IEEEB0,
6101 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
6102 MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN);
6103 return;
6104 }
6105 /* Step 2: Check CL73 state machine */
6106 CL22_RD_OVER_CL45(cb, phy,
6107 MDIO_REG_BANK_CL73_USERB0,
6108 MDIO_CL73_USERB0_CL73_USTAT1,
6109 &ustat_val);
6110 if ((ustat_val &
6111 (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
6112 MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) !=
6113 (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
6114 MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) {
6115 ELINK_DEBUG_P1(cb, "CL73 state-machine is not stable. "
6116 "ustat_val(0x8371) = 0x%x\n", ustat_val);
6117 return;
6118 }
6119 /* Step 3: Check CL37 Message Pages received to indicate LP
6120 * supports only CL37
6121 */
6122 CL22_RD_OVER_CL45(cb, phy,
6123 MDIO_REG_BANK_REMOTE_PHY,
6124 MDIO_REMOTE_PHY_MISC_RX_STATUS,
6125 &cl37_fsm_received);
6126 if ((cl37_fsm_received &
6127 (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
6128 MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) !=
6129 (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
6130 MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) {
6131 ELINK_DEBUG_P1(cb, "No CL37 FSM were received. "
6132 "misc_rx_status(0x8330) = 0x%x\n",
6133 cl37_fsm_received);
6134 return;
6135 }
6136 /* The combined cl37/cl73 fsm state information indicating that
6137 * we are connected to a device which does not support cl73, but
6138 * does support cl37 BAM. In this case we disable cl73 and
6139 * restart cl37 auto-neg
6140 */
6141
6142 /* Disable CL73 */
6143 CL22_WR_OVER_CL45(cb, phy,
6144 MDIO_REG_BANK_CL73_IEEEB0,
6145 MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
6146 0);
6147 /* Restart CL37 autoneg */
6148 elink_restart_autoneg(phy, params, 0);
6149 ELINK_DEBUG_P0(cb, "Disabling CL73, and restarting CL37 autoneg\n");
6150 }
6151
elink_xgxs_an_resolve(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars,u32 gp_status)6152 static void elink_xgxs_an_resolve(struct elink_phy *phy,
6153 struct elink_params *params,
6154 struct elink_vars *vars,
6155 u32 gp_status)
6156 {
6157 if (gp_status & ELINK_MDIO_AN_CL73_OR_37_COMPLETE)
6158 vars->link_status |=
6159 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
6160
6161 if (elink_direct_parallel_detect_used(phy, params))
6162 vars->link_status |=
6163 LINK_STATUS_PARALLEL_DETECTION_USED;
6164 }
6165 #endif /* EXCLUDE_XGXS */
elink_get_link_speed_duplex(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars,u16 is_link_up,u16 speed_mask,u16 is_duplex)6166 static elink_status_t elink_get_link_speed_duplex(struct elink_phy *phy,
6167 struct elink_params *params,
6168 struct elink_vars *vars,
6169 u16 is_link_up,
6170 u16 speed_mask,
6171 u16 is_duplex)
6172 {
6173 #ifdef ELINK_DEBUG
6174 struct elink_dev *cb = params->cb;
6175 #endif
6176 if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG)
6177 vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
6178 if (is_link_up) {
6179 ELINK_DEBUG_P0(cb, "phy link up\n");
6180
6181 vars->phy_link_up = 1;
6182 vars->link_status |= LINK_STATUS_LINK_UP;
6183
6184 switch (speed_mask) {
6185 case ELINK_GP_STATUS_10M:
6186 vars->line_speed = ELINK_SPEED_10;
6187 if (is_duplex == DUPLEX_FULL)
6188 vars->link_status |= ELINK_LINK_10TFD;
6189 else
6190 vars->link_status |= ELINK_LINK_10THD;
6191 break;
6192
6193 case ELINK_GP_STATUS_100M:
6194 vars->line_speed = ELINK_SPEED_100;
6195 if (is_duplex == DUPLEX_FULL)
6196 vars->link_status |= ELINK_LINK_100TXFD;
6197 else
6198 vars->link_status |= ELINK_LINK_100TXHD;
6199 break;
6200
6201 case ELINK_GP_STATUS_1G:
6202 case ELINK_GP_STATUS_1G_KX:
6203 vars->line_speed = ELINK_SPEED_1000;
6204 if (is_duplex == DUPLEX_FULL)
6205 vars->link_status |= ELINK_LINK_1000TFD;
6206 else
6207 vars->link_status |= ELINK_LINK_1000THD;
6208 break;
6209
6210 case ELINK_GP_STATUS_2_5G:
6211 vars->line_speed = ELINK_SPEED_2500;
6212 if (is_duplex == DUPLEX_FULL)
6213 vars->link_status |= ELINK_LINK_2500TFD;
6214 else
6215 vars->link_status |= ELINK_LINK_2500THD;
6216 break;
6217
6218 case ELINK_GP_STATUS_5G:
6219 case ELINK_GP_STATUS_6G:
6220 ELINK_DEBUG_P1(cb,
6221 "link speed unsupported gp_status 0x%x\n",
6222 speed_mask);
6223 return ELINK_STATUS_ERROR;
6224
6225 case ELINK_GP_STATUS_10G_KX4:
6226 case ELINK_GP_STATUS_10G_HIG:
6227 case ELINK_GP_STATUS_10G_CX4:
6228 case ELINK_GP_STATUS_10G_KR:
6229 case ELINK_GP_STATUS_10G_SFI:
6230 case ELINK_GP_STATUS_10G_XFI:
6231 vars->line_speed = ELINK_SPEED_10000;
6232 vars->link_status |= ELINK_LINK_10GTFD;
6233 break;
6234 case ELINK_GP_STATUS_20G_DXGXS:
6235 case ELINK_GP_STATUS_20G_KR2:
6236 vars->line_speed = ELINK_SPEED_20000;
6237 vars->link_status |= ELINK_LINK_20GTFD;
6238 break;
6239 default:
6240 ELINK_DEBUG_P1(cb,
6241 "link speed unsupported gp_status 0x%x\n",
6242 speed_mask);
6243 return ELINK_STATUS_ERROR;
6244 }
6245 } else { /* link_down */
6246 ELINK_DEBUG_P0(cb, "phy link down\n");
6247
6248 vars->phy_link_up = 0;
6249
6250 vars->duplex = DUPLEX_FULL;
6251 vars->flow_ctrl = ELINK_FLOW_CTRL_NONE;
6252 vars->mac_type = ELINK_MAC_TYPE_NONE;
6253 }
6254 ELINK_DEBUG_P2(cb, " phy_link_up %x line_speed %d\n",
6255 vars->phy_link_up, vars->line_speed);
6256 return ELINK_STATUS_OK;
6257 }
6258
6259 #ifndef EXCLUDE_XGXS
elink_link_settings_status(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)6260 static elink_status_t elink_link_settings_status(struct elink_phy *phy,
6261 struct elink_params *params,
6262 struct elink_vars *vars)
6263 {
6264 struct elink_dev *cb = params->cb;
6265
6266 u16 gp_status, duplex = DUPLEX_HALF, link_up = 0, speed_mask;
6267 elink_status_t rc = ELINK_STATUS_OK;
6268
6269 /* Read gp_status */
6270 CL22_RD_OVER_CL45(cb, phy,
6271 MDIO_REG_BANK_GP_STATUS,
6272 MDIO_GP_STATUS_TOP_AN_STATUS1,
6273 &gp_status);
6274 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
6275 duplex = DUPLEX_FULL;
6276 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS)
6277 link_up = 1;
6278 speed_mask = gp_status & ELINK_GP_STATUS_SPEED_MASK;
6279 ELINK_DEBUG_P3(cb, "gp_status 0x%x, is_link_up %d, speed_mask 0x%x\n",
6280 gp_status, link_up, speed_mask);
6281 rc = elink_get_link_speed_duplex(phy, params, vars, link_up, speed_mask,
6282 duplex);
6283 if (rc == ELINK_STATUS_ERROR)
6284 return rc;
6285
6286 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
6287 if (ELINK_SINGLE_MEDIA_DIRECT(params)) {
6288 vars->duplex = duplex;
6289 elink_flow_ctrl_resolve(phy, params, vars, gp_status);
6290 if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG)
6291 elink_xgxs_an_resolve(phy, params, vars,
6292 gp_status);
6293 }
6294 } else { /* Link_down */
6295 if ((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) &&
6296 ELINK_SINGLE_MEDIA_DIRECT(params)) {
6297 /* Check signal is detected */
6298 elink_check_fallback_to_cl37(phy, params);
6299 }
6300 }
6301
6302 /* Read LP advertised speeds*/
6303 if (ELINK_SINGLE_MEDIA_DIRECT(params) &&
6304 (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)) {
6305 u16 val;
6306
6307 CL22_RD_OVER_CL45(cb, phy, MDIO_REG_BANK_CL73_IEEEB1,
6308 MDIO_CL73_IEEEB1_AN_LP_ADV2, &val);
6309
6310 if (val & MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX)
6311 vars->link_status |=
6312 LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
6313 if (val & (MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 |
6314 MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR))
6315 vars->link_status |=
6316 LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
6317
6318 CL22_RD_OVER_CL45(cb, phy, MDIO_REG_BANK_OVER_1G,
6319 MDIO_OVER_1G_LP_UP1, &val);
6320
6321 if (val & MDIO_OVER_1G_UP1_2_5G)
6322 vars->link_status |=
6323 LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE;
6324 if (val & (MDIO_OVER_1G_UP1_10G | MDIO_OVER_1G_UP1_10GH))
6325 vars->link_status |=
6326 LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
6327 }
6328
6329 ELINK_DEBUG_P3(cb, "duplex %x flow_ctrl 0x%x link_status 0x%x\n",
6330 vars->duplex, vars->flow_ctrl, vars->link_status);
6331 return rc;
6332 }
6333 #endif // EXCLUDE_XGXS
6334
6335 #ifndef EXCLUDE_WARPCORE
elink_warpcore_read_status(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)6336 static elink_status_t elink_warpcore_read_status(struct elink_phy *phy,
6337 struct elink_params *params,
6338 struct elink_vars *vars)
6339 {
6340 struct elink_dev *cb = params->cb;
6341 u8 lane;
6342 u16 gp_status1, gp_speed, link_up, duplex = DUPLEX_FULL;
6343 elink_status_t rc = ELINK_STATUS_OK;
6344 lane = elink_get_warpcore_lane(phy, params);
6345 /* Read gp_status */
6346 if ((params->loopback_mode) &&
6347 (phy->flags & ELINK_FLAGS_WC_DUAL_MODE)) {
6348 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
6349 MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up);
6350 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
6351 MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up);
6352 link_up &= 0x1;
6353 } else if ((phy->req_line_speed > ELINK_SPEED_10000) &&
6354 (phy->supported & ELINK_SUPPORTED_20000baseMLD2_Full)) {
6355 u16 temp_link_up;
6356 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
6357 1, &temp_link_up);
6358 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
6359 1, &link_up);
6360 ELINK_DEBUG_P2(cb, "PCS RX link status = 0x%x-->0x%x\n",
6361 temp_link_up, link_up);
6362 link_up &= (1<<2);
6363 if (link_up)
6364 elink_ext_phy_resolve_fc(phy, params, vars);
6365 } else {
6366 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
6367 MDIO_WC_REG_GP2_STATUS_GP_2_1,
6368 &gp_status1);
6369 ELINK_DEBUG_P1(cb, "0x81d1 = 0x%x\n", gp_status1);
6370 /* Check for either KR, 1G, or AN up. */
6371 link_up = ((gp_status1 >> 8) |
6372 (gp_status1 >> 12) |
6373 (gp_status1)) &
6374 (1 << lane);
6375 if (phy->supported & ELINK_SUPPORTED_20000baseKR2_Full) {
6376 u16 an_link;
6377 elink_cl45_read(cb, phy, MDIO_AN_DEVAD,
6378 MDIO_AN_REG_STATUS, &an_link);
6379 elink_cl45_read(cb, phy, MDIO_AN_DEVAD,
6380 MDIO_AN_REG_STATUS, &an_link);
6381 link_up |= (an_link & (1<<2));
6382 }
6383 if (link_up && ELINK_SINGLE_MEDIA_DIRECT(params)) {
6384 u16 pd, gp_status4;
6385 if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG) {
6386 /* Check Autoneg complete */
6387 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
6388 MDIO_WC_REG_GP2_STATUS_GP_2_4,
6389 &gp_status4);
6390 if (gp_status4 & ((1<<12)<<lane))
6391 vars->link_status |=
6392 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
6393
6394 /* Check parallel detect used */
6395 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
6396 MDIO_WC_REG_PAR_DET_10G_STATUS,
6397 &pd);
6398 if (pd & (1<<15))
6399 vars->link_status |=
6400 LINK_STATUS_PARALLEL_DETECTION_USED;
6401 }
6402 elink_ext_phy_resolve_fc(phy, params, vars);
6403 vars->duplex = duplex;
6404 }
6405 }
6406
6407 if ((vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) &&
6408 ELINK_SINGLE_MEDIA_DIRECT(params)) {
6409 u16 val;
6410
6411 elink_cl45_read(cb, phy, MDIO_AN_DEVAD,
6412 MDIO_AN_REG_LP_AUTO_NEG2, &val);
6413
6414 if (val & MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX)
6415 vars->link_status |=
6416 LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
6417 if (val & (MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 |
6418 MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR))
6419 vars->link_status |=
6420 LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
6421
6422 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
6423 MDIO_WC_REG_DIGITAL3_LP_UP1, &val);
6424
6425 if (val & MDIO_OVER_1G_UP1_2_5G)
6426 vars->link_status |=
6427 LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE;
6428 if (val & (MDIO_OVER_1G_UP1_10G | MDIO_OVER_1G_UP1_10GH))
6429 vars->link_status |=
6430 LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
6431
6432 }
6433
6434
6435 if (lane < 2) {
6436 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
6437 MDIO_WC_REG_GP2_STATUS_GP_2_2, &gp_speed);
6438 } else {
6439 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
6440 MDIO_WC_REG_GP2_STATUS_GP_2_3, &gp_speed);
6441 }
6442 ELINK_DEBUG_P2(cb, "lane %d gp_speed 0x%x\n", lane, gp_speed);
6443
6444 if ((lane & 1) == 0)
6445 gp_speed <<= 8;
6446 gp_speed &= 0x3f00;
6447 link_up = !!link_up;
6448
6449 /* Reset the TX FIFO to fix SGMII issue */
6450 rc = elink_get_link_speed_duplex(phy, params, vars, link_up, gp_speed,
6451 duplex);
6452
6453 /* In case of KR link down, start up the recovering procedure */
6454 if ((!link_up) && (phy->media_type == ELINK_ETH_PHY_KR) &&
6455 (!(phy->flags & ELINK_FLAGS_WC_DUAL_MODE)))
6456 vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
6457
6458 ELINK_DEBUG_P3(cb, "duplex %x flow_ctrl 0x%x link_status 0x%x\n",
6459 vars->duplex, vars->flow_ctrl, vars->link_status);
6460 return rc;
6461 }
6462 #endif /* #ifndef EXCLUDE_WARPCORE */
6463 #ifndef EXCLUDE_XGXS
elink_set_gmii_tx_driver(struct elink_params * params)6464 static void elink_set_gmii_tx_driver(struct elink_params *params)
6465 {
6466 struct elink_dev *cb = params->cb;
6467 struct elink_phy *phy = ¶ms->phy[ELINK_INT_PHY];
6468 u16 lp_up2;
6469 u16 tx_driver;
6470 u16 bank;
6471
6472 /* Read precomp */
6473 CL22_RD_OVER_CL45(cb, phy,
6474 MDIO_REG_BANK_OVER_1G,
6475 MDIO_OVER_1G_LP_UP2, &lp_up2);
6476
6477 /* Bits [10:7] at lp_up2, positioned at [15:12] */
6478 lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >>
6479 MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT) <<
6480 MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT);
6481
6482 if (lp_up2 == 0)
6483 return;
6484
6485 for (bank = MDIO_REG_BANK_TX0; bank <= MDIO_REG_BANK_TX3;
6486 bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0)) {
6487 CL22_RD_OVER_CL45(cb, phy,
6488 bank,
6489 MDIO_TX0_TX_DRIVER, &tx_driver);
6490
6491 /* Replace tx_driver bits [15:12] */
6492 if (lp_up2 !=
6493 (tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK)) {
6494 tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
6495 tx_driver |= lp_up2;
6496 CL22_WR_OVER_CL45(cb, phy,
6497 bank,
6498 MDIO_TX0_TX_DRIVER, tx_driver);
6499 }
6500 }
6501 }
6502
elink_emac_program(struct elink_params * params,struct elink_vars * vars)6503 static elink_status_t elink_emac_program(struct elink_params *params,
6504 struct elink_vars *vars)
6505 {
6506 struct elink_dev *cb = params->cb;
6507 u8 port = params->port;
6508 u16 mode = 0;
6509
6510 ELINK_DEBUG_P0(cb, "setting link speed & duplex\n");
6511 elink_bits_dis(cb, GRCBASE_EMAC0 + port*0x400 +
6512 EMAC_REG_EMAC_MODE,
6513 (EMAC_MODE_25G_MODE |
6514 EMAC_MODE_PORT_MII_10M |
6515 EMAC_MODE_HALF_DUPLEX));
6516 switch (vars->line_speed) {
6517 case ELINK_SPEED_10:
6518 mode |= EMAC_MODE_PORT_MII_10M;
6519 break;
6520
6521 case ELINK_SPEED_100:
6522 mode |= EMAC_MODE_PORT_MII;
6523 break;
6524
6525 case ELINK_SPEED_1000:
6526 mode |= EMAC_MODE_PORT_GMII;
6527 break;
6528
6529 case ELINK_SPEED_2500:
6530 mode |= (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_GMII);
6531 break;
6532
6533 default:
6534 /* 10G not valid for EMAC */
6535 ELINK_DEBUG_P1(cb, "Invalid line_speed 0x%x\n",
6536 vars->line_speed);
6537 return ELINK_STATUS_ERROR;
6538 }
6539
6540 if (vars->duplex == DUPLEX_HALF)
6541 mode |= EMAC_MODE_HALF_DUPLEX;
6542 elink_bits_en(cb,
6543 GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
6544 mode);
6545
6546 elink_set_led(params, vars, ELINK_LED_MODE_OPER, vars->line_speed);
6547 return ELINK_STATUS_OK;
6548 }
6549
elink_set_preemphasis(struct elink_phy * phy,struct elink_params * params)6550 static void elink_set_preemphasis(struct elink_phy *phy,
6551 struct elink_params *params)
6552 {
6553
6554 u16 bank, i = 0;
6555 struct elink_dev *cb = params->cb;
6556
6557 for (bank = MDIO_REG_BANK_RX0, i = 0; bank <= MDIO_REG_BANK_RX3;
6558 bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0), i++) {
6559 CL22_WR_OVER_CL45(cb, phy,
6560 bank,
6561 MDIO_RX0_RX_EQ_BOOST,
6562 phy->rx_preemphasis[i]);
6563 }
6564
6565 for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3;
6566 bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0), i++) {
6567 CL22_WR_OVER_CL45(cb, phy,
6568 bank,
6569 MDIO_TX0_TX_DRIVER,
6570 phy->tx_preemphasis[i]);
6571 }
6572 }
6573
elink_xgxs_config_init(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)6574 static void elink_xgxs_config_init(struct elink_phy *phy,
6575 struct elink_params *params,
6576 struct elink_vars *vars)
6577 {
6578 #ifdef ELINK_DEBUG
6579 struct elink_dev *cb = params->cb;
6580 #endif
6581 u8 enable_cl73 = (ELINK_SINGLE_MEDIA_DIRECT(params) ||
6582 (params->loopback_mode == ELINK_LOOPBACK_XGXS));
6583 if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
6584 if (ELINK_SINGLE_MEDIA_DIRECT(params) &&
6585 (params->feature_config_flags &
6586 ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED))
6587 elink_set_preemphasis(phy, params);
6588
6589 /* Forced speed requested? */
6590 if (vars->line_speed != ELINK_SPEED_AUTO_NEG ||
6591 (ELINK_SINGLE_MEDIA_DIRECT(params) &&
6592 params->loopback_mode == ELINK_LOOPBACK_EXT)) {
6593 ELINK_DEBUG_P0(cb, "not SGMII, no AN\n");
6594
6595 /* Disable autoneg */
6596 elink_set_autoneg(phy, params, vars, 0);
6597
6598 /* Program speed and duplex */
6599 elink_program_serdes(phy, params, vars);
6600
6601 } else { /* AN_mode */
6602 ELINK_DEBUG_P0(cb, "not SGMII, AN\n");
6603
6604 /* AN enabled */
6605 elink_set_brcm_cl37_advertisement(phy, params);
6606
6607 /* Program duplex & pause advertisement (for aneg) */
6608 elink_set_ieee_aneg_advertisement(phy, params,
6609 vars->ieee_fc);
6610
6611 /* Enable autoneg */
6612 elink_set_autoneg(phy, params, vars, enable_cl73);
6613
6614 /* Enable and restart AN */
6615 elink_restart_autoneg(phy, params, enable_cl73);
6616 }
6617
6618 } else { /* SGMII mode */
6619 ELINK_DEBUG_P0(cb, "SGMII\n");
6620
6621 elink_initialize_sgmii_process(phy, params, vars);
6622 }
6623 }
6624
elink_prepare_xgxs(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)6625 static elink_status_t elink_prepare_xgxs(struct elink_phy *phy,
6626 struct elink_params *params,
6627 struct elink_vars *vars)
6628 {
6629 elink_status_t rc;
6630 vars->phy_flags |= PHY_XGXS_FLAG;
6631 if ((phy->req_line_speed &&
6632 ((phy->req_line_speed == ELINK_SPEED_100) ||
6633 (phy->req_line_speed == ELINK_SPEED_10))) ||
6634 (!phy->req_line_speed &&
6635 (phy->speed_cap_mask >=
6636 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
6637 (phy->speed_cap_mask <
6638 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
6639 (phy->type == PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT_SD))
6640 vars->phy_flags |= PHY_SGMII_FLAG;
6641 else
6642 vars->phy_flags &= ~PHY_SGMII_FLAG;
6643
6644 elink_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
6645 elink_set_aer_mmd(params, phy);
6646 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
6647 elink_set_master_ln(params, phy);
6648
6649 rc = elink_reset_unicore(params, phy, 0);
6650 /* Reset the SerDes and wait for reset bit return low */
6651 if (rc != ELINK_STATUS_OK)
6652 return rc;
6653
6654 elink_set_aer_mmd(params, phy);
6655 /* Setting the masterLn_def again after the reset */
6656 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
6657 elink_set_master_ln(params, phy);
6658 elink_set_swap_lanes(params, phy);
6659 }
6660
6661 return rc;
6662 }
6663 #endif // #ifndef EXCLUDE_NON_COMMON_INIT
6664 #endif /* EXCLUDE_XGXS */
6665
6666 #ifndef EXCLUDE_NON_COMMON_INIT
6667 #ifndef ELINK_EMUL_ONLY
elink_wait_reset_complete(struct elink_dev * cb,struct elink_phy * phy,struct elink_params * params)6668 static u16 elink_wait_reset_complete(struct elink_dev *cb,
6669 struct elink_phy *phy,
6670 struct elink_params *params)
6671 {
6672 u16 cnt, ctrl;
6673 /* Wait for soft reset to get cleared up to 1 sec */
6674 for (cnt = 0; cnt < 1000; cnt++) {
6675 #ifndef EXCLUDE_BCM54618SE
6676 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE)
6677 elink_cl22_read(cb, phy,
6678 MDIO_PMA_REG_CTRL, &ctrl);
6679 else
6680 #endif
6681 elink_cl45_read(cb, phy,
6682 MDIO_PMA_DEVAD,
6683 MDIO_PMA_REG_CTRL, &ctrl);
6684 if (!(ctrl & (1<<15)))
6685 break;
6686 MSLEEP(cb, 1);
6687 }
6688
6689 if (cnt == 1000)
6690 elink_cb_event_log(cb, ELINK_LOG_ID_PHY_UNINITIALIZED, params->port); // "Warning: PHY was not initialized,"
6691 // " Port %d\n",
6692
6693 ELINK_DEBUG_P2(cb, "control reg 0x%x (after %d ms)\n", ctrl, cnt);
6694 return cnt;
6695 }
6696 #endif /* ELINK_EMUL_ONLY */
6697
elink_link_int_enable(struct elink_params * params)6698 static void elink_link_int_enable(struct elink_params *params)
6699 {
6700 u8 port = params->port;
6701 u32 mask;
6702 struct elink_dev *cb = params->cb;
6703
6704 /* Setting the status to report on link up for either XGXS or SerDes */
6705 if (CHIP_IS_E3(params->chip_id)) {
6706 mask = ELINK_NIG_MASK_XGXS0_LINK_STATUS;
6707 if (!(ELINK_SINGLE_MEDIA_DIRECT(params)))
6708 mask |= ELINK_NIG_MASK_MI_INT;
6709 } else if (params->switch_cfg == ELINK_SWITCH_CFG_10G) {
6710 mask = (ELINK_NIG_MASK_XGXS0_LINK10G |
6711 ELINK_NIG_MASK_XGXS0_LINK_STATUS);
6712 ELINK_DEBUG_P0(cb, "enabled XGXS interrupt\n");
6713 if (!(ELINK_SINGLE_MEDIA_DIRECT(params)) &&
6714 params->phy[ELINK_INT_PHY].type !=
6715 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) {
6716 mask |= ELINK_NIG_MASK_MI_INT;
6717 ELINK_DEBUG_P0(cb, "enabled external phy int\n");
6718 }
6719
6720 } else { /* SerDes */
6721 mask = ELINK_NIG_MASK_SERDES0_LINK_STATUS;
6722 ELINK_DEBUG_P0(cb, "enabled SerDes interrupt\n");
6723 if (!(ELINK_SINGLE_MEDIA_DIRECT(params)) &&
6724 params->phy[ELINK_INT_PHY].type !=
6725 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN) {
6726 mask |= ELINK_NIG_MASK_MI_INT;
6727 ELINK_DEBUG_P0(cb, "enabled external phy int\n");
6728 }
6729 }
6730 elink_bits_en(cb,
6731 NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
6732 mask);
6733
6734 ELINK_DEBUG_P3(cb, "port %x, is_xgxs %x, int_status 0x%x\n", port,
6735 (params->switch_cfg == ELINK_SWITCH_CFG_10G),
6736 REG_RD(cb, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
6737 ELINK_DEBUG_P3(cb, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n",
6738 REG_RD(cb, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
6739 REG_RD(cb, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
6740 REG_RD(cb, NIG_REG_SERDES0_STATUS_LINK_STATUS+port*0x3c));
6741 ELINK_DEBUG_P2(cb, " 10G %x, XGXS_LINK %x\n",
6742 REG_RD(cb, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
6743 REG_RD(cb, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
6744 }
6745
elink_rearm_latch_signal(struct elink_dev * cb,u8 port,u8 exp_mi_int)6746 static void elink_rearm_latch_signal(struct elink_dev *cb, u8 port,
6747 u8 exp_mi_int)
6748 {
6749 u32 latch_status = 0;
6750
6751 /* Disable the MI INT ( external phy int ) by writing 1 to the
6752 * status register. Link down indication is high-active-signal,
6753 * so in this case we need to write the status to clear the XOR
6754 */
6755 /* Read Latched signals */
6756 latch_status = REG_RD(cb,
6757 NIG_REG_LATCH_STATUS_0 + port*8);
6758 ELINK_DEBUG_P1(cb, "latch_status = 0x%x\n", latch_status);
6759 /* Handle only those with latched-signal=up.*/
6760 if (exp_mi_int)
6761 elink_bits_en(cb,
6762 NIG_REG_STATUS_INTERRUPT_PORT0
6763 + port*4,
6764 ELINK_NIG_STATUS_EMAC0_MI_INT);
6765 else
6766 elink_bits_dis(cb,
6767 NIG_REG_STATUS_INTERRUPT_PORT0
6768 + port*4,
6769 ELINK_NIG_STATUS_EMAC0_MI_INT);
6770
6771 if (latch_status & 1) {
6772
6773 /* For all latched-signal=up : Re-Arm Latch signals */
6774 REG_WR(cb, NIG_REG_LATCH_STATUS_0 + port*8,
6775 (latch_status & 0xfffe) | (latch_status & 1));
6776 }
6777 /* For all latched-signal=up,Write original_signal to status */
6778 }
6779
elink_link_int_ack(struct elink_params * params,struct elink_vars * vars,u8 is_10g_plus)6780 static void elink_link_int_ack(struct elink_params *params,
6781 struct elink_vars *vars, u8 is_10g_plus)
6782 {
6783 struct elink_dev *cb = params->cb;
6784 u8 port = params->port;
6785 u32 mask;
6786 /* First reset all status we assume only one line will be
6787 * change at a time
6788 */
6789 elink_bits_dis(cb, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
6790 (ELINK_NIG_STATUS_XGXS0_LINK10G |
6791 ELINK_NIG_STATUS_XGXS0_LINK_STATUS |
6792 ELINK_NIG_STATUS_SERDES0_LINK_STATUS));
6793 if (vars->phy_link_up) {
6794 if (ELINK_USES_WARPCORE(params->chip_id))
6795 mask = ELINK_NIG_STATUS_XGXS0_LINK_STATUS;
6796 else {
6797 if (is_10g_plus)
6798 mask = ELINK_NIG_STATUS_XGXS0_LINK10G;
6799 else if (params->switch_cfg == ELINK_SWITCH_CFG_10G) {
6800 /* Disable the link interrupt by writing 1 to
6801 * the relevant lane in the status register
6802 */
6803 u32 ser_lane =
6804 ((params->lane_config &
6805 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
6806 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
6807 mask = ((1 << ser_lane) <<
6808 ELINK_NIG_STATUS_XGXS0_LINK_STATUS_SIZE);
6809 } else
6810 mask = ELINK_NIG_STATUS_SERDES0_LINK_STATUS;
6811 }
6812 ELINK_DEBUG_P1(cb, "Ack link up interrupt with mask 0x%x\n",
6813 mask);
6814 elink_bits_en(cb,
6815 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
6816 mask);
6817 }
6818 }
6819
6820 #if !defined(ELINK_EMUL_ONLY) && (!defined(EXCLUDE_BCM8727_BCM8073) || !defined(EXCLUDE_SFX7101) || !defined(EXCLUDE_BCM8705) || !defined(EXCLUDE_BCM87x6))
elink_format_ver(u32 num,u8 * str,u16 * len)6821 static elink_status_t elink_format_ver(u32 num, u8 *str, u16 *len)
6822 {
6823 #ifdef ELINK_ENHANCEMENTS
6824 u8 *str_ptr = str;
6825 u32 mask = 0xf0000000;
6826 u8 shift = 8*4;
6827 u8 digit;
6828 u8 remove_leading_zeros = 1;
6829 if (*len < 10) {
6830 /* Need more than 10chars for this format */
6831 *str_ptr = '\0';
6832 (*len)--;
6833 return ELINK_STATUS_ERROR;
6834 }
6835 while (shift > 0) {
6836
6837 shift -= 4;
6838 digit = ((num & mask) >> shift);
6839 if (digit == 0 && remove_leading_zeros) {
6840 mask = mask >> 4;
6841 continue;
6842 } else if (digit < 0xa)
6843 *str_ptr = digit + '0';
6844 else
6845 *str_ptr = digit - 0xa + 'a';
6846 remove_leading_zeros = 0;
6847 str_ptr++;
6848 (*len)--;
6849 mask = mask >> 4;
6850 if (shift == 4*4) {
6851 *str_ptr = '.';
6852 str_ptr++;
6853 (*len)--;
6854 remove_leading_zeros = 1;
6855 }
6856 }
6857 #endif /* ELINK_ENHANCEMENTS */
6858 return ELINK_STATUS_OK;
6859 }
6860 #endif /* ELINK_EMUL_ONLY */
6861
6862
6863 #ifndef EXCLUDE_BCM8705
elink_null_format_ver(u32 spirom_ver,u8 * str,u16 * len)6864 static elink_status_t elink_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
6865 {
6866 #ifdef ELINK_ENHANCEMENTS
6867 str[0] = '\0';
6868 (*len)--;
6869 #endif // ELINK_ENHANCEMENTS
6870 return ELINK_STATUS_OK;
6871 }
6872 #endif // EXCLUDE_BCM8705
6873
6874 #ifdef ELINK_ENHANCEMENTS
elink_get_ext_phy_fw_version(struct elink_params * params,u8 * version,u16 len)6875 elink_status_t elink_get_ext_phy_fw_version(struct elink_params *params, u8 *version,
6876 u16 len)
6877 {
6878 struct elink_dev *cb;
6879 u32 spirom_ver = 0;
6880 elink_status_t status = ELINK_STATUS_OK;
6881 u8 *ver_p = version;
6882 u16 remain_len = len;
6883 if (version == NULL || params == NULL)
6884 return ELINK_STATUS_ERROR;
6885 cb = params->cb;
6886
6887 /* Extract first external phy*/
6888 version[0] = '\0';
6889 spirom_ver = REG_RD(cb, params->phy[ELINK_EXT_PHY1].ver_addr);
6890
6891 if (params->phy[ELINK_EXT_PHY1].format_fw_ver) {
6892 status |= params->phy[ELINK_EXT_PHY1].format_fw_ver(spirom_ver,
6893 ver_p,
6894 &remain_len);
6895 ver_p += (len - remain_len);
6896 }
6897 if ((params->num_phys == ELINK_MAX_PHYS) &&
6898 (params->phy[ELINK_EXT_PHY2].ver_addr != 0)) {
6899 spirom_ver = REG_RD(cb, params->phy[ELINK_EXT_PHY2].ver_addr);
6900 if (params->phy[ELINK_EXT_PHY2].format_fw_ver) {
6901 *ver_p = '/';
6902 ver_p++;
6903 remain_len--;
6904 status |= params->phy[ELINK_EXT_PHY2].format_fw_ver(
6905 spirom_ver,
6906 ver_p,
6907 &remain_len);
6908 ver_p = version + (len - remain_len);
6909 }
6910 }
6911 *ver_p = '\0';
6912 return status;
6913 }
6914 #endif // ELINK_ENHANCEMENTS
6915
6916 #ifndef EXCLUDE_XGXS
elink_set_xgxs_loopback(struct elink_phy * phy,struct elink_params * params)6917 static void elink_set_xgxs_loopback(struct elink_phy *phy,
6918 struct elink_params *params)
6919 {
6920 #ifdef ELINK_INCLUDE_LOOPBACK
6921 u8 port = params->port;
6922 struct elink_dev *cb = params->cb;
6923
6924 if (phy->req_line_speed != ELINK_SPEED_1000) {
6925 u32 md_devad = 0;
6926
6927 ELINK_DEBUG_P0(cb, "XGXS 10G loopback enable\n");
6928
6929 if (!CHIP_IS_E3(params->chip_id)) {
6930 /* Change the uni_phy_addr in the nig */
6931 md_devad = REG_RD(cb, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
6932 port*0x18));
6933
6934 REG_WR(cb, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
6935 0x5);
6936 }
6937
6938 elink_cl45_write(cb, phy,
6939 5,
6940 (MDIO_REG_BANK_AER_BLOCK +
6941 (MDIO_AER_BLOCK_AER_REG & 0xf)),
6942 0x2800);
6943
6944 elink_cl45_write(cb, phy,
6945 5,
6946 (MDIO_REG_BANK_CL73_IEEEB0 +
6947 (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
6948 0x6041);
6949 MSLEEP(cb, 200);
6950 /* Set aer mmd back */
6951 elink_set_aer_mmd(params, phy);
6952
6953 if (!CHIP_IS_E3(params->chip_id)) {
6954 /* And md_devad */
6955 REG_WR(cb, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
6956 md_devad);
6957 }
6958 } else {
6959 u16 mii_ctrl;
6960 ELINK_DEBUG_P0(cb, "XGXS 1G loopback enable\n");
6961 elink_cl45_read(cb, phy, 5,
6962 (MDIO_REG_BANK_COMBO_IEEE0 +
6963 (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
6964 &mii_ctrl);
6965 elink_cl45_write(cb, phy, 5,
6966 (MDIO_REG_BANK_COMBO_IEEE0 +
6967 (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
6968 mii_ctrl |
6969 MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK);
6970 }
6971 #endif // ELINK_INCLUDE_LOOPBACK
6972 }
6973 #endif /* EXCLUDE_XGXS */
6974
elink_set_led(struct elink_params * params,struct elink_vars * vars,u8 mode,u32 speed)6975 elink_status_t elink_set_led(struct elink_params *params,
6976 struct elink_vars *vars, u8 mode, u32 speed)
6977 {
6978 u8 port = params->port;
6979 u16 hw_led_mode = params->hw_led_mode;
6980 elink_status_t rc = ELINK_STATUS_OK;
6981 u8 phy_idx;
6982 u32 tmp;
6983 u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
6984 struct elink_dev *cb = params->cb;
6985 ELINK_DEBUG_P2(cb, "elink_set_led: port %x, mode %d\n", port, mode);
6986 ELINK_DEBUG_P2(cb, "speed 0x%x, hw_led_mode 0x%x\n",
6987 speed, hw_led_mode);
6988 /* In case */
6989 for (phy_idx = ELINK_EXT_PHY1; phy_idx < ELINK_MAX_PHYS; phy_idx++) {
6990 if (params->phy[phy_idx].set_link_led) {
6991 params->phy[phy_idx].set_link_led(
6992 ¶ms->phy[phy_idx], params, mode);
6993 }
6994 }
6995 #ifdef ELINK_INCLUDE_EMUL
6996 if (params->feature_config_flags &
6997 ELINK_FEATURE_CONFIG_EMUL_DISABLE_EMAC)
6998 return rc;
6999 #endif
7000
7001 switch (mode) {
7002 case ELINK_LED_MODE_FRONT_PANEL_OFF:
7003 case ELINK_LED_MODE_OFF:
7004 REG_WR(cb, NIG_REG_LED_10G_P0 + port*4, 0);
7005 REG_WR(cb, NIG_REG_LED_MODE_P0 + port*4,
7006 SHARED_HW_CFG_LED_MAC1);
7007
7008 tmp = EMAC_RD(cb, EMAC_REG_EMAC_LED);
7009 if (params->phy[ELINK_EXT_PHY1].type ==
7010 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE)
7011 tmp &= ~(EMAC_LED_1000MB_OVERRIDE |
7012 EMAC_LED_100MB_OVERRIDE |
7013 EMAC_LED_10MB_OVERRIDE);
7014 else
7015 tmp |= EMAC_LED_OVERRIDE;
7016
7017 EMAC_WR(cb, EMAC_REG_EMAC_LED, tmp);
7018 break;
7019
7020 case ELINK_LED_MODE_OPER:
7021 /* For all other phys, OPER mode is same as ON, so in case
7022 * link is down, do nothing
7023 */
7024 if (!vars->link_up)
7025 break;
7026 case ELINK_LED_MODE_ON:
7027 if (((params->phy[ELINK_EXT_PHY1].type ==
7028 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) ||
7029 (params->phy[ELINK_EXT_PHY1].type ==
7030 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722)) &&
7031 CHIP_IS_E2(params->chip_id) && params->num_phys == 2) {
7032 /* This is a work-around for E2+8727 Configurations */
7033 if (mode == ELINK_LED_MODE_ON ||
7034 speed == ELINK_SPEED_10000){
7035 REG_WR(cb, NIG_REG_LED_MODE_P0 + port*4, 0);
7036 REG_WR(cb, NIG_REG_LED_10G_P0 + port*4, 1);
7037
7038 tmp = EMAC_RD(cb, EMAC_REG_EMAC_LED);
7039 EMAC_WR(cb, EMAC_REG_EMAC_LED,
7040 (tmp | EMAC_LED_OVERRIDE));
7041 /* Return here without enabling traffic
7042 * LED blink and setting rate in ON mode.
7043 * In oper mode, enabling LED blink
7044 * and setting rate is needed.
7045 */
7046 if (mode == ELINK_LED_MODE_ON)
7047 return rc;
7048 }
7049 } else if (ELINK_SINGLE_MEDIA_DIRECT(params)) {
7050 /* This is a work-around for HW issue found when link
7051 * is up in CL73
7052 */
7053 if ((!CHIP_IS_E3(params->chip_id)) ||
7054 (CHIP_IS_E3(params->chip_id) &&
7055 mode == ELINK_LED_MODE_ON))
7056 REG_WR(cb, NIG_REG_LED_10G_P0 + port*4, 1);
7057
7058 if (CHIP_IS_E1X(params->chip_id) ||
7059 CHIP_IS_E2(params->chip_id) ||
7060 (mode == ELINK_LED_MODE_ON))
7061 REG_WR(cb, NIG_REG_LED_MODE_P0 + port*4, 0);
7062 else
7063 REG_WR(cb, NIG_REG_LED_MODE_P0 + port*4,
7064 hw_led_mode);
7065 } else if ((params->phy[ELINK_EXT_PHY1].type ==
7066 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) &&
7067 (mode == ELINK_LED_MODE_ON)) {
7068 REG_WR(cb, NIG_REG_LED_MODE_P0 + port*4, 0);
7069 tmp = EMAC_RD(cb, EMAC_REG_EMAC_LED);
7070 EMAC_WR(cb, EMAC_REG_EMAC_LED, tmp |
7071 EMAC_LED_OVERRIDE | EMAC_LED_1000MB_OVERRIDE);
7072 /* Break here; otherwise, it'll disable the
7073 * intended override.
7074 */
7075 break;
7076 } else {
7077 u32 nig_led_mode = ((params->hw_led_mode <<
7078 SHARED_HW_CFG_LED_MODE_SHIFT) ==
7079 SHARED_HW_CFG_LED_EXTPHY2) ?
7080 (SHARED_HW_CFG_LED_PHY1 >>
7081 SHARED_HW_CFG_LED_MODE_SHIFT) : hw_led_mode;
7082 REG_WR(cb, NIG_REG_LED_MODE_P0 + port*4,
7083 nig_led_mode);
7084 }
7085
7086 REG_WR(cb, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + port*4, 0);
7087 /* Set blinking rate to ~15.9Hz */
7088 if (CHIP_IS_E3(params->chip_id))
7089 REG_WR(cb, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
7090 LED_BLINK_RATE_VAL_E3);
7091 else
7092 REG_WR(cb, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
7093 LED_BLINK_RATE_VAL_E1X_E2);
7094 REG_WR(cb, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
7095 port*4, 1);
7096 tmp = EMAC_RD(cb, EMAC_REG_EMAC_LED);
7097 EMAC_WR(cb, EMAC_REG_EMAC_LED,
7098 (tmp & (~EMAC_LED_OVERRIDE)));
7099
7100 #ifndef ELINK_AUX_POWER
7101 if (CHIP_IS_E1(params->chip_id) &&
7102 ((speed == ELINK_SPEED_2500) ||
7103 (speed == ELINK_SPEED_1000) ||
7104 (speed == ELINK_SPEED_100) ||
7105 (speed == ELINK_SPEED_10))) {
7106 /* For speeds less than 10G LED scheme is different */
7107 REG_WR(cb, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
7108 + port*4, 1);
7109 REG_WR(cb, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
7110 port*4, 0);
7111 REG_WR(cb, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
7112 port*4, 1);
7113 }
7114 #endif // ELINK_AUX_POWER
7115 break;
7116
7117 default:
7118 rc = ELINK_STATUS_ERROR;
7119 ELINK_DEBUG_P1(cb, "elink_set_led: Invalid led mode %d\n",
7120 mode);
7121 break;
7122 }
7123 return rc;
7124
7125 }
7126
7127 #endif // EXCLUDE_NON_COMMON_INIT
7128 #ifdef ELINK_ENHANCEMENTS
7129 /* This function comes to reflect the actual link state read DIRECTLY from the
7130 * HW
7131 */
elink_test_link(struct elink_params * params,struct elink_vars * vars,u8 is_serdes)7132 elink_status_t elink_test_link(struct elink_params *params, struct elink_vars *vars,
7133 u8 is_serdes)
7134 {
7135 struct elink_dev *cb = params->cb;
7136 u16 gp_status = 0, phy_index = 0;
7137 u8 ext_phy_link_up = 0, serdes_phy_type;
7138 struct elink_vars temp_vars;
7139 struct elink_phy *int_phy = ¶ms->phy[ELINK_INT_PHY];
7140 #ifdef ELINK_INCLUDE_FPGA
7141 if (CHIP_REV_IS_FPGA(params->chip_id))
7142 return ELINK_STATUS_OK;
7143 #endif /* ELINK_INCLUDE_FPGA */
7144 #ifdef ELINK_INCLUDE_EMUL
7145 if (CHIP_REV_IS_EMUL(params->chip_id))
7146 return ELINK_STATUS_OK;
7147 #endif /* ELINK_INCLUDE_EMUL */
7148
7149 if (CHIP_IS_E3(params->chip_id)) {
7150 u16 link_up;
7151 if (params->req_line_speed[ELINK_LINK_CONFIG_IDX(ELINK_INT_PHY)]
7152 > ELINK_SPEED_10000) {
7153 /* Check 20G link */
7154 elink_cl45_read(cb, int_phy, MDIO_WC_DEVAD,
7155 1, &link_up);
7156 elink_cl45_read(cb, int_phy, MDIO_WC_DEVAD,
7157 1, &link_up);
7158 link_up &= (1<<2);
7159 } else {
7160 /* Check 10G link and below*/
7161 u8 lane = elink_get_warpcore_lane(int_phy, params);
7162 elink_cl45_read(cb, int_phy, MDIO_WC_DEVAD,
7163 MDIO_WC_REG_GP2_STATUS_GP_2_1,
7164 &gp_status);
7165 gp_status = ((gp_status >> 8) & 0xf) |
7166 ((gp_status >> 12) & 0xf);
7167 link_up = gp_status & (1 << lane);
7168 }
7169 if (!link_up)
7170 return ELINK_STATUS_NO_LINK;
7171 } else {
7172 CL22_RD_OVER_CL45(cb, int_phy,
7173 MDIO_REG_BANK_GP_STATUS,
7174 MDIO_GP_STATUS_TOP_AN_STATUS1,
7175 &gp_status);
7176 /* Link is up only if both local phy and external phy are up */
7177 if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS))
7178 return ELINK_STATUS_NO_LINK;
7179 }
7180 /* In XGXS loopback mode, do not check external PHY */
7181 if (params->loopback_mode == ELINK_LOOPBACK_XGXS)
7182 return ELINK_STATUS_OK;
7183
7184 switch (params->num_phys) {
7185 case 1:
7186 /* No external PHY */
7187 return ELINK_STATUS_OK;
7188 case 2:
7189 ext_phy_link_up = params->phy[ELINK_EXT_PHY1].read_status(
7190 ¶ms->phy[ELINK_EXT_PHY1],
7191 params, &temp_vars);
7192 break;
7193 case 3: /* Dual Media */
7194 for (phy_index = ELINK_EXT_PHY1; phy_index < params->num_phys;
7195 phy_index++) {
7196 serdes_phy_type = ((params->phy[phy_index].media_type ==
7197 ELINK_ETH_PHY_SFPP_10G_FIBER) ||
7198 (params->phy[phy_index].media_type ==
7199 ELINK_ETH_PHY_SFP_1G_FIBER) ||
7200 (params->phy[phy_index].media_type ==
7201 ELINK_ETH_PHY_XFP_FIBER) ||
7202 (params->phy[phy_index].media_type ==
7203 ELINK_ETH_PHY_DA_TWINAX));
7204
7205 if (is_serdes != serdes_phy_type)
7206 continue;
7207 if (params->phy[phy_index].read_status) {
7208 ext_phy_link_up |=
7209 params->phy[phy_index].read_status(
7210 ¶ms->phy[phy_index],
7211 params, &temp_vars);
7212 }
7213 }
7214 break;
7215 }
7216 if (ext_phy_link_up)
7217 return ELINK_STATUS_OK;
7218 return ELINK_STATUS_NO_LINK;
7219 }
7220 #endif // ELINK_ENHANCEMENT
7221
7222 #ifndef EXCLUDE_NON_COMMON_INIT
elink_link_initialize(struct elink_params * params,struct elink_vars * vars)7223 static elink_status_t elink_link_initialize(struct elink_params *params,
7224 struct elink_vars *vars)
7225 {
7226 u8 phy_index, non_ext_phy;
7227 struct elink_dev *cb = params->cb;
7228 /* In case of external phy existence, the line speed would be the
7229 * line speed linked up by the external phy. In case it is direct
7230 * only, then the line_speed during initialization will be
7231 * equal to the req_line_speed
7232 */
7233 vars->line_speed = params->phy[ELINK_INT_PHY].req_line_speed;
7234
7235 /* Initialize the internal phy in case this is a direct board
7236 * (no external phys), or this board has external phy which requires
7237 * to first.
7238 */
7239 #ifndef EXCLUDE_XGXS
7240 if (!ELINK_USES_WARPCORE(params->chip_id))
7241 elink_prepare_xgxs(¶ms->phy[ELINK_INT_PHY], params, vars);
7242 #endif // EXCLUDE_XGXS
7243 /* init ext phy and enable link state int */
7244 non_ext_phy = (ELINK_SINGLE_MEDIA_DIRECT(params) ||
7245 (params->loopback_mode == ELINK_LOOPBACK_XGXS));
7246
7247 if (non_ext_phy ||
7248 (params->phy[ELINK_EXT_PHY1].flags & ELINK_FLAGS_INIT_XGXS_FIRST) ||
7249 (params->loopback_mode == ELINK_LOOPBACK_EXT_PHY)) {
7250 struct elink_phy *phy = ¶ms->phy[ELINK_INT_PHY];
7251 #ifndef EXCLUDE_XGXS
7252 if (vars->line_speed == ELINK_SPEED_AUTO_NEG &&
7253 (CHIP_IS_E1X(params->chip_id) ||
7254 CHIP_IS_E2(params->chip_id)))
7255 elink_set_parallel_detection(phy, params);
7256 #endif // EXCLUDE_XGXS
7257 if (params->phy[ELINK_INT_PHY].config_init)
7258 params->phy[ELINK_INT_PHY].config_init(phy, params, vars);
7259 }
7260
7261 /* Re-read this value in case it was changed inside config_init due to
7262 * limitations of optic module
7263 */
7264 vars->line_speed = params->phy[ELINK_INT_PHY].req_line_speed;
7265
7266 /* Init external phy*/
7267 if (non_ext_phy) {
7268 if (params->phy[ELINK_INT_PHY].supported &
7269 ELINK_SUPPORTED_FIBRE)
7270 vars->link_status |= LINK_STATUS_SERDES_LINK;
7271 } else {
7272 for (phy_index = ELINK_EXT_PHY1; phy_index < params->num_phys;
7273 phy_index++) {
7274 /* No need to initialize second phy in case of first
7275 * phy only selection. In case of second phy, we do
7276 * need to initialize the first phy, since they are
7277 * connected.
7278 */
7279 if (params->phy[phy_index].supported &
7280 ELINK_SUPPORTED_FIBRE)
7281 vars->link_status |= LINK_STATUS_SERDES_LINK;
7282
7283 if (phy_index == ELINK_EXT_PHY2 &&
7284 (elink_phy_selection(params) ==
7285 PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) {
7286 ELINK_DEBUG_P0(cb,
7287 "Not initializing second phy\n");
7288 continue;
7289 }
7290 params->phy[phy_index].config_init(
7291 ¶ms->phy[phy_index],
7292 params, vars);
7293 }
7294 }
7295 /* Reset the interrupt indication after phy was initialized */
7296 elink_bits_dis(cb, NIG_REG_STATUS_INTERRUPT_PORT0 +
7297 params->port*4,
7298 (ELINK_NIG_STATUS_XGXS0_LINK10G |
7299 ELINK_NIG_STATUS_XGXS0_LINK_STATUS |
7300 ELINK_NIG_STATUS_SERDES0_LINK_STATUS |
7301 ELINK_NIG_MASK_MI_INT));
7302 return ELINK_STATUS_OK;
7303 }
7304
7305 #ifndef EXCLUDE_XGXS
elink_int_link_reset(struct elink_phy * phy,struct elink_params * params)7306 static void elink_int_link_reset(struct elink_phy *phy,
7307 struct elink_params *params)
7308 {
7309 #ifndef EXCLUDE_LINK_RESET
7310 /* Reset the SerDes/XGXS */
7311 REG_WR(params->cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
7312 (0x1ff << (params->port*16)));
7313 #endif // EXCLUDE_LINK_RESET
7314 }
7315 #endif // EXCLUDE_XGXS
7316
7317 #if (!defined ELINK_EMUL_ONLY) && ((!defined EXCLUDE_BCM87x6) || (!defined EXCLUDE_SFX7101) || (!defined EXCLUDE_BCM8705))
elink_common_ext_link_reset(struct elink_phy * phy,struct elink_params * params)7318 static void elink_common_ext_link_reset(struct elink_phy *phy,
7319 struct elink_params *params)
7320 {
7321 #ifndef EXCLUDE_LINK_RESET
7322 struct elink_dev *cb = params->cb;
7323 u8 gpio_port;
7324 /* HW reset */
7325 if (CHIP_IS_E2(params->chip_id))
7326 gpio_port = PATH_ID(cb);
7327 else
7328 gpio_port = params->port;
7329 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_1,
7330 MISC_REGISTERS_GPIO_OUTPUT_LOW,
7331 gpio_port);
7332 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_2,
7333 MISC_REGISTERS_GPIO_OUTPUT_LOW,
7334 gpio_port);
7335 ELINK_DEBUG_P0(cb, "reset external PHY\n");
7336 #endif /* EXCLUDE_LINK_RESET */
7337 }
7338 #endif /* ELINK_EMUL_ONLY */
7339
elink_update_link_down(struct elink_params * params,struct elink_vars * vars)7340 static elink_status_t elink_update_link_down(struct elink_params *params,
7341 struct elink_vars *vars)
7342 {
7343 struct elink_dev *cb = params->cb;
7344 u8 port = params->port;
7345
7346 ELINK_DEBUG_P1(cb, "Port %x: Link is down\n", port);
7347 elink_set_led(params, vars, ELINK_LED_MODE_OFF, 0);
7348 vars->phy_flags &= ~PHY_PHYSICAL_LINK_FLAG;
7349 /* Indicate no mac active */
7350 vars->mac_type = ELINK_MAC_TYPE_NONE;
7351
7352 /* Update shared memory */
7353 vars->link_status &= ~ELINK_LINK_UPDATE_MASK;
7354 vars->line_speed = 0;
7355 elink_update_mng(params, vars->link_status);
7356
7357 /* Activate nig drain */
7358 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
7359
7360 /* Disable emac */
7361 if (!CHIP_IS_E3(params->chip_id))
7362 REG_WR(cb, NIG_REG_NIG_EMAC0_EN + port*4, 0);
7363
7364 MSLEEP(cb, 10);
7365 #if !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1)
7366 /* Reset BigMac/Xmac */
7367 if (CHIP_IS_E1X(params->chip_id) ||
7368 CHIP_IS_E2(params->chip_id))
7369 elink_set_bmac_rx(cb, params->chip_id, params->port, 0);
7370 #endif // #if !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1)
7371
7372 #ifndef EXCLUDE_WARPCORE
7373 if (CHIP_IS_E3(params->chip_id)) {
7374 /* Prevent LPI Generation by chip */
7375 REG_WR(cb, MISC_REG_CPMU_LP_FW_ENABLE_P0 + (params->port << 2),
7376 0);
7377 REG_WR(cb, MISC_REG_CPMU_LP_MASK_ENT_P0 + (params->port << 2),
7378 0);
7379 vars->eee_status &= ~(SHMEM_EEE_LP_ADV_STATUS_MASK |
7380 SHMEM_EEE_ACTIVE_BIT);
7381
7382 elink_update_mng_eee(params, vars->eee_status);
7383 elink_set_xmac_rxtx(params, 0);
7384 elink_set_umac_rxtx(params, 0);
7385 }
7386 #endif // EXCLUDE_WARPCORE
7387
7388 return ELINK_STATUS_OK;
7389 }
7390
elink_update_link_up(struct elink_params * params,struct elink_vars * vars,u8 link_10g)7391 static elink_status_t elink_update_link_up(struct elink_params *params,
7392 struct elink_vars *vars,
7393 u8 link_10g)
7394 {
7395 struct elink_dev *cb = params->cb;
7396 u8 phy_idx, port = params->port;
7397 elink_status_t rc = ELINK_STATUS_OK;
7398
7399 vars->link_status |= (LINK_STATUS_LINK_UP |
7400 LINK_STATUS_PHYSICAL_LINK_FLAG);
7401 vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
7402
7403 if (vars->flow_ctrl & ELINK_FLOW_CTRL_TX)
7404 vars->link_status |=
7405 LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
7406
7407 if (vars->flow_ctrl & ELINK_FLOW_CTRL_RX)
7408 vars->link_status |=
7409 LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
7410 #ifndef EXCLUDE_WARPCORE
7411 if (ELINK_USES_WARPCORE(params->chip_id)) {
7412 if (link_10g) {
7413 if (elink_xmac_enable(params, vars, 0) ==
7414 ELINK_STATUS_NO_LINK) {
7415 ELINK_DEBUG_P0(cb, "Found errors on XMAC\n");
7416 vars->link_up = 0;
7417 vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
7418 vars->link_status &= ~LINK_STATUS_LINK_UP;
7419 }
7420 } else
7421 elink_umac_enable(params, vars, 0);
7422 elink_set_led(params, vars,
7423 ELINK_LED_MODE_OPER, vars->line_speed);
7424
7425 if ((vars->eee_status & SHMEM_EEE_ACTIVE_BIT) &&
7426 (vars->eee_status & SHMEM_EEE_LPI_REQUESTED_BIT)) {
7427 ELINK_DEBUG_P0(cb, "Enabling LPI assertion\n");
7428 REG_WR(cb, MISC_REG_CPMU_LP_FW_ENABLE_P0 +
7429 (params->port << 2), 1);
7430 REG_WR(cb, MISC_REG_CPMU_LP_DR_ENABLE, 1);
7431 REG_WR(cb, MISC_REG_CPMU_LP_MASK_ENT_P0 +
7432 (params->port << 2), 0xfc20);
7433 }
7434 }
7435 #endif // EXCLUDE_WARPCORE
7436 #ifndef EXCLUDE_XGXS
7437 if ((CHIP_IS_E1X(params->chip_id) ||
7438 CHIP_IS_E2(params->chip_id))) {
7439 if (link_10g) {
7440 if (elink_bmac_enable(params, vars, 0, 1) ==
7441 ELINK_STATUS_NO_LINK) {
7442 ELINK_DEBUG_P0(cb, "Found errors on BMAC\n");
7443 vars->link_up = 0;
7444 vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
7445 vars->link_status &= ~LINK_STATUS_LINK_UP;
7446 }
7447
7448 elink_set_led(params, vars,
7449 ELINK_LED_MODE_OPER, ELINK_SPEED_10000);
7450 } else {
7451 rc = elink_emac_program(params, vars);
7452 elink_emac_enable(params, vars, 0);
7453
7454 /* AN complete? */
7455 if ((vars->link_status &
7456 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
7457 && (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
7458 ELINK_SINGLE_MEDIA_DIRECT(params))
7459 elink_set_gmii_tx_driver(params);
7460 }
7461 }
7462 #endif // EXCLUDE_XGXS
7463
7464 #ifndef ELINK_AUX_POWER
7465 /* PBF - link up */
7466 if (CHIP_IS_E1X(params->chip_id))
7467 rc |= elink_pbf_update(params, vars->flow_ctrl,
7468 vars->line_speed);
7469 #endif /* ELINK_AUX_POWER */
7470
7471 /* Disable drain */
7472 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
7473
7474 /* Update shared memory */
7475 elink_update_mng(params, vars->link_status);
7476 #ifndef EXCLUDE_WARPCORE
7477 elink_update_mng_eee(params, vars->eee_status);
7478 #endif /* #ifndef EXCLUDE_WARPCORE */
7479 /* Check remote fault */
7480 for (phy_idx = ELINK_INT_PHY; phy_idx < ELINK_MAX_PHYS; phy_idx++) {
7481 if (params->phy[phy_idx].flags & ELINK_FLAGS_TX_ERROR_CHECK) {
7482 elink_check_half_open_conn(params, vars, 0);
7483 break;
7484 }
7485 }
7486 MSLEEP(cb, 20);
7487 return rc;
7488 }
7489
elink_chng_link_count(struct elink_params * params,u8 clear)7490 static void elink_chng_link_count(struct elink_params *params, u8 clear)
7491 {
7492 struct elink_dev *cb = params->cb;
7493 u32 addr, val;
7494
7495 /* Verify the link_change_count is supported by the MFW */
7496 if (!(SHMEM2_HAS(cb, params->shmem2_base, link_change_count)))
7497 return;
7498
7499 addr = params->shmem2_base +
7500 OFFSETOF(struct shmem2_region, link_change_count[params->port]);
7501 if (clear)
7502 val = 0;
7503 else
7504 val = REG_RD(cb, addr) + 1;
7505 REG_WR(cb, addr, val);
7506 }
7507
7508 /* The elink_link_update function should be called upon link
7509 * interrupt.
7510 * Link is considered up as follows:
7511 * - DIRECT_SINGLE_MEDIA - Only XGXS link (internal link) needs
7512 * to be up
7513 * - SINGLE_MEDIA - The link between the 577xx and the external
7514 * phy (XGXS) need to up as well as the external link of the
7515 * phy (PHY_EXT1)
7516 * - DUAL_MEDIA - The link between the 577xx and the first
7517 * external phy needs to be up, and at least one of the 2
7518 * external phy link must be up.
7519 */
elink_link_update(struct elink_params * params,struct elink_vars * vars)7520 elink_status_t elink_link_update(struct elink_params *params, struct elink_vars *vars)
7521 {
7522 struct elink_dev *cb = params->cb;
7523 struct elink_vars phy_vars[ELINK_MAX_PHYS];
7524 u8 port = params->port;
7525 u8 link_10g_plus, phy_index;
7526 u32 prev_link_status = vars->link_status;
7527 u8 ext_phy_link_up = 0, cur_link_up;
7528 elink_status_t rc = ELINK_STATUS_OK;
7529 u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
7530 u8 active_external_phy = ELINK_INT_PHY;
7531 vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
7532 vars->link_status &= ~ELINK_LINK_UPDATE_MASK;
7533 for (phy_index = ELINK_INT_PHY; phy_index < params->num_phys;
7534 phy_index++) {
7535 phy_vars[phy_index].flow_ctrl = 0;
7536 phy_vars[phy_index].link_status = 0;
7537 phy_vars[phy_index].line_speed = 0;
7538 phy_vars[phy_index].duplex = DUPLEX_FULL;
7539 phy_vars[phy_index].phy_link_up = 0;
7540 phy_vars[phy_index].link_up = 0;
7541 phy_vars[phy_index].fault_detected = 0;
7542 /* different consideration, since vars holds inner state */
7543 phy_vars[phy_index].eee_status = vars->eee_status;
7544 }
7545
7546 if (ELINK_USES_WARPCORE(params->chip_id))
7547 elink_set_aer_mmd(params, ¶ms->phy[ELINK_INT_PHY]);
7548
7549 ELINK_DEBUG_P3(cb, "port %x, XGXS?%x, int_status 0x%x\n",
7550 port, (vars->phy_flags & PHY_XGXS_FLAG),
7551 REG_RD(cb, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
7552
7553 ELINK_DEBUG_P3(cb, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
7554 REG_RD(cb, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
7555 REG_RD(cb, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18) > 0,
7556 REG_RD(cb, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
7557
7558 ELINK_DEBUG_P2(cb, " 10G %x, XGXS_LINK %x\n",
7559 REG_RD(cb, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
7560 REG_RD(cb, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
7561
7562 /* Disable emac */
7563 if (!CHIP_IS_E3(params->chip_id))
7564 REG_WR(cb, NIG_REG_NIG_EMAC0_EN + port*4, 0);
7565
7566 /* Step 1:
7567 * Check external link change only for external phys, and apply
7568 * priority selection between them in case the link on both phys
7569 * is up. Note that instead of the common vars, a temporary
7570 * vars argument is used since each phy may have different link/
7571 * speed/duplex result
7572 */
7573 for (phy_index = ELINK_EXT_PHY1; phy_index < params->num_phys;
7574 phy_index++) {
7575 struct elink_phy *phy = ¶ms->phy[phy_index];
7576 if (!phy->read_status)
7577 continue;
7578 /* Read link status and params of this ext phy */
7579 cur_link_up = phy->read_status(phy, params,
7580 &phy_vars[phy_index]);
7581 if (cur_link_up) {
7582 ELINK_DEBUG_P1(cb, "phy in index %d link is up\n",
7583 phy_index);
7584 } else {
7585 ELINK_DEBUG_P1(cb, "phy in index %d link is down\n",
7586 phy_index);
7587 continue;
7588 }
7589
7590 if (!ext_phy_link_up) {
7591 ext_phy_link_up = 1;
7592 active_external_phy = phy_index;
7593 } else {
7594 switch (elink_phy_selection(params)) {
7595 case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
7596 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
7597 /* In this option, the first PHY makes sure to pass the
7598 * traffic through itself only.
7599 * Its not clear how to reset the link on the second phy
7600 */
7601 active_external_phy = ELINK_EXT_PHY1;
7602 break;
7603 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
7604 /* In this option, the first PHY makes sure to pass the
7605 * traffic through the second PHY.
7606 */
7607 active_external_phy = ELINK_EXT_PHY2;
7608 break;
7609 default:
7610 /* Link indication on both PHYs with the following cases
7611 * is invalid:
7612 * - FIRST_PHY means that second phy wasn't initialized,
7613 * hence its link is expected to be down
7614 * - SECOND_PHY means that first phy should not be able
7615 * to link up by itself (using configuration)
7616 * - DEFAULT should be overriden during initialiazation
7617 */
7618 ELINK_DEBUG_P1(cb, "Invalid link indication"
7619 "mpc=0x%x. DISABLING LINK !!!\n",
7620 params->multi_phy_config);
7621 ext_phy_link_up = 0;
7622 break;
7623 }
7624 }
7625 }
7626 prev_line_speed = vars->line_speed;
7627 /* Step 2:
7628 * Read the status of the internal phy. In case of
7629 * DIRECT_SINGLE_MEDIA board, this link is the external link,
7630 * otherwise this is the link between the 577xx and the first
7631 * external phy
7632 */
7633 if (params->phy[ELINK_INT_PHY].read_status)
7634 params->phy[ELINK_INT_PHY].read_status(
7635 ¶ms->phy[ELINK_INT_PHY],
7636 params, vars);
7637 /* The INT_PHY flow control reside in the vars. This include the
7638 * case where the speed or flow control are not set to AUTO.
7639 * Otherwise, the active external phy flow control result is set
7640 * to the vars. The ext_phy_line_speed is needed to check if the
7641 * speed is different between the internal phy and external phy.
7642 * This case may be result of intermediate link speed change.
7643 */
7644 if (active_external_phy > ELINK_INT_PHY) {
7645 vars->flow_ctrl = phy_vars[active_external_phy].flow_ctrl;
7646 /* Link speed is taken from the XGXS. AN and FC result from
7647 * the external phy.
7648 */
7649 vars->link_status |= phy_vars[active_external_phy].link_status;
7650
7651 /* if active_external_phy is first PHY and link is up - disable
7652 * disable TX on second external PHY
7653 */
7654 if (active_external_phy == ELINK_EXT_PHY1) {
7655 if (params->phy[ELINK_EXT_PHY2].phy_specific_func) {
7656 ELINK_DEBUG_P0(cb,
7657 "Disabling TX on EXT_PHY2\n");
7658 params->phy[ELINK_EXT_PHY2].phy_specific_func(
7659 ¶ms->phy[ELINK_EXT_PHY2],
7660 params, ELINK_DISABLE_TX);
7661 }
7662 }
7663
7664 ext_phy_line_speed = phy_vars[active_external_phy].line_speed;
7665 vars->duplex = phy_vars[active_external_phy].duplex;
7666 if (params->phy[active_external_phy].supported &
7667 ELINK_SUPPORTED_FIBRE)
7668 vars->link_status |= LINK_STATUS_SERDES_LINK;
7669 else
7670 vars->link_status &= ~LINK_STATUS_SERDES_LINK;
7671
7672 vars->eee_status = phy_vars[active_external_phy].eee_status;
7673
7674 ELINK_DEBUG_P1(cb, "Active external phy selected: %x\n",
7675 active_external_phy);
7676 }
7677
7678 for (phy_index = ELINK_EXT_PHY1; phy_index < params->num_phys;
7679 phy_index++) {
7680 if (params->phy[phy_index].flags &
7681 ELINK_FLAGS_REARM_LATCH_SIGNAL) {
7682 elink_rearm_latch_signal(cb, port,
7683 phy_index ==
7684 active_external_phy);
7685 break;
7686 }
7687 }
7688 ELINK_DEBUG_P3(cb, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x,"
7689 " ext_phy_line_speed = %d\n", vars->flow_ctrl,
7690 vars->link_status, ext_phy_line_speed);
7691 /* Upon link speed change set the NIG into drain mode. Comes to
7692 * deals with possible FIFO glitch due to clk change when speed
7693 * is decreased without link down indicator
7694 */
7695
7696 if (vars->phy_link_up) {
7697 if (!(ELINK_SINGLE_MEDIA_DIRECT(params)) && ext_phy_link_up &&
7698 (ext_phy_line_speed != vars->line_speed)) {
7699 ELINK_DEBUG_P2(cb, "Internal link speed %d is"
7700 " different than the external"
7701 " link speed %d\n", vars->line_speed,
7702 ext_phy_line_speed);
7703 vars->phy_link_up = 0;
7704 } else if (prev_line_speed != vars->line_speed) {
7705 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4,
7706 0);
7707 MSLEEP(cb, 1);
7708 }
7709 }
7710
7711 /* Anything 10 and over uses the bmac */
7712 link_10g_plus = (vars->line_speed >= ELINK_SPEED_10000);
7713
7714 elink_link_int_ack(params, vars, link_10g_plus);
7715
7716 /* In case external phy link is up, and internal link is down
7717 * (not initialized yet probably after link initialization, it
7718 * needs to be initialized.
7719 * Note that after link down-up as result of cable plug, the xgxs
7720 * link would probably become up again without the need
7721 * initialize it
7722 */
7723 if (!(ELINK_SINGLE_MEDIA_DIRECT(params))) {
7724 ELINK_DEBUG_P3(cb, "ext_phy_link_up = %d, int_link_up = %d,"
7725 " init_preceding = %d\n", ext_phy_link_up,
7726 vars->phy_link_up,
7727 params->phy[ELINK_EXT_PHY1].flags &
7728 ELINK_FLAGS_INIT_XGXS_FIRST);
7729 if (!(params->phy[ELINK_EXT_PHY1].flags &
7730 ELINK_FLAGS_INIT_XGXS_FIRST)
7731 && ext_phy_link_up && !vars->phy_link_up) {
7732 vars->line_speed = ext_phy_line_speed;
7733 if (vars->line_speed < ELINK_SPEED_1000)
7734 vars->phy_flags |= PHY_SGMII_FLAG;
7735 else
7736 vars->phy_flags &= ~PHY_SGMII_FLAG;
7737
7738 if (params->phy[ELINK_INT_PHY].config_init)
7739 params->phy[ELINK_INT_PHY].config_init(
7740 ¶ms->phy[ELINK_INT_PHY], params,
7741 vars);
7742 }
7743 }
7744 /* Link is up only if both local phy and external phy (in case of
7745 * non-direct board) are up and no fault detected on active PHY.
7746 */
7747 vars->link_up = (vars->phy_link_up &&
7748 (ext_phy_link_up ||
7749 ELINK_SINGLE_MEDIA_DIRECT(params)) &&
7750 (phy_vars[active_external_phy].fault_detected == 0));
7751
7752 /* Update the PFC configuration in case it was changed */
7753 if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED)
7754 vars->link_status |= LINK_STATUS_PFC_ENABLED;
7755 else
7756 vars->link_status &= ~LINK_STATUS_PFC_ENABLED;
7757
7758 if (vars->link_up)
7759 rc = elink_update_link_up(params, vars, link_10g_plus);
7760 else
7761 rc = elink_update_link_down(params, vars);
7762
7763 if ((prev_link_status ^ vars->link_status) & LINK_STATUS_LINK_UP)
7764 elink_chng_link_count(params, 0);
7765
7766 #ifndef ELINK_AUX_POWER
7767 /* Update MCP link status was changed */
7768 if (params->feature_config_flags & ELINK_FEATURE_CONFIG_BC_SUPPORTS_AFEX)
7769 elink_cb_fw_command(cb, DRV_MSG_CODE_LINK_STATUS_CHANGED, 0);
7770 #endif // ELINK_AUX_POWER
7771
7772 return rc;
7773 }
7774
7775 #endif // EXCLUDE_NON_COMMON_INIT
7776 #ifndef ELINK_EMUL_ONLY
7777 /*****************************************************************************/
7778 /* External Phy section */
7779 /*****************************************************************************/
elink_ext_phy_hw_reset(struct elink_dev * cb,u8 port)7780 void elink_ext_phy_hw_reset(struct elink_dev *cb, u8 port)
7781 {
7782 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_1,
7783 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
7784 MSLEEP(cb, 1);
7785 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_1,
7786 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
7787 }
7788
7789 #if !defined(EXCLUDE_BCM8727_BCM8073) || !defined(EXCLUDE_SFX7101) || !defined(EXCLUDE_BCM8481) || !defined(EXCLUDE_BCM84833) || !defined(EXCLUDE_SFX7101) || !defined(EXCLUDE_BCM8705) || !defined(EXCLUDE_BCM87x6)
elink_save_spirom_version(struct elink_dev * cb,u8 port,u32 spirom_ver,u32 ver_addr)7790 static void elink_save_spirom_version(struct elink_dev *cb, u8 port,
7791 u32 spirom_ver, u32 ver_addr)
7792 {
7793 ELINK_DEBUG_P3(cb, "FW version 0x%x:0x%x for port %d\n",
7794 (u16)(spirom_ver>>16), (u16)spirom_ver, port);
7795
7796 if (ver_addr)
7797 REG_WR(cb, ver_addr, spirom_ver);
7798 }
7799
7800 #if (!defined EXCLUDE_XGXS) && (!defined EXCLUDE_COMMON_INIT)
elink_save_bcm_spirom_ver(struct elink_dev * cb,struct elink_phy * phy,u8 port)7801 static void elink_save_bcm_spirom_ver(struct elink_dev *cb,
7802 struct elink_phy *phy,
7803 u8 port)
7804 {
7805 u16 fw_ver1, fw_ver2;
7806
7807 elink_cl45_read(cb, phy, MDIO_PMA_DEVAD,
7808 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
7809 elink_cl45_read(cb, phy, MDIO_PMA_DEVAD,
7810 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
7811 elink_save_spirom_version(cb, port, (u32)(fw_ver1<<16 | fw_ver2),
7812 phy->ver_addr);
7813 }
7814 #endif // EXCLUDE_XGXS
7815
7816 #ifndef EXCLUDE_NON_COMMON_INIT
elink_ext_phy_10G_an_resolve(struct elink_dev * cb,struct elink_phy * phy,struct elink_vars * vars)7817 static void elink_ext_phy_10G_an_resolve(struct elink_dev *cb,
7818 struct elink_phy *phy,
7819 struct elink_vars *vars)
7820 {
7821 u16 val;
7822 elink_cl45_read(cb, phy,
7823 MDIO_AN_DEVAD,
7824 MDIO_AN_REG_STATUS, &val);
7825 elink_cl45_read(cb, phy,
7826 MDIO_AN_DEVAD,
7827 MDIO_AN_REG_STATUS, &val);
7828 if (val & (1<<5))
7829 vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
7830 if ((val & (1<<0)) == 0)
7831 vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED;
7832 }
7833 #endif // #ifndef EXCLUDE_NON_COMMON_INIT
7834 #endif // #if !defined(EXCLUDE_BCM8727_BCM8073) || !defined(EXCLUDE_BCM8481) || !defined(EXCLUDE_BCM84833) || !defined(EXCLUDE_SFX7101)
7835
7836 /******************************************************************/
7837 /* common BCM8073/BCM8727 PHY SECTION */
7838 /******************************************************************/
7839 #ifndef EXCLUDE_BCM8727_BCM8073
7840 #ifndef EXCLUDE_NON_COMMON_INIT
elink_8073_resolve_fc(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)7841 static void elink_8073_resolve_fc(struct elink_phy *phy,
7842 struct elink_params *params,
7843 struct elink_vars *vars)
7844 {
7845 struct elink_dev *cb = params->cb;
7846 if (phy->req_line_speed == ELINK_SPEED_10 ||
7847 phy->req_line_speed == ELINK_SPEED_100) {
7848 vars->flow_ctrl = phy->req_flow_ctrl;
7849 return;
7850 }
7851
7852 if (elink_ext_phy_resolve_fc(phy, params, vars) &&
7853 (vars->flow_ctrl == ELINK_FLOW_CTRL_NONE)) {
7854 u16 pause_result;
7855 u16 ld_pause; /* local */
7856 u16 lp_pause; /* link partner */
7857 elink_cl45_read(cb, phy,
7858 MDIO_AN_DEVAD,
7859 MDIO_AN_REG_CL37_FC_LD, &ld_pause);
7860
7861 elink_cl45_read(cb, phy,
7862 MDIO_AN_DEVAD,
7863 MDIO_AN_REG_CL37_FC_LP, &lp_pause);
7864 pause_result = (ld_pause &
7865 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
7866 pause_result |= (lp_pause &
7867 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
7868
7869 elink_pause_resolve(vars, pause_result);
7870 ELINK_DEBUG_P1(cb, "Ext PHY CL37 pause result 0x%x\n",
7871 pause_result);
7872 }
7873 }
7874 #endif // EXCLUDE_NON_COMMON_INIT
7875 #ifndef EXCLUDE_COMMON_INIT
elink_8073_8727_external_rom_boot(struct elink_dev * cb,struct elink_phy * phy,u8 port)7876 static elink_status_t elink_8073_8727_external_rom_boot(struct elink_dev *cb,
7877 struct elink_phy *phy,
7878 u8 port)
7879 {
7880 u32 count = 0;
7881 u16 fw_ver1, fw_msgout;
7882 elink_status_t rc = ELINK_STATUS_OK;
7883
7884 /* Boot port from external ROM */
7885 /* EDC grst */
7886 elink_cl45_write(cb, phy,
7887 MDIO_PMA_DEVAD,
7888 MDIO_PMA_REG_GEN_CTRL,
7889 0x0001);
7890
7891 /* Ucode reboot and rst */
7892 elink_cl45_write(cb, phy,
7893 MDIO_PMA_DEVAD,
7894 MDIO_PMA_REG_GEN_CTRL,
7895 0x008c);
7896
7897 elink_cl45_write(cb, phy,
7898 MDIO_PMA_DEVAD,
7899 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
7900
7901 /* Reset internal microprocessor */
7902 elink_cl45_write(cb, phy,
7903 MDIO_PMA_DEVAD,
7904 MDIO_PMA_REG_GEN_CTRL,
7905 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
7906
7907 /* Release srst bit */
7908 elink_cl45_write(cb, phy,
7909 MDIO_PMA_DEVAD,
7910 MDIO_PMA_REG_GEN_CTRL,
7911 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
7912
7913 /* Delay 100ms per the PHY specifications */
7914 MSLEEP(cb, 100);
7915
7916 /* 8073 sometimes taking longer to download */
7917 do {
7918 count++;
7919 if (count > 300) {
7920 ELINK_DEBUG_P2(cb,
7921 "elink_8073_8727_external_rom_boot port %x:"
7922 "Download failed. fw version = 0x%x\n",
7923 port, fw_ver1);
7924 rc = ELINK_STATUS_ERROR;
7925 break;
7926 }
7927
7928 elink_cl45_read(cb, phy,
7929 MDIO_PMA_DEVAD,
7930 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
7931 elink_cl45_read(cb, phy,
7932 MDIO_PMA_DEVAD,
7933 MDIO_PMA_REG_M8051_MSGOUT_REG, &fw_msgout);
7934
7935 MSLEEP(cb, 1);
7936 } while (fw_ver1 == 0 || fw_ver1 == 0x4321 ||
7937 ((fw_msgout & 0xff) != 0x03 && (phy->type ==
7938 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)));
7939
7940 /* Clear ser_boot_ctl bit */
7941 elink_cl45_write(cb, phy,
7942 MDIO_PMA_DEVAD,
7943 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
7944 elink_save_bcm_spirom_ver(cb, phy, port);
7945
7946 ELINK_DEBUG_P2(cb,
7947 "elink_8073_8727_external_rom_boot port %x:"
7948 "Download complete. fw version = 0x%x\n",
7949 port, fw_ver1);
7950
7951 return rc;
7952 }
7953 #endif // EXCLUDE_COMMON_INIT
7954
7955 /******************************************************************/
7956 /* BCM8073 PHY SECTION */
7957 /******************************************************************/
7958 #ifndef EXCLUDE_NON_COMMON_INIT
elink_8073_is_snr_needed(struct elink_dev * cb,struct elink_phy * phy)7959 static elink_status_t elink_8073_is_snr_needed(struct elink_dev *cb, struct elink_phy *phy)
7960 {
7961 /* This is only required for 8073A1, version 102 only */
7962 u16 val;
7963
7964 /* Read 8073 HW revision*/
7965 elink_cl45_read(cb, phy,
7966 MDIO_PMA_DEVAD,
7967 MDIO_PMA_REG_8073_CHIP_REV, &val);
7968
7969 if (val != 1) {
7970 /* No need to workaround in 8073 A1 */
7971 return ELINK_STATUS_OK;
7972 }
7973
7974 elink_cl45_read(cb, phy,
7975 MDIO_PMA_DEVAD,
7976 MDIO_PMA_REG_ROM_VER2, &val);
7977
7978 /* SNR should be applied only for version 0x102 */
7979 if (val != 0x102)
7980 return ELINK_STATUS_OK;
7981
7982 return 1;
7983 }
7984
elink_8073_xaui_wa(struct elink_dev * cb,struct elink_phy * phy)7985 static elink_status_t elink_8073_xaui_wa(struct elink_dev *cb, struct elink_phy *phy)
7986 {
7987 u16 val, cnt, cnt1 ;
7988
7989 elink_cl45_read(cb, phy,
7990 MDIO_PMA_DEVAD,
7991 MDIO_PMA_REG_8073_CHIP_REV, &val);
7992
7993 if (val > 0) {
7994 /* No need to workaround in 8073 A1 */
7995 return ELINK_STATUS_OK;
7996 }
7997 /* XAUI workaround in 8073 A0: */
7998
7999 /* After loading the boot ROM and restarting Autoneg, poll
8000 * Dev1, Reg $C820:
8001 */
8002
8003 for (cnt = 0; cnt < 1000; cnt++) {
8004 elink_cl45_read(cb, phy,
8005 MDIO_PMA_DEVAD,
8006 MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
8007 &val);
8008 /* If bit [14] = 0 or bit [13] = 0, continue on with
8009 * system initialization (XAUI work-around not required, as
8010 * these bits indicate 2.5G or 1G link up).
8011 */
8012 if (!(val & (1<<14)) || !(val & (1<<13))) {
8013 ELINK_DEBUG_P0(cb, "XAUI work-around not required\n");
8014 return ELINK_STATUS_OK;
8015 } else if (!(val & (1<<15))) {
8016 ELINK_DEBUG_P0(cb, "bit 15 went off\n");
8017 /* If bit 15 is 0, then poll Dev1, Reg $C841 until it's
8018 * MSB (bit15) goes to 1 (indicating that the XAUI
8019 * workaround has completed), then continue on with
8020 * system initialization.
8021 */
8022 for (cnt1 = 0; cnt1 < 1000; cnt1++) {
8023 elink_cl45_read(cb, phy,
8024 MDIO_PMA_DEVAD,
8025 MDIO_PMA_REG_8073_XAUI_WA, &val);
8026 if (val & (1<<15)) {
8027 ELINK_DEBUG_P0(cb,
8028 "XAUI workaround has completed\n");
8029 return ELINK_STATUS_OK;
8030 }
8031 MSLEEP(cb, 3);
8032 }
8033 break;
8034 }
8035 MSLEEP(cb, 3);
8036 }
8037 ELINK_DEBUG_P0(cb, "Warning: XAUI work-around timeout !!!\n");
8038 return ELINK_STATUS_ERROR;
8039 }
8040
8041 #ifdef ELINK_INCLUDE_LOOPBACK
elink_807x_force_10G(struct elink_dev * cb,struct elink_phy * phy)8042 static void elink_807x_force_10G(struct elink_dev *cb, struct elink_phy *phy)
8043 {
8044 /* Force KR or KX */
8045 elink_cl45_write(cb, phy,
8046 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040);
8047 elink_cl45_write(cb, phy,
8048 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0x000b);
8049 elink_cl45_write(cb, phy,
8050 MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0000);
8051 elink_cl45_write(cb, phy,
8052 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
8053 }
8054 #endif // ELINK_INCLUDE_LOOPBACK
8055
elink_8073_set_pause_cl37(struct elink_params * params,struct elink_phy * phy,struct elink_vars * vars)8056 static void elink_8073_set_pause_cl37(struct elink_params *params,
8057 struct elink_phy *phy,
8058 struct elink_vars *vars)
8059 {
8060 u16 cl37_val;
8061 struct elink_dev *cb = params->cb;
8062 elink_cl45_read(cb, phy,
8063 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &cl37_val);
8064
8065 cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
8066 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
8067 elink_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
8068 if ((vars->ieee_fc &
8069 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
8070 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
8071 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
8072 }
8073 if ((vars->ieee_fc &
8074 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
8075 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
8076 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
8077 }
8078 if ((vars->ieee_fc &
8079 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
8080 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
8081 cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
8082 }
8083 ELINK_DEBUG_P1(cb,
8084 "Ext phy AN advertize cl37 0x%x\n", cl37_val);
8085
8086 elink_cl45_write(cb, phy,
8087 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, cl37_val);
8088 #ifndef ELINK_AUX_POWER
8089 MSLEEP(cb, 500);
8090 #endif // ELINK_AUX_POWER
8091 }
8092
elink_8073_specific_func(struct elink_phy * phy,struct elink_params * params,u32 action)8093 static void elink_8073_specific_func(struct elink_phy *phy,
8094 struct elink_params *params,
8095 u32 action)
8096 {
8097 struct elink_dev *cb = params->cb;
8098 switch (action) {
8099 case ELINK_PHY_INIT:
8100 /* Enable LASI */
8101 elink_cl45_write(cb, phy,
8102 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, (1<<2));
8103 elink_cl45_write(cb, phy,
8104 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x0004);
8105 break;
8106 }
8107 }
8108
elink_8073_config_init(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)8109 static elink_status_t elink_8073_config_init(struct elink_phy *phy,
8110 struct elink_params *params,
8111 struct elink_vars *vars)
8112 {
8113 struct elink_dev *cb = params->cb;
8114 u16 val = 0, tmp1;
8115 u8 gpio_port;
8116 ELINK_DEBUG_P0(cb, "Init 8073\n");
8117
8118 if (CHIP_IS_E2(params->chip_id))
8119 gpio_port = PATH_ID(cb);
8120 else
8121 gpio_port = params->port;
8122 /* Restore normal power mode*/
8123 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_2,
8124 MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
8125
8126 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_1,
8127 MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
8128
8129 elink_8073_specific_func(phy, params, ELINK_PHY_INIT);
8130 elink_8073_set_pause_cl37(params, phy, vars);
8131
8132 elink_cl45_read(cb, phy,
8133 MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
8134
8135 elink_cl45_read(cb, phy,
8136 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1);
8137
8138 ELINK_DEBUG_P1(cb, "Before rom RX_ALARM(port1): 0x%x\n", tmp1);
8139
8140 /* Swap polarity if required - Must be done only in non-1G mode */
8141 if (params->lane_config & PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED) {
8142 /* Configure the 8073 to swap _P and _N of the KR lines */
8143 ELINK_DEBUG_P0(cb, "Swapping polarity for the 8073\n");
8144 /* 10G Rx/Tx and 1G Tx signal polarity swap */
8145 elink_cl45_read(cb, phy,
8146 MDIO_PMA_DEVAD,
8147 MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL, &val);
8148 elink_cl45_write(cb, phy,
8149 MDIO_PMA_DEVAD,
8150 MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL,
8151 (val | (3<<9)));
8152 }
8153
8154
8155 /* Enable CL37 BAM */
8156 if (REG_RD(cb, params->shmem_base +
8157 OFFSETOF(struct shmem_region, dev_info.
8158 port_hw_config[params->port].default_cfg)) &
8159 PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED) {
8160
8161 elink_cl45_read(cb, phy,
8162 MDIO_AN_DEVAD,
8163 MDIO_AN_REG_8073_BAM, &val);
8164 elink_cl45_write(cb, phy,
8165 MDIO_AN_DEVAD,
8166 MDIO_AN_REG_8073_BAM, val | 1);
8167 ELINK_DEBUG_P0(cb, "Enable CL37 BAM on KR\n");
8168 }
8169 #ifdef ELINK_INCLUDE_LOOPBACK
8170 if (params->loopback_mode == ELINK_LOOPBACK_EXT) {
8171 elink_807x_force_10G(cb, phy);
8172 ELINK_DEBUG_P0(cb, "Forced speed 10G on 807X\n");
8173 return ELINK_STATUS_OK;
8174 } else {
8175 elink_cl45_write(cb, phy,
8176 MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0002);
8177 }
8178 #endif // ELINK_INCLUDE_LOOPBACK
8179 if (phy->req_line_speed != ELINK_SPEED_AUTO_NEG) {
8180 if (phy->req_line_speed == ELINK_SPEED_10000) {
8181 val = (1<<7);
8182 } else if (phy->req_line_speed == ELINK_SPEED_2500) {
8183 val = (1<<5);
8184 /* Note that 2.5G works only when used with 1G
8185 * advertisement
8186 */
8187 } else
8188 val = (1<<5);
8189 } else {
8190 val = 0;
8191 if (phy->speed_cap_mask &
8192 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
8193 val |= (1<<7);
8194
8195 /* Note that 2.5G works only when used with 1G advertisement */
8196 if (phy->speed_cap_mask &
8197 (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
8198 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
8199 val |= (1<<5);
8200 ELINK_DEBUG_P1(cb, "807x autoneg val = 0x%x\n", val);
8201 }
8202
8203 elink_cl45_write(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV, val);
8204 elink_cl45_read(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, &tmp1);
8205
8206 if (((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
8207 (phy->req_line_speed == ELINK_SPEED_AUTO_NEG)) ||
8208 (phy->req_line_speed == ELINK_SPEED_2500)) {
8209 u16 phy_ver;
8210 /* Allow 2.5G for A1 and above */
8211 elink_cl45_read(cb, phy,
8212 MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV,
8213 &phy_ver);
8214 ELINK_DEBUG_P0(cb, "Add 2.5G\n");
8215 if (phy_ver > 0)
8216 tmp1 |= 1;
8217 else
8218 tmp1 &= 0xfffe;
8219 } else {
8220 ELINK_DEBUG_P0(cb, "Disable 2.5G\n");
8221 tmp1 &= 0xfffe;
8222 }
8223
8224 elink_cl45_write(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, tmp1);
8225 /* Add support for CL37 (passive mode) II */
8226
8227 elink_cl45_read(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &tmp1);
8228 elink_cl45_write(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD,
8229 (tmp1 | ((phy->req_duplex == DUPLEX_FULL) ?
8230 0x20 : 0x40)));
8231
8232 /* Add support for CL37 (passive mode) III */
8233 elink_cl45_write(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
8234
8235 /* The SNR will improve about 2db by changing BW and FEE main
8236 * tap. Rest commands are executed after link is up
8237 * Change FFE main cursor to 5 in EDC register
8238 */
8239 if (elink_8073_is_snr_needed(cb, phy))
8240 elink_cl45_write(cb, phy,
8241 MDIO_PMA_DEVAD, MDIO_PMA_REG_EDC_FFE_MAIN,
8242 0xFB0C);
8243
8244 /* Enable FEC (Forware Error Correction) Request in the AN */
8245 elink_cl45_read(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, &tmp1);
8246 tmp1 |= (1<<15);
8247 elink_cl45_write(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, tmp1);
8248
8249 elink_ext_phy_set_pause(params, phy, vars);
8250
8251 /* Restart autoneg */
8252 MSLEEP(cb, 500);
8253 elink_cl45_write(cb, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
8254 ELINK_DEBUG_P2(cb, "807x Autoneg Restart: Advertise 1G=%x, 10G=%x\n",
8255 ((val & (1<<5)) > 0), ((val & (1<<7)) > 0));
8256 return ELINK_STATUS_OK;
8257 }
8258
elink_8073_read_status(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)8259 static u8 elink_8073_read_status(struct elink_phy *phy,
8260 struct elink_params *params,
8261 struct elink_vars *vars)
8262 {
8263 struct elink_dev *cb = params->cb;
8264 u8 link_up = 0;
8265 u16 val1, val2;
8266 u16 link_status = 0;
8267 u16 an1000_status = 0;
8268
8269 elink_cl45_read(cb, phy,
8270 MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
8271
8272 ELINK_DEBUG_P1(cb, "8703 LASI status 0x%x\n", val1);
8273
8274 /* Clear the interrupt LASI status register */
8275 elink_cl45_read(cb, phy,
8276 MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2);
8277 elink_cl45_read(cb, phy,
8278 MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val1);
8279 ELINK_DEBUG_P2(cb, "807x PCS status 0x%x->0x%x\n", val2, val1);
8280 /* Clear MSG-OUT */
8281 elink_cl45_read(cb, phy,
8282 MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
8283
8284 /* Check the LASI */
8285 elink_cl45_read(cb, phy,
8286 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2);
8287
8288 ELINK_DEBUG_P1(cb, "KR 0x9003 0x%x\n", val2);
8289
8290 /* Check the link status */
8291 elink_cl45_read(cb, phy,
8292 MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2);
8293 ELINK_DEBUG_P1(cb, "KR PCS status 0x%x\n", val2);
8294
8295 elink_cl45_read(cb, phy,
8296 MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
8297 elink_cl45_read(cb, phy,
8298 MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
8299 link_up = ((val1 & 4) == 4);
8300 ELINK_DEBUG_P1(cb, "PMA_REG_STATUS=0x%x\n", val1);
8301
8302 if (link_up &&
8303 ((phy->req_line_speed != ELINK_SPEED_10000))) {
8304 if (elink_8073_xaui_wa(cb, phy) != 0)
8305 return 0;
8306 }
8307 elink_cl45_read(cb, phy,
8308 MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status);
8309 elink_cl45_read(cb, phy,
8310 MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status);
8311
8312 /* Check the link status on 1.1.2 */
8313 elink_cl45_read(cb, phy,
8314 MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
8315 elink_cl45_read(cb, phy,
8316 MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
8317 ELINK_DEBUG_P3(cb, "KR PMA status 0x%x->0x%x,"
8318 "an_link_status=0x%x\n", val2, val1, an1000_status);
8319
8320 link_up = (((val1 & 4) == 4) || (an1000_status & (1<<1)));
8321 if (link_up && elink_8073_is_snr_needed(cb, phy)) {
8322 /* The SNR will improve about 2dbby changing the BW and FEE main
8323 * tap. The 1st write to change FFE main tap is set before
8324 * restart AN. Change PLL Bandwidth in EDC register
8325 */
8326 elink_cl45_write(cb, phy,
8327 MDIO_PMA_DEVAD, MDIO_PMA_REG_PLL_BANDWIDTH,
8328 0x26BC);
8329
8330 /* Change CDR Bandwidth in EDC register */
8331 elink_cl45_write(cb, phy,
8332 MDIO_PMA_DEVAD, MDIO_PMA_REG_CDR_BANDWIDTH,
8333 0x0333);
8334 }
8335 elink_cl45_read(cb, phy,
8336 MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
8337 &link_status);
8338
8339 /* Bits 0..2 --> speed detected, bits 13..15--> link is down */
8340 if ((link_status & (1<<2)) && (!(link_status & (1<<15)))) {
8341 link_up = 1;
8342 vars->line_speed = ELINK_SPEED_10000;
8343 ELINK_DEBUG_P1(cb, "port %x: External link up in 10G\n",
8344 params->port);
8345 } else if ((link_status & (1<<1)) && (!(link_status & (1<<14)))) {
8346 link_up = 1;
8347 vars->line_speed = ELINK_SPEED_2500;
8348 ELINK_DEBUG_P1(cb, "port %x: External link up in 2.5G\n",
8349 params->port);
8350 } else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
8351 link_up = 1;
8352 vars->line_speed = ELINK_SPEED_1000;
8353 ELINK_DEBUG_P1(cb, "port %x: External link up in 1G\n",
8354 params->port);
8355 } else {
8356 link_up = 0;
8357 ELINK_DEBUG_P1(cb, "port %x: External link is down\n",
8358 params->port);
8359 }
8360
8361 if (link_up) {
8362 /* Swap polarity if required */
8363 if (params->lane_config &
8364 PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED) {
8365 /* Configure the 8073 to swap P and N of the KR lines */
8366 elink_cl45_read(cb, phy,
8367 MDIO_XS_DEVAD,
8368 MDIO_XS_REG_8073_RX_CTRL_PCIE, &val1);
8369 /* Set bit 3 to invert Rx in 1G mode and clear this bit
8370 * when it`s in 10G mode.
8371 */
8372 if (vars->line_speed == ELINK_SPEED_1000) {
8373 ELINK_DEBUG_P0(cb, "Swapping 1G polarity for"
8374 "the 8073\n");
8375 val1 |= (1<<3);
8376 } else
8377 val1 &= ~(1<<3);
8378
8379 elink_cl45_write(cb, phy,
8380 MDIO_XS_DEVAD,
8381 MDIO_XS_REG_8073_RX_CTRL_PCIE,
8382 val1);
8383 }
8384 elink_ext_phy_10G_an_resolve(cb, phy, vars);
8385 elink_8073_resolve_fc(phy, params, vars);
8386 vars->duplex = DUPLEX_FULL;
8387 }
8388
8389 if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
8390 elink_cl45_read(cb, phy, MDIO_AN_DEVAD,
8391 MDIO_AN_REG_LP_AUTO_NEG2, &val1);
8392
8393 if (val1 & (1<<5))
8394 vars->link_status |=
8395 LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
8396 if (val1 & (1<<7))
8397 vars->link_status |=
8398 LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
8399 }
8400
8401 return link_up;
8402 }
8403
elink_8073_link_reset(struct elink_phy * phy,struct elink_params * params)8404 static void elink_8073_link_reset(struct elink_phy *phy,
8405 struct elink_params *params)
8406 {
8407 #ifndef EXCLUDE_LINK_RESET
8408 struct elink_dev *cb = params->cb;
8409 u8 gpio_port;
8410 if (CHIP_IS_E2(params->chip_id))
8411 gpio_port = PATH_ID(cb);
8412 else
8413 gpio_port = params->port;
8414 ELINK_DEBUG_P1(cb, "Setting 8073 port %d into low power mode\n",
8415 gpio_port);
8416 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_2,
8417 MISC_REGISTERS_GPIO_OUTPUT_LOW,
8418 gpio_port);
8419 #endif // EXCLUDE_LINK_RESET
8420 }
8421 #endif // EXCLUDE_NON_COMMON_INIT
8422 #endif // EXCLUDE_BCM8727_BCM8073
8423
8424 /******************************************************************/
8425 /* BCM8705 PHY SECTION */
8426 /******************************************************************/
8427 #ifndef EXCLUDE_BCM8705
elink_8705_config_init(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)8428 static elink_status_t elink_8705_config_init(struct elink_phy *phy,
8429 struct elink_params *params,
8430 struct elink_vars *vars)
8431 {
8432 struct elink_dev *cb = params->cb;
8433 ELINK_DEBUG_P0(cb, "init 8705\n");
8434 /* Restore normal power mode*/
8435 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_2,
8436 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
8437 /* HW reset */
8438 elink_ext_phy_hw_reset(cb, params->port);
8439 elink_cl45_write(cb, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
8440 elink_wait_reset_complete(cb, phy, params);
8441
8442 elink_cl45_write(cb, phy,
8443 MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL, 0x8288);
8444 elink_cl45_write(cb, phy,
8445 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, 0x7fbf);
8446 elink_cl45_write(cb, phy,
8447 MDIO_PMA_DEVAD, MDIO_PMA_REG_CMU_PLL_BYPASS, 0x0100);
8448 elink_cl45_write(cb, phy,
8449 MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_CNTL, 0x1);
8450 /* BCM8705 doesn't have microcode, hence the 0 */
8451 elink_save_spirom_version(cb, params->port, params->shmem_base, 0);
8452 return ELINK_STATUS_OK;
8453 }
8454
elink_8705_read_status(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)8455 static u8 elink_8705_read_status(struct elink_phy *phy,
8456 struct elink_params *params,
8457 struct elink_vars *vars)
8458 {
8459 u8 link_up = 0;
8460 u16 val1, rx_sd;
8461 struct elink_dev *cb = params->cb;
8462 ELINK_DEBUG_P0(cb, "read status 8705\n");
8463 elink_cl45_read(cb, phy,
8464 MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1);
8465 ELINK_DEBUG_P1(cb, "8705 LASI status 0x%x\n", val1);
8466
8467 elink_cl45_read(cb, phy,
8468 MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1);
8469 ELINK_DEBUG_P1(cb, "8705 LASI status 0x%x\n", val1);
8470
8471 elink_cl45_read(cb, phy,
8472 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd);
8473
8474 elink_cl45_read(cb, phy,
8475 MDIO_PMA_DEVAD, 0xc809, &val1);
8476 elink_cl45_read(cb, phy,
8477 MDIO_PMA_DEVAD, 0xc809, &val1);
8478
8479 ELINK_DEBUG_P1(cb, "8705 1.c809 val=0x%x\n", val1);
8480 link_up = ((rx_sd & 0x1) && (val1 & (1<<9)) && ((val1 & (1<<8)) == 0));
8481 if (link_up) {
8482 vars->line_speed = ELINK_SPEED_10000;
8483 elink_ext_phy_resolve_fc(phy, params, vars);
8484 }
8485 return link_up;
8486 }
8487
8488 #endif /* EXCLUDE_BCM8705 */
8489 /******************************************************************/
8490 /* SFP+ module Section */
8491 /******************************************************************/
8492 #ifndef EXCLUDE_NON_COMMON_INIT
8493 #ifndef EXCLUDE_BCM8727_BCM8073
elink_set_disable_pmd_transmit(struct elink_params * params,struct elink_phy * phy,u8 pmd_dis)8494 static void elink_set_disable_pmd_transmit(struct elink_params *params,
8495 struct elink_phy *phy,
8496 u8 pmd_dis)
8497 {
8498 struct elink_dev *cb = params->cb;
8499 /* Disable transmitter only for bootcodes which can enable it afterwards
8500 * (for D3 link)
8501 */
8502 if (pmd_dis) {
8503 if (params->feature_config_flags &
8504 ELINK_FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED) {
8505 ELINK_DEBUG_P0(cb, "Disabling PMD transmitter\n");
8506 } else {
8507 ELINK_DEBUG_P0(cb, "NOT disabling PMD transmitter\n");
8508 return;
8509 }
8510 } else
8511 ELINK_DEBUG_P0(cb, "Enabling PMD transmitter\n");
8512 elink_cl45_write(cb, phy,
8513 MDIO_PMA_DEVAD,
8514 MDIO_PMA_REG_TX_DISABLE, pmd_dis);
8515 }
8516 #endif // EXCLUDE_BCM8727_BCM8073
8517
8518 #if !defined(EXCLUDE_BCM87x6) || !defined(EXCLUDE_BCM8727_BCM8073)
elink_get_gpio_port(struct elink_params * params)8519 static u8 elink_get_gpio_port(struct elink_params *params)
8520 {
8521 u8 gpio_port;
8522 u32 swap_val, swap_override;
8523 struct elink_dev *cb = params->cb;
8524 if (CHIP_IS_E2(params->chip_id))
8525 gpio_port = PATH_ID(cb);
8526 else
8527 gpio_port = params->port;
8528 swap_val = REG_RD(cb, NIG_REG_PORT_SWAP);
8529 swap_override = REG_RD(cb, NIG_REG_STRAP_OVERRIDE);
8530 return gpio_port ^ (swap_val && swap_override);
8531 }
8532
elink_sfp_e1e2_set_transmitter(struct elink_params * params,struct elink_phy * phy,u8 tx_en)8533 static void elink_sfp_e1e2_set_transmitter(struct elink_params *params,
8534 struct elink_phy *phy,
8535 u8 tx_en)
8536 {
8537 u16 val;
8538 u8 port = params->port;
8539 struct elink_dev *cb = params->cb;
8540 u32 tx_en_mode;
8541
8542 /* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/
8543 tx_en_mode = REG_RD(cb, params->shmem_base +
8544 OFFSETOF(struct shmem_region,
8545 dev_info.port_hw_config[port].sfp_ctrl)) &
8546 PORT_HW_CFG_TX_LASER_MASK;
8547 ELINK_DEBUG_P3(cb, "Setting transmitter tx_en=%x for port %x "
8548 "mode = %x\n", tx_en, port, tx_en_mode);
8549 switch (tx_en_mode) {
8550 case PORT_HW_CFG_TX_LASER_MDIO:
8551
8552 elink_cl45_read(cb, phy,
8553 MDIO_PMA_DEVAD,
8554 MDIO_PMA_REG_PHY_IDENTIFIER,
8555 &val);
8556
8557 if (tx_en)
8558 val &= ~(1<<15);
8559 else
8560 val |= (1<<15);
8561
8562 elink_cl45_write(cb, phy,
8563 MDIO_PMA_DEVAD,
8564 MDIO_PMA_REG_PHY_IDENTIFIER,
8565 val);
8566 break;
8567 case PORT_HW_CFG_TX_LASER_GPIO0:
8568 case PORT_HW_CFG_TX_LASER_GPIO1:
8569 case PORT_HW_CFG_TX_LASER_GPIO2:
8570 case PORT_HW_CFG_TX_LASER_GPIO3:
8571 {
8572 u16 gpio_pin;
8573 u8 gpio_port, gpio_mode;
8574 if (tx_en)
8575 gpio_mode = MISC_REGISTERS_GPIO_OUTPUT_HIGH;
8576 else
8577 gpio_mode = MISC_REGISTERS_GPIO_OUTPUT_LOW;
8578
8579 gpio_pin = tx_en_mode - PORT_HW_CFG_TX_LASER_GPIO0;
8580 gpio_port = elink_get_gpio_port(params);
8581 ELINK_SET_GPIO(cb, gpio_pin, gpio_mode, gpio_port);
8582 break;
8583 }
8584 default:
8585 ELINK_DEBUG_P1(cb, "Invalid TX_LASER_MDIO 0x%x\n", tx_en_mode);
8586 break;
8587 }
8588 }
8589 #endif /* !defined(EXCLUDE_BCM87x6) || !defined(EXCLUDE_BCM8727_BCM8073) */
8590
elink_sfp_set_transmitter(struct elink_params * params,struct elink_phy * phy,u8 tx_en)8591 static void elink_sfp_set_transmitter(struct elink_params *params,
8592 struct elink_phy *phy,
8593 u8 tx_en)
8594 {
8595 #ifdef ELINK_ENHANCEMENTS
8596 struct elink_dev *cb = params->cb;
8597 ELINK_DEBUG_P1(cb, "Setting SFP+ transmitter to %d\n", tx_en);
8598 #endif // ELINK_ENHANCEMENTS
8599 #ifndef EXCLUDE_WARPCORE
8600 if (CHIP_IS_E3(params->chip_id))
8601 elink_sfp_e3_set_transmitter(params, phy, tx_en);
8602 #endif // EXCLUDE_WARPCORE
8603 #ifdef ELINK_ENHANCEMENTS
8604 else
8605 #endif // ELINK_ENHANCEMENTS
8606 #if !defined(EXCLUDE_BCM87x6) || !defined(EXCLUDE_BCM8727_BCM8073)
8607 elink_sfp_e1e2_set_transmitter(params, phy, tx_en);
8608 #endif
8609 }
8610
elink_8726_read_sfp_module_eeprom(struct elink_phy * phy,struct elink_params * params,u8 dev_addr,u16 addr,u8 byte_cnt,u8 * o_buf,u8 is_init)8611 static elink_status_t elink_8726_read_sfp_module_eeprom(struct elink_phy *phy,
8612 struct elink_params *params,
8613 u8 dev_addr, u16 addr, u8 byte_cnt,
8614 u8 *o_buf, u8 is_init)
8615 {
8616 #ifndef EXCLUDE_BCM87x6
8617 struct elink_dev *cb = params->cb;
8618 u16 val = 0;
8619 u16 i;
8620 if (byte_cnt > ELINK_SFP_EEPROM_PAGE_SIZE) {
8621 ELINK_DEBUG_P0(cb,
8622 "Reading from eeprom is limited to 0xf\n");
8623 return ELINK_STATUS_ERROR;
8624 }
8625 /* Set the read command byte count */
8626 elink_cl45_write(cb, phy,
8627 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
8628 (byte_cnt | (dev_addr << 8)));
8629
8630 /* Set the read command address */
8631 elink_cl45_write(cb, phy,
8632 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
8633 addr);
8634
8635 /* Activate read command */
8636 elink_cl45_write(cb, phy,
8637 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
8638 0x2c0f);
8639
8640 /* Wait up to 500us for command complete status */
8641 for (i = 0; i < 100; i++) {
8642 elink_cl45_read(cb, phy,
8643 MDIO_PMA_DEVAD,
8644 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
8645 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
8646 MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
8647 break;
8648 USLEEP(cb, 5);
8649 }
8650
8651 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
8652 MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
8653 ELINK_DEBUG_P1(cb,
8654 "Got bad status 0x%x when reading from SFP+ EEPROM\n",
8655 (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK));
8656 return ELINK_STATUS_ERROR;
8657 }
8658
8659 /* Read the buffer */
8660 for (i = 0; i < byte_cnt; i++) {
8661 elink_cl45_read(cb, phy,
8662 MDIO_PMA_DEVAD,
8663 MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF + i, &val);
8664 o_buf[i] = (u8)(val & MDIO_PMA_REG_8726_TWO_WIRE_DATA_MASK);
8665 }
8666
8667 for (i = 0; i < 100; i++) {
8668 elink_cl45_read(cb, phy,
8669 MDIO_PMA_DEVAD,
8670 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
8671 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
8672 MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
8673 return ELINK_STATUS_OK;
8674 MSLEEP(cb, 1);
8675 }
8676 #endif // EXCLUDE_BCM87x6
8677 return ELINK_STATUS_ERROR;
8678 }
8679
8680 #ifndef EXCLUDE_WARPCORE
8681 #ifndef EXCLUDE_NON_COMMON_INIT
elink_warpcore_power_module(struct elink_params * params,u8 power)8682 static void elink_warpcore_power_module(struct elink_params *params,
8683 u8 power)
8684 {
8685 u32 pin_cfg;
8686 struct elink_dev *cb = params->cb;
8687
8688 pin_cfg = (REG_RD(cb, params->shmem_base +
8689 OFFSETOF(struct shmem_region,
8690 dev_info.port_hw_config[params->port].e3_sfp_ctrl)) &
8691 PORT_HW_CFG_E3_PWR_DIS_MASK) >>
8692 PORT_HW_CFG_E3_PWR_DIS_SHIFT;
8693
8694 if (pin_cfg == PIN_CFG_NA)
8695 return;
8696 ELINK_DEBUG_P2(cb, "Setting SFP+ module power to %d using pin cfg %d\n",
8697 power, pin_cfg);
8698 /* Low ==> corresponding SFP+ module is powered
8699 * high ==> the SFP+ module is powered down
8700 */
8701 elink_set_cfg_pin(cb, pin_cfg, power ^ 1);
8702 }
8703 #endif
elink_warpcore_read_sfp_module_eeprom(struct elink_phy * phy,struct elink_params * params,u8 dev_addr,u16 addr,u8 byte_cnt,u8 * o_buf,u8 is_init)8704 static elink_status_t elink_warpcore_read_sfp_module_eeprom(struct elink_phy *phy,
8705 struct elink_params *params,
8706 u8 dev_addr,
8707 u16 addr, u8 byte_cnt,
8708 u8 *o_buf, u8 is_init)
8709 {
8710 elink_status_t rc = ELINK_STATUS_OK;
8711 u8 i, j = 0, cnt = 0;
8712 u32 data_array[4];
8713 u16 addr32;
8714 struct elink_dev *cb = params->cb;
8715
8716 if (byte_cnt > ELINK_SFP_EEPROM_PAGE_SIZE) {
8717 ELINK_DEBUG_P0(cb,
8718 "Reading from eeprom is limited to 16 bytes\n");
8719 return ELINK_STATUS_ERROR;
8720 }
8721
8722 /* 4 byte aligned address */
8723 addr32 = addr & (~0x3);
8724 do {
8725 if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) {
8726 elink_warpcore_power_module(params, 0);
8727 /* Note that 100us are not enough here */
8728 MSLEEP(cb, 1);
8729 elink_warpcore_power_module(params, 1);
8730 }
8731 rc = elink_bsc_read(params, cb, dev_addr, addr32, 0, byte_cnt,
8732 data_array);
8733 } while ((rc != ELINK_STATUS_OK) && (++cnt < I2C_WA_RETRY_CNT));
8734
8735 if (rc == ELINK_STATUS_OK) {
8736 for (i = (addr - addr32); i < byte_cnt + (addr - addr32); i++) {
8737 o_buf[j] = *((u8 *)data_array + i);
8738 j++;
8739 }
8740 }
8741
8742 return rc;
8743 }
8744 #endif /* EXCLUDE_WARPCORE */
8745
8746 #ifndef EXCLUDE_BCM8727_BCM8073
elink_8727_read_sfp_module_eeprom(struct elink_phy * phy,struct elink_params * params,u8 dev_addr,u16 addr,u8 byte_cnt,u8 * o_buf,u8 is_init)8747 static elink_status_t elink_8727_read_sfp_module_eeprom(struct elink_phy *phy,
8748 struct elink_params *params,
8749 u8 dev_addr, u16 addr, u8 byte_cnt,
8750 u8 *o_buf, u8 is_init)
8751 {
8752 struct elink_dev *cb = params->cb;
8753 u16 val, i;
8754
8755 if (byte_cnt > ELINK_SFP_EEPROM_PAGE_SIZE) {
8756 ELINK_DEBUG_P0(cb,
8757 "Reading from eeprom is limited to 0xf\n");
8758 return ELINK_STATUS_ERROR;
8759 }
8760
8761 /* Set 2-wire transfer rate of SFP+ module EEPROM
8762 * to 100Khz since some DACs(direct attached cables) do
8763 * not work at 400Khz.
8764 */
8765 elink_cl45_write(cb, phy,
8766 MDIO_PMA_DEVAD,
8767 MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR,
8768 ((dev_addr << 8) | 1));
8769
8770 /* Need to read from 1.8000 to clear it */
8771 elink_cl45_read(cb, phy,
8772 MDIO_PMA_DEVAD,
8773 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
8774 &val);
8775
8776 /* Set the read command byte count */
8777 elink_cl45_write(cb, phy,
8778 MDIO_PMA_DEVAD,
8779 MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
8780 ((byte_cnt < 2) ? 2 : byte_cnt));
8781
8782 /* Set the read command address */
8783 elink_cl45_write(cb, phy,
8784 MDIO_PMA_DEVAD,
8785 MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
8786 addr);
8787 /* Set the destination address */
8788 elink_cl45_write(cb, phy,
8789 MDIO_PMA_DEVAD,
8790 0x8004,
8791 MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF);
8792
8793 /* Activate read command */
8794 elink_cl45_write(cb, phy,
8795 MDIO_PMA_DEVAD,
8796 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
8797 0x8002);
8798 /* Wait appropriate time for two-wire command to finish before
8799 * polling the status register
8800 */
8801 MSLEEP(cb, 1);
8802
8803 /* Wait up to 500us for command complete status */
8804 for (i = 0; i < 100; i++) {
8805 elink_cl45_read(cb, phy,
8806 MDIO_PMA_DEVAD,
8807 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
8808 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
8809 MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
8810 break;
8811 USLEEP(cb, 5);
8812 }
8813
8814 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
8815 MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
8816 ELINK_DEBUG_P1(cb,
8817 "Got bad status 0x%x when reading from SFP+ EEPROM\n",
8818 (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK));
8819 return ELINK_STATUS_TIMEOUT;
8820 }
8821
8822 /* Read the buffer */
8823 for (i = 0; i < byte_cnt; i++) {
8824 elink_cl45_read(cb, phy,
8825 MDIO_PMA_DEVAD,
8826 MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF + i, &val);
8827 o_buf[i] = (u8)(val & MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK);
8828 }
8829
8830 for (i = 0; i < 100; i++) {
8831 elink_cl45_read(cb, phy,
8832 MDIO_PMA_DEVAD,
8833 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
8834 if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
8835 MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
8836 return ELINK_STATUS_OK;
8837 MSLEEP(cb, 1);
8838 }
8839
8840 return ELINK_STATUS_ERROR;
8841 }
8842 #endif /* EXCLUDE_BCM8727_BCM8073 */
8843 #endif /* #ifndef EXCLUDE_NON_COMMON_INIT */
8844 #endif /* ELINK_EMUL_ONLY */
8845 #ifndef EXCLUDE_FROM_BNX2X
elink_validate_cc_dmi(u8 * sfp_a2_buf)8846 elink_status_t elink_validate_cc_dmi(u8 *sfp_a2_buf)
8847 {
8848 u8 i, checksum = 0;
8849 for (i = 0; i < ELINK_SFP_EEPROM_A2_CHECKSUM_RANGE; i++)
8850 checksum += sfp_a2_buf[i];
8851 if (checksum == sfp_a2_buf[ELINK_SFP_EEPROM_A2_CC_DMI_ADDR])
8852 return ELINK_STATUS_OK;
8853
8854 return ELINK_STATUS_ERROR;
8855 }
8856 #endif
8857 #ifndef EXCLUDE_NON_COMMON_INIT
elink_read_sfp_module_eeprom(struct elink_phy * phy,struct elink_params * params,u8 dev_addr,u16 addr,u16 byte_cnt,u8 * o_buf)8858 elink_status_t elink_read_sfp_module_eeprom(struct elink_phy *phy,
8859 struct elink_params *params, u8 dev_addr,
8860 u16 addr, u16 byte_cnt, u8 *o_buf)
8861 {
8862 elink_status_t rc = 0;
8863 #ifdef ELINK_DEBUG
8864 struct elink_dev *cb = params->cb;
8865 #endif
8866 u8 xfer_size;
8867 u8 *user_data = o_buf;
8868 read_sfp_module_eeprom_func_p read_func;
8869 if ((dev_addr != 0xa0) && (dev_addr != 0xa2)) {
8870 ELINK_DEBUG_P1(cb, "invalid dev_addr 0x%x\n", dev_addr);
8871 return ELINK_STATUS_ERROR;
8872 }
8873
8874 #ifndef ELINK_EMUL_ONLY
8875 switch (phy->type) {
8876 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
8877 read_func = elink_8726_read_sfp_module_eeprom;
8878 break;
8879 #ifndef EXCLUDE_BCM8727_BCM8073
8880 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
8881 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
8882 read_func = elink_8727_read_sfp_module_eeprom;
8883 break;
8884 #endif
8885 #ifndef EXCLUDE_WARPCORE
8886 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
8887 read_func = elink_warpcore_read_sfp_module_eeprom;
8888 break;
8889 #endif /* EXCLUDE_WARPCORE */
8890 default:
8891 return ELINK_OP_NOT_SUPPORTED;
8892 }
8893
8894 while (!rc && (byte_cnt > 0)) {
8895 xfer_size = (byte_cnt > ELINK_SFP_EEPROM_PAGE_SIZE) ?
8896 ELINK_SFP_EEPROM_PAGE_SIZE : byte_cnt;
8897 rc = read_func(phy, params, dev_addr, addr, xfer_size,
8898 user_data, 0);
8899 byte_cnt -= xfer_size;
8900 user_data += xfer_size;
8901 addr += xfer_size;
8902 }
8903 #endif /* ELINK_EMUL_ONLY */
8904 return rc;
8905 }
8906 #endif // EXCLUDE_NON_COMMON_INIT
8907 #ifndef ELINK_EMUL_ONLY
8908
8909 #ifndef EXCLUDE_NON_COMMON_INIT
8910 #if !defined(EXCLUDE_BCM87x6) || !defined(EXCLUDE_BCM8727_BCM8073) || !defined(EXCLUDE_WARPCORE)
elink_get_edc_mode(struct elink_phy * phy,struct elink_params * params,u16 * edc_mode)8911 static elink_status_t elink_get_edc_mode(struct elink_phy *phy,
8912 struct elink_params *params,
8913 u16 *edc_mode)
8914 {
8915 struct elink_dev *cb = params->cb;
8916 u32 sync_offset = 0, phy_idx, media_types;
8917 u8 val[ELINK_SFP_EEPROM_FC_TX_TECH_ADDR + 1], check_limiting_mode = 0;
8918 *edc_mode = ELINK_EDC_MODE_LIMITING;
8919 phy->media_type = ELINK_ETH_PHY_UNSPECIFIED;
8920 /* First check for copper cable */
8921 if (elink_read_sfp_module_eeprom(phy,
8922 params,
8923 ELINK_I2C_DEV_ADDR_A0,
8924 0,
8925 ELINK_SFP_EEPROM_FC_TX_TECH_ADDR + 1,
8926 (u8 *)val) != 0) {
8927 ELINK_DEBUG_P0(cb, "Failed to read from SFP+ module EEPROM\n");
8928 return ELINK_STATUS_ERROR;
8929 }
8930 #ifndef EXCLUDE_WARPCORE
8931 params->link_attr_sync &= ~LINK_SFP_EEPROM_COMP_CODE_MASK;
8932 params->link_attr_sync |= val[ELINK_SFP_EEPROM_10G_COMP_CODE_ADDR] <<
8933 LINK_SFP_EEPROM_COMP_CODE_SHIFT;
8934 elink_update_link_attr(params, params->link_attr_sync);
8935 #endif
8936 switch (val[ELINK_SFP_EEPROM_CON_TYPE_ADDR]) {
8937 case ELINK_SFP_EEPROM_CON_TYPE_VAL_COPPER:
8938 {
8939 u8 copper_module_type;
8940 phy->media_type = ELINK_ETH_PHY_DA_TWINAX;
8941 /* Check if its active cable (includes SFP+ module)
8942 * of passive cable
8943 */
8944 copper_module_type = val[ELINK_SFP_EEPROM_FC_TX_TECH_ADDR];
8945 if (copper_module_type &
8946 ELINK_SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
8947 ELINK_DEBUG_P0(cb, "Active Copper cable detected\n");
8948 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
8949 *edc_mode = ELINK_EDC_MODE_ACTIVE_DAC;
8950 else
8951 check_limiting_mode = 1;
8952 } else {
8953 *edc_mode = ELINK_EDC_MODE_PASSIVE_DAC;
8954 /* Even in case PASSIVE_DAC indication is not set,
8955 * treat it as a passive DAC cable, since some cables
8956 * don't have this indication.
8957 */
8958 if (copper_module_type &
8959 ELINK_SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
8960 ELINK_DEBUG_P0(cb,
8961 "Passive Copper cable detected\n");
8962 } else {
8963 ELINK_DEBUG_P0(cb,
8964 "Unknown copper-cable-type\n");
8965 }
8966 }
8967 break;
8968 }
8969 case ELINK_SFP_EEPROM_CON_TYPE_VAL_UNKNOWN:
8970 case ELINK_SFP_EEPROM_CON_TYPE_VAL_LC:
8971 case ELINK_SFP_EEPROM_CON_TYPE_VAL_RJ45:
8972 check_limiting_mode = 1;
8973 /* Module is considered as 1G in case it's NOT compliant with
8974 * any 10G ethernet protocol.
8975 */
8976 if ((val[ELINK_SFP_EEPROM_10G_COMP_CODE_ADDR] &
8977 (ELINK_SFP_EEPROM_10G_COMP_CODE_SR_MASK |
8978 ELINK_SFP_EEPROM_10G_COMP_CODE_LR_MASK |
8979 ELINK_SFP_EEPROM_10G_COMP_CODE_LRM_MASK)) == 0) {
8980 ELINK_DEBUG_P0(cb, "1G SFP module detected\n");
8981 phy->media_type = ELINK_ETH_PHY_SFP_1G_FIBER;
8982 if (phy->req_line_speed != ELINK_SPEED_1000) {
8983 #ifndef ELINK_AUX_POWER
8984 u8 gport = params->port;
8985 #endif
8986 phy->req_line_speed = ELINK_SPEED_1000;
8987 #ifndef ELINK_AUX_POWER
8988 if (!CHIP_IS_E1X(params->chip_id)) {
8989 gport = PATH_ID(cb) +
8990 (params->port << 1);
8991 }
8992 elink_cb_event_log(cb, ELINK_LOG_ID_NON_10G_MODULE, gport); //"Warning: Link speed was forced to 1000Mbps."
8993 // " Current SFP module in port %d is not"
8994 // " compliant with 10G Ethernet\n",
8995 #endif
8996 }
8997
8998 if (val[ELINK_SFP_EEPROM_1G_COMP_CODE_ADDR] &
8999 ELINK_SFP_EEPROM_1G_COMP_CODE_BASE_T) {
9000 /* Some 1G-baseT modules will not link up,
9001 * unless TX_EN is toggled with long delay in
9002 * between.
9003 */
9004 elink_sfp_set_transmitter(params, phy, 0);
9005 MSLEEP(cb, 40);
9006 elink_sfp_set_transmitter(params, phy, 1);
9007 }
9008 } else {
9009 int idx, cfg_idx = 0;
9010 ELINK_DEBUG_P0(cb, "10G Optic module detected\n");
9011 for (idx = ELINK_INT_PHY; idx < ELINK_MAX_PHYS; idx++) {
9012 if (params->phy[idx].type == phy->type) {
9013 cfg_idx = ELINK_LINK_CONFIG_IDX(idx);
9014 break;
9015 }
9016 }
9017 phy->media_type = ELINK_ETH_PHY_SFPP_10G_FIBER;
9018 phy->req_line_speed = params->req_line_speed[cfg_idx];
9019 }
9020 break;
9021 default:
9022 ELINK_DEBUG_P1(cb, "Unable to determine module type 0x%x !!!\n",
9023 val[ELINK_SFP_EEPROM_CON_TYPE_ADDR]);
9024 return ELINK_STATUS_ERROR;
9025 }
9026 sync_offset = params->shmem_base +
9027 OFFSETOF(struct shmem_region,
9028 dev_info.port_hw_config[params->port].media_type);
9029 media_types = REG_RD(cb, sync_offset);
9030 /* Update media type for non-PMF sync */
9031 for (phy_idx = ELINK_INT_PHY; phy_idx < ELINK_MAX_PHYS; phy_idx++) {
9032 if (&(params->phy[phy_idx]) == phy) {
9033 media_types &= ~(PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
9034 (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
9035 media_types |= ((phy->media_type &
9036 PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
9037 (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
9038 break;
9039 }
9040 }
9041 REG_WR(cb, sync_offset, media_types);
9042 if (check_limiting_mode) {
9043 u8 options[ELINK_SFP_EEPROM_OPTIONS_SIZE];
9044 if (elink_read_sfp_module_eeprom(phy,
9045 params,
9046 ELINK_I2C_DEV_ADDR_A0,
9047 ELINK_SFP_EEPROM_OPTIONS_ADDR,
9048 ELINK_SFP_EEPROM_OPTIONS_SIZE,
9049 options) != 0) {
9050 ELINK_DEBUG_P0(cb,
9051 "Failed to read Option field from module EEPROM\n");
9052 return ELINK_STATUS_ERROR;
9053 }
9054 if ((options[0] & ELINK_SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK))
9055 *edc_mode = ELINK_EDC_MODE_LINEAR;
9056 else
9057 *edc_mode = ELINK_EDC_MODE_LIMITING;
9058 }
9059 ELINK_DEBUG_P1(cb, "EDC mode is set to 0x%x\n", *edc_mode);
9060 return ELINK_STATUS_OK;
9061 }
9062 #ifdef ELINK_ENHANCEMENTS
9063 /* This function read the relevant field from the module (SFP+), and verify it
9064 * is compliant with this board
9065 */
elink_verify_sfp_module(struct elink_phy * phy,struct elink_params * params)9066 static elink_status_t elink_verify_sfp_module(struct elink_phy *phy,
9067 struct elink_params *params)
9068 {
9069 struct elink_dev *cb = params->cb;
9070 u32 val, cmd;
9071 u32 fw_resp, fw_cmd_param;
9072 char vendor_name[ELINK_SFP_EEPROM_VENDOR_NAME_SIZE+1];
9073 char vendor_pn[ELINK_SFP_EEPROM_PART_NO_SIZE+1];
9074 phy->flags &= ~ELINK_FLAGS_SFP_NOT_APPROVED;
9075 val = REG_RD(cb, params->shmem_base +
9076 OFFSETOF(struct shmem_region, dev_info.
9077 port_feature_config[params->port].config));
9078 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
9079 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT) {
9080 ELINK_DEBUG_P0(cb, "NOT enforcing module verification\n");
9081 return ELINK_STATUS_OK;
9082 }
9083
9084 if (params->feature_config_flags &
9085 ELINK_FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY) {
9086 /* Use specific phy request */
9087 cmd = DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL;
9088 } else if (params->feature_config_flags &
9089 ELINK_FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY) {
9090 /* Use first phy request only in case of non-dual media*/
9091 if (ELINK_DUAL_MEDIA(params)) {
9092 ELINK_DEBUG_P0(cb,
9093 "FW does not support OPT MDL verification\n");
9094 return ELINK_STATUS_ERROR;
9095 }
9096 cmd = DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL;
9097 } else {
9098 /* No support in OPT MDL detection */
9099 ELINK_DEBUG_P0(cb,
9100 "FW does not support OPT MDL verification\n");
9101 return ELINK_STATUS_ERROR;
9102 }
9103
9104 fw_cmd_param = ELINK_FW_PARAM_SET(phy->addr, phy->type, phy->mdio_ctrl);
9105 fw_resp = elink_cb_fw_command(cb, cmd, fw_cmd_param);
9106 if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) {
9107 ELINK_DEBUG_P0(cb, "Approved module\n");
9108 return ELINK_STATUS_OK;
9109 }
9110
9111 /* Format the warning message */
9112 if (elink_read_sfp_module_eeprom(phy,
9113 params,
9114 ELINK_I2C_DEV_ADDR_A0,
9115 ELINK_SFP_EEPROM_VENDOR_NAME_ADDR,
9116 ELINK_SFP_EEPROM_VENDOR_NAME_SIZE,
9117 (u8 *)vendor_name))
9118 vendor_name[0] = '\0';
9119 else
9120 vendor_name[ELINK_SFP_EEPROM_VENDOR_NAME_SIZE] = '\0';
9121 if (elink_read_sfp_module_eeprom(phy,
9122 params,
9123 ELINK_I2C_DEV_ADDR_A0,
9124 ELINK_SFP_EEPROM_PART_NO_ADDR,
9125 ELINK_SFP_EEPROM_PART_NO_SIZE,
9126 (u8 *)vendor_pn))
9127 vendor_pn[0] = '\0';
9128 else
9129 vendor_pn[ELINK_SFP_EEPROM_PART_NO_SIZE] = '\0';
9130
9131 elink_cb_event_log(cb, ELINK_LOG_ID_UNQUAL_IO_MODULE, params->port, vendor_name, vendor_pn); // "Warning: Unqualified SFP+ module detected,"
9132 // " Port %d from %s part number %s\n",
9133
9134 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
9135 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG)
9136 phy->flags |= ELINK_FLAGS_SFP_NOT_APPROVED;
9137 return ELINK_STATUS_ERROR;
9138 }
9139 #endif /* ELINK_ENHANCEMENTS */
9140
9141 #ifndef EXCLUDE_BCM8727_BCM8073
elink_wait_for_sfp_module_initialized(struct elink_phy * phy,struct elink_params * params)9142 static elink_status_t elink_wait_for_sfp_module_initialized(struct elink_phy *phy,
9143 struct elink_params *params)
9144
9145 {
9146 u8 val;
9147 elink_status_t rc;
9148 struct elink_dev *cb = params->cb;
9149 u16 timeout;
9150 /* Initialization time after hot-plug may take up to 300ms for
9151 * some phys type ( e.g. JDSU )
9152 */
9153
9154 for (timeout = 0; timeout < 60; timeout++) {
9155 #ifndef EXCLUDE_WARPCORE
9156 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
9157 rc = elink_warpcore_read_sfp_module_eeprom(
9158 phy, params, ELINK_I2C_DEV_ADDR_A0, 1, 1, &val,
9159 1);
9160 else
9161 #endif
9162 rc = elink_read_sfp_module_eeprom(phy, params,
9163 ELINK_I2C_DEV_ADDR_A0,
9164 1, 1, &val);
9165 if (rc == 0) {
9166 ELINK_DEBUG_P1(cb,
9167 "SFP+ module initialization took %d ms\n",
9168 timeout * 5);
9169 return ELINK_STATUS_OK;
9170 }
9171 MSLEEP(cb, 5);
9172 }
9173 rc = elink_read_sfp_module_eeprom(phy, params, ELINK_I2C_DEV_ADDR_A0,
9174 1, 1, &val);
9175 return rc;
9176 }
9177 #endif /* EXCLUDE_BCM8727_BCM8073 */
9178 #endif /* #if !defined(EXCLUDE_BCM87x6) || !defined(EXCLUDE_BCM8727_BCM8073) || !defined(EXCLUDE_WARPCORE) */
9179
9180 #ifndef EXCLUDE_BCM8727_BCM8073
elink_8727_power_module(struct elink_dev * cb,struct elink_phy * phy,u8 is_power_up)9181 static void elink_8727_power_module(struct elink_dev *cb,
9182 struct elink_phy *phy,
9183 u8 is_power_up) {
9184 /* Make sure GPIOs are not using for LED mode */
9185 u16 val;
9186 /* In the GPIO register, bit 4 is use to determine if the GPIOs are
9187 * operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
9188 * output
9189 * Bits 0-1 determine the GPIOs value for OUTPUT in case bit 4 val is 0
9190 * Bits 8-9 determine the GPIOs value for INPUT in case bit 4 val is 1
9191 * where the 1st bit is the over-current(only input), and 2nd bit is
9192 * for power( only output )
9193 *
9194 * In case of NOC feature is disabled and power is up, set GPIO control
9195 * as input to enable listening of over-current indication
9196 */
9197 if (phy->flags & ELINK_FLAGS_NOC)
9198 return;
9199 if (is_power_up)
9200 val = (1<<4);
9201 else
9202 /* Set GPIO control to OUTPUT, and set the power bit
9203 * to according to the is_power_up
9204 */
9205 val = (1<<1);
9206
9207 elink_cl45_write(cb, phy,
9208 MDIO_PMA_DEVAD,
9209 MDIO_PMA_REG_8727_GPIO_CTRL,
9210 val);
9211 }
9212 #endif /* EXCLUDE_BCM8727_BCM8073 */
9213
9214 #ifndef EXCLUDE_BCM87x6
elink_8726_set_limiting_mode(struct elink_dev * cb,struct elink_phy * phy,u16 edc_mode)9215 static elink_status_t elink_8726_set_limiting_mode(struct elink_dev *cb,
9216 struct elink_phy *phy,
9217 u16 edc_mode)
9218 {
9219 u16 cur_limiting_mode;
9220
9221 elink_cl45_read(cb, phy,
9222 MDIO_PMA_DEVAD,
9223 MDIO_PMA_REG_ROM_VER2,
9224 &cur_limiting_mode);
9225 ELINK_DEBUG_P1(cb, "Current Limiting mode is 0x%x\n",
9226 cur_limiting_mode);
9227
9228 if (edc_mode == ELINK_EDC_MODE_LIMITING) {
9229 ELINK_DEBUG_P0(cb, "Setting LIMITING MODE\n");
9230 elink_cl45_write(cb, phy,
9231 MDIO_PMA_DEVAD,
9232 MDIO_PMA_REG_ROM_VER2,
9233 ELINK_EDC_MODE_LIMITING);
9234 } else { /* LRM mode ( default )*/
9235
9236 ELINK_DEBUG_P0(cb, "Setting LRM MODE\n");
9237
9238 /* Changing to LRM mode takes quite few seconds. So do it only
9239 * if current mode is limiting (default is LRM)
9240 */
9241 if (cur_limiting_mode != ELINK_EDC_MODE_LIMITING)
9242 return ELINK_STATUS_OK;
9243
9244 elink_cl45_write(cb, phy,
9245 MDIO_PMA_DEVAD,
9246 MDIO_PMA_REG_LRM_MODE,
9247 0);
9248 elink_cl45_write(cb, phy,
9249 MDIO_PMA_DEVAD,
9250 MDIO_PMA_REG_ROM_VER2,
9251 0x128);
9252 elink_cl45_write(cb, phy,
9253 MDIO_PMA_DEVAD,
9254 MDIO_PMA_REG_MISC_CTRL0,
9255 0x4008);
9256 elink_cl45_write(cb, phy,
9257 MDIO_PMA_DEVAD,
9258 MDIO_PMA_REG_LRM_MODE,
9259 0xaaaa);
9260 }
9261 return ELINK_STATUS_OK;
9262 }
9263 #endif /* #ifndef EXCLUDE_BCM87x6 */
9264
9265 #ifndef EXCLUDE_BCM8727_BCM8073
elink_8727_set_limiting_mode(struct elink_dev * cb,struct elink_phy * phy,u16 edc_mode)9266 static elink_status_t elink_8727_set_limiting_mode(struct elink_dev *cb,
9267 struct elink_phy *phy,
9268 u16 edc_mode)
9269 {
9270 u16 phy_identifier;
9271 u16 rom_ver2_val;
9272 elink_cl45_read(cb, phy,
9273 MDIO_PMA_DEVAD,
9274 MDIO_PMA_REG_PHY_IDENTIFIER,
9275 &phy_identifier);
9276
9277 elink_cl45_write(cb, phy,
9278 MDIO_PMA_DEVAD,
9279 MDIO_PMA_REG_PHY_IDENTIFIER,
9280 (phy_identifier & ~(1<<9)));
9281
9282 elink_cl45_read(cb, phy,
9283 MDIO_PMA_DEVAD,
9284 MDIO_PMA_REG_ROM_VER2,
9285 &rom_ver2_val);
9286 /* Keep the MSB 8-bits, and set the LSB 8-bits with the edc_mode */
9287 elink_cl45_write(cb, phy,
9288 MDIO_PMA_DEVAD,
9289 MDIO_PMA_REG_ROM_VER2,
9290 (rom_ver2_val & 0xff00) | (edc_mode & 0x00ff));
9291
9292 elink_cl45_write(cb, phy,
9293 MDIO_PMA_DEVAD,
9294 MDIO_PMA_REG_PHY_IDENTIFIER,
9295 (phy_identifier | (1<<9)));
9296
9297 return ELINK_STATUS_OK;
9298 }
9299
elink_8727_specific_func(struct elink_phy * phy,struct elink_params * params,u32 action)9300 static void elink_8727_specific_func(struct elink_phy *phy,
9301 struct elink_params *params,
9302 u32 action)
9303 {
9304 struct elink_dev *cb = params->cb;
9305 u16 val;
9306 switch (action) {
9307 case ELINK_DISABLE_TX:
9308 elink_sfp_set_transmitter(params, phy, 0);
9309 break;
9310 case ELINK_ENABLE_TX:
9311 if (!(phy->flags & ELINK_FLAGS_SFP_NOT_APPROVED))
9312 elink_sfp_set_transmitter(params, phy, 1);
9313 break;
9314 case ELINK_PHY_INIT:
9315 elink_cl45_write(cb, phy,
9316 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
9317 (1<<2) | (1<<5));
9318 elink_cl45_write(cb, phy,
9319 MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL,
9320 0);
9321 elink_cl45_write(cb, phy,
9322 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x0006);
9323 /* Make MOD_ABS give interrupt on change */
9324 elink_cl45_read(cb, phy, MDIO_PMA_DEVAD,
9325 MDIO_PMA_REG_8727_PCS_OPT_CTRL,
9326 &val);
9327 val |= (1<<12);
9328 if (phy->flags & ELINK_FLAGS_NOC)
9329 val |= (3<<5);
9330 /* Set 8727 GPIOs to input to allow reading from the 8727 GPIO0
9331 * status which reflect SFP+ module over-current
9332 */
9333 if (!(phy->flags & ELINK_FLAGS_NOC))
9334 val &= 0xff8f; /* Reset bits 4-6 */
9335 elink_cl45_write(cb, phy,
9336 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL,
9337 val);
9338 break;
9339 default:
9340 ELINK_DEBUG_P1(cb, "Function 0x%x not supported by 8727\n",
9341 action);
9342 return;
9343 }
9344 }
9345
9346 #ifdef ELINK_ENHANCEMENTS
elink_set_e1e2_module_fault_led(struct elink_params * params,u8 gpio_mode)9347 static void elink_set_e1e2_module_fault_led(struct elink_params *params,
9348 u8 gpio_mode)
9349 {
9350 struct elink_dev *cb = params->cb;
9351
9352 u32 fault_led_gpio = REG_RD(cb, params->shmem_base +
9353 OFFSETOF(struct shmem_region,
9354 dev_info.port_hw_config[params->port].sfp_ctrl)) &
9355 PORT_HW_CFG_FAULT_MODULE_LED_MASK;
9356 switch (fault_led_gpio) {
9357 case PORT_HW_CFG_FAULT_MODULE_LED_DISABLED:
9358 return;
9359 case PORT_HW_CFG_FAULT_MODULE_LED_GPIO0:
9360 case PORT_HW_CFG_FAULT_MODULE_LED_GPIO1:
9361 case PORT_HW_CFG_FAULT_MODULE_LED_GPIO2:
9362 case PORT_HW_CFG_FAULT_MODULE_LED_GPIO3:
9363 {
9364 u8 gpio_port = elink_get_gpio_port(params);
9365 u16 gpio_pin = fault_led_gpio -
9366 PORT_HW_CFG_FAULT_MODULE_LED_GPIO0;
9367 ELINK_DEBUG_P3(cb, "Set fault module-detected led "
9368 "pin %x port %x mode %x\n",
9369 gpio_pin, gpio_port, gpio_mode);
9370 ELINK_SET_GPIO(cb, gpio_pin, gpio_mode, gpio_port);
9371 }
9372 break;
9373 default:
9374 ELINK_DEBUG_P1(cb, "Error: Invalid fault led mode 0x%x\n",
9375 fault_led_gpio);
9376 }
9377 }
9378 #endif /* #ifdef ELINK_ENHANCEMENTS */
9379 #endif // EXCLUDE_BCM8727_BCM8073
9380 #endif // EXCLUDE_NON_COMMON_INIT
9381
9382 #ifdef ELINK_ENHANCEMENTS
elink_set_e3_module_fault_led(struct elink_params * params,u8 gpio_mode)9383 static void elink_set_e3_module_fault_led(struct elink_params *params,
9384 u8 gpio_mode)
9385 {
9386 u32 pin_cfg;
9387 u8 port = params->port;
9388 struct elink_dev *cb = params->cb;
9389 pin_cfg = (REG_RD(cb, params->shmem_base +
9390 OFFSETOF(struct shmem_region,
9391 dev_info.port_hw_config[port].e3_sfp_ctrl)) &
9392 PORT_HW_CFG_E3_FAULT_MDL_LED_MASK) >>
9393 PORT_HW_CFG_E3_FAULT_MDL_LED_SHIFT;
9394 ELINK_DEBUG_P2(cb, "Setting Fault LED to %d using pin cfg %d\n",
9395 gpio_mode, pin_cfg);
9396 elink_set_cfg_pin(cb, pin_cfg, gpio_mode);
9397 }
9398
elink_set_sfp_module_fault_led(struct elink_params * params,u8 gpio_mode)9399 static void elink_set_sfp_module_fault_led(struct elink_params *params,
9400 u8 gpio_mode)
9401 {
9402 struct elink_dev *cb = params->cb;
9403 ELINK_DEBUG_P1(cb, "Setting SFP+ module fault LED to %d\n", gpio_mode);
9404 if (CHIP_IS_E3(params->chip_id)) {
9405 /* Low ==> if SFP+ module is supported otherwise
9406 * High ==> if SFP+ module is not on the approved vendor list
9407 */
9408 elink_set_e3_module_fault_led(params, gpio_mode);
9409 } else
9410 elink_set_e1e2_module_fault_led(params, gpio_mode);
9411 }
9412 #endif /* #ifdef ELINK_ENHANCEMENTS */
9413
9414 #ifndef EXCLUDE_WARPCORE
9415 #ifndef EXCLUDE_NON_COMMON_INIT
elink_warpcore_hw_reset(struct elink_phy * phy,struct elink_params * params)9416 static void elink_warpcore_hw_reset(struct elink_phy *phy,
9417 struct elink_params *params)
9418 {
9419 struct elink_dev *cb = params->cb;
9420 elink_warpcore_power_module(params, 0);
9421 /* Put Warpcore in low power mode */
9422 REG_WR(cb, MISC_REG_WC0_RESET, 0x0c0e);
9423
9424 /* Put LCPLL in low power mode */
9425 REG_WR(cb, MISC_REG_LCPLL_E40_PWRDWN, 1);
9426 REG_WR(cb, MISC_REG_LCPLL_E40_RESETB_ANA, 0);
9427 REG_WR(cb, MISC_REG_LCPLL_E40_RESETB_DIG, 0);
9428 }
9429 #endif // #ifndef EXCLUDE_NON_COMMON_INIT
9430 #endif // #ifndef EXCLUDE_WARPCORE
9431
9432 #ifndef EXCLUDE_NON_COMMON_INIT
elink_power_sfp_module(struct elink_params * params,struct elink_phy * phy,u8 power)9433 static void elink_power_sfp_module(struct elink_params *params,
9434 struct elink_phy *phy,
9435 u8 power)
9436 {
9437 #ifdef ELINK_DEBUG
9438 struct elink_dev *cb = params->cb;
9439 #endif /* ELINK_DEBUG */
9440 ELINK_DEBUG_P1(cb, "Setting SFP+ power to %x\n", power);
9441
9442 switch (phy->type) {
9443 #ifndef EXCLUDE_BCM8727_BCM8073
9444 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
9445 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
9446 elink_8727_power_module(params->cb, phy, power);
9447 break;
9448 #endif // EXCLUDE_BCM8727_BCM8073
9449 #ifndef EXCLUDE_WARPCORE
9450 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
9451 elink_warpcore_power_module(params, power);
9452 break;
9453 #endif // EXCLUDE_WARPCORE
9454 default:
9455 break;
9456 }
9457 }
9458 #ifndef EXCLUDE_WARPCORE
elink_warpcore_set_limiting_mode(struct elink_params * params,struct elink_phy * phy,u16 edc_mode)9459 static void elink_warpcore_set_limiting_mode(struct elink_params *params,
9460 struct elink_phy *phy,
9461 u16 edc_mode)
9462 {
9463 u16 val = 0;
9464 u16 mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
9465 struct elink_dev *cb = params->cb;
9466
9467 u8 lane = elink_get_warpcore_lane(phy, params);
9468 /* This is a global register which controls all lanes */
9469 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
9470 MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
9471 val &= ~(0xf << (lane << 2));
9472
9473 switch (edc_mode) {
9474 case ELINK_EDC_MODE_LINEAR:
9475 case ELINK_EDC_MODE_LIMITING:
9476 mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
9477 break;
9478 case ELINK_EDC_MODE_PASSIVE_DAC:
9479 case ELINK_EDC_MODE_ACTIVE_DAC:
9480 mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC;
9481 break;
9482 default:
9483 break;
9484 }
9485
9486 val |= (mode << (lane << 2));
9487 elink_cl45_write(cb, phy, MDIO_WC_DEVAD,
9488 MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, val);
9489 /* A must read */
9490 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
9491 MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
9492
9493 /* Restart microcode to re-read the new mode */
9494 elink_warpcore_reset_lane(cb, phy, 1);
9495 elink_warpcore_reset_lane(cb, phy, 0);
9496
9497 }
9498 #endif // EXCLUDE_WARPCORE
9499
elink_set_limiting_mode(struct elink_params * params,struct elink_phy * phy,u16 edc_mode)9500 static void elink_set_limiting_mode(struct elink_params *params,
9501 struct elink_phy *phy,
9502 u16 edc_mode)
9503 {
9504 switch (phy->type) {
9505 #ifndef EXCLUDE_BCM87x6
9506 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
9507 elink_8726_set_limiting_mode(params->cb, phy, edc_mode);
9508 break;
9509 #endif /* #ifndef EXCLUDE_BCM87x6 */
9510 #ifndef EXCLUDE_BCM8727_BCM8073
9511 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
9512 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
9513 elink_8727_set_limiting_mode(params->cb, phy, edc_mode);
9514 break;
9515 #endif // EXCLUDE_BCM8727_BCM8073
9516 #ifndef EXCLUDE_WARPCORE
9517 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
9518 elink_warpcore_set_limiting_mode(params, phy, edc_mode);
9519 break;
9520 #endif // EXCLUDE_WARPCORE
9521 }
9522 }
9523
elink_sfp_module_detection(struct elink_phy * phy,struct elink_params * params)9524 elink_status_t elink_sfp_module_detection(struct elink_phy *phy,
9525 struct elink_params *params)
9526 {
9527 struct elink_dev *cb = params->cb;
9528 u16 edc_mode;
9529 elink_status_t rc = ELINK_STATUS_OK;
9530
9531 u32 val = REG_RD(cb, params->shmem_base +
9532 OFFSETOF(struct shmem_region, dev_info.
9533 port_feature_config[params->port].config));
9534 /* Enabled transmitter by default */
9535 elink_sfp_set_transmitter(params, phy, 1);
9536 ELINK_DEBUG_P1(cb, "SFP+ module plugged in/out detected on port %d\n",
9537 params->port);
9538 /* Power up module */
9539 elink_power_sfp_module(params, phy, 1);
9540 if (elink_get_edc_mode(phy, params, &edc_mode) != 0) {
9541 ELINK_DEBUG_P0(cb, "Failed to get valid module type\n");
9542 return ELINK_STATUS_ERROR;
9543 #ifdef ELINK_ENHANCEMENTS
9544 } else if (elink_verify_sfp_module(phy, params) != 0) {
9545 /* Check SFP+ module compatibility */
9546 ELINK_DEBUG_P0(cb, "Module verification failed!!\n");
9547 rc = ELINK_STATUS_ERROR;
9548 /* Turn on fault module-detected led */
9549 elink_set_sfp_module_fault_led(params,
9550 MISC_REGISTERS_GPIO_HIGH);
9551
9552 /* Check if need to power down the SFP+ module */
9553 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
9554 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN) {
9555 ELINK_DEBUG_P0(cb, "Shutdown SFP+ module!!\n");
9556 elink_power_sfp_module(params, phy, 0);
9557 return rc;
9558 }
9559 } else {
9560 /* Turn off fault module-detected led */
9561 elink_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_LOW);
9562 #endif // ELINK_ENHANCEMENTS
9563 }
9564
9565 /* Check and set limiting mode / LRM mode on 8726. On 8727 it
9566 * is done automatically
9567 */
9568 elink_set_limiting_mode(params, phy, edc_mode);
9569
9570 /* Disable transmit for this module if the module is not approved, and
9571 * laser needs to be disabled.
9572 */
9573 if ((rc != 0) &&
9574 ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
9575 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER))
9576 elink_sfp_set_transmitter(params, phy, 0);
9577
9578 return rc;
9579 }
9580 #endif // EXCLUDE_NON_COMMON_INIT
9581
9582 #ifdef ELINK_ENHANCEMENTS
elink_handle_module_detect_int(struct elink_params * params)9583 void elink_handle_module_detect_int(struct elink_params *params)
9584 {
9585 struct elink_dev *cb = params->cb;
9586 struct elink_phy *phy;
9587 u32 gpio_val;
9588 u8 gpio_num, gpio_port;
9589 if (CHIP_IS_E3(params->chip_id)) {
9590 phy = ¶ms->phy[ELINK_INT_PHY];
9591 /* Always enable TX laser,will be disabled in case of fault */
9592 elink_sfp_set_transmitter(params, phy, 1);
9593 } else {
9594 phy = ¶ms->phy[ELINK_EXT_PHY1];
9595 }
9596 if (elink_get_mod_abs_int_cfg(cb, params->chip_id, params->shmem_base,
9597 params->port, &gpio_num, &gpio_port) ==
9598 ELINK_STATUS_ERROR) {
9599 ELINK_DEBUG_P0(cb, "Failed to get MOD_ABS interrupt config\n");
9600 return;
9601 }
9602
9603 /* Set valid module led off */
9604 elink_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_HIGH);
9605
9606 /* Get current gpio val reflecting module plugged in / out*/
9607 gpio_val = ELINK_GET_GPIO(cb, gpio_num, gpio_port);
9608
9609 /* Call the handling function in case module is detected */
9610 if (gpio_val == 0) {
9611 #ifdef ELINK_AUX_POWER
9612 phy->flags |= ELINK_FLAGS_SFP_MODULE_PLUGGED_IN_WC;
9613 #endif
9614 elink_set_mdio_emac_per_phy(cb, params);
9615 elink_set_aer_mmd(params, phy);
9616
9617 elink_power_sfp_module(params, phy, 1);
9618 ELINK_SET_GPIO_INT(cb, gpio_num,
9619 MISC_REGISTERS_GPIO_INT_OUTPUT_CLR,
9620 gpio_port);
9621 if (elink_wait_for_sfp_module_initialized(phy, params) == 0) {
9622 elink_sfp_module_detection(phy, params);
9623 if (CHIP_IS_E3(params->chip_id)) {
9624 u16 rx_tx_in_reset;
9625 /* In case WC is out of reset, reconfigure the
9626 * link speed while taking into account 1G
9627 * module limitation.
9628 */
9629 elink_cl45_read(cb, phy,
9630 MDIO_WC_DEVAD,
9631 MDIO_WC_REG_DIGITAL5_MISC6,
9632 &rx_tx_in_reset);
9633 if ((!rx_tx_in_reset) &&
9634 (params->link_flags &
9635 ELINK_PHY_INITIALIZED)) {
9636 elink_warpcore_reset_lane(cb, phy, 1);
9637 elink_warpcore_config_sfi(phy, params);
9638 elink_warpcore_reset_lane(cb, phy, 0);
9639 }
9640 }
9641 } else {
9642 ELINK_DEBUG_P0(cb, "SFP+ module is not initialized\n");
9643 }
9644 } else {
9645 #ifdef ELINK_AUX_POWER
9646 phy->flags &= ~ELINK_FLAGS_SFP_MODULE_PLUGGED_IN_WC;
9647 #endif
9648 ELINK_SET_GPIO_INT(cb, gpio_num,
9649 MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
9650 gpio_port);
9651 /* Module was plugged out.
9652 * Disable transmit for this module
9653 */
9654 phy->media_type = ELINK_ETH_PHY_NOT_PRESENT;
9655 }
9656 }
9657 #endif // ELINK_ENHANCEMENTS
9658
9659 /******************************************************************/
9660 /* Used by 8706 and 8727 */
9661 /******************************************************************/
9662 #ifndef EXCLUDE_NON_COMMON_INIT
9663 #if !defined(EXCLUDE_BCM87x6) || !defined(EXCLUDE_BCM8727_BCM8073)
elink_sfp_mask_fault(struct elink_dev * cb,struct elink_phy * phy,u16 alarm_status_offset,u16 alarm_ctrl_offset)9664 static void elink_sfp_mask_fault(struct elink_dev *cb,
9665 struct elink_phy *phy,
9666 u16 alarm_status_offset,
9667 u16 alarm_ctrl_offset)
9668 {
9669 u16 alarm_status, val;
9670 elink_cl45_read(cb, phy,
9671 MDIO_PMA_DEVAD, alarm_status_offset,
9672 &alarm_status);
9673 elink_cl45_read(cb, phy,
9674 MDIO_PMA_DEVAD, alarm_status_offset,
9675 &alarm_status);
9676 /* Mask or enable the fault event. */
9677 elink_cl45_read(cb, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, &val);
9678 if (alarm_status & (1<<0))
9679 val &= ~(1<<0);
9680 else
9681 val |= (1<<0);
9682 elink_cl45_write(cb, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, val);
9683 }
9684 #endif // #if !defined(EXCLUDE_BCM87x6) || !defined(EXCLUDE_BCM8727_BCM8073
9685 /******************************************************************/
9686 /* common BCM8706/BCM8726 PHY SECTION */
9687 /******************************************************************/
9688 #ifndef EXCLUDE_BCM87x6
elink_8706_8726_read_status(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)9689 static u8 elink_8706_8726_read_status(struct elink_phy *phy,
9690 struct elink_params *params,
9691 struct elink_vars *vars)
9692 {
9693 u8 link_up = 0;
9694 u16 val1, val2, rx_sd, pcs_status;
9695 struct elink_dev *cb = params->cb;
9696 ELINK_DEBUG_P0(cb, "XGXS 8706/8726\n");
9697 /* Clear RX Alarm*/
9698 elink_cl45_read(cb, phy,
9699 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2);
9700
9701 elink_sfp_mask_fault(cb, phy, MDIO_PMA_LASI_TXSTAT,
9702 MDIO_PMA_LASI_TXCTRL);
9703
9704 /* Clear LASI indication*/
9705 elink_cl45_read(cb, phy,
9706 MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
9707 elink_cl45_read(cb, phy,
9708 MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2);
9709 ELINK_DEBUG_P2(cb, "8706/8726 LASI status 0x%x--> 0x%x\n", val1, val2);
9710
9711 elink_cl45_read(cb, phy,
9712 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd);
9713 elink_cl45_read(cb, phy,
9714 MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &pcs_status);
9715 elink_cl45_read(cb, phy,
9716 MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2);
9717 elink_cl45_read(cb, phy,
9718 MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2);
9719
9720 ELINK_DEBUG_P3(cb, "8706/8726 rx_sd 0x%x pcs_status 0x%x 1Gbps"
9721 " link_status 0x%x\n", rx_sd, pcs_status, val2);
9722 /* Link is up if both bit 0 of pmd_rx_sd and bit 0 of pcs_status
9723 * are set, or if the autoneg bit 1 is set
9724 */
9725 link_up = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1)));
9726 if (link_up) {
9727 if (val2 & (1<<1))
9728 vars->line_speed = ELINK_SPEED_1000;
9729 else
9730 vars->line_speed = ELINK_SPEED_10000;
9731 elink_ext_phy_resolve_fc(phy, params, vars);
9732 vars->duplex = DUPLEX_FULL;
9733 }
9734
9735 /* Capture 10G link fault. Read twice to clear stale value. */
9736 if (vars->line_speed == ELINK_SPEED_10000) {
9737 elink_cl45_read(cb, phy, MDIO_PMA_DEVAD,
9738 MDIO_PMA_LASI_TXSTAT, &val1);
9739 elink_cl45_read(cb, phy, MDIO_PMA_DEVAD,
9740 MDIO_PMA_LASI_TXSTAT, &val1);
9741 if (val1 & (1<<0))
9742 vars->fault_detected = 1;
9743 }
9744
9745 return link_up;
9746 }
9747
9748 /******************************************************************/
9749 /* BCM8706 PHY SECTION */
9750 /******************************************************************/
elink_8706_config_init(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)9751 static u8 elink_8706_config_init(struct elink_phy *phy,
9752 struct elink_params *params,
9753 struct elink_vars *vars)
9754 {
9755 u32 tx_en_mode;
9756 u16 cnt, val, tmp1;
9757 struct elink_dev *cb = params->cb;
9758
9759 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_2,
9760 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
9761 /* HW reset */
9762 elink_ext_phy_hw_reset(cb, params->port);
9763 elink_cl45_write(cb, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
9764 elink_wait_reset_complete(cb, phy, params);
9765
9766 /* Wait until fw is loaded */
9767 for (cnt = 0; cnt < 100; cnt++) {
9768 elink_cl45_read(cb, phy,
9769 MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1, &val);
9770 if (val)
9771 break;
9772 MSLEEP(cb, 10);
9773 }
9774 ELINK_DEBUG_P1(cb, "XGXS 8706 is initialized after %d ms\n", cnt);
9775 if ((params->feature_config_flags &
9776 ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
9777 u8 i;
9778 u16 reg;
9779 for (i = 0; i < 4; i++) {
9780 reg = MDIO_XS_8706_REG_BANK_RX0 +
9781 i*(MDIO_XS_8706_REG_BANK_RX1 -
9782 MDIO_XS_8706_REG_BANK_RX0);
9783 elink_cl45_read(cb, phy, MDIO_XS_DEVAD, reg, &val);
9784 /* Clear first 3 bits of the control */
9785 val &= ~0x7;
9786 /* Set control bits according to configuration */
9787 val |= (phy->rx_preemphasis[i] & 0x7);
9788 ELINK_DEBUG_P2(cb, "Setting RX Equalizer to BCM8706"
9789 " reg 0x%x <-- val 0x%x\n", reg, val);
9790 elink_cl45_write(cb, phy, MDIO_XS_DEVAD, reg, val);
9791 }
9792 }
9793 /* Force speed */
9794 if (phy->req_line_speed == ELINK_SPEED_10000) {
9795 ELINK_DEBUG_P0(cb, "XGXS 8706 force 10Gbps\n");
9796
9797 elink_cl45_write(cb, phy,
9798 MDIO_PMA_DEVAD,
9799 MDIO_PMA_REG_DIGITAL_CTRL, 0x400);
9800 elink_cl45_write(cb, phy,
9801 MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL,
9802 0);
9803 /* Arm LASI for link and Tx fault. */
9804 elink_cl45_write(cb, phy,
9805 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 3);
9806 } else {
9807 /* Force 1Gbps using autoneg with 1G advertisement */
9808
9809 /* Allow CL37 through CL73 */
9810 ELINK_DEBUG_P0(cb, "XGXS 8706 AutoNeg\n");
9811 elink_cl45_write(cb, phy,
9812 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c);
9813
9814 /* Enable Full-Duplex advertisement on CL37 */
9815 elink_cl45_write(cb, phy,
9816 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LP, 0x0020);
9817 /* Enable CL37 AN */
9818 elink_cl45_write(cb, phy,
9819 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
9820 /* 1G support */
9821 elink_cl45_write(cb, phy,
9822 MDIO_AN_DEVAD, MDIO_AN_REG_ADV, (1<<5));
9823
9824 /* Enable clause 73 AN */
9825 elink_cl45_write(cb, phy,
9826 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
9827 elink_cl45_write(cb, phy,
9828 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
9829 0x0400);
9830 elink_cl45_write(cb, phy,
9831 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,
9832 0x0004);
9833 }
9834 elink_save_bcm_spirom_ver(cb, phy, params->port);
9835
9836 /* If TX Laser is controlled by GPIO_0, do not let PHY go into low
9837 * power mode, if TX Laser is disabled
9838 */
9839
9840 tx_en_mode = REG_RD(cb, params->shmem_base +
9841 OFFSETOF(struct shmem_region,
9842 dev_info.port_hw_config[params->port].sfp_ctrl))
9843 & PORT_HW_CFG_TX_LASER_MASK;
9844
9845 if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) {
9846 ELINK_DEBUG_P0(cb, "Enabling TXONOFF_PWRDN_DIS\n");
9847 elink_cl45_read(cb, phy,
9848 MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, &tmp1);
9849 tmp1 |= 0x1;
9850 elink_cl45_write(cb, phy,
9851 MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, tmp1);
9852 }
9853
9854 return ELINK_STATUS_OK;
9855 }
9856
elink_8706_read_status(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)9857 static elink_status_t elink_8706_read_status(struct elink_phy *phy,
9858 struct elink_params *params,
9859 struct elink_vars *vars)
9860 {
9861 return elink_8706_8726_read_status(phy, params, vars);
9862 }
9863
9864 /******************************************************************/
9865 /* BCM8726 PHY SECTION */
9866 /******************************************************************/
elink_8726_config_loopback(struct elink_phy * phy,struct elink_params * params)9867 static void elink_8726_config_loopback(struct elink_phy *phy,
9868 struct elink_params *params)
9869 {
9870 struct elink_dev *cb = params->cb;
9871 ELINK_DEBUG_P0(cb, "PMA/PMD ext_phy_loopback: 8726\n");
9872 elink_cl45_write(cb, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0001);
9873 }
9874
elink_8726_external_rom_boot(struct elink_phy * phy,struct elink_params * params)9875 static void elink_8726_external_rom_boot(struct elink_phy *phy,
9876 struct elink_params *params)
9877 {
9878 struct elink_dev *cb = params->cb;
9879 /* Need to wait 100ms after reset */
9880 MSLEEP(cb, 100);
9881
9882 /* Micro controller re-boot */
9883 elink_cl45_write(cb, phy,
9884 MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x018B);
9885
9886 /* Set soft reset */
9887 elink_cl45_write(cb, phy,
9888 MDIO_PMA_DEVAD,
9889 MDIO_PMA_REG_GEN_CTRL,
9890 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
9891
9892 elink_cl45_write(cb, phy,
9893 MDIO_PMA_DEVAD,
9894 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
9895
9896 elink_cl45_write(cb, phy,
9897 MDIO_PMA_DEVAD,
9898 MDIO_PMA_REG_GEN_CTRL,
9899 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
9900
9901 /* Wait for 150ms for microcode load */
9902 MSLEEP(cb, 150);
9903
9904 /* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO */
9905 elink_cl45_write(cb, phy,
9906 MDIO_PMA_DEVAD,
9907 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
9908
9909 MSLEEP(cb, 200);
9910 elink_save_bcm_spirom_ver(cb, phy, params->port);
9911 }
9912
elink_8726_read_status(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)9913 static u8 elink_8726_read_status(struct elink_phy *phy,
9914 struct elink_params *params,
9915 struct elink_vars *vars)
9916 {
9917 struct elink_dev *cb = params->cb;
9918 u16 val1;
9919 u8 link_up = elink_8706_8726_read_status(phy, params, vars);
9920 if (link_up) {
9921 elink_cl45_read(cb, phy,
9922 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
9923 &val1);
9924 if (val1 & (1<<15)) {
9925 ELINK_DEBUG_P0(cb, "Tx is disabled\n");
9926 link_up = 0;
9927 vars->line_speed = 0;
9928 }
9929 }
9930 return link_up;
9931 }
9932
9933
elink_8726_config_init(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)9934 static elink_status_t elink_8726_config_init(struct elink_phy *phy,
9935 struct elink_params *params,
9936 struct elink_vars *vars)
9937 {
9938 struct elink_dev *cb = params->cb;
9939 ELINK_DEBUG_P0(cb, "Initializing BCM8726\n");
9940
9941 elink_cl45_write(cb, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
9942 elink_wait_reset_complete(cb, phy, params);
9943
9944 elink_8726_external_rom_boot(phy, params);
9945
9946 /* Need to call module detected on initialization since the module
9947 * detection triggered by actual module insertion might occur before
9948 * driver is loaded, and when driver is loaded, it reset all
9949 * registers, including the transmitter
9950 */
9951 elink_sfp_module_detection(phy, params);
9952
9953 if (phy->req_line_speed == ELINK_SPEED_1000) {
9954 ELINK_DEBUG_P0(cb, "Setting 1G force\n");
9955 elink_cl45_write(cb, phy,
9956 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40);
9957 elink_cl45_write(cb, phy,
9958 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
9959 elink_cl45_write(cb, phy,
9960 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x5);
9961 elink_cl45_write(cb, phy,
9962 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
9963 0x400);
9964 } else if ((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) &&
9965 (phy->speed_cap_mask &
9966 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) &&
9967 ((phy->speed_cap_mask &
9968 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) !=
9969 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
9970 ELINK_DEBUG_P0(cb, "Setting 1G clause37\n");
9971 /* Set Flow control */
9972 elink_ext_phy_set_pause(params, phy, vars);
9973 elink_cl45_write(cb, phy,
9974 MDIO_AN_DEVAD, MDIO_AN_REG_ADV, 0x20);
9975 elink_cl45_write(cb, phy,
9976 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c);
9977 elink_cl45_write(cb, phy,
9978 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, 0x0020);
9979 elink_cl45_write(cb, phy,
9980 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
9981 elink_cl45_write(cb, phy,
9982 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
9983 /* Enable RX-ALARM control to receive interrupt for 1G speed
9984 * change
9985 */
9986 elink_cl45_write(cb, phy,
9987 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x4);
9988 elink_cl45_write(cb, phy,
9989 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
9990 0x400);
9991
9992 } else { /* Default 10G. Set only LASI control */
9993 elink_cl45_write(cb, phy,
9994 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 1);
9995 }
9996
9997 /* Set TX PreEmphasis if needed */
9998 if ((params->feature_config_flags &
9999 ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
10000 ELINK_DEBUG_P2(cb,
10001 "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x\n",
10002 phy->tx_preemphasis[0],
10003 phy->tx_preemphasis[1]);
10004 elink_cl45_write(cb, phy,
10005 MDIO_PMA_DEVAD,
10006 MDIO_PMA_REG_8726_TX_CTRL1,
10007 phy->tx_preemphasis[0]);
10008
10009 elink_cl45_write(cb, phy,
10010 MDIO_PMA_DEVAD,
10011 MDIO_PMA_REG_8726_TX_CTRL2,
10012 phy->tx_preemphasis[1]);
10013 }
10014
10015 return ELINK_STATUS_OK;
10016
10017 }
10018
elink_8726_link_reset(struct elink_phy * phy,struct elink_params * params)10019 static void elink_8726_link_reset(struct elink_phy *phy,
10020 struct elink_params *params)
10021 {
10022 #ifndef EXCLUDE_LINK_RESET
10023 struct elink_dev *cb = params->cb;
10024 ELINK_DEBUG_P1(cb, "elink_8726_link_reset port %d\n", params->port);
10025 /* Set serial boot control for external load */
10026 elink_cl45_write(cb, phy,
10027 MDIO_PMA_DEVAD,
10028 MDIO_PMA_REG_GEN_CTRL, 0x0001);
10029 #endif // EXCLUDE_LINK_RESET
10030 }
10031 #endif /* #ifndef EXCLUDE_BCM87x6 */
10032
10033 /******************************************************************/
10034 /* BCM8727 PHY SECTION */
10035 /******************************************************************/
10036
10037 #ifndef EXCLUDE_BCM8727_BCM8073
elink_8727_set_link_led(struct elink_phy * phy,struct elink_params * params,u8 mode)10038 static void elink_8727_set_link_led(struct elink_phy *phy,
10039 struct elink_params *params, u8 mode)
10040 {
10041 struct elink_dev *cb = params->cb;
10042 u16 led_mode_bitmask = 0;
10043 u16 gpio_pins_bitmask = 0;
10044 u16 val;
10045 /* Only NOC flavor requires to set the LED specifically */
10046 if (!(phy->flags & ELINK_FLAGS_NOC))
10047 return;
10048 switch (mode) {
10049 case ELINK_LED_MODE_FRONT_PANEL_OFF:
10050 case ELINK_LED_MODE_OFF:
10051 led_mode_bitmask = 0;
10052 gpio_pins_bitmask = 0x03;
10053 break;
10054 case ELINK_LED_MODE_ON:
10055 led_mode_bitmask = 0;
10056 gpio_pins_bitmask = 0x02;
10057 break;
10058 case ELINK_LED_MODE_OPER:
10059 led_mode_bitmask = 0x60;
10060 gpio_pins_bitmask = 0x11;
10061 break;
10062 }
10063 elink_cl45_read(cb, phy,
10064 MDIO_PMA_DEVAD,
10065 MDIO_PMA_REG_8727_PCS_OPT_CTRL,
10066 &val);
10067 val &= 0xff8f;
10068 val |= led_mode_bitmask;
10069 elink_cl45_write(cb, phy,
10070 MDIO_PMA_DEVAD,
10071 MDIO_PMA_REG_8727_PCS_OPT_CTRL,
10072 val);
10073 elink_cl45_read(cb, phy,
10074 MDIO_PMA_DEVAD,
10075 MDIO_PMA_REG_8727_GPIO_CTRL,
10076 &val);
10077 val &= 0xffe0;
10078 val |= gpio_pins_bitmask;
10079 elink_cl45_write(cb, phy,
10080 MDIO_PMA_DEVAD,
10081 MDIO_PMA_REG_8727_GPIO_CTRL,
10082 val);
10083 }
elink_8727_hw_reset(struct elink_phy * phy,struct elink_params * params)10084 static void elink_8727_hw_reset(struct elink_phy *phy,
10085 struct elink_params *params) {
10086 u32 swap_val, swap_override;
10087 u8 port;
10088 /* The PHY reset is controlled by GPIO 1. Fake the port number
10089 * to cancel the swap done in set_gpio()
10090 */
10091 struct elink_dev *cb = params->cb;
10092 swap_val = REG_RD(cb, NIG_REG_PORT_SWAP);
10093 swap_override = REG_RD(cb, NIG_REG_STRAP_OVERRIDE);
10094 port = (swap_val && swap_override) ^ 1;
10095 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_1,
10096 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
10097 }
10098
elink_8727_config_speed(struct elink_phy * phy,struct elink_params * params)10099 static void elink_8727_config_speed(struct elink_phy *phy,
10100 struct elink_params *params)
10101 {
10102 struct elink_dev *cb = params->cb;
10103 u16 tmp1, val;
10104 /* Set option 1G speed */
10105 if ((phy->req_line_speed == ELINK_SPEED_1000) ||
10106 (phy->media_type == ELINK_ETH_PHY_SFP_1G_FIBER)) {
10107 ELINK_DEBUG_P0(cb, "Setting 1G force\n");
10108 elink_cl45_write(cb, phy,
10109 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40);
10110 elink_cl45_write(cb, phy,
10111 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
10112 elink_cl45_read(cb, phy,
10113 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1);
10114 ELINK_DEBUG_P1(cb, "1.7 = 0x%x\n", tmp1);
10115 /* Power down the XAUI until link is up in case of dual-media
10116 * and 1G
10117 */
10118 if (ELINK_DUAL_MEDIA(params)) {
10119 elink_cl45_read(cb, phy,
10120 MDIO_PMA_DEVAD,
10121 MDIO_PMA_REG_8727_PCS_GP, &val);
10122 val |= (3<<10);
10123 elink_cl45_write(cb, phy,
10124 MDIO_PMA_DEVAD,
10125 MDIO_PMA_REG_8727_PCS_GP, val);
10126 }
10127 } else if ((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) &&
10128 ((phy->speed_cap_mask &
10129 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) &&
10130 ((phy->speed_cap_mask &
10131 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) !=
10132 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
10133
10134 ELINK_DEBUG_P0(cb, "Setting 1G clause37\n");
10135 elink_cl45_write(cb, phy,
10136 MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL, 0);
10137 elink_cl45_write(cb, phy,
10138 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1300);
10139 } else {
10140 /* Since the 8727 has only single reset pin, need to set the 10G
10141 * registers although it is default
10142 */
10143 elink_cl45_write(cb, phy,
10144 MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL,
10145 0x0020);
10146 elink_cl45_write(cb, phy,
10147 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x0100);
10148 elink_cl45_write(cb, phy,
10149 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040);
10150 elink_cl45_write(cb, phy,
10151 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2,
10152 0x0008);
10153 }
10154 }
10155
elink_8727_config_init(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)10156 static elink_status_t elink_8727_config_init(struct elink_phy *phy,
10157 struct elink_params *params,
10158 struct elink_vars *vars)
10159 {
10160 u32 tx_en_mode;
10161 u16 tmp1, mod_abs, tmp2;
10162 struct elink_dev *cb = params->cb;
10163 /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
10164
10165 elink_wait_reset_complete(cb, phy, params);
10166
10167 ELINK_DEBUG_P0(cb, "Initializing BCM8727\n");
10168
10169 elink_8727_specific_func(phy, params, ELINK_PHY_INIT);
10170 /* Initially configure MOD_ABS to interrupt when module is
10171 * presence( bit 8)
10172 */
10173 elink_cl45_read(cb, phy,
10174 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
10175 /* Set EDC off by setting OPTXLOS signal input to low (bit 9).
10176 * When the EDC is off it locks onto a reference clock and avoids
10177 * becoming 'lost'
10178 */
10179 mod_abs &= ~(1<<8);
10180 if (!(phy->flags & ELINK_FLAGS_NOC))
10181 mod_abs &= ~(1<<9);
10182 elink_cl45_write(cb, phy,
10183 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
10184
10185 /* Enable/Disable PHY transmitter output */
10186 elink_set_disable_pmd_transmit(params, phy, 0);
10187
10188 elink_8727_power_module(cb, phy, 1);
10189
10190 elink_cl45_read(cb, phy,
10191 MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
10192
10193 elink_cl45_read(cb, phy,
10194 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1);
10195
10196 elink_8727_config_speed(phy, params);
10197
10198
10199 /* Set TX PreEmphasis if needed */
10200 if ((params->feature_config_flags &
10201 ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
10202 ELINK_DEBUG_P2(cb, "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x\n",
10203 phy->tx_preemphasis[0],
10204 phy->tx_preemphasis[1]);
10205 elink_cl45_write(cb, phy,
10206 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL1,
10207 phy->tx_preemphasis[0]);
10208
10209 elink_cl45_write(cb, phy,
10210 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL2,
10211 phy->tx_preemphasis[1]);
10212 }
10213
10214 /* If TX Laser is controlled by GPIO_0, do not let PHY go into low
10215 * power mode, if TX Laser is disabled
10216 */
10217 tx_en_mode = REG_RD(cb, params->shmem_base +
10218 OFFSETOF(struct shmem_region,
10219 dev_info.port_hw_config[params->port].sfp_ctrl))
10220 & PORT_HW_CFG_TX_LASER_MASK;
10221
10222 if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) {
10223
10224 ELINK_DEBUG_P0(cb, "Enabling TXONOFF_PWRDN_DIS\n");
10225 elink_cl45_read(cb, phy,
10226 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, &tmp2);
10227 tmp2 |= 0x1000;
10228 tmp2 &= 0xFFEF;
10229 elink_cl45_write(cb, phy,
10230 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, tmp2);
10231 elink_cl45_read(cb, phy,
10232 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
10233 &tmp2);
10234 elink_cl45_write(cb, phy,
10235 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
10236 (tmp2 & 0x7fff));
10237 }
10238
10239 return ELINK_STATUS_OK;
10240 }
10241
elink_8727_handle_mod_abs(struct elink_phy * phy,struct elink_params * params)10242 static void elink_8727_handle_mod_abs(struct elink_phy *phy,
10243 struct elink_params *params)
10244 {
10245 struct elink_dev *cb = params->cb;
10246 u16 mod_abs, rx_alarm_status;
10247 u32 val = REG_RD(cb, params->shmem_base +
10248 OFFSETOF(struct shmem_region, dev_info.
10249 port_feature_config[params->port].
10250 config));
10251 elink_cl45_read(cb, phy,
10252 MDIO_PMA_DEVAD,
10253 MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
10254 if (mod_abs & (1<<8)) {
10255
10256 /* Module is absent */
10257 ELINK_DEBUG_P0(cb,
10258 "MOD_ABS indication show module is absent\n");
10259 phy->media_type = ELINK_ETH_PHY_NOT_PRESENT;
10260 /* 1. Set mod_abs to detect next module
10261 * presence event
10262 * 2. Set EDC off by setting OPTXLOS signal input to low
10263 * (bit 9).
10264 * When the EDC is off it locks onto a reference clock and
10265 * avoids becoming 'lost'.
10266 */
10267 mod_abs &= ~(1<<8);
10268 if (!(phy->flags & ELINK_FLAGS_NOC))
10269 mod_abs &= ~(1<<9);
10270 elink_cl45_write(cb, phy,
10271 MDIO_PMA_DEVAD,
10272 MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
10273
10274 /* Clear RX alarm since it stays up as long as
10275 * the mod_abs wasn't changed
10276 */
10277 elink_cl45_read(cb, phy,
10278 MDIO_PMA_DEVAD,
10279 MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
10280
10281 } else {
10282 /* Module is present */
10283 ELINK_DEBUG_P0(cb,
10284 "MOD_ABS indication show module is present\n");
10285 /* First disable transmitter, and if the module is ok, the
10286 * module_detection will enable it
10287 * 1. Set mod_abs to detect next module absent event ( bit 8)
10288 * 2. Restore the default polarity of the OPRXLOS signal and
10289 * this signal will then correctly indicate the presence or
10290 * absence of the Rx signal. (bit 9)
10291 */
10292 mod_abs |= (1<<8);
10293 if (!(phy->flags & ELINK_FLAGS_NOC))
10294 mod_abs |= (1<<9);
10295 elink_cl45_write(cb, phy,
10296 MDIO_PMA_DEVAD,
10297 MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
10298
10299 /* Clear RX alarm since it stays up as long as the mod_abs
10300 * wasn't changed. This is need to be done before calling the
10301 * module detection, otherwise it will clear* the link update
10302 * alarm
10303 */
10304 elink_cl45_read(cb, phy,
10305 MDIO_PMA_DEVAD,
10306 MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
10307
10308
10309 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
10310 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
10311 elink_sfp_set_transmitter(params, phy, 0);
10312
10313 if (elink_wait_for_sfp_module_initialized(phy, params) == 0)
10314 elink_sfp_module_detection(phy, params);
10315 else
10316 ELINK_DEBUG_P0(cb, "SFP+ module is not initialized\n");
10317
10318 /* Reconfigure link speed based on module type limitations */
10319 elink_8727_config_speed(phy, params);
10320 }
10321
10322 ELINK_DEBUG_P1(cb, "8727 RX_ALARM_STATUS 0x%x\n",
10323 rx_alarm_status);
10324 /* No need to check link status in case of module plugged in/out */
10325 }
10326
elink_8727_read_status(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)10327 static u8 elink_8727_read_status(struct elink_phy *phy,
10328 struct elink_params *params,
10329 struct elink_vars *vars)
10330
10331 {
10332 struct elink_dev *cb = params->cb;
10333 u8 link_up = 0;
10334 u16 link_status = 0;
10335 u16 rx_alarm_status, lasi_ctrl, val1;
10336
10337 /* If PHY is not initialized, do not check link status */
10338 elink_cl45_read(cb, phy,
10339 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,
10340 &lasi_ctrl);
10341 if (!lasi_ctrl)
10342 return 0;
10343
10344 /* Check the LASI on Rx */
10345 elink_cl45_read(cb, phy,
10346 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT,
10347 &rx_alarm_status);
10348 vars->line_speed = 0;
10349 ELINK_DEBUG_P1(cb, "8727 RX_ALARM_STATUS 0x%x\n", rx_alarm_status);
10350
10351 elink_sfp_mask_fault(cb, phy, MDIO_PMA_LASI_TXSTAT,
10352 MDIO_PMA_LASI_TXCTRL);
10353
10354 elink_cl45_read(cb, phy,
10355 MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
10356
10357 ELINK_DEBUG_P1(cb, "8727 LASI status 0x%x\n", val1);
10358
10359 /* Clear MSG-OUT */
10360 elink_cl45_read(cb, phy,
10361 MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
10362
10363 /* If a module is present and there is need to check
10364 * for over current
10365 */
10366 if (!(phy->flags & ELINK_FLAGS_NOC) && !(rx_alarm_status & (1<<5))) {
10367 /* Check over-current using 8727 GPIO0 input*/
10368 elink_cl45_read(cb, phy,
10369 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_GPIO_CTRL,
10370 &val1);
10371
10372 if ((val1 & (1<<8)) == 0) {
10373 #ifndef ELINK_AUX_POWER
10374 u8 oc_port = params->port;
10375 if (!CHIP_IS_E1X(params->chip_id))
10376 oc_port = PATH_ID(cb) + (params->port << 1);
10377 ELINK_DEBUG_P1(cb,
10378 "8727 Power fault has been detected on port %d\n",
10379 oc_port);
10380 elink_cb_event_log(cb, ELINK_LOG_ID_OVER_CURRENT, oc_port); //"Error: Power fault on Port %d has "
10381 // "been detected and the power to "
10382 // "that SFP+ module has been removed "
10383 // "to prevent failure of the card. "
10384 // "Please remove the SFP+ module and "
10385 // "restart the system to clear this "
10386 // "error.\n",
10387 #endif
10388 /* Disable all RX_ALARMs except for mod_abs */
10389 elink_cl45_write(cb, phy,
10390 MDIO_PMA_DEVAD,
10391 MDIO_PMA_LASI_RXCTRL, (1<<5));
10392
10393 elink_cl45_read(cb, phy,
10394 MDIO_PMA_DEVAD,
10395 MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
10396 /* Wait for module_absent_event */
10397 val1 |= (1<<8);
10398 elink_cl45_write(cb, phy,
10399 MDIO_PMA_DEVAD,
10400 MDIO_PMA_REG_PHY_IDENTIFIER, val1);
10401 /* Clear RX alarm */
10402 elink_cl45_read(cb, phy,
10403 MDIO_PMA_DEVAD,
10404 MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
10405 elink_8727_power_module(params->cb, phy, 0);
10406 return 0;
10407 }
10408 } /* Over current check */
10409
10410 /* When module absent bit is set, check module */
10411 if (rx_alarm_status & (1<<5)) {
10412 elink_8727_handle_mod_abs(phy, params);
10413 /* Enable all mod_abs and link detection bits */
10414 elink_cl45_write(cb, phy,
10415 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
10416 ((1<<5) | (1<<2)));
10417 }
10418
10419 if (!(phy->flags & ELINK_FLAGS_SFP_NOT_APPROVED)) {
10420 ELINK_DEBUG_P0(cb, "Enabling 8727 TX laser\n");
10421 elink_sfp_set_transmitter(params, phy, 1);
10422 } else {
10423 ELINK_DEBUG_P0(cb, "Tx is disabled\n");
10424 return 0;
10425 }
10426
10427 elink_cl45_read(cb, phy,
10428 MDIO_PMA_DEVAD,
10429 MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &link_status);
10430
10431 /* Bits 0..2 --> speed detected,
10432 * Bits 13..15--> link is down
10433 */
10434 if ((link_status & (1<<2)) && (!(link_status & (1<<15)))) {
10435 link_up = 1;
10436 vars->line_speed = ELINK_SPEED_10000;
10437 ELINK_DEBUG_P1(cb, "port %x: External link up in 10G\n",
10438 params->port);
10439 } else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
10440 link_up = 1;
10441 vars->line_speed = ELINK_SPEED_1000;
10442 ELINK_DEBUG_P1(cb, "port %x: External link up in 1G\n",
10443 params->port);
10444 } else {
10445 link_up = 0;
10446 ELINK_DEBUG_P1(cb, "port %x: External link is down\n",
10447 params->port);
10448 }
10449
10450 /* Capture 10G link fault. */
10451 if (vars->line_speed == ELINK_SPEED_10000) {
10452 elink_cl45_read(cb, phy, MDIO_PMA_DEVAD,
10453 MDIO_PMA_LASI_TXSTAT, &val1);
10454
10455 elink_cl45_read(cb, phy, MDIO_PMA_DEVAD,
10456 MDIO_PMA_LASI_TXSTAT, &val1);
10457
10458 if (val1 & (1<<0)) {
10459 vars->fault_detected = 1;
10460 }
10461 }
10462
10463 if (link_up) {
10464 elink_ext_phy_resolve_fc(phy, params, vars);
10465 vars->duplex = DUPLEX_FULL;
10466 ELINK_DEBUG_P1(cb, "duplex = 0x%x\n", vars->duplex);
10467 }
10468
10469 if ((ELINK_DUAL_MEDIA(params)) &&
10470 (phy->req_line_speed == ELINK_SPEED_1000)) {
10471 elink_cl45_read(cb, phy,
10472 MDIO_PMA_DEVAD,
10473 MDIO_PMA_REG_8727_PCS_GP, &val1);
10474 /* In case of dual-media board and 1G, power up the XAUI side,
10475 * otherwise power it down. For 10G it is done automatically
10476 */
10477 if (link_up)
10478 val1 &= ~(3<<10);
10479 else
10480 val1 |= (3<<10);
10481 elink_cl45_write(cb, phy,
10482 MDIO_PMA_DEVAD,
10483 MDIO_PMA_REG_8727_PCS_GP, val1);
10484 }
10485 return link_up;
10486 }
10487
elink_8727_link_reset(struct elink_phy * phy,struct elink_params * params)10488 static void elink_8727_link_reset(struct elink_phy *phy,
10489 struct elink_params *params)
10490 {
10491 #ifndef EXCLUDE_LINK_RESET
10492 struct elink_dev *cb = params->cb;
10493
10494 /* Enable/Disable PHY transmitter output */
10495 elink_set_disable_pmd_transmit(params, phy, 1);
10496
10497 /* Disable Transmitter */
10498 elink_sfp_set_transmitter(params, phy, 0);
10499 /* Clear LASI */
10500 elink_cl45_write(cb, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0);
10501
10502 #endif // EXCLUDE_LINK_RESET
10503 }
10504 #endif /* EXCLUDE_BCM8727_BCM8073 */
10505 #endif // EXCLUDE_NON_COMMON_INIT
10506
10507 /******************************************************************/
10508 /* BCM8481/BCM84823/BCM84833 PHY SECTION */
10509 /******************************************************************/
10510 #if !defined(EXCLUDE_BCM8481) || !defined(EXCLUDE_BCM84833)
elink_save_848xx_spirom_version(struct elink_phy * phy,struct elink_dev * cb,u8 port)10511 static void elink_save_848xx_spirom_version(struct elink_phy *phy,
10512 struct elink_dev *cb,
10513 u8 port)
10514 {
10515 #ifndef EXCLUDE_BCM8481
10516 u16 val, fw_ver2, cnt, i;
10517 static struct elink_reg_set reg_set[] = {
10518 {MDIO_PMA_DEVAD, 0xA819, 0x0014},
10519 {MDIO_PMA_DEVAD, 0xA81A, 0xc200},
10520 {MDIO_PMA_DEVAD, 0xA81B, 0x0000},
10521 {MDIO_PMA_DEVAD, 0xA81C, 0x0300},
10522 {MDIO_PMA_DEVAD, 0xA817, 0x0009}
10523 };
10524 #endif
10525 u16 fw_ver1;
10526
10527 if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
10528 (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
10529 elink_cl45_read(cb, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1);
10530 elink_save_spirom_version(cb, port, fw_ver1 & 0xfff,
10531 phy->ver_addr);
10532 } else {
10533 #ifndef EXCLUDE_BCM8481
10534 /* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */
10535 /* (1) set reg 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
10536 for (i = 0; i < ARRAY_SIZE(reg_set); i++)
10537 elink_cl45_write(cb, phy, reg_set[i].devad,
10538 reg_set[i].reg, reg_set[i].val);
10539
10540 for (cnt = 0; cnt < 100; cnt++) {
10541 elink_cl45_read(cb, phy, MDIO_PMA_DEVAD, 0xA818, &val);
10542 if (val & 1)
10543 break;
10544 USLEEP(cb, 5);
10545 }
10546 if (cnt == 100) {
10547 ELINK_DEBUG_P0(cb, "Unable to read 848xx "
10548 "phy fw version(1)\n");
10549 elink_save_spirom_version(cb, port, 0,
10550 phy->ver_addr);
10551 return;
10552 }
10553
10554
10555 /* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
10556 elink_cl45_write(cb, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000);
10557 elink_cl45_write(cb, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
10558 elink_cl45_write(cb, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A);
10559 for (cnt = 0; cnt < 100; cnt++) {
10560 elink_cl45_read(cb, phy, MDIO_PMA_DEVAD, 0xA818, &val);
10561 if (val & 1)
10562 break;
10563 USLEEP(cb, 5);
10564 }
10565 if (cnt == 100) {
10566 ELINK_DEBUG_P0(cb, "Unable to read 848xx phy fw "
10567 "version(2)\n");
10568 elink_save_spirom_version(cb, port, 0,
10569 phy->ver_addr);
10570 return;
10571 }
10572
10573 /* lower 16 bits of the register SPI_FW_STATUS */
10574 elink_cl45_read(cb, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
10575 /* upper 16 bits of register SPI_FW_STATUS */
10576 elink_cl45_read(cb, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
10577
10578 elink_save_spirom_version(cb, port, (fw_ver2<<16) | fw_ver1,
10579 phy->ver_addr);
10580 #endif /* EXCLUDE_BCM8481 */
10581 }
10582
10583 }
10584 #ifndef EXCLUDE_NON_COMMON_INIT
elink_848xx_set_led(struct elink_dev * cb,struct elink_phy * phy)10585 static void elink_848xx_set_led(struct elink_dev *cb,
10586 struct elink_phy *phy)
10587 {
10588 u16 val, offset, i;
10589 static struct elink_reg_set reg_set[] = {
10590 {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0080},
10591 {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0x0018},
10592 {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x0006},
10593 {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_BLINK, 0x0000},
10594 {MDIO_PMA_DEVAD, MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH,
10595 MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ},
10596 {MDIO_AN_DEVAD, 0xFFFB, 0xFFFD}
10597 };
10598 /* PHYC_CTL_LED_CTL */
10599 elink_cl45_read(cb, phy,
10600 MDIO_PMA_DEVAD,
10601 MDIO_PMA_REG_8481_LINK_SIGNAL, &val);
10602 val &= 0xFE00;
10603 val |= 0x0092;
10604
10605 elink_cl45_write(cb, phy,
10606 MDIO_PMA_DEVAD,
10607 MDIO_PMA_REG_8481_LINK_SIGNAL, val);
10608
10609 for (i = 0; i < ARRAY_SIZE(reg_set); i++)
10610 elink_cl45_write(cb, phy, reg_set[i].devad, reg_set[i].reg,
10611 reg_set[i].val);
10612
10613 if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
10614 (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834))
10615 offset = MDIO_PMA_REG_84833_CTL_LED_CTL_1;
10616 else
10617 offset = MDIO_PMA_REG_84823_CTL_LED_CTL_1;
10618
10619 /* stretch_en for LED3*/
10620 elink_cl45_read_or_write(cb, phy,
10621 MDIO_PMA_DEVAD, offset,
10622 MDIO_PMA_REG_84823_LED3_STRETCH_EN);
10623 }
10624
elink_848xx_specific_func(struct elink_phy * phy,struct elink_params * params,u32 action)10625 static void elink_848xx_specific_func(struct elink_phy *phy,
10626 struct elink_params *params,
10627 u32 action)
10628 {
10629 struct elink_dev *cb = params->cb;
10630 switch (action) {
10631 case ELINK_PHY_INIT:
10632 if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
10633 (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
10634 /* Save spirom version */
10635 elink_save_848xx_spirom_version(phy, cb, params->port);
10636 }
10637 /* This phy uses the NIG latch mechanism since link indication
10638 * arrives through its LED4 and not via its LASI signal, so we
10639 * get steady signal instead of clear on read
10640 */
10641 elink_bits_en(cb, NIG_REG_LATCH_BC_0 + params->port*4,
10642 1 << ELINK_NIG_LATCH_BC_ENABLE_MI_INT);
10643
10644 elink_848xx_set_led(cb, phy);
10645 break;
10646 }
10647 }
10648
elink_848xx_cmn_config_init(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)10649 static elink_status_t elink_848xx_cmn_config_init(struct elink_phy *phy,
10650 struct elink_params *params,
10651 struct elink_vars *vars)
10652 {
10653 struct elink_dev *cb = params->cb;
10654 u16 autoneg_val, an_1000_val, an_10_100_val;
10655
10656 elink_848xx_specific_func(phy, params, ELINK_PHY_INIT);
10657 elink_cl45_write(cb, phy,
10658 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0000);
10659
10660 /* set 1000 speed advertisement */
10661 elink_cl45_read(cb, phy,
10662 MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
10663 &an_1000_val);
10664
10665 elink_ext_phy_set_pause(params, phy, vars);
10666 elink_cl45_read(cb, phy,
10667 MDIO_AN_DEVAD,
10668 MDIO_AN_REG_8481_LEGACY_AN_ADV,
10669 &an_10_100_val);
10670 elink_cl45_read(cb, phy,
10671 MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_CTRL,
10672 &autoneg_val);
10673 /* Disable forced speed */
10674 autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13));
10675 an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8));
10676
10677 if (((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) &&
10678 (phy->speed_cap_mask &
10679 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
10680 (phy->req_line_speed == ELINK_SPEED_1000)) {
10681 an_1000_val |= (1<<8);
10682 autoneg_val |= (1<<9 | 1<<12);
10683 if (phy->req_duplex == DUPLEX_FULL)
10684 an_1000_val |= (1<<9);
10685 ELINK_DEBUG_P0(cb, "Advertising 1G\n");
10686 } else
10687 an_1000_val &= ~((1<<8) | (1<<9));
10688
10689 elink_cl45_write(cb, phy,
10690 MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
10691 an_1000_val);
10692
10693 /* Set 10/100 speed advertisement */
10694 if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG) {
10695 if (phy->speed_cap_mask &
10696 PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) {
10697 /* Enable autoneg and restart autoneg for legacy speeds
10698 */
10699 autoneg_val |= (1<<9 | 1<<12);
10700 an_10_100_val |= (1<<8);
10701 ELINK_DEBUG_P0(cb, "Advertising 100M-FD\n");
10702 }
10703
10704 if (phy->speed_cap_mask &
10705 PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) {
10706 /* Enable autoneg and restart autoneg for legacy speeds
10707 */
10708 autoneg_val |= (1<<9 | 1<<12);
10709 an_10_100_val |= (1<<7);
10710 ELINK_DEBUG_P0(cb, "Advertising 100M-HD\n");
10711 }
10712
10713 if ((phy->speed_cap_mask &
10714 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
10715 (phy->supported & ELINK_SUPPORTED_10baseT_Full)) {
10716 an_10_100_val |= (1<<6);
10717 autoneg_val |= (1<<9 | 1<<12);
10718 ELINK_DEBUG_P0(cb, "Advertising 10M-FD\n");
10719 }
10720
10721 if ((phy->speed_cap_mask &
10722 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) &&
10723 (phy->supported & ELINK_SUPPORTED_10baseT_Half)) {
10724 an_10_100_val |= (1<<5);
10725 autoneg_val |= (1<<9 | 1<<12);
10726 ELINK_DEBUG_P0(cb, "Advertising 10M-HD\n");
10727 }
10728 }
10729
10730 /* Only 10/100 are allowed to work in FORCE mode */
10731 if ((phy->req_line_speed == ELINK_SPEED_100) &&
10732 (phy->supported &
10733 (ELINK_SUPPORTED_100baseT_Half |
10734 ELINK_SUPPORTED_100baseT_Full))) {
10735 autoneg_val |= (1<<13);
10736 /* Enabled AUTO-MDIX when autoneg is disabled */
10737 elink_cl45_write(cb, phy,
10738 MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
10739 (1<<15 | 1<<9 | 7<<0));
10740 /* The PHY needs this set even for forced link. */
10741 an_10_100_val |= (1<<8) | (1<<7);
10742 ELINK_DEBUG_P0(cb, "Setting 100M force\n");
10743 }
10744 if ((phy->req_line_speed == ELINK_SPEED_10) &&
10745 (phy->supported &
10746 (ELINK_SUPPORTED_10baseT_Half |
10747 ELINK_SUPPORTED_10baseT_Full))) {
10748 /* Enabled AUTO-MDIX when autoneg is disabled */
10749 elink_cl45_write(cb, phy,
10750 MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
10751 (1<<15 | 1<<9 | 7<<0));
10752 ELINK_DEBUG_P0(cb, "Setting 10M force\n");
10753 }
10754
10755 elink_cl45_write(cb, phy,
10756 MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_AN_ADV,
10757 an_10_100_val);
10758
10759 if (phy->req_duplex == DUPLEX_FULL)
10760 autoneg_val |= (1<<8);
10761
10762 /* Always write this if this is not 84833/4.
10763 * For 84833/4, write it only when it's a forced speed.
10764 */
10765 if (((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
10766 (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) ||
10767 ((autoneg_val & (1<<12)) == 0))
10768 elink_cl45_write(cb, phy,
10769 MDIO_AN_DEVAD,
10770 MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val);
10771
10772 if (((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) &&
10773 (phy->speed_cap_mask &
10774 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
10775 (phy->req_line_speed == ELINK_SPEED_10000)) {
10776 ELINK_DEBUG_P0(cb, "Advertising 10G\n");
10777 /* Restart autoneg for 10G*/
10778
10779 elink_cl45_read_or_write(
10780 cb, phy,
10781 MDIO_AN_DEVAD,
10782 MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
10783 0x1000);
10784 elink_cl45_write(cb, phy,
10785 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
10786 0x3200);
10787 } else
10788 elink_cl45_write(cb, phy,
10789 MDIO_AN_DEVAD,
10790 MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
10791 1);
10792
10793 return ELINK_STATUS_OK;
10794 }
10795 #endif // EXCLUDE_NON_COMMON_INIT
10796 #endif // #if !defined(EXCLUDE_BCM8481) || !defined(EXCLUDE_BCM84833)
10797
10798 #ifndef EXCLUDE_BCM8481
10799 #ifndef EXCLUDE_NON_COMMON_INIT
elink_8481_config_init(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)10800 static elink_status_t elink_8481_config_init(struct elink_phy *phy,
10801 struct elink_params *params,
10802 struct elink_vars *vars)
10803 {
10804 struct elink_dev *cb = params->cb;
10805 /* Restore normal power mode*/
10806 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_2,
10807 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
10808
10809 /* HW reset */
10810 elink_ext_phy_hw_reset(cb, params->port);
10811 elink_wait_reset_complete(cb, phy, params);
10812
10813 elink_cl45_write(cb, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
10814 return elink_848xx_cmn_config_init(phy, params, vars);
10815 }
10816 #endif // #ifndef EXCLUDE_NON_COMMON_INIT
10817 #endif // EXCLUDE_BCM8481
10818
10819 #ifndef EXCLUDE_BCM84833
10820 #define PHY84833_CMDHDLR_WAIT 300
10821 #define PHY84833_CMDHDLR_MAX_ARGS 5
elink_84833_cmd_hdlr(struct elink_phy * phy,struct elink_params * params,u16 fw_cmd,u16 cmd_args[],int argc)10822 static elink_status_t elink_84833_cmd_hdlr(struct elink_phy *phy,
10823 struct elink_params *params, u16 fw_cmd,
10824 u16 cmd_args[], int argc)
10825 {
10826 int idx;
10827 u16 val;
10828 struct elink_dev *cb = params->cb;
10829 /* Write CMD_OPEN_OVERRIDE to STATUS reg */
10830 elink_cl45_write(cb, phy, MDIO_CTL_DEVAD,
10831 MDIO_84833_CMD_HDLR_STATUS,
10832 PHY84833_STATUS_CMD_OPEN_OVERRIDE);
10833 for (idx = 0; idx < PHY84833_CMDHDLR_WAIT; idx++) {
10834 elink_cl45_read(cb, phy, MDIO_CTL_DEVAD,
10835 MDIO_84833_CMD_HDLR_STATUS, &val);
10836 if (val == PHY84833_STATUS_CMD_OPEN_FOR_CMDS)
10837 break;
10838 MSLEEP(cb, 1);
10839 }
10840 if (idx >= PHY84833_CMDHDLR_WAIT) {
10841 ELINK_DEBUG_P0(cb, "FW cmd: FW not ready.\n");
10842 return ELINK_STATUS_ERROR;
10843 }
10844
10845 /* Prepare argument(s) and issue command */
10846 for (idx = 0; idx < argc; idx++) {
10847 elink_cl45_write(cb, phy, MDIO_CTL_DEVAD,
10848 MDIO_84833_CMD_HDLR_DATA1 + idx,
10849 cmd_args[idx]);
10850 }
10851 elink_cl45_write(cb, phy, MDIO_CTL_DEVAD,
10852 MDIO_84833_CMD_HDLR_COMMAND, fw_cmd);
10853 for (idx = 0; idx < PHY84833_CMDHDLR_WAIT; idx++) {
10854 elink_cl45_read(cb, phy, MDIO_CTL_DEVAD,
10855 MDIO_84833_CMD_HDLR_STATUS, &val);
10856 if ((val == PHY84833_STATUS_CMD_COMPLETE_PASS) ||
10857 (val == PHY84833_STATUS_CMD_COMPLETE_ERROR))
10858 break;
10859 MSLEEP(cb, 1);
10860 }
10861 if ((idx >= PHY84833_CMDHDLR_WAIT) ||
10862 (val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) {
10863 ELINK_DEBUG_P0(cb, "FW cmd failed.\n");
10864 return ELINK_STATUS_ERROR;
10865 }
10866 /* Gather returning data */
10867 for (idx = 0; idx < argc; idx++) {
10868 elink_cl45_read(cb, phy, MDIO_CTL_DEVAD,
10869 MDIO_84833_CMD_HDLR_DATA1 + idx,
10870 &cmd_args[idx]);
10871 }
10872 elink_cl45_write(cb, phy, MDIO_CTL_DEVAD,
10873 MDIO_84833_CMD_HDLR_STATUS,
10874 PHY84833_STATUS_CMD_CLEAR_COMPLETE);
10875 return ELINK_STATUS_OK;
10876 }
10877
10878 #ifndef EXCLUDE_NON_COMMON_INIT
elink_84833_pair_swap_cfg(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)10879 static elink_status_t elink_84833_pair_swap_cfg(struct elink_phy *phy,
10880 struct elink_params *params,
10881 struct elink_vars *vars)
10882 {
10883 u32 pair_swap;
10884 u16 data[PHY84833_CMDHDLR_MAX_ARGS];
10885 elink_status_t status;
10886 struct elink_dev *cb = params->cb;
10887
10888 /* Check for configuration. */
10889 pair_swap = REG_RD(cb, params->shmem_base +
10890 OFFSETOF(struct shmem_region,
10891 dev_info.port_hw_config[params->port].xgbt_phy_cfg)) &
10892 PORT_HW_CFG_RJ45_PAIR_SWAP_MASK;
10893
10894 if (pair_swap == 0)
10895 return ELINK_STATUS_OK;
10896
10897 /* Only the second argument is used for this command */
10898 data[1] = (u16)pair_swap;
10899
10900 status = elink_84833_cmd_hdlr(phy, params,
10901 PHY84833_CMD_SET_PAIR_SWAP, data, PHY84833_CMDHDLR_MAX_ARGS);
10902 if (status == ELINK_STATUS_OK)
10903 ELINK_DEBUG_P1(cb, "Pairswap OK, val=0x%x\n", data[1]);
10904
10905 return status;
10906 }
10907 #endif // #ifndef EXCLUDE_NON_COMMON_INIT
10908
elink_84833_get_reset_gpios(struct elink_dev * cb,u32 shmem_base_path[],u32 chip_id)10909 static u8 elink_84833_get_reset_gpios(struct elink_dev *cb,
10910 u32 shmem_base_path[],
10911 u32 chip_id)
10912 {
10913 u32 reset_pin[2];
10914 u32 idx;
10915 u8 reset_gpios;
10916 if (CHIP_IS_E3(chip_id)) {
10917 /* Assume that these will be GPIOs, not EPIOs. */
10918 for (idx = 0; idx < 2; idx++) {
10919 /* Map config param to register bit. */
10920 reset_pin[idx] = REG_RD(cb, shmem_base_path[idx] +
10921 OFFSETOF(struct shmem_region,
10922 dev_info.port_hw_config[0].e3_cmn_pin_cfg));
10923 reset_pin[idx] = (reset_pin[idx] &
10924 PORT_HW_CFG_E3_PHY_RESET_MASK) >>
10925 PORT_HW_CFG_E3_PHY_RESET_SHIFT;
10926 reset_pin[idx] -= PIN_CFG_GPIO0_P0;
10927 reset_pin[idx] = (1 << reset_pin[idx]);
10928 }
10929 reset_gpios = (u8)(reset_pin[0] | reset_pin[1]);
10930 } else {
10931 /* E2, look from diff place of shmem. */
10932 for (idx = 0; idx < 2; idx++) {
10933 reset_pin[idx] = REG_RD(cb, shmem_base_path[idx] +
10934 OFFSETOF(struct shmem_region,
10935 dev_info.port_hw_config[0].default_cfg));
10936 reset_pin[idx] &= PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK;
10937 reset_pin[idx] -= PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0;
10938 reset_pin[idx] >>= PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT;
10939 reset_pin[idx] = (1 << reset_pin[idx]);
10940 }
10941 reset_gpios = (u8)(reset_pin[0] | reset_pin[1]);
10942 }
10943
10944 return reset_gpios;
10945 }
10946
10947 #ifndef EXCLUDE_NON_COMMON_INIT
elink_84833_hw_reset_phy(struct elink_phy * phy,struct elink_params * params)10948 static elink_status_t elink_84833_hw_reset_phy(struct elink_phy *phy,
10949 struct elink_params *params)
10950 {
10951 struct elink_dev *cb = params->cb;
10952 u8 reset_gpios;
10953 u32 other_shmem_base_addr = REG_RD(cb, params->shmem2_base +
10954 OFFSETOF(struct shmem2_region,
10955 other_shmem_base_addr));
10956
10957 u32 shmem_base_path[2];
10958
10959 /* Work around for 84833 LED failure inside RESET status */
10960 elink_cl45_write(cb, phy, MDIO_AN_DEVAD,
10961 MDIO_AN_REG_8481_LEGACY_MII_CTRL,
10962 MDIO_AN_REG_8481_MII_CTRL_FORCE_1G);
10963 elink_cl45_write(cb, phy, MDIO_AN_DEVAD,
10964 MDIO_AN_REG_8481_1G_100T_EXT_CTRL,
10965 MIDO_AN_REG_8481_EXT_CTRL_FORCE_LEDS_OFF);
10966
10967 shmem_base_path[0] = params->shmem_base;
10968 shmem_base_path[1] = other_shmem_base_addr;
10969
10970 reset_gpios = elink_84833_get_reset_gpios(cb, shmem_base_path,
10971 params->chip_id);
10972
10973 #ifndef EDEBUG
10974 ELINK_SET_MULT_GPIO(cb, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
10975 USLEEP(cb, 10);
10976 ELINK_DEBUG_P1(cb, "84833 hw reset on pin values 0x%x\n",
10977 reset_gpios);
10978 #endif // EDEBUG
10979
10980 return ELINK_STATUS_OK;
10981 }
10982 #endif // EXCLUDE_NON_COMMON_INIT
10983 #endif // #ifndef EXCLUDE_BCM84833
10984
10985 #ifndef EXCLUDE_NON_COMMON_INIT
10986 #ifndef EXCLUDE_WARPCORE
elink_8483x_disable_eee(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)10987 static elink_status_t elink_8483x_disable_eee(struct elink_phy *phy,
10988 struct elink_params *params,
10989 struct elink_vars *vars)
10990 {
10991 elink_status_t rc;
10992 #if defined(ELINK_DEBUG)
10993 struct elink_dev *cb = params->cb;
10994 #endif
10995 u16 cmd_args = 0;
10996
10997 ELINK_DEBUG_P0(cb, "Don't Advertise 10GBase-T EEE\n");
10998
10999 /* Prevent Phy from working in EEE and advertising it */
11000 rc = elink_84833_cmd_hdlr(phy, params,
11001 PHY84833_CMD_SET_EEE_MODE, &cmd_args, 1);
11002 if (rc != ELINK_STATUS_OK) {
11003 ELINK_DEBUG_P0(cb, "EEE disable failed.\n");
11004 return rc;
11005 }
11006
11007 return elink_eee_disable(phy, params, vars);
11008 }
11009
elink_8483x_enable_eee(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)11010 static elink_status_t elink_8483x_enable_eee(struct elink_phy *phy,
11011 struct elink_params *params,
11012 struct elink_vars *vars)
11013 {
11014 elink_status_t rc;
11015 #ifdef ELINK_DEBUG
11016 struct elink_dev *cb = params->cb;
11017 #endif
11018 u16 cmd_args = 1;
11019
11020 rc = elink_84833_cmd_hdlr(phy, params,
11021 PHY84833_CMD_SET_EEE_MODE, &cmd_args, 1);
11022 if (rc != ELINK_STATUS_OK) {
11023 ELINK_DEBUG_P0(cb, "EEE enable failed.\n");
11024 return rc;
11025 }
11026
11027 return elink_eee_advertise(phy, params, vars, SHMEM_EEE_10G_ADV);
11028 }
11029 #endif /* #ifndef EXCLUDE_WARPCORE */
11030
11031 #if !defined(EXCLUDE_BCM8481) || !defined(EXCLUDE_BCM84833)
11032 #define PHY84833_CONSTANT_LATENCY 1193
elink_848x3_config_init(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)11033 static elink_status_t elink_848x3_config_init(struct elink_phy *phy,
11034 struct elink_params *params,
11035 struct elink_vars *vars)
11036 {
11037 struct elink_dev *cb = params->cb;
11038 u8 port, initialize = 1;
11039 u16 val;
11040 u32 actual_phy_selection;
11041 #ifndef EXCLUDE_BCM84833
11042 u16 cmd_args[PHY84833_CMDHDLR_MAX_ARGS];
11043 #endif // EXCLUDE_BCM84833
11044 elink_status_t rc = ELINK_STATUS_OK;
11045
11046 MSLEEP(cb, 1);
11047
11048 if (!(CHIP_IS_E1X(params->chip_id)))
11049 port = PATH_ID(cb);
11050 else
11051 port = params->port;
11052
11053 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
11054 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_3,
11055 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
11056 port);
11057 } else {
11058 /* MDIO reset */
11059 elink_cl45_write(cb, phy,
11060 MDIO_PMA_DEVAD,
11061 MDIO_PMA_REG_CTRL, 0x8000);
11062 }
11063
11064 elink_wait_reset_complete(cb, phy, params);
11065
11066 /* Wait for GPHY to come out of reset */
11067 MSLEEP(cb, 50);
11068 #ifndef EXCLUDE_BCM84833
11069 if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
11070 (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
11071 #endif // EXCLUDE_BCM84833
11072 #ifndef EXCLUDE_BCM8481
11073 /* BCM84823 requires that XGXS links up first @ 10G for normal
11074 * behavior.
11075 */
11076 u16 temp;
11077 temp = vars->line_speed;
11078 vars->line_speed = ELINK_SPEED_10000;
11079 elink_set_autoneg(¶ms->phy[ELINK_INT_PHY], params, vars, 0);
11080 elink_program_serdes(¶ms->phy[ELINK_INT_PHY], params, vars);
11081 vars->line_speed = temp;
11082 #endif // EXCLUDE_BCM8481
11083 #ifndef EXCLUDE_BCM84833
11084 }
11085 #endif /* Set dual-media configuration according to configuration */
11086
11087 elink_cl45_read(cb, phy, MDIO_CTL_DEVAD,
11088 MDIO_CTL_REG_84823_MEDIA, &val);
11089 val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
11090 MDIO_CTL_REG_84823_MEDIA_LINE_MASK |
11091 MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN |
11092 MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK |
11093 MDIO_CTL_REG_84823_MEDIA_FIBER_1G);
11094
11095 if (CHIP_IS_E3(params->chip_id)) {
11096 val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
11097 MDIO_CTL_REG_84823_MEDIA_LINE_MASK);
11098 } else {
11099 val |= (MDIO_CTL_REG_84823_CTRL_MAC_XFI |
11100 MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L);
11101 }
11102
11103 actual_phy_selection = elink_phy_selection(params);
11104
11105 switch (actual_phy_selection) {
11106 case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
11107 /* Do nothing. Essentially this is like the priority copper */
11108 break;
11109 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
11110 val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER;
11111 break;
11112 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
11113 val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER;
11114 break;
11115 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
11116 /* Do nothing here. The first PHY won't be initialized at all */
11117 break;
11118 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
11119 val |= MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN;
11120 initialize = 0;
11121 break;
11122 }
11123 if (params->phy[ELINK_EXT_PHY2].req_line_speed == ELINK_SPEED_1000)
11124 val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G;
11125
11126 elink_cl45_write(cb, phy, MDIO_CTL_DEVAD,
11127 MDIO_CTL_REG_84823_MEDIA, val);
11128 ELINK_DEBUG_P2(cb, "Multi_phy config = 0x%x, Media control = 0x%x\n",
11129 params->multi_phy_config, val);
11130
11131 #ifndef EXCLUDE_BCM84833
11132 if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
11133 (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
11134 elink_84833_pair_swap_cfg(phy, params, vars);
11135
11136 /* Keep AutogrEEEn disabled. */
11137 cmd_args[0] = 0x0;
11138 cmd_args[1] = 0x0;
11139 cmd_args[2] = PHY84833_CONSTANT_LATENCY + 1;
11140 cmd_args[3] = PHY84833_CONSTANT_LATENCY;
11141 rc = elink_84833_cmd_hdlr(phy, params,
11142 PHY84833_CMD_SET_EEE_MODE, cmd_args,
11143 PHY84833_CMDHDLR_MAX_ARGS);
11144 if (rc != ELINK_STATUS_OK)
11145 ELINK_DEBUG_P0(cb, "Cfg AutogrEEEn failed.\n");
11146 }
11147 #endif // #ifndef EXCLUDE_BCM84833
11148 if (initialize)
11149 rc = elink_848xx_cmn_config_init(phy, params, vars);
11150 #ifdef ELINK_ENHANCEMENTS
11151 else
11152 elink_save_848xx_spirom_version(phy, cb, params->port);
11153 #endif // ELINK_ENHANCEMENTS
11154 /* 84833 PHY has a better feature and doesn't need to support this. */
11155 #ifndef EXCLUDE_BCM8481
11156 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
11157 u32 cms_enable = REG_RD(cb, params->shmem_base +
11158 OFFSETOF(struct shmem_region,
11159 dev_info.port_hw_config[params->port].default_cfg)) &
11160 PORT_HW_CFG_ENABLE_CMS_MASK;
11161
11162 elink_cl45_read(cb, phy, MDIO_CTL_DEVAD,
11163 MDIO_CTL_REG_84823_USER_CTRL_REG, &val);
11164 if (cms_enable)
11165 val |= MDIO_CTL_REG_84823_USER_CTRL_CMS;
11166 else
11167 val &= ~MDIO_CTL_REG_84823_USER_CTRL_CMS;
11168 elink_cl45_write(cb, phy, MDIO_CTL_DEVAD,
11169 MDIO_CTL_REG_84823_USER_CTRL_REG, val);
11170 }
11171 #endif /* EXCLUDE_BCM8481 */
11172
11173 #ifndef EXCLUDE_WARPCORE
11174 elink_cl45_read(cb, phy, MDIO_CTL_DEVAD,
11175 MDIO_84833_TOP_CFG_FW_REV, &val);
11176
11177 /* Configure EEE support */
11178 if ((val >= MDIO_84833_TOP_CFG_FW_EEE) &&
11179 (val != MDIO_84833_TOP_CFG_FW_NO_EEE) &&
11180 elink_eee_has_cap(params)) {
11181 rc = elink_eee_initial_config(params, vars, SHMEM_EEE_10G_ADV);
11182 if (rc != ELINK_STATUS_OK) {
11183 ELINK_DEBUG_P0(cb, "Failed to configure EEE timers\n");
11184 elink_8483x_disable_eee(phy, params, vars);
11185 return rc;
11186 }
11187
11188 if ((phy->req_duplex == DUPLEX_FULL) &&
11189 (params->eee_mode & ELINK_EEE_MODE_ADV_LPI) &&
11190 (elink_eee_calc_timer(params) ||
11191 !(params->eee_mode & ELINK_EEE_MODE_ENABLE_LPI)))
11192 rc = elink_8483x_enable_eee(phy, params, vars);
11193 else
11194 rc = elink_8483x_disable_eee(phy, params, vars);
11195 if (rc != ELINK_STATUS_OK) {
11196 ELINK_DEBUG_P0(cb, "Failed to set EEE advertisement\n");
11197 return rc;
11198 }
11199 } else {
11200 vars->eee_status &= ~SHMEM_EEE_SUPPORTED_MASK;
11201 }
11202 #endif /* #ifndef EXCLUDE_WARPCORE */
11203
11204 #ifndef EXCLUDE_BCM84833
11205 if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
11206 (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
11207 /* Bring PHY out of super isolate mode as the final step. */
11208 elink_cl45_read_and_write(cb, phy,
11209 MDIO_CTL_DEVAD,
11210 MDIO_84833_TOP_CFG_XGPHY_STRAP1,
11211 (u16)~MDIO_84833_SUPER_ISOLATE);
11212 }
11213 #endif /* #ifndef EXCLUDE_BCM84833 */
11214 return rc;
11215 }
11216
elink_848xx_read_status(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)11217 static u8 elink_848xx_read_status(struct elink_phy *phy,
11218 struct elink_params *params,
11219 struct elink_vars *vars)
11220 {
11221 struct elink_dev *cb = params->cb;
11222 u16 val, val1, val2;
11223 u8 link_up = 0;
11224
11225
11226 /* Check 10G-BaseT link status */
11227 /* Check PMD signal ok */
11228 elink_cl45_read(cb, phy,
11229 MDIO_AN_DEVAD, 0xFFFA, &val1);
11230 elink_cl45_read(cb, phy,
11231 MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL,
11232 &val2);
11233 ELINK_DEBUG_P1(cb, "BCM848xx: PMD_SIGNAL 1.a811 = 0x%x\n", val2);
11234
11235 /* Check link 10G */
11236 if (val2 & (1<<11)) {
11237 vars->line_speed = ELINK_SPEED_10000;
11238 vars->duplex = DUPLEX_FULL;
11239 link_up = 1;
11240 elink_ext_phy_10G_an_resolve(cb, phy, vars);
11241 } else { /* Check Legacy speed link */
11242 u16 legacy_status, legacy_speed;
11243
11244 /* Enable expansion register 0x42 (Operation mode status) */
11245 elink_cl45_write(cb, phy,
11246 MDIO_AN_DEVAD,
11247 MDIO_AN_REG_8481_EXPANSION_REG_ACCESS, 0xf42);
11248
11249 /* Get legacy speed operation status */
11250 elink_cl45_read(cb, phy,
11251 MDIO_AN_DEVAD,
11252 MDIO_AN_REG_8481_EXPANSION_REG_RD_RW,
11253 &legacy_status);
11254
11255 ELINK_DEBUG_P1(cb, "Legacy speed status = 0x%x\n",
11256 legacy_status);
11257 link_up = ((legacy_status & (1<<11)) == (1<<11));
11258 legacy_speed = (legacy_status & (3<<9));
11259 if (legacy_speed == (0<<9))
11260 vars->line_speed = ELINK_SPEED_10;
11261 else if (legacy_speed == (1<<9))
11262 vars->line_speed = ELINK_SPEED_100;
11263 else if (legacy_speed == (2<<9))
11264 vars->line_speed = ELINK_SPEED_1000;
11265 else { /* Should not happen: Treat as link down */
11266 vars->line_speed = 0;
11267 link_up = 0;
11268 }
11269
11270 #ifndef BNX2X_UPSTREAM /* ! BNX2X_UPSTREAM */
11271 if (params->feature_config_flags &
11272 ELINK_FEATURE_CONFIG_IEEE_PHY_TEST) {
11273 u16 mii_ctrl;
11274
11275 elink_cl45_read(cb, phy,
11276 MDIO_AN_DEVAD,
11277 MDIO_AN_REG_8481_LEGACY_MII_CTRL,
11278 &mii_ctrl);
11279 /* For IEEE testing, check for a fake link. */
11280 link_up |= ((mii_ctrl & 0x3040) == 0x40);
11281 }
11282 #endif
11283
11284 if (link_up) {
11285 if (legacy_status & (1<<8))
11286 vars->duplex = DUPLEX_FULL;
11287 else
11288 vars->duplex = DUPLEX_HALF;
11289
11290 ELINK_DEBUG_P2(cb,
11291 "Link is up in %dMbps, is_duplex_full= %d\n",
11292 vars->line_speed,
11293 (vars->duplex == DUPLEX_FULL));
11294 /* Check legacy speed AN resolution */
11295 elink_cl45_read(cb, phy,
11296 MDIO_AN_DEVAD,
11297 MDIO_AN_REG_8481_LEGACY_MII_STATUS,
11298 &val);
11299 if (val & (1<<5))
11300 vars->link_status |=
11301 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
11302 elink_cl45_read(cb, phy,
11303 MDIO_AN_DEVAD,
11304 MDIO_AN_REG_8481_LEGACY_AN_EXPANSION,
11305 &val);
11306 if ((val & (1<<0)) == 0)
11307 vars->link_status |=
11308 LINK_STATUS_PARALLEL_DETECTION_USED;
11309 }
11310 }
11311 if (link_up) {
11312 ELINK_DEBUG_P1(cb, "BCM848x3: link speed is %d\n",
11313 vars->line_speed);
11314 elink_ext_phy_resolve_fc(phy, params, vars);
11315
11316 /* Read LP advertised speeds */
11317 elink_cl45_read(cb, phy, MDIO_AN_DEVAD,
11318 MDIO_AN_REG_CL37_FC_LP, &val);
11319 if (val & (1<<5))
11320 vars->link_status |=
11321 LINK_STATUS_LINK_PARTNER_10THD_CAPABLE;
11322 if (val & (1<<6))
11323 vars->link_status |=
11324 LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE;
11325 if (val & (1<<7))
11326 vars->link_status |=
11327 LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE;
11328 if (val & (1<<8))
11329 vars->link_status |=
11330 LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE;
11331 if (val & (1<<9))
11332 vars->link_status |=
11333 LINK_STATUS_LINK_PARTNER_100T4_CAPABLE;
11334
11335 elink_cl45_read(cb, phy, MDIO_AN_DEVAD,
11336 MDIO_AN_REG_1000T_STATUS, &val);
11337
11338 if (val & (1<<10))
11339 vars->link_status |=
11340 LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE;
11341 if (val & (1<<11))
11342 vars->link_status |=
11343 LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
11344
11345 elink_cl45_read(cb, phy, MDIO_AN_DEVAD,
11346 MDIO_AN_REG_MASTER_STATUS, &val);
11347
11348 if (val & (1<<11))
11349 vars->link_status |=
11350 LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
11351
11352 #if (!defined EXCLUDE_BCM84833) && (!defined EXCLUDE_WARPCORE)
11353 /* Determine if EEE was negotiated */
11354 if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
11355 (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834))
11356 elink_eee_an_resolve(phy, params, vars);
11357 #endif /* #ifndef EXCLUDE_WARPCORE */
11358 }
11359
11360 return link_up;
11361 }
11362
elink_848xx_format_ver(u32 raw_ver,u8 * str,u16 * len)11363 static elink_status_t elink_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
11364 {
11365 elink_status_t status = ELINK_STATUS_OK;
11366 #ifdef ELINK_ENHANCEMENTS
11367 u32 spirom_ver;
11368 spirom_ver = ((raw_ver & 0xF80) >> 7) << 16 | (raw_ver & 0x7F);
11369 status = elink_format_ver(spirom_ver, str, len);
11370 #endif // ELINK_ENHANCEMENTS
11371 return status;
11372 }
11373
11374 #ifndef EXCLUDE_BCM8481
elink_8481_hw_reset(struct elink_phy * phy,struct elink_params * params)11375 static void elink_8481_hw_reset(struct elink_phy *phy,
11376 struct elink_params *params)
11377 {
11378 ELINK_SET_GPIO(params->cb, MISC_REGISTERS_GPIO_1,
11379 MISC_REGISTERS_GPIO_OUTPUT_LOW, 0);
11380 ELINK_SET_GPIO(params->cb, MISC_REGISTERS_GPIO_1,
11381 MISC_REGISTERS_GPIO_OUTPUT_LOW, 1);
11382 }
11383
elink_8481_link_reset(struct elink_phy * phy,struct elink_params * params)11384 static void elink_8481_link_reset(struct elink_phy *phy,
11385 struct elink_params *params)
11386 {
11387 #ifndef EXCLUDE_LINK_RESET
11388 elink_cl45_write(params->cb, phy,
11389 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
11390 elink_cl45_write(params->cb, phy,
11391 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1);
11392 #endif // EXCLUDE_LINK_RESET
11393 }
11394 #endif // #ifndef EXCLUDE_8481
11395
elink_848x3_link_reset(struct elink_phy * phy,struct elink_params * params)11396 static void elink_848x3_link_reset(struct elink_phy *phy,
11397 struct elink_params *params)
11398 {
11399 struct elink_dev *cb = params->cb;
11400 u8 port;
11401 u16 val16;
11402
11403 if (!(CHIP_IS_E1X(params->chip_id)))
11404 port = PATH_ID(cb);
11405 else
11406 port = params->port;
11407
11408 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
11409 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_3,
11410 MISC_REGISTERS_GPIO_OUTPUT_LOW,
11411 port);
11412 } else {
11413 elink_cl45_read(cb, phy,
11414 MDIO_CTL_DEVAD,
11415 MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val16);
11416 val16 |= MDIO_84833_SUPER_ISOLATE;
11417 elink_cl45_write(cb, phy,
11418 MDIO_CTL_DEVAD,
11419 MDIO_84833_TOP_CFG_XGPHY_STRAP1, val16);
11420 }
11421 }
11422
elink_848xx_set_link_led(struct elink_phy * phy,struct elink_params * params,u8 mode)11423 static void elink_848xx_set_link_led(struct elink_phy *phy,
11424 struct elink_params *params, u8 mode)
11425 {
11426 struct elink_dev *cb = params->cb;
11427 u16 val;
11428 #ifndef ELINK_AUX_POWER
11429 u8 port;
11430
11431 if (!(CHIP_IS_E1X(params->chip_id)))
11432 port = PATH_ID(cb);
11433 else
11434 port = params->port;
11435 #endif
11436 switch (mode) {
11437 case ELINK_LED_MODE_OFF:
11438
11439 ELINK_DEBUG_P1(cb, "Port 0x%x: LED MODE OFF\n", port);
11440
11441 if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
11442 SHARED_HW_CFG_LED_EXTPHY1) {
11443
11444 /* Set LED masks */
11445 elink_cl45_write(cb, phy,
11446 MDIO_PMA_DEVAD,
11447 MDIO_PMA_REG_8481_LED1_MASK,
11448 0x0);
11449
11450 elink_cl45_write(cb, phy,
11451 MDIO_PMA_DEVAD,
11452 MDIO_PMA_REG_8481_LED2_MASK,
11453 0x0);
11454
11455 elink_cl45_write(cb, phy,
11456 MDIO_PMA_DEVAD,
11457 MDIO_PMA_REG_8481_LED3_MASK,
11458 0x0);
11459
11460 elink_cl45_write(cb, phy,
11461 MDIO_PMA_DEVAD,
11462 MDIO_PMA_REG_8481_LED5_MASK,
11463 0x0);
11464
11465 } else {
11466 elink_cl45_write(cb, phy,
11467 MDIO_PMA_DEVAD,
11468 MDIO_PMA_REG_8481_LED1_MASK,
11469 0x0);
11470 }
11471 break;
11472 case ELINK_LED_MODE_FRONT_PANEL_OFF:
11473
11474 ELINK_DEBUG_P1(cb, "Port 0x%x: LED MODE FRONT PANEL OFF\n",
11475 port);
11476
11477 if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
11478 SHARED_HW_CFG_LED_EXTPHY1) {
11479
11480 /* Set LED masks */
11481 elink_cl45_write(cb, phy,
11482 MDIO_PMA_DEVAD,
11483 MDIO_PMA_REG_8481_LED1_MASK,
11484 0x0);
11485
11486 elink_cl45_write(cb, phy,
11487 MDIO_PMA_DEVAD,
11488 MDIO_PMA_REG_8481_LED2_MASK,
11489 0x0);
11490
11491 elink_cl45_write(cb, phy,
11492 MDIO_PMA_DEVAD,
11493 MDIO_PMA_REG_8481_LED3_MASK,
11494 0x0);
11495
11496 elink_cl45_write(cb, phy,
11497 MDIO_PMA_DEVAD,
11498 MDIO_PMA_REG_8481_LED5_MASK,
11499 0x20);
11500
11501 } else {
11502 elink_cl45_write(cb, phy,
11503 MDIO_PMA_DEVAD,
11504 MDIO_PMA_REG_8481_LED1_MASK,
11505 0x0);
11506 if (phy->type ==
11507 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) {
11508 /* Disable MI_INT interrupt before setting LED4
11509 * source to constant off.
11510 */
11511 if (REG_RD(cb, NIG_REG_MASK_INTERRUPT_PORT0 +
11512 params->port*4) &
11513 ELINK_NIG_MASK_MI_INT) {
11514 params->link_flags |=
11515 ELINK_LINK_FLAGS_INT_DISABLED;
11516
11517 elink_bits_dis(
11518 cb,
11519 NIG_REG_MASK_INTERRUPT_PORT0 +
11520 params->port*4,
11521 ELINK_NIG_MASK_MI_INT);
11522 }
11523 elink_cl45_write(cb, phy,
11524 MDIO_PMA_DEVAD,
11525 MDIO_PMA_REG_8481_SIGNAL_MASK,
11526 0x0);
11527 }
11528 }
11529 break;
11530 case ELINK_LED_MODE_ON:
11531
11532 ELINK_DEBUG_P1(cb, "Port 0x%x: LED MODE ON\n", port);
11533
11534 if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
11535 SHARED_HW_CFG_LED_EXTPHY1) {
11536 /* Set control reg */
11537 elink_cl45_read(cb, phy,
11538 MDIO_PMA_DEVAD,
11539 MDIO_PMA_REG_8481_LINK_SIGNAL,
11540 &val);
11541 val &= 0x8000;
11542 val |= 0x2492;
11543
11544 elink_cl45_write(cb, phy,
11545 MDIO_PMA_DEVAD,
11546 MDIO_PMA_REG_8481_LINK_SIGNAL,
11547 val);
11548
11549 /* Set LED masks */
11550 elink_cl45_write(cb, phy,
11551 MDIO_PMA_DEVAD,
11552 MDIO_PMA_REG_8481_LED1_MASK,
11553 0x0);
11554
11555 elink_cl45_write(cb, phy,
11556 MDIO_PMA_DEVAD,
11557 MDIO_PMA_REG_8481_LED2_MASK,
11558 0x20);
11559
11560 elink_cl45_write(cb, phy,
11561 MDIO_PMA_DEVAD,
11562 MDIO_PMA_REG_8481_LED3_MASK,
11563 0x20);
11564
11565 elink_cl45_write(cb, phy,
11566 MDIO_PMA_DEVAD,
11567 MDIO_PMA_REG_8481_LED5_MASK,
11568 0x0);
11569 } else {
11570 elink_cl45_write(cb, phy,
11571 MDIO_PMA_DEVAD,
11572 MDIO_PMA_REG_8481_LED1_MASK,
11573 0x20);
11574 if (phy->type ==
11575 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) {
11576 /* Disable MI_INT interrupt before setting LED4
11577 * source to constant on.
11578 */
11579 if (REG_RD(cb, NIG_REG_MASK_INTERRUPT_PORT0 +
11580 params->port*4) &
11581 ELINK_NIG_MASK_MI_INT) {
11582 params->link_flags |=
11583 ELINK_LINK_FLAGS_INT_DISABLED;
11584
11585 elink_bits_dis(
11586 cb,
11587 NIG_REG_MASK_INTERRUPT_PORT0 +
11588 params->port*4,
11589 ELINK_NIG_MASK_MI_INT);
11590 }
11591 elink_cl45_write(cb, phy,
11592 MDIO_PMA_DEVAD,
11593 MDIO_PMA_REG_8481_SIGNAL_MASK,
11594 0x20);
11595 }
11596 }
11597 break;
11598
11599 case ELINK_LED_MODE_OPER:
11600
11601 ELINK_DEBUG_P1(cb, "Port 0x%x: LED MODE OPER\n", port);
11602
11603 if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
11604 SHARED_HW_CFG_LED_EXTPHY1) {
11605
11606 /* Set control reg */
11607 elink_cl45_read(cb, phy,
11608 MDIO_PMA_DEVAD,
11609 MDIO_PMA_REG_8481_LINK_SIGNAL,
11610 &val);
11611
11612 if (!((val &
11613 MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK)
11614 >> MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT)) {
11615 ELINK_DEBUG_P0(cb, "Setting LINK_SIGNAL\n");
11616 elink_cl45_write(cb, phy,
11617 MDIO_PMA_DEVAD,
11618 MDIO_PMA_REG_8481_LINK_SIGNAL,
11619 0xa492);
11620 }
11621
11622 /* Set LED masks */
11623 elink_cl45_write(cb, phy,
11624 MDIO_PMA_DEVAD,
11625 MDIO_PMA_REG_8481_LED1_MASK,
11626 0x10);
11627
11628 elink_cl45_write(cb, phy,
11629 MDIO_PMA_DEVAD,
11630 MDIO_PMA_REG_8481_LED2_MASK,
11631 0x80);
11632
11633 elink_cl45_write(cb, phy,
11634 MDIO_PMA_DEVAD,
11635 MDIO_PMA_REG_8481_LED3_MASK,
11636 0x98);
11637
11638 elink_cl45_write(cb, phy,
11639 MDIO_PMA_DEVAD,
11640 MDIO_PMA_REG_8481_LED5_MASK,
11641 0x40);
11642
11643 } else {
11644 /* EXTPHY2 LED mode indicate that the 100M/1G/10G LED
11645 * sources are all wired through LED1, rather than only
11646 * 10G in other modes.
11647 */
11648 val = ((params->hw_led_mode <<
11649 SHARED_HW_CFG_LED_MODE_SHIFT) ==
11650 SHARED_HW_CFG_LED_EXTPHY2) ? 0x98 : 0x80;
11651
11652 elink_cl45_write(cb, phy,
11653 MDIO_PMA_DEVAD,
11654 MDIO_PMA_REG_8481_LED1_MASK,
11655 val);
11656
11657 /* Tell LED3 to blink on source */
11658 elink_cl45_read(cb, phy,
11659 MDIO_PMA_DEVAD,
11660 MDIO_PMA_REG_8481_LINK_SIGNAL,
11661 &val);
11662 val &= ~(7<<6);
11663 val |= (1<<6); /* A83B[8:6]= 1 */
11664 elink_cl45_write(cb, phy,
11665 MDIO_PMA_DEVAD,
11666 MDIO_PMA_REG_8481_LINK_SIGNAL,
11667 val);
11668 if (phy->type ==
11669 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) {
11670 /* Restore LED4 source to external link,
11671 * and re-enable interrupts.
11672 */
11673 elink_cl45_write(cb, phy,
11674 MDIO_PMA_DEVAD,
11675 MDIO_PMA_REG_8481_SIGNAL_MASK,
11676 0x40);
11677 if (params->link_flags &
11678 ELINK_LINK_FLAGS_INT_DISABLED) {
11679 elink_link_int_enable(params);
11680 params->link_flags &=
11681 ~ELINK_LINK_FLAGS_INT_DISABLED;
11682 }
11683 }
11684 }
11685 break;
11686 }
11687
11688 /* This is a workaround for E3+84833 until autoneg
11689 * restart is fixed in f/w
11690 */
11691 if (CHIP_IS_E3(params->chip_id)) {
11692 elink_cl45_read(cb, phy, MDIO_WC_DEVAD,
11693 MDIO_WC_REG_GP2_STATUS_GP_2_1, &val);
11694 }
11695 }
11696 #endif /* EXCLUDE_BCM8481 / EXCLUDE_BCM8481 */
11697 #endif // EXCLUDE_NON_COMMON_INIT
11698
11699 /******************************************************************/
11700 /* 54618SE PHY SECTION */
11701 /******************************************************************/
11702 #if (!defined EXCLUDE_NON_COMMON_INIT) && (!defined EXCLUDE_BCM54618SE)
11703 #ifdef ELINK_AUX_POWER
elink_54618se_init_required(struct elink_phy * phy,struct elink_params * params)11704 static int elink_54618se_init_required(struct elink_phy *phy,
11705 struct elink_params *params)
11706 {
11707 u16 autoneg_val, an_1000_val, an_10_100_val, ctrl, legacy_status;
11708 struct elink_dev *cb = params->cb;
11709 /* read all advertisement */
11710 elink_cl22_read(cb, phy,
11711 MDIO_PMA_REG_CTRL, &ctrl);
11712 /* In case PHY is in reset */
11713 if (ctrl & (1<<15))
11714 return 1;
11715
11716 elink_cl22_read(cb, phy,
11717 0x09,
11718 &an_1000_val);
11719 elink_cl22_read(cb, phy,
11720 0x04,
11721 &an_10_100_val);
11722 elink_cl22_read(cb, phy,
11723 MDIO_PMA_REG_CTRL,
11724 &autoneg_val);
11725 elink_cl22_read(cb, phy,
11726 0x19,
11727 &legacy_status);
11728 /* Check conditions to avoid link reset in case link was
11729 * already initialized and up
11730 */
11731 if ((an_1000_val & 0x300) &&
11732 (an_10_100_val & 0x1e0) &&
11733 (autoneg_val & 0x1000) &&
11734 (legacy_status & (1<<2)))
11735 return 0;
11736 return 1;
11737 }
11738 #endif // ELINK_AUX_POWER
elink_54618se_specific_func(struct elink_phy * phy,struct elink_params * params,u32 action)11739 static void elink_54618se_specific_func(struct elink_phy *phy,
11740 struct elink_params *params,
11741 u32 action)
11742 {
11743 struct elink_dev *cb = params->cb;
11744 u16 temp;
11745 switch (action) {
11746 case ELINK_PHY_INIT:
11747 /* Configure LED4: set to INTR (0x6). */
11748 /* Accessing shadow register 0xe. */
11749 elink_cl22_write(cb, phy,
11750 MDIO_REG_GPHY_SHADOW,
11751 MDIO_REG_GPHY_SHADOW_LED_SEL2);
11752 elink_cl22_read(cb, phy,
11753 MDIO_REG_GPHY_SHADOW,
11754 &temp);
11755 temp &= ~(0xf << 4);
11756 temp |= (0x6 << 4);
11757 elink_cl22_write(cb, phy,
11758 MDIO_REG_GPHY_SHADOW,
11759 MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
11760 /* Configure INTR based on link status change. */
11761 elink_cl22_write(cb, phy,
11762 MDIO_REG_INTR_MASK,
11763 ~MDIO_REG_INTR_MASK_LINK_STATUS);
11764 break;
11765 }
11766 }
11767
elink_54618se_config_init(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)11768 static elink_status_t elink_54618se_config_init(struct elink_phy *phy,
11769 struct elink_params *params,
11770 struct elink_vars *vars)
11771 {
11772 struct elink_dev *cb = params->cb;
11773 u8 port;
11774 u16 autoneg_val, an_1000_val, an_10_100_val, fc_val, temp;
11775 u32 cfg_pin;
11776 #ifdef ELINK_AUX_POWER
11777 u32 link_init_required = 1;
11778 if (!elink_54618se_init_required(phy, params))
11779 link_init_required = 0;
11780 if (link_init_required) {
11781 #endif
11782
11783 ELINK_DEBUG_P0(cb, "54618SE cfg init\n");
11784 MSLEEP(cb, 1);
11785
11786 /* This works with E3 only, no need to check the chip
11787 * before determining the port.
11788 */
11789 port = params->port;
11790
11791 cfg_pin = (REG_RD(cb, params->shmem_base +
11792 OFFSETOF(struct shmem_region,
11793 dev_info.port_hw_config[port].e3_cmn_pin_cfg)) &
11794 PORT_HW_CFG_E3_PHY_RESET_MASK) >>
11795 PORT_HW_CFG_E3_PHY_RESET_SHIFT;
11796
11797 /* Drive pin high to bring the GPHY out of reset. */
11798 elink_set_cfg_pin(cb, cfg_pin, 1);
11799
11800 /* wait for GPHY to reset */
11801 MSLEEP(cb, 50);
11802
11803 /* reset phy */
11804 elink_cl22_write(cb, phy,
11805 MDIO_PMA_REG_CTRL, 0x8000);
11806 elink_wait_reset_complete(cb, phy, params);
11807
11808 /* Wait for GPHY to reset */
11809 MSLEEP(cb, 50);
11810
11811 #ifdef ELINK_AUX_POWER
11812 } // If init required
11813 #endif
11814
11815 elink_54618se_specific_func(phy, params, ELINK_PHY_INIT);
11816 /* Flip the signal detect polarity (set 0x1c.0x1e[8]). */
11817 elink_cl22_write(cb, phy,
11818 MDIO_REG_GPHY_SHADOW,
11819 MDIO_REG_GPHY_SHADOW_AUTO_DET_MED);
11820 elink_cl22_read(cb, phy,
11821 MDIO_REG_GPHY_SHADOW,
11822 &temp);
11823 temp |= MDIO_REG_GPHY_SHADOW_INVERT_FIB_SD;
11824 elink_cl22_write(cb, phy,
11825 MDIO_REG_GPHY_SHADOW,
11826 MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
11827
11828 /* Set up fc */
11829 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
11830 elink_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
11831 #ifdef ELINK_AUX_POWER
11832 if (!link_init_required)
11833 return ELINK_STATUS_OK;
11834 #endif
11835 fc_val = 0;
11836 if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
11837 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC)
11838 fc_val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
11839
11840 if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
11841 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
11842 fc_val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
11843
11844 /* Read all advertisement */
11845 elink_cl22_read(cb, phy,
11846 0x09,
11847 &an_1000_val);
11848
11849 elink_cl22_read(cb, phy,
11850 0x04,
11851 &an_10_100_val);
11852
11853 elink_cl22_read(cb, phy,
11854 MDIO_PMA_REG_CTRL,
11855 &autoneg_val);
11856
11857 /* Disable forced speed */
11858 autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13));
11859 an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8) | (1<<10) |
11860 (1<<11));
11861
11862 if (((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) &&
11863 (phy->speed_cap_mask &
11864 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
11865 (phy->req_line_speed == ELINK_SPEED_1000)) {
11866 an_1000_val |= (1<<8);
11867 autoneg_val |= (1<<9 | 1<<12);
11868 if (phy->req_duplex == DUPLEX_FULL)
11869 an_1000_val |= (1<<9);
11870 ELINK_DEBUG_P0(cb, "Advertising 1G\n");
11871 } else
11872 an_1000_val &= ~((1<<8) | (1<<9));
11873
11874 elink_cl22_write(cb, phy,
11875 0x09,
11876 an_1000_val);
11877 elink_cl22_read(cb, phy,
11878 0x09,
11879 &an_1000_val);
11880
11881 /* Advertise 10/100 link speed */
11882 if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG) {
11883 if (phy->speed_cap_mask &
11884 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) {
11885 an_10_100_val |= (1<<5);
11886 autoneg_val |= (1<<9 | 1<<12);
11887 ELINK_DEBUG_P0(cb, "Advertising 10M-HD\n");
11888 }
11889 if (phy->speed_cap_mask &
11890 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) {
11891 an_10_100_val |= (1<<6);
11892 autoneg_val |= (1<<9 | 1<<12);
11893 ELINK_DEBUG_P0(cb, "Advertising 10M-FD\n");
11894 }
11895 if (phy->speed_cap_mask &
11896 PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) {
11897 an_10_100_val |= (1<<7);
11898 autoneg_val |= (1<<9 | 1<<12);
11899 ELINK_DEBUG_P0(cb, "Advertising 100M-HD\n");
11900 }
11901 if (phy->speed_cap_mask &
11902 PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) {
11903 an_10_100_val |= (1<<8);
11904 autoneg_val |= (1<<9 | 1<<12);
11905 ELINK_DEBUG_P0(cb, "Advertising 100M-FD\n");
11906 }
11907 }
11908
11909 /* Only 10/100 are allowed to work in FORCE mode */
11910 if (phy->req_line_speed == ELINK_SPEED_100) {
11911 autoneg_val |= (1<<13);
11912 /* Enabled AUTO-MDIX when autoneg is disabled */
11913 elink_cl22_write(cb, phy,
11914 0x18,
11915 (1<<15 | 1<<9 | 7<<0));
11916 ELINK_DEBUG_P0(cb, "Setting 100M force\n");
11917 }
11918 if (phy->req_line_speed == ELINK_SPEED_10) {
11919 /* Enabled AUTO-MDIX when autoneg is disabled */
11920 elink_cl22_write(cb, phy,
11921 0x18,
11922 (1<<15 | 1<<9 | 7<<0));
11923 ELINK_DEBUG_P0(cb, "Setting 10M force\n");
11924 }
11925
11926 if ((phy->flags & ELINK_FLAGS_EEE) && elink_eee_has_cap(params)) {
11927 elink_status_t rc;
11928
11929 elink_cl22_write(cb, phy, MDIO_REG_GPHY_EXP_ACCESS,
11930 MDIO_REG_GPHY_EXP_ACCESS_TOP |
11931 MDIO_REG_GPHY_EXP_TOP_2K_BUF);
11932 elink_cl22_read(cb, phy, MDIO_REG_GPHY_EXP_ACCESS_GATE, &temp);
11933 temp &= 0xfffe;
11934 elink_cl22_write(cb, phy, MDIO_REG_GPHY_EXP_ACCESS_GATE, temp);
11935
11936 rc = elink_eee_initial_config(params, vars, SHMEM_EEE_1G_ADV);
11937 if (rc != ELINK_STATUS_OK) {
11938 ELINK_DEBUG_P0(cb, "Failed to configure EEE timers\n");
11939 elink_eee_disable(phy, params, vars);
11940 } else if ((params->eee_mode & ELINK_EEE_MODE_ADV_LPI) &&
11941 (phy->req_duplex == DUPLEX_FULL) &&
11942 (elink_eee_calc_timer(params) ||
11943 !(params->eee_mode & ELINK_EEE_MODE_ENABLE_LPI))) {
11944 /* Need to advertise EEE only when requested,
11945 * and either no LPI assertion was requested,
11946 * or it was requested and a valid timer was set.
11947 * Also notice full duplex is required for EEE.
11948 */
11949 elink_eee_advertise(phy, params, vars,
11950 SHMEM_EEE_1G_ADV);
11951 } else {
11952 ELINK_DEBUG_P0(cb, "Don't Advertise 1GBase-T EEE\n");
11953 elink_eee_disable(phy, params, vars);
11954 }
11955 } else {
11956 vars->eee_status &= ~SHMEM_EEE_1G_ADV <<
11957 SHMEM_EEE_SUPPORTED_SHIFT;
11958
11959 if (phy->flags & ELINK_FLAGS_EEE) {
11960 /* Handle legacy auto-grEEEn */
11961 if (params->feature_config_flags &
11962 ELINK_FEATURE_CONFIG_AUTOGREEEN_ENABLED) {
11963 temp = 6;
11964 ELINK_DEBUG_P0(cb, "Enabling Auto-GrEEEn\n");
11965 } else {
11966 temp = 0;
11967 ELINK_DEBUG_P0(cb, "Don't Adv. EEE\n");
11968 }
11969 elink_cl45_write(cb, phy, MDIO_AN_DEVAD,
11970 MDIO_AN_REG_EEE_ADV, temp);
11971 }
11972 }
11973
11974 elink_cl22_write(cb, phy,
11975 0x04,
11976 an_10_100_val | fc_val);
11977
11978 if (phy->req_duplex == DUPLEX_FULL)
11979 autoneg_val |= (1<<8);
11980
11981 elink_cl22_write(cb, phy,
11982 MDIO_PMA_REG_CTRL, autoneg_val);
11983
11984 return ELINK_STATUS_OK;
11985 }
11986
11987
elink_5461x_set_link_led(struct elink_phy * phy,struct elink_params * params,u8 mode)11988 static void elink_5461x_set_link_led(struct elink_phy *phy,
11989 struct elink_params *params, u8 mode)
11990 {
11991 #ifdef ELINK_ENHANCEMENTS
11992 struct elink_dev *cb = params->cb;
11993 u16 temp;
11994
11995 elink_cl22_write(cb, phy,
11996 MDIO_REG_GPHY_SHADOW,
11997 MDIO_REG_GPHY_SHADOW_LED_SEL1);
11998 elink_cl22_read(cb, phy,
11999 MDIO_REG_GPHY_SHADOW,
12000 &temp);
12001 temp &= 0xff00;
12002
12003 ELINK_DEBUG_P1(cb, "54618x set link led (mode=%x)\n", mode);
12004 switch (mode) {
12005 case ELINK_LED_MODE_FRONT_PANEL_OFF:
12006 case ELINK_LED_MODE_OFF:
12007 temp |= 0x00ee;
12008 break;
12009 case ELINK_LED_MODE_OPER:
12010 temp |= 0x0001;
12011 break;
12012 case ELINK_LED_MODE_ON:
12013 temp |= 0x00ff;
12014 break;
12015 default:
12016 break;
12017 }
12018 elink_cl22_write(cb, phy,
12019 MDIO_REG_GPHY_SHADOW,
12020 MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
12021 return;
12022 #endif // ELINK_ENHANCEMENTS
12023 }
12024
12025
elink_54618se_link_reset(struct elink_phy * phy,struct elink_params * params)12026 static void elink_54618se_link_reset(struct elink_phy *phy,
12027 struct elink_params *params)
12028 {
12029 struct elink_dev *cb = params->cb;
12030 u32 cfg_pin;
12031 u8 port;
12032
12033 #ifdef ELINK_AUX_POWER
12034 if (!elink_54618se_init_required(phy, params))
12035 return;
12036 #endif // ELINK_AUX_POWER
12037 /* In case of no EPIO routed to reset the GPHY, put it
12038 * in low power mode.
12039 */
12040 elink_cl22_write(cb, phy, MDIO_PMA_REG_CTRL, 0x800);
12041 /* This works with E3 only, no need to check the chip
12042 * before determining the port.
12043 */
12044 port = params->port;
12045 cfg_pin = (REG_RD(cb, params->shmem_base +
12046 OFFSETOF(struct shmem_region,
12047 dev_info.port_hw_config[port].e3_cmn_pin_cfg)) &
12048 PORT_HW_CFG_E3_PHY_RESET_MASK) >>
12049 PORT_HW_CFG_E3_PHY_RESET_SHIFT;
12050
12051 /* Drive pin low to put GPHY in reset. */
12052 elink_set_cfg_pin(cb, cfg_pin, 0);
12053 }
12054
elink_54618se_read_status(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)12055 static u8 elink_54618se_read_status(struct elink_phy *phy,
12056 struct elink_params *params,
12057 struct elink_vars *vars)
12058 {
12059 struct elink_dev *cb = params->cb;
12060 u16 val;
12061 u8 link_up = 0;
12062 u16 legacy_status, legacy_speed;
12063
12064 /* Get speed operation status */
12065 elink_cl22_read(cb, phy,
12066 MDIO_REG_GPHY_AUX_STATUS,
12067 &legacy_status);
12068 ELINK_DEBUG_P1(cb, "54618SE read_status: 0x%x\n", legacy_status);
12069
12070 /* Read status to clear the PHY interrupt. */
12071 elink_cl22_read(cb, phy,
12072 MDIO_REG_INTR_STATUS,
12073 &val);
12074
12075 link_up = ((legacy_status & (1<<2)) == (1<<2));
12076
12077 if (link_up) {
12078 legacy_speed = (legacy_status & (7<<8));
12079 if (legacy_speed == (7<<8)) {
12080 vars->line_speed = ELINK_SPEED_1000;
12081 vars->duplex = DUPLEX_FULL;
12082 } else if (legacy_speed == (6<<8)) {
12083 vars->line_speed = ELINK_SPEED_1000;
12084 vars->duplex = DUPLEX_HALF;
12085 } else if (legacy_speed == (5<<8)) {
12086 vars->line_speed = ELINK_SPEED_100;
12087 vars->duplex = DUPLEX_FULL;
12088 }
12089 /* Omitting 100Base-T4 for now */
12090 else if (legacy_speed == (3<<8)) {
12091 vars->line_speed = ELINK_SPEED_100;
12092 vars->duplex = DUPLEX_HALF;
12093 } else if (legacy_speed == (2<<8)) {
12094 vars->line_speed = ELINK_SPEED_10;
12095 vars->duplex = DUPLEX_FULL;
12096 } else if (legacy_speed == (1<<8)) {
12097 vars->line_speed = ELINK_SPEED_10;
12098 vars->duplex = DUPLEX_HALF;
12099 } else /* Should not happen */
12100 vars->line_speed = 0;
12101
12102 ELINK_DEBUG_P2(cb,
12103 "Link is up in %dMbps, is_duplex_full= %d\n",
12104 vars->line_speed,
12105 (vars->duplex == DUPLEX_FULL));
12106
12107 /* Check legacy speed AN resolution */
12108 elink_cl22_read(cb, phy,
12109 0x01,
12110 &val);
12111 if (val & (1<<5))
12112 vars->link_status |=
12113 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
12114 elink_cl22_read(cb, phy,
12115 0x06,
12116 &val);
12117 if ((val & (1<<0)) == 0)
12118 vars->link_status |=
12119 LINK_STATUS_PARALLEL_DETECTION_USED;
12120
12121 ELINK_DEBUG_P1(cb, "BCM54618SE: link speed is %d\n",
12122 vars->line_speed);
12123
12124 elink_ext_phy_resolve_fc(phy, params, vars);
12125
12126 if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
12127 /* Report LP advertised speeds */
12128 elink_cl22_read(cb, phy, 0x5, &val);
12129
12130 if (val & (1<<5))
12131 vars->link_status |=
12132 LINK_STATUS_LINK_PARTNER_10THD_CAPABLE;
12133 if (val & (1<<6))
12134 vars->link_status |=
12135 LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE;
12136 if (val & (1<<7))
12137 vars->link_status |=
12138 LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE;
12139 if (val & (1<<8))
12140 vars->link_status |=
12141 LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE;
12142 if (val & (1<<9))
12143 vars->link_status |=
12144 LINK_STATUS_LINK_PARTNER_100T4_CAPABLE;
12145
12146 elink_cl22_read(cb, phy, 0xa, &val);
12147 if (val & (1<<10))
12148 vars->link_status |=
12149 LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE;
12150 if (val & (1<<11))
12151 vars->link_status |=
12152 LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
12153
12154 if ((phy->flags & ELINK_FLAGS_EEE) &&
12155 elink_eee_has_cap(params))
12156 elink_eee_an_resolve(phy, params, vars);
12157 }
12158 }
12159 return link_up;
12160 }
12161
elink_54618se_config_loopback(struct elink_phy * phy,struct elink_params * params)12162 static void elink_54618se_config_loopback(struct elink_phy *phy,
12163 struct elink_params *params)
12164 {
12165 #ifdef ELINK_INCLUDE_LOOPBACK
12166 struct elink_dev *cb = params->cb;
12167 u16 val;
12168 u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
12169
12170 ELINK_DEBUG_P0(cb, "2PMA/PMD ext_phy_loopback: 54618se\n");
12171
12172 /* Enable master/slave manual mmode and set to master */
12173 /* mii write 9 [bits set 11 12] */
12174 elink_cl22_write(cb, phy, 0x09, 3<<11);
12175
12176 /* forced 1G and disable autoneg */
12177 /* set val [mii read 0] */
12178 /* set val [expr $val & [bits clear 6 12 13]] */
12179 /* set val [expr $val | [bits set 6 8]] */
12180 /* mii write 0 $val */
12181 elink_cl22_read(cb, phy, 0x00, &val);
12182 val &= ~((1<<6) | (1<<12) | (1<<13));
12183 val |= (1<<6) | (1<<8);
12184 elink_cl22_write(cb, phy, 0x00, val);
12185
12186 /* Set external loopback and Tx using 6dB coding */
12187 /* mii write 0x18 7 */
12188 /* set val [mii read 0x18] */
12189 /* mii write 0x18 [expr $val | [bits set 10 15]] */
12190 elink_cl22_write(cb, phy, 0x18, 7);
12191 elink_cl22_read(cb, phy, 0x18, &val);
12192 elink_cl22_write(cb, phy, 0x18, val | (1<<10) | (1<<15));
12193
12194 /* This register opens the gate for the UMAC despite its name */
12195 REG_WR(cb, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
12196
12197 /* Maximum Frame Length (RW). Defines a 14-Bit maximum frame
12198 * length used by the MAC receive logic to check frames.
12199 */
12200 REG_WR(cb, umac_base + UMAC_REG_MAXFR, 0x2710);
12201 #endif // ELINK_INCLUDE_LOOPBACK
12202 }
12203
12204 #endif // (!defined EXCLUDE_NON_COMMON_INIT) && (!defined EXCLUDE_BCM54618SE)
12205 /******************************************************************/
12206 /* SFX7101 PHY SECTION */
12207 /******************************************************************/
12208 #ifndef EXCLUDE_SFX7101
elink_7101_config_loopback(struct elink_phy * phy,struct elink_params * params)12209 static void elink_7101_config_loopback(struct elink_phy *phy,
12210 struct elink_params *params)
12211 {
12212 struct elink_dev *cb = params->cb;
12213 /* SFX7101_XGXS_TEST1 */
12214 elink_cl45_write(cb, phy,
12215 MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100);
12216 }
12217
elink_7101_config_init(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)12218 static elink_status_t elink_7101_config_init(struct elink_phy *phy,
12219 struct elink_params *params,
12220 struct elink_vars *vars)
12221 {
12222 u16 fw_ver1, fw_ver2, val;
12223 struct elink_dev *cb = params->cb;
12224 ELINK_DEBUG_P0(cb, "Setting the SFX7101 LASI indication\n");
12225
12226 /* Restore normal power mode*/
12227 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_2,
12228 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
12229 /* HW reset */
12230 elink_ext_phy_hw_reset(cb, params->port);
12231 elink_wait_reset_complete(cb, phy, params);
12232
12233 elink_cl45_write(cb, phy,
12234 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x1);
12235 ELINK_DEBUG_P0(cb, "Setting the SFX7101 LED to blink on traffic\n");
12236 elink_cl45_write(cb, phy,
12237 MDIO_PMA_DEVAD, MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
12238
12239 elink_ext_phy_set_pause(params, phy, vars);
12240 /* Restart autoneg */
12241 elink_cl45_read(cb, phy,
12242 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, &val);
12243 val |= 0x200;
12244 elink_cl45_write(cb, phy,
12245 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, val);
12246
12247 /* Save spirom version */
12248 elink_cl45_read(cb, phy,
12249 MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER1, &fw_ver1);
12250
12251 elink_cl45_read(cb, phy,
12252 MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2, &fw_ver2);
12253 elink_save_spirom_version(cb, params->port,
12254 (u32)(fw_ver1<<16 | fw_ver2), phy->ver_addr);
12255 return ELINK_STATUS_OK;
12256 }
12257
elink_7101_read_status(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)12258 static u8 elink_7101_read_status(struct elink_phy *phy,
12259 struct elink_params *params,
12260 struct elink_vars *vars)
12261 {
12262 struct elink_dev *cb = params->cb;
12263 u8 link_up;
12264 u16 val1, val2;
12265 elink_cl45_read(cb, phy,
12266 MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2);
12267 elink_cl45_read(cb, phy,
12268 MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
12269 ELINK_DEBUG_P2(cb, "10G-base-T LASI status 0x%x->0x%x\n",
12270 val2, val1);
12271 elink_cl45_read(cb, phy,
12272 MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
12273 elink_cl45_read(cb, phy,
12274 MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
12275 ELINK_DEBUG_P2(cb, "10G-base-T PMA status 0x%x->0x%x\n",
12276 val2, val1);
12277 link_up = ((val1 & 4) == 4);
12278 /* If link is up print the AN outcome of the SFX7101 PHY */
12279 if (link_up) {
12280 elink_cl45_read(cb, phy,
12281 MDIO_AN_DEVAD, MDIO_AN_REG_MASTER_STATUS,
12282 &val2);
12283 vars->line_speed = ELINK_SPEED_10000;
12284 vars->duplex = DUPLEX_FULL;
12285 ELINK_DEBUG_P2(cb, "SFX7101 AN status 0x%x->Master=%x\n",
12286 val2, (val2 & (1<<14)));
12287 elink_ext_phy_10G_an_resolve(cb, phy, vars);
12288 elink_ext_phy_resolve_fc(phy, params, vars);
12289
12290 /* Read LP advertised speeds */
12291 if (val2 & (1<<11))
12292 vars->link_status |=
12293 LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
12294 }
12295 return link_up;
12296 }
12297
elink_7101_format_ver(u32 spirom_ver,u8 * str,u16 * len)12298 static elink_status_t elink_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
12299 {
12300 if (*len < 5)
12301 return ELINK_STATUS_ERROR;
12302 str[0] = (spirom_ver & 0xFF);
12303 str[1] = (spirom_ver & 0xFF00) >> 8;
12304 str[2] = (spirom_ver & 0xFF0000) >> 16;
12305 str[3] = (spirom_ver & 0xFF000000) >> 24;
12306 str[4] = '\0';
12307 *len -= 5;
12308 return ELINK_STATUS_OK;
12309 }
12310
elink_sfx7101_sp_sw_reset(struct elink_dev * cb,struct elink_phy * phy)12311 void elink_sfx7101_sp_sw_reset(struct elink_dev *cb, struct elink_phy *phy)
12312 {
12313 u16 val, cnt;
12314
12315 elink_cl45_read(cb, phy,
12316 MDIO_PMA_DEVAD,
12317 MDIO_PMA_REG_7101_RESET, &val);
12318
12319 for (cnt = 0; cnt < 10; cnt++) {
12320 MSLEEP(cb, 50);
12321 /* Writes a self-clearing reset */
12322 elink_cl45_write(cb, phy,
12323 MDIO_PMA_DEVAD,
12324 MDIO_PMA_REG_7101_RESET,
12325 (val | (1<<15)));
12326 /* Wait for clear */
12327 elink_cl45_read(cb, phy,
12328 MDIO_PMA_DEVAD,
12329 MDIO_PMA_REG_7101_RESET, &val);
12330
12331 if ((val & (1<<15)) == 0)
12332 break;
12333 }
12334 }
12335
elink_7101_hw_reset(struct elink_phy * phy,struct elink_params * params)12336 static void elink_7101_hw_reset(struct elink_phy *phy,
12337 struct elink_params *params) {
12338 #ifdef ELINK_ENHANCEMENTS
12339 /* Low power mode is controlled by GPIO 2 */
12340 ELINK_SET_GPIO(params->cb, MISC_REGISTERS_GPIO_2,
12341 MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
12342 /* The PHY reset is controlled by GPIO 1 */
12343 ELINK_SET_GPIO(params->cb, MISC_REGISTERS_GPIO_1,
12344 MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
12345 #endif // ELINK_ENHANCEMENTS
12346 }
12347
elink_7101_set_link_led(struct elink_phy * phy,struct elink_params * params,u8 mode)12348 static void elink_7101_set_link_led(struct elink_phy *phy,
12349 struct elink_params *params, u8 mode)
12350 {
12351 u16 val = 0;
12352 struct elink_dev *cb = params->cb;
12353 switch (mode) {
12354 case ELINK_LED_MODE_FRONT_PANEL_OFF:
12355 case ELINK_LED_MODE_OFF:
12356 val = 2;
12357 break;
12358 case ELINK_LED_MODE_ON:
12359 val = 1;
12360 break;
12361 case ELINK_LED_MODE_OPER:
12362 val = 0;
12363 break;
12364 }
12365 elink_cl45_write(cb, phy,
12366 MDIO_PMA_DEVAD,
12367 MDIO_PMA_REG_7107_LINK_LED_CNTL,
12368 val);
12369 }
12370 #endif /* EXCLUDE_SFX7101 */
12371 #endif /* ELINK_EMUL_ONLY */
12372
12373 /******************************************************************/
12374 /* STATIC PHY DECLARATION */
12375 /******************************************************************/
12376
12377 static const struct elink_phy phy_null = {
12378 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
12379 /*.addr = */0,
12380 /*.def_md_devad = */0,
12381 /*.flags = */ELINK_FLAGS_INIT_XGXS_FIRST,
12382 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12383 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12384 /*.mdio_ctrl = */0,
12385 /*.supported = */0,
12386 /*.media_type = */ELINK_ETH_PHY_NOT_PRESENT,
12387 /*.ver_addr = */0,
12388 /*.req_flow_ctrl = */0,
12389 /*.req_line_speed = */0,
12390 /*.speed_cap_mask = */0,
12391 /*.req_duplex = */0,
12392 /*.rsrv = */0,
12393 /*.config_init = */(config_init_t)NULL,
12394 /*.read_status = */(read_status_t)NULL,
12395 /*.link_reset = */(link_reset_t)NULL,
12396 /*.config_loopback = */(config_loopback_t)NULL,
12397 /*.format_fw_ver = */(format_fw_ver_t)NULL,
12398 /*.hw_reset = */(hw_reset_t)NULL,
12399 /*.set_link_led = */(set_link_led_t)NULL,
12400 /*.phy_specific_func = */(phy_specific_func_t)NULL
12401 };
12402
12403 #ifndef EXCLUDE_SERDES
12404 static const struct elink_phy phy_serdes = {
12405 /*.type = */PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
12406 /*.addr = */0xff,
12407 /*.def_md_devad = */0,
12408 /*.flags = */0,
12409 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12410 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12411 /*.mdio_ctrl = */0,
12412 /*.supported = */(ELINK_SUPPORTED_10baseT_Half |
12413 ELINK_SUPPORTED_10baseT_Full |
12414 ELINK_SUPPORTED_100baseT_Half |
12415 ELINK_SUPPORTED_100baseT_Full |
12416 ELINK_SUPPORTED_1000baseT_Full |
12417 ELINK_SUPPORTED_2500baseX_Full |
12418 ELINK_SUPPORTED_TP |
12419 ELINK_SUPPORTED_Autoneg |
12420 ELINK_SUPPORTED_Pause |
12421 ELINK_SUPPORTED_Asym_Pause),
12422 /*.media_type = */ELINK_ETH_PHY_BASE_T,
12423 /*.ver_addr = */0,
12424 /*.req_flow_ctrl = */0,
12425 /*.req_line_speed = */0,
12426 /*.speed_cap_mask = */0,
12427 /*.req_duplex = */0,
12428 /*.rsrv = */0,
12429 /*.config_init = */(config_init_t)elink_xgxs_config_init,
12430 /*.read_status = */(read_status_t)elink_link_settings_status,
12431 /*.link_reset = */(link_reset_t)elink_int_link_reset,
12432 /*.config_loopback = */(config_loopback_t)NULL,
12433 /*.format_fw_ver = */(format_fw_ver_t)NULL,
12434 /*.hw_reset = */(hw_reset_t)NULL,
12435 /*.set_link_led = */(set_link_led_t)NULL,
12436 /*.phy_specific_func = */(phy_specific_func_t)NULL
12437 };
12438
12439 #endif /* #ifndef EXCLUDE_SERDES */
12440 #ifndef EXCLUDE_XGXS
12441 static const struct elink_phy phy_xgxs = {
12442 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
12443 /*.addr = */0xff,
12444 /*.def_md_devad = */0,
12445 /*.flags = */0,
12446 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12447 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12448 /*.mdio_ctrl = */0,
12449 /*.supported = */(ELINK_SUPPORTED_10baseT_Half |
12450 ELINK_SUPPORTED_10baseT_Full |
12451 ELINK_SUPPORTED_100baseT_Half |
12452 ELINK_SUPPORTED_100baseT_Full |
12453 ELINK_SUPPORTED_1000baseT_Full |
12454 ELINK_SUPPORTED_2500baseX_Full |
12455 ELINK_SUPPORTED_10000baseT_Full |
12456 ELINK_SUPPORTED_FIBRE |
12457 ELINK_SUPPORTED_Autoneg |
12458 ELINK_SUPPORTED_Pause |
12459 ELINK_SUPPORTED_Asym_Pause),
12460 /*.media_type = */ELINK_ETH_PHY_CX4,
12461 /*.ver_addr = */0,
12462 /*.req_flow_ctrl = */0,
12463 /*.req_line_speed = */0,
12464 /*.speed_cap_mask = */0,
12465 /*.req_duplex = */0,
12466 /*.rsrv = */0,
12467 #ifndef EXCLUDE_NON_COMMON_INIT
12468 /*.config_init = */(config_init_t)elink_xgxs_config_init,
12469 /*.read_status = */(read_status_t)elink_link_settings_status,
12470 /*.link_reset = */(link_reset_t)elink_int_link_reset,
12471 /*.config_loopback = */(config_loopback_t)elink_set_xgxs_loopback,
12472 /*.format_fw_ver= */(format_fw_ver_t)NULL,
12473 /*.hw_reset = */(hw_reset_t)NULL,
12474 /*.set_link_led = */(set_link_led_t)NULL,
12475 /*.phy_specific_func = */(phy_specific_func_t)elink_xgxs_specific_func
12476 #endif
12477 };
12478 #endif
12479 #ifndef EXCLUDE_WARPCORE
12480 static const struct elink_phy phy_warpcore = {
12481 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
12482 /*.addr = */0xff,
12483 /*.def_md_devad = */0,
12484 /*.flags = */ELINK_FLAGS_TX_ERROR_CHECK,
12485 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12486 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12487 /*.mdio_ctrl = */0,
12488 /*.supported = */(ELINK_SUPPORTED_10baseT_Half |
12489 ELINK_SUPPORTED_10baseT_Full |
12490 ELINK_SUPPORTED_100baseT_Half |
12491 ELINK_SUPPORTED_100baseT_Full |
12492 ELINK_SUPPORTED_1000baseT_Full |
12493 ELINK_SUPPORTED_10000baseT_Full |
12494 ELINK_SUPPORTED_20000baseKR2_Full |
12495 ELINK_SUPPORTED_20000baseMLD2_Full |
12496 ELINK_SUPPORTED_FIBRE |
12497 ELINK_SUPPORTED_Autoneg |
12498 ELINK_SUPPORTED_Pause |
12499 ELINK_SUPPORTED_Asym_Pause),
12500 /*.media_type = */ELINK_ETH_PHY_UNSPECIFIED,
12501 /*.ver_addr = */0,
12502 /*.req_flow_ctrl = */0,
12503 /*.req_line_speed = */0,
12504 /*.speed_cap_mask = */0,
12505 /* req_duplex = */0,
12506 /* rsrv = */0,
12507 #ifndef EXCLUDE_NON_COMMON_INIT
12508 /*.config_init = */(config_init_t)elink_warpcore_config_init,
12509 /*.read_status = */(read_status_t)elink_warpcore_read_status,
12510 /*.link_reset = */(link_reset_t)elink_warpcore_link_reset,
12511 /*.config_loopback = */(config_loopback_t)elink_set_warpcore_loopback,
12512 /*.format_fw_ver= */(format_fw_ver_t)NULL,
12513 /*.hw_reset = */(hw_reset_t)elink_warpcore_hw_reset,
12514 /*.set_link_led = */(set_link_led_t)NULL,
12515 /*.phy_specific_func = */(phy_specific_func_t)NULL
12516 #endif
12517 };
12518
12519 #endif /* #ifndef EXCLUDE_WARPCORE */
12520
12521 #ifndef ELINK_EMUL_ONLY
12522 #ifndef EXCLUDE_SFX7101
12523 static const struct elink_phy phy_7101 = {
12524 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
12525 /*.addr = */0xff,
12526 /*.def_md_devad = */0,
12527 /*.flags = */ELINK_FLAGS_FAN_FAILURE_DET_REQ,
12528 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12529 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12530 /*.mdio_ctrl = */0,
12531 /*.supported = */(ELINK_SUPPORTED_10000baseT_Full |
12532 ELINK_SUPPORTED_TP |
12533 ELINK_SUPPORTED_Autoneg |
12534 ELINK_SUPPORTED_Pause |
12535 ELINK_SUPPORTED_Asym_Pause),
12536 /*.media_type = */ELINK_ETH_PHY_BASE_T,
12537 /*.ver_addr = */0,
12538 /*.req_flow_ctrl = */0,
12539 /*.req_line_speed = */0,
12540 /*.speed_cap_mask = */0,
12541 /*.req_duplex = */0,
12542 /*.rsrv = */0,
12543 /*.config_init = */(config_init_t)elink_7101_config_init,
12544 /*.read_status = */(read_status_t)elink_7101_read_status,
12545 /*.link_reset = */(link_reset_t)elink_common_ext_link_reset,
12546 /*.config_loopback = */(config_loopback_t)elink_7101_config_loopback,
12547 /*.format_fw_ver= */(format_fw_ver_t)elink_7101_format_ver,
12548 /*.hw_reset = */(hw_reset_t)elink_7101_hw_reset,
12549 /*.set_link_led = */(set_link_led_t)elink_7101_set_link_led,
12550 /*.phy_specific_func = */(phy_specific_func_t)NULL
12551 };
12552 #endif /* EXCLUDE_SFX7101 */
12553 #ifndef EXCLUDE_BCM8727_BCM8073
12554 static const struct elink_phy phy_8073 = {
12555 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
12556 /*.addr = */0xff,
12557 /*.def_md_devad = */0,
12558 /*.flags = */0,
12559 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12560 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12561 /*.mdio_ctrl = */0,
12562 /*.supported = */(ELINK_SUPPORTED_10000baseT_Full |
12563 ELINK_SUPPORTED_2500baseX_Full |
12564 ELINK_SUPPORTED_1000baseT_Full |
12565 ELINK_SUPPORTED_FIBRE |
12566 ELINK_SUPPORTED_Autoneg |
12567 ELINK_SUPPORTED_Pause |
12568 ELINK_SUPPORTED_Asym_Pause),
12569 /*.media_type = */ELINK_ETH_PHY_KR,
12570 /*.ver_addr = */0,
12571 /*.req_flow_ctrl = */0,
12572 /*.req_line_speed = */0,
12573 /*.speed_cap_mask = */0,
12574 /*.req_duplex = */0,
12575 /*.rsrv = */0,
12576 #ifndef EXCLUDE_NON_COMMON_INIT
12577 /*.config_init = */(config_init_t)elink_8073_config_init,
12578 /*.read_status = */(read_status_t)elink_8073_read_status,
12579 /*.link_reset = */(link_reset_t)elink_8073_link_reset,
12580 /*.config_loopback = */(config_loopback_t)NULL,
12581 /*.format_fw_ver= */(format_fw_ver_t)elink_format_ver,
12582 /*.hw_reset = */(hw_reset_t)NULL,
12583 /*.set_link_led = */(set_link_led_t)NULL,
12584 /*.phy_specific_func = */(phy_specific_func_t)elink_8073_specific_func
12585 #endif
12586 };
12587 #endif
12588 #ifndef EXCLUDE_BCM8705
12589 static const struct elink_phy phy_8705 = {
12590 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
12591 /*.addr = */0xff,
12592 /*.def_md_devad = */0,
12593 /*.flags = */ELINK_FLAGS_INIT_XGXS_FIRST,
12594 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12595 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12596 /*.mdio_ctrl = */0,
12597 /*.supported = */(ELINK_SUPPORTED_10000baseT_Full |
12598 ELINK_SUPPORTED_FIBRE |
12599 ELINK_SUPPORTED_Pause |
12600 ELINK_SUPPORTED_Asym_Pause),
12601 /*.media_type = */ELINK_ETH_PHY_XFP_FIBER,
12602 /*.ver_addr = */0,
12603 /*.req_flow_ctrl = */0,
12604 /*.req_line_speed = */0,
12605 /*.speed_cap_mask = */0,
12606 /*.req_duplex = */0,
12607 /*.rsrv = */0,
12608 /*.config_init = */(config_init_t)elink_8705_config_init,
12609 /*.read_status = */(read_status_t)elink_8705_read_status,
12610 /*.link_reset = */(link_reset_t)elink_common_ext_link_reset,
12611 /*.config_loopback = */(config_loopback_t)NULL,
12612 /*.format_fw_ver= */(format_fw_ver_t)elink_null_format_ver,
12613 /*.hw_reset = */(hw_reset_t)NULL,
12614 /*.set_link_led = */(set_link_led_t)NULL,
12615 /*.phy_specific_func = */(phy_specific_func_t)NULL
12616 };
12617 #endif /* EXCLUDE_BCM8705 */
12618 #ifndef EXCLUDE_BCM87x6
12619 static const struct elink_phy phy_8706 = {
12620 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
12621 /*.addr = */0xff,
12622 /*.def_md_devad = */0,
12623 /*.flags = */ELINK_FLAGS_INIT_XGXS_FIRST,
12624 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12625 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12626 /*.mdio_ctrl = */0,
12627 /*.supported = */(ELINK_SUPPORTED_10000baseT_Full |
12628 ELINK_SUPPORTED_1000baseT_Full |
12629 ELINK_SUPPORTED_FIBRE |
12630 ELINK_SUPPORTED_Pause |
12631 ELINK_SUPPORTED_Asym_Pause),
12632 /*.media_type = */ELINK_ETH_PHY_SFPP_10G_FIBER,
12633 /*.ver_addr = */0,
12634 /*.req_flow_ctrl = */0,
12635 /*.req_line_speed = */0,
12636 /*.speed_cap_mask = */0,
12637 /*.req_duplex = */0,
12638 /*.rsrv = */0,
12639 /*.config_init = */(config_init_t)elink_8706_config_init,
12640 /*.read_status = */(read_status_t)elink_8706_read_status,
12641 /*.link_reset = */(link_reset_t)elink_common_ext_link_reset,
12642 /*.config_loopback = */(config_loopback_t)NULL,
12643 /*.format_fw_ver= */(format_fw_ver_t)elink_format_ver,
12644 /*.hw_reset = */(hw_reset_t)NULL,
12645 /*.set_link_led = */(set_link_led_t)NULL,
12646 /*.phy_specific_func = */(phy_specific_func_t)NULL
12647 };
12648
12649 static const struct elink_phy phy_8726 = {
12650 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
12651 /*.addr = */0xff,
12652 /*.def_md_devad = */0,
12653 /*.flags = */(ELINK_FLAGS_INIT_XGXS_FIRST |
12654 ELINK_FLAGS_TX_ERROR_CHECK),
12655 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12656 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12657 /*.mdio_ctrl = */0,
12658 /*.supported = */(ELINK_SUPPORTED_10000baseT_Full |
12659 ELINK_SUPPORTED_1000baseT_Full |
12660 ELINK_SUPPORTED_Autoneg |
12661 ELINK_SUPPORTED_FIBRE |
12662 ELINK_SUPPORTED_Pause |
12663 ELINK_SUPPORTED_Asym_Pause),
12664 /*.media_type = */ELINK_ETH_PHY_NOT_PRESENT,
12665 /*.ver_addr = */0,
12666 /*.req_flow_ctrl = */0,
12667 /*.req_line_speed = */0,
12668 /*.speed_cap_mask = */0,
12669 /*.req_duplex = */0,
12670 /*.rsrv = */0,
12671 /*.config_init = */(config_init_t)elink_8726_config_init,
12672 /*.read_status = */(read_status_t)elink_8726_read_status,
12673 /*.link_reset = */(link_reset_t)elink_8726_link_reset,
12674 /*.config_loopback = */(config_loopback_t)elink_8726_config_loopback,
12675 /*.format_fw_ver= */(format_fw_ver_t)elink_format_ver,
12676 /*.hw_reset = */(hw_reset_t)NULL,
12677 /*.set_link_led = */(set_link_led_t)NULL,
12678 /*.phy_specific_func = */(phy_specific_func_t)NULL
12679 };
12680 #endif /* #ifndef EXCLUDE_BCM87x6 */
12681
12682 #ifndef EXCLUDE_BCM8727_BCM8073
12683 static const struct elink_phy phy_8727 = {
12684 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
12685 /*.addr = */0xff,
12686 /*.def_md_devad = */0,
12687 /*.flags = */(ELINK_FLAGS_FAN_FAILURE_DET_REQ |
12688 ELINK_FLAGS_TX_ERROR_CHECK),
12689 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12690 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12691 /*.mdio_ctrl = */0,
12692 /*.supported = */(ELINK_SUPPORTED_10000baseT_Full |
12693 ELINK_SUPPORTED_1000baseT_Full |
12694 ELINK_SUPPORTED_FIBRE |
12695 ELINK_SUPPORTED_Pause |
12696 ELINK_SUPPORTED_Asym_Pause),
12697 /*.media_type = */ELINK_ETH_PHY_NOT_PRESENT,
12698 /*.ver_addr = */0,
12699 /*.req_flow_ctrl = */0,
12700 /*.req_line_speed = */0,
12701 /*.speed_cap_mask = */0,
12702 /*.req_duplex = */0,
12703 /*.rsrv = */0,
12704 #ifndef EXCLUDE_NON_COMMON_INIT
12705 /*.config_init = */(config_init_t)elink_8727_config_init,
12706 /*.read_status = */(read_status_t)elink_8727_read_status,
12707 /*.link_reset = */(link_reset_t)elink_8727_link_reset,
12708 /*.config_loopback = */(config_loopback_t)NULL,
12709 /*.format_fw_ver= */(format_fw_ver_t)elink_format_ver,
12710 /*.hw_reset = */(hw_reset_t)elink_8727_hw_reset,
12711 /*.set_link_led = */(set_link_led_t)elink_8727_set_link_led,
12712 /*.phy_specific_func = */(phy_specific_func_t)elink_8727_specific_func
12713 #endif
12714 };
12715 #endif
12716 #ifndef EXCLUDE_BCM8481
12717 static const struct elink_phy phy_8481 = {
12718 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
12719 /*.addr = */0xff,
12720 /*.def_md_devad = */0,
12721 /*.flags = */ELINK_FLAGS_FAN_FAILURE_DET_REQ |
12722 ELINK_FLAGS_REARM_LATCH_SIGNAL,
12723 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12724 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12725 /*.mdio_ctrl = */0,
12726 /*.supported = */(ELINK_SUPPORTED_10baseT_Half |
12727 ELINK_SUPPORTED_10baseT_Full |
12728 ELINK_SUPPORTED_100baseT_Half |
12729 ELINK_SUPPORTED_100baseT_Full |
12730 ELINK_SUPPORTED_1000baseT_Full |
12731 ELINK_SUPPORTED_10000baseT_Full |
12732 ELINK_SUPPORTED_TP |
12733 ELINK_SUPPORTED_Autoneg |
12734 ELINK_SUPPORTED_Pause |
12735 ELINK_SUPPORTED_Asym_Pause),
12736 /*.media_type = */ELINK_ETH_PHY_BASE_T,
12737 /*.ver_addr = */0,
12738 /*.req_flow_ctrl = */0,
12739 /*.req_line_speed = */0,
12740 /*.speed_cap_mask = */0,
12741 /*.req_duplex = */0,
12742 /*.rsrv = */0,
12743 #ifndef EXCLUDE_NON_COMMON_INIT
12744 /*.config_init = */(config_init_t)elink_8481_config_init,
12745 /*.read_status = */(read_status_t)elink_848xx_read_status,
12746 /*.link_reset = */(link_reset_t)elink_8481_link_reset,
12747 /*.config_loopback = */(config_loopback_t)NULL,
12748 /*.format_fw_ver= */(format_fw_ver_t)elink_848xx_format_ver,
12749 /*.hw_reset = */(hw_reset_t)elink_8481_hw_reset,
12750 /*.set_link_led = */(set_link_led_t)elink_848xx_set_link_led,
12751 /*.phy_specific_func = */(phy_specific_func_t)NULL
12752 #endif
12753 };
12754
12755 static const struct elink_phy phy_84823 = {
12756 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
12757 /*.addr = */0xff,
12758 /*.def_md_devad = */0,
12759 /*.flags = */(ELINK_FLAGS_FAN_FAILURE_DET_REQ |
12760 ELINK_FLAGS_REARM_LATCH_SIGNAL |
12761 ELINK_FLAGS_TX_ERROR_CHECK),
12762 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12763 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12764 /*.mdio_ctrl = */0,
12765 /*.supported = */(ELINK_SUPPORTED_10baseT_Half |
12766 ELINK_SUPPORTED_10baseT_Full |
12767 ELINK_SUPPORTED_100baseT_Half |
12768 ELINK_SUPPORTED_100baseT_Full |
12769 ELINK_SUPPORTED_1000baseT_Full |
12770 ELINK_SUPPORTED_10000baseT_Full |
12771 ELINK_SUPPORTED_TP |
12772 ELINK_SUPPORTED_Autoneg |
12773 ELINK_SUPPORTED_Pause |
12774 ELINK_SUPPORTED_Asym_Pause),
12775 /*.media_type = */ELINK_ETH_PHY_BASE_T,
12776 /*.ver_addr = */0,
12777 /*.req_flow_ctrl = */0,
12778 /*.req_line_speed = */0,
12779 /*.speed_cap_mask = */0,
12780 /*.req_duplex = */0,
12781 /*.rsrv = */0,
12782 #ifndef EXCLUDE_NON_COMMON_INIT
12783 /*.config_init = */(config_init_t)elink_848x3_config_init,
12784 /*.read_status = */(read_status_t)elink_848xx_read_status,
12785 /*.link_reset = */(link_reset_t)elink_848x3_link_reset,
12786 /*.config_loopback = */(config_loopback_t)NULL,
12787 /*.format_fw_ver= */(format_fw_ver_t)elink_848xx_format_ver,
12788 /*.hw_reset = */(hw_reset_t)NULL,
12789 /*.set_link_led = */(set_link_led_t)elink_848xx_set_link_led,
12790 /*.phy_specific_func = */(phy_specific_func_t)elink_848xx_specific_func
12791 #endif // #ifndef EXCLUDE_NON_COMMON_INIT
12792 };
12793 #endif /* EXCLUDE_BCM8481 */
12794
12795 #ifndef EXCLUDE_BCM84833
12796 static const struct elink_phy phy_84833 = {
12797 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
12798 /*.addr = */0xff,
12799 /*.def_md_devad = */0,
12800 /*.flags = */(ELINK_FLAGS_FAN_FAILURE_DET_REQ |
12801 ELINK_FLAGS_REARM_LATCH_SIGNAL |
12802 ELINK_FLAGS_TX_ERROR_CHECK |
12803 ELINK_FLAGS_TEMPERATURE),
12804 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12805 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12806 /*.mdio_ctrl = */0,
12807 /*.supported = */(ELINK_SUPPORTED_100baseT_Half |
12808 ELINK_SUPPORTED_100baseT_Full |
12809 ELINK_SUPPORTED_1000baseT_Full |
12810 ELINK_SUPPORTED_10000baseT_Full |
12811 ELINK_SUPPORTED_TP |
12812 ELINK_SUPPORTED_Autoneg |
12813 ELINK_SUPPORTED_Pause |
12814 ELINK_SUPPORTED_Asym_Pause),
12815 /*.media_type = */ELINK_ETH_PHY_BASE_T,
12816 /*.ver_addr = */0,
12817 /*.req_flow_ctrl = */0,
12818 /*.req_line_speed = */0,
12819 /*.speed_cap_mask = */0,
12820 /*.req_duplex = */0,
12821 /*.rsrv = */0,
12822 #ifndef EXCLUDE_NON_COMMON_INIT
12823 /*.config_init = */(config_init_t)elink_848x3_config_init,
12824 /*.read_status = */(read_status_t)elink_848xx_read_status,
12825 /*.link_reset = */(link_reset_t)elink_848x3_link_reset,
12826 /*.config_loopback = */(config_loopback_t)NULL,
12827 /*.format_fw_ver= */(format_fw_ver_t)elink_848xx_format_ver,
12828 /*.hw_reset = */(hw_reset_t)elink_84833_hw_reset_phy,
12829 /*.set_link_led = */(set_link_led_t)elink_848xx_set_link_led,
12830 /*.phy_specific_func = */(phy_specific_func_t)elink_848xx_specific_func
12831 #endif
12832 };
12833
12834 static const struct elink_phy phy_84834 = {
12835 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834,
12836 /*.addr = */0xff,
12837 /*.def_md_devad = */0,
12838 /*.flags = */ELINK_FLAGS_FAN_FAILURE_DET_REQ |
12839 ELINK_FLAGS_REARM_LATCH_SIGNAL,
12840 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12841 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12842 /*.mdio_ctrl = */0,
12843 /*.supported = */(ELINK_SUPPORTED_100baseT_Half |
12844 ELINK_SUPPORTED_100baseT_Full |
12845 ELINK_SUPPORTED_1000baseT_Full |
12846 ELINK_SUPPORTED_10000baseT_Full |
12847 ELINK_SUPPORTED_TP |
12848 ELINK_SUPPORTED_Autoneg |
12849 ELINK_SUPPORTED_Pause |
12850 ELINK_SUPPORTED_Asym_Pause),
12851 /*.media_type = */ELINK_ETH_PHY_BASE_T,
12852 /*.ver_addr = */0,
12853 /*.req_flow_ctrl = */0,
12854 /*.req_line_speed = */0,
12855 /*.speed_cap_mask = */0,
12856 /*.req_duplex = */0,
12857 /*.rsrv = */0,
12858 #ifndef EXCLUDE_NON_COMMON_INIT
12859 /*.config_init = */(config_init_t)elink_848x3_config_init,
12860 /*.read_status = */(read_status_t)elink_848xx_read_status,
12861 /*.link_reset = */(link_reset_t)elink_848x3_link_reset,
12862 /*.config_loopback = */(config_loopback_t)NULL,
12863 /*.format_fw_ver= */(format_fw_ver_t)elink_848xx_format_ver,
12864 /*.hw_reset = */(hw_reset_t)elink_84833_hw_reset_phy,
12865 /*.set_link_led = */(set_link_led_t)elink_848xx_set_link_led,
12866 /*.phy_specific_func = */(phy_specific_func_t)elink_848xx_specific_func
12867 #endif
12868 };
12869 #endif // #ifndef EXCLUDE_BCM84833
12870
12871 #ifndef EXCLUDE_BCM54618SE
12872 static const struct elink_phy phy_54618se = {
12873 /*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE,
12874 /*.addr = */0xff,
12875 /*.def_md_devad = */0,
12876 /*.flags = */ELINK_FLAGS_INIT_XGXS_FIRST,
12877 /*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12878 /*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
12879 /*.mdio_ctrl = */0,
12880 /*.supported = */(ELINK_SUPPORTED_10baseT_Half |
12881 ELINK_SUPPORTED_10baseT_Full |
12882 ELINK_SUPPORTED_100baseT_Half |
12883 ELINK_SUPPORTED_100baseT_Full |
12884 ELINK_SUPPORTED_1000baseT_Full |
12885 ELINK_SUPPORTED_TP |
12886 ELINK_SUPPORTED_Autoneg |
12887 ELINK_SUPPORTED_Pause |
12888 ELINK_SUPPORTED_Asym_Pause),
12889 /*.media_type = */ELINK_ETH_PHY_BASE_T,
12890 /*.ver_addr = */0,
12891 /*.req_flow_ctrl = */0,
12892 /*.req_line_speed = */0,
12893 /*.speed_cap_mask = */0,
12894 /* req_duplex = */0,
12895 /* rsrv = */0,
12896 #ifndef EXCLUDE_NON_COMMON_INIT
12897 /*.config_init = */(config_init_t)elink_54618se_config_init,
12898 /*.read_status = */(read_status_t)elink_54618se_read_status,
12899 /*.link_reset = */(link_reset_t)elink_54618se_link_reset,
12900 /*.config_loopback = */(config_loopback_t)elink_54618se_config_loopback,
12901 /*.format_fw_ver= */(format_fw_ver_t)NULL,
12902 /*.hw_reset = */(hw_reset_t)NULL,
12903 /*.set_link_led = */(set_link_led_t)elink_5461x_set_link_led,
12904 /*.phy_specific_func = */(phy_specific_func_t)elink_54618se_specific_func
12905 #endif
12906 };
12907 #endif
12908 #endif /* ELINK_EMUL_ONLY */
12909 /*****************************************************************/
12910 /* */
12911 /* Populate the phy according. Main function: elink_populate_phy */
12912 /* */
12913 /*****************************************************************/
12914
12915 #ifndef EXCLUDE_COMMON_INIT
elink_populate_preemphasis(struct elink_dev * cb,u32 shmem_base,struct elink_phy * phy,u8 port,u8 phy_index)12916 static void elink_populate_preemphasis(struct elink_dev *cb, u32 shmem_base,
12917 struct elink_phy *phy, u8 port,
12918 u8 phy_index)
12919 {
12920 /* Get the 4 lanes xgxs config rx and tx */
12921 u32 rx = 0, tx = 0, i;
12922 for (i = 0; i < 2; i++) {
12923 /* INT_PHY and ELINK_EXT_PHY1 share the same value location in
12924 * the shmem. When num_phys is greater than 1, than this value
12925 * applies only to ELINK_EXT_PHY1
12926 */
12927 if (phy_index == ELINK_INT_PHY || phy_index == ELINK_EXT_PHY1) {
12928 rx = REG_RD(cb, shmem_base +
12929 OFFSETOF(struct shmem_region,
12930 dev_info.port_hw_config[port].xgxs_config_rx[i<<1]));
12931
12932 tx = REG_RD(cb, shmem_base +
12933 OFFSETOF(struct shmem_region,
12934 dev_info.port_hw_config[port].xgxs_config_tx[i<<1]));
12935 } else {
12936 rx = REG_RD(cb, shmem_base +
12937 OFFSETOF(struct shmem_region,
12938 dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
12939
12940 tx = REG_RD(cb, shmem_base +
12941 OFFSETOF(struct shmem_region,
12942 dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
12943 }
12944
12945 phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff);
12946 phy->rx_preemphasis[(i << 1) + 1] = (rx & 0xffff);
12947
12948 phy->tx_preemphasis[i << 1] = ((tx>>16) & 0xffff);
12949 phy->tx_preemphasis[(i << 1) + 1] = (tx & 0xffff);
12950 }
12951 }
12952
12953 #ifndef ELINK_EMUL_ONLY
elink_get_ext_phy_config(struct elink_dev * cb,u32 shmem_base,u8 phy_index,u8 port)12954 static u32 elink_get_ext_phy_config(struct elink_dev *cb, u32 shmem_base,
12955 u8 phy_index, u8 port)
12956 {
12957 u32 ext_phy_config = 0;
12958 switch (phy_index) {
12959 case ELINK_EXT_PHY1:
12960 ext_phy_config = REG_RD(cb, shmem_base +
12961 OFFSETOF(struct shmem_region,
12962 dev_info.port_hw_config[port].external_phy_config));
12963 break;
12964 case ELINK_EXT_PHY2:
12965 ext_phy_config = REG_RD(cb, shmem_base +
12966 OFFSETOF(struct shmem_region,
12967 dev_info.port_hw_config[port].external_phy_config2));
12968 break;
12969 default:
12970 ELINK_DEBUG_P1(cb, "Invalid phy_index %d\n", phy_index);
12971 return ELINK_STATUS_ERROR;
12972 }
12973
12974 return ext_phy_config;
12975 }
12976 #endif /* ELINK_EMUL_ONLY */
elink_populate_int_phy(struct elink_dev * cb,u32 shmem_base,u8 port,struct elink_phy * phy)12977 static elink_status_t elink_populate_int_phy(struct elink_dev *cb, u32 shmem_base, u8 port,
12978 struct elink_phy *phy)
12979 {
12980 u32 phy_addr;
12981 u32 chip_id;
12982 u32 switch_cfg = (REG_RD(cb, shmem_base +
12983 OFFSETOF(struct shmem_region,
12984 dev_info.port_feature_config[port].link_config)) &
12985 PORT_FEATURE_CONNECTED_SWITCH_MASK);
12986 chip_id = (REG_RD(cb, MISC_REG_CHIP_NUM) << 16) |
12987 ((REG_RD(cb, MISC_REG_CHIP_REV) & 0xf) << 12);
12988
12989 ELINK_DEBUG_P1(cb, ":chip_id = 0x%x\n", chip_id);
12990 #ifndef EXCLUDE_WARPCORE
12991 if (ELINK_USES_WARPCORE(chip_id)) {
12992 u32 serdes_net_if;
12993 phy_addr = REG_RD(cb,
12994 MISC_REG_WC0_CTRL_PHY_ADDR);
12995 *phy = phy_warpcore;
12996 if (REG_RD(cb, MISC_REG_PORT4MODE_EN_OVWR) == 0x3)
12997 phy->flags |= ELINK_FLAGS_4_PORT_MODE;
12998 else
12999 phy->flags &= ~ELINK_FLAGS_4_PORT_MODE;
13000 /* Check Dual mode */
13001 serdes_net_if = (REG_RD(cb, shmem_base +
13002 OFFSETOF(struct shmem_region, dev_info.
13003 port_hw_config[port].default_cfg)) &
13004 PORT_HW_CFG_NET_SERDES_IF_MASK);
13005 /* Set the appropriate supported and flags indications per
13006 * interface type of the chip
13007 */
13008 switch (serdes_net_if) {
13009 case PORT_HW_CFG_NET_SERDES_IF_SGMII:
13010 phy->supported &= (ELINK_SUPPORTED_10baseT_Half |
13011 ELINK_SUPPORTED_10baseT_Full |
13012 ELINK_SUPPORTED_100baseT_Half |
13013 ELINK_SUPPORTED_100baseT_Full |
13014 ELINK_SUPPORTED_1000baseT_Full |
13015 ELINK_SUPPORTED_FIBRE |
13016 ELINK_SUPPORTED_Autoneg |
13017 ELINK_SUPPORTED_Pause |
13018 ELINK_SUPPORTED_Asym_Pause);
13019 phy->media_type = ELINK_ETH_PHY_BASE_T;
13020 break;
13021 case PORT_HW_CFG_NET_SERDES_IF_XFI:
13022 phy->supported &= (ELINK_SUPPORTED_1000baseT_Full |
13023 ELINK_SUPPORTED_10000baseT_Full |
13024 ELINK_SUPPORTED_FIBRE |
13025 ELINK_SUPPORTED_Pause |
13026 ELINK_SUPPORTED_Asym_Pause);
13027 phy->media_type = ELINK_ETH_PHY_XFP_FIBER;
13028 break;
13029 case PORT_HW_CFG_NET_SERDES_IF_SFI:
13030 phy->supported &= (ELINK_SUPPORTED_1000baseT_Full |
13031 ELINK_SUPPORTED_10000baseT_Full |
13032 ELINK_SUPPORTED_FIBRE |
13033 ELINK_SUPPORTED_Pause |
13034 ELINK_SUPPORTED_Asym_Pause);
13035 phy->media_type = ELINK_ETH_PHY_SFPP_10G_FIBER;
13036 break;
13037 case PORT_HW_CFG_NET_SERDES_IF_KR:
13038 phy->media_type = ELINK_ETH_PHY_KR;
13039 phy->supported &= (ELINK_SUPPORTED_1000baseT_Full |
13040 ELINK_SUPPORTED_10000baseT_Full |
13041 ELINK_SUPPORTED_FIBRE |
13042 ELINK_SUPPORTED_Autoneg |
13043 ELINK_SUPPORTED_Pause |
13044 ELINK_SUPPORTED_Asym_Pause);
13045 break;
13046 case PORT_HW_CFG_NET_SERDES_IF_DXGXS:
13047 phy->media_type = ELINK_ETH_PHY_KR;
13048 phy->flags |= ELINK_FLAGS_WC_DUAL_MODE;
13049 phy->supported &= (ELINK_SUPPORTED_20000baseMLD2_Full |
13050 ELINK_SUPPORTED_FIBRE |
13051 ELINK_SUPPORTED_Pause |
13052 ELINK_SUPPORTED_Asym_Pause);
13053 break;
13054 case PORT_HW_CFG_NET_SERDES_IF_KR2:
13055 phy->media_type = ELINK_ETH_PHY_KR;
13056 phy->flags |= ELINK_FLAGS_WC_DUAL_MODE;
13057 phy->supported &= (ELINK_SUPPORTED_20000baseKR2_Full |
13058 ELINK_SUPPORTED_10000baseT_Full |
13059 ELINK_SUPPORTED_1000baseT_Full |
13060 ELINK_SUPPORTED_Autoneg |
13061 ELINK_SUPPORTED_FIBRE |
13062 ELINK_SUPPORTED_Pause |
13063 ELINK_SUPPORTED_Asym_Pause);
13064 phy->flags &= ~ELINK_FLAGS_TX_ERROR_CHECK;
13065 break;
13066 default:
13067 ELINK_DEBUG_P1(cb, "Unknown WC interface type 0x%x\n",
13068 serdes_net_if);
13069 break;
13070 }
13071
13072 /* Enable MDC/MDIO work-around for E3 A0 since free running MDC
13073 * was not set as expected. For B0, ECO will be enabled so there
13074 * won't be an issue there
13075 */
13076 if (CHIP_REV(chip_id) == CHIP_REV_Ax)
13077 phy->flags |= ELINK_FLAGS_MDC_MDIO_WA;
13078 else
13079 phy->flags |= ELINK_FLAGS_MDC_MDIO_WA_B0;
13080 } else
13081 #endif
13082 {
13083 switch (switch_cfg) {
13084 #ifndef EXCLUDE_SERDES
13085 case ELINK_SWITCH_CFG_1G:
13086 phy_addr = REG_RD(cb,
13087 NIG_REG_SERDES0_CTRL_PHY_ADDR +
13088 port * 0x10);
13089 *phy = phy_serdes;
13090 break;
13091 #endif /* #ifndef EXCLUDE_SERDES */
13092 #ifndef EXCLUDE_XGXS
13093 case ELINK_SWITCH_CFG_10G:
13094 phy_addr = REG_RD(cb,
13095 NIG_REG_XGXS0_CTRL_PHY_ADDR +
13096 port * 0x18);
13097 *phy = phy_xgxs;
13098 break;
13099 #endif /* EXCLUDE_XGXS */
13100 default:
13101 ELINK_DEBUG_P0(cb, "Invalid switch_cfg\n");
13102 return ELINK_STATUS_ERROR;
13103 }
13104 }
13105 phy->addr = (u8)phy_addr;
13106 phy->mdio_ctrl = elink_get_emac_base(cb,
13107 SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH,
13108 port);
13109 if (CHIP_IS_E2(chip_id))
13110 phy->def_md_devad = ELINK_E2_DEFAULT_PHY_DEV_ADDR;
13111 else
13112 phy->def_md_devad = ELINK_DEFAULT_PHY_DEV_ADDR;
13113
13114 ELINK_DEBUG_P3(cb, "Internal phy port=%d, addr=0x%x, mdio_ctl=0x%x\n",
13115 port, phy->addr, phy->mdio_ctrl);
13116
13117 elink_populate_preemphasis(cb, shmem_base, phy, port, ELINK_INT_PHY);
13118 return ELINK_STATUS_OK;
13119 }
13120
13121 #ifndef ELINK_EMUL_ONLY
elink_populate_ext_phy(struct elink_dev * cb,u8 phy_index,u32 shmem_base,u32 shmem2_base,u8 port,struct elink_phy * phy)13122 static elink_status_t elink_populate_ext_phy(struct elink_dev *cb,
13123 u8 phy_index,
13124 u32 shmem_base,
13125 u32 shmem2_base,
13126 u8 port,
13127 struct elink_phy *phy)
13128 {
13129 u32 ext_phy_config, phy_type, config2;
13130 u32 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH;
13131 ext_phy_config = elink_get_ext_phy_config(cb, shmem_base,
13132 phy_index, port);
13133 phy_type = ELINK_XGXS_EXT_PHY_TYPE(ext_phy_config);
13134 /* Select the phy type */
13135 switch (phy_type) {
13136 #ifndef EXCLUDE_BCM8727_BCM8073
13137 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
13138 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED;
13139 *phy = phy_8073;
13140 break;
13141 #endif
13142 #ifndef EXCLUDE_BCM8705
13143 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
13144 *phy = phy_8705;
13145 break;
13146 #endif
13147 #ifndef EXCLUDE_BCM87x6
13148 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
13149 *phy = phy_8706;
13150 break;
13151 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
13152 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
13153 *phy = phy_8726;
13154 break;
13155 #endif /* EXCLUDE_BCM87x6 */
13156 #ifndef EXCLUDE_BCM8727_BCM8073
13157 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
13158 /* BCM8727_NOC => BCM8727 no over current */
13159 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
13160 *phy = phy_8727;
13161 phy->flags |= ELINK_FLAGS_NOC;
13162 break;
13163 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
13164 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
13165 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
13166 *phy = phy_8727;
13167 break;
13168 #endif
13169 #ifndef EXCLUDE_BCM8481
13170 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
13171 *phy = phy_8481;
13172 break;
13173 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
13174 *phy = phy_84823;
13175 break;
13176 #endif
13177 #ifndef EXCLUDE_BCM84833
13178 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
13179 *phy = phy_84833;
13180 break;
13181 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
13182 *phy = phy_84834;
13183 break;
13184 #endif
13185 #ifndef EXCLUDE_BCM54618SE
13186 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616:
13187 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE:
13188 *phy = phy_54618se;
13189 if (phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE)
13190 phy->flags |= ELINK_FLAGS_EEE;
13191 break;
13192 #endif
13193 #ifndef EXCLUDE_SFX7101
13194 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
13195 *phy = phy_7101;
13196 break;
13197 #endif
13198 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
13199 *phy = phy_null;
13200 return ELINK_STATUS_ERROR;
13201 default:
13202 *phy = phy_null;
13203 /* In case external PHY wasn't found */
13204 if ((phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
13205 (phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN))
13206 return ELINK_STATUS_ERROR;
13207 return ELINK_STATUS_OK;
13208 }
13209
13210 phy->addr = ELINK_XGXS_EXT_PHY_ADDR(ext_phy_config);
13211 elink_populate_preemphasis(cb, shmem_base, phy, port, phy_index);
13212
13213 /* The shmem address of the phy version is located on different
13214 * structures. In case this structure is too old, do not set
13215 * the address
13216 */
13217 config2 = REG_RD(cb, shmem_base + OFFSETOF(struct shmem_region,
13218 dev_info.shared_hw_config.config2));
13219 if (phy_index == ELINK_EXT_PHY1) {
13220 phy->ver_addr = shmem_base + OFFSETOF(struct shmem_region,
13221 port_mb[port].ext_phy_fw_version);
13222
13223 /* Check specific mdc mdio settings */
13224 if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK)
13225 mdc_mdio_access = config2 &
13226 SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK;
13227 } else {
13228 u32 size = REG_RD(cb, shmem2_base);
13229
13230 if (size >
13231 OFFSETOF(struct shmem2_region, ext_phy_fw_version2)) {
13232 phy->ver_addr = shmem2_base +
13233 OFFSETOF(struct shmem2_region,
13234 ext_phy_fw_version2[port]);
13235 }
13236 /* Check specific mdc mdio settings */
13237 if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK)
13238 mdc_mdio_access = (config2 &
13239 SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK) >>
13240 (SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT -
13241 SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT);
13242 }
13243 phy->mdio_ctrl = elink_get_emac_base(cb, mdc_mdio_access, port);
13244
13245 if (((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
13246 (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) &&
13247 (phy->ver_addr)) {
13248 /* Remove 100Mb link supported for BCM84833/4 when phy fw
13249 * version lower than or equal to 1.39
13250 */
13251 u32 raw_ver = REG_RD(cb, phy->ver_addr);
13252 if (((raw_ver & 0x7F) <= 39) &&
13253 (((raw_ver & 0xF80) >> 7) <= 1))
13254 phy->supported &= ~(ELINK_SUPPORTED_100baseT_Half |
13255 ELINK_SUPPORTED_100baseT_Full);
13256 }
13257
13258 ELINK_DEBUG_P3(cb, "phy_type 0x%x port %d found in index %d\n",
13259 phy_type, port, phy_index);
13260 ELINK_DEBUG_P2(cb, " addr=0x%x, mdio_ctl=0x%x\n",
13261 phy->addr, phy->mdio_ctrl);
13262 return ELINK_STATUS_OK;
13263 }
13264 #endif /* ELINK_EMUL_ONLY */
13265
elink_populate_phy(struct elink_dev * cb,u8 phy_index,u32 shmem_base,u32 shmem2_base,u8 port,struct elink_phy * phy)13266 static elink_status_t elink_populate_phy(struct elink_dev *cb, u8 phy_index, u32 shmem_base,
13267 u32 shmem2_base, u8 port, struct elink_phy *phy)
13268 {
13269 elink_status_t status = ELINK_STATUS_OK;
13270 phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN;
13271 if (phy_index == ELINK_INT_PHY)
13272 return elink_populate_int_phy(cb, shmem_base, port, phy);
13273 #ifndef ELINK_EMUL_ONLY
13274 status = elink_populate_ext_phy(cb, phy_index, shmem_base, shmem2_base,
13275 port, phy);
13276 #endif /* ELINK_EMUL_ONLY */
13277 return status;
13278 }
13279
elink_phy_def_cfg(struct elink_params * params,struct elink_phy * phy,u8 phy_index)13280 static void elink_phy_def_cfg(struct elink_params *params,
13281 struct elink_phy *phy,
13282 u8 phy_index)
13283 {
13284 struct elink_dev *cb = params->cb;
13285 u32 link_config;
13286 /* Populate the default phy configuration for MF mode */
13287 if (phy_index == ELINK_EXT_PHY2) {
13288 link_config = REG_RD(cb, params->shmem_base +
13289 OFFSETOF(struct shmem_region, dev_info.
13290 port_feature_config[params->port].link_config2));
13291 phy->speed_cap_mask = REG_RD(cb, params->shmem_base +
13292 OFFSETOF(struct shmem_region,
13293 dev_info.
13294 port_hw_config[params->port].speed_capability_mask2));
13295 } else {
13296 link_config = REG_RD(cb, params->shmem_base +
13297 OFFSETOF(struct shmem_region, dev_info.
13298 port_feature_config[params->port].link_config));
13299 phy->speed_cap_mask = REG_RD(cb, params->shmem_base +
13300 OFFSETOF(struct shmem_region,
13301 dev_info.
13302 port_hw_config[params->port].speed_capability_mask));
13303 }
13304 ELINK_DEBUG_P3(cb,
13305 "Default config phy idx %x cfg 0x%x speed_cap_mask 0x%x\n",
13306 phy_index, link_config, phy->speed_cap_mask);
13307
13308 phy->req_duplex = DUPLEX_FULL;
13309 switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) {
13310 case PORT_FEATURE_LINK_SPEED_10M_HALF:
13311 phy->req_duplex = DUPLEX_HALF;
13312 case PORT_FEATURE_LINK_SPEED_10M_FULL:
13313 phy->req_line_speed = ELINK_SPEED_10;
13314 break;
13315 case PORT_FEATURE_LINK_SPEED_100M_HALF:
13316 phy->req_duplex = DUPLEX_HALF;
13317 case PORT_FEATURE_LINK_SPEED_100M_FULL:
13318 phy->req_line_speed = ELINK_SPEED_100;
13319 break;
13320 case PORT_FEATURE_LINK_SPEED_1G:
13321 phy->req_line_speed = ELINK_SPEED_1000;
13322 break;
13323 case PORT_FEATURE_LINK_SPEED_2_5G:
13324 phy->req_line_speed = ELINK_SPEED_2500;
13325 break;
13326 case PORT_FEATURE_LINK_SPEED_10G_CX4:
13327 phy->req_line_speed = ELINK_SPEED_10000;
13328 break;
13329 default:
13330 phy->req_line_speed = ELINK_SPEED_AUTO_NEG;
13331 break;
13332 }
13333
13334 switch (link_config & PORT_FEATURE_FLOW_CONTROL_MASK) {
13335 case PORT_FEATURE_FLOW_CONTROL_AUTO:
13336 phy->req_flow_ctrl = ELINK_FLOW_CTRL_AUTO;
13337 break;
13338 case PORT_FEATURE_FLOW_CONTROL_TX:
13339 phy->req_flow_ctrl = ELINK_FLOW_CTRL_TX;
13340 break;
13341 case PORT_FEATURE_FLOW_CONTROL_RX:
13342 phy->req_flow_ctrl = ELINK_FLOW_CTRL_RX;
13343 break;
13344 case PORT_FEATURE_FLOW_CONTROL_BOTH:
13345 phy->req_flow_ctrl = ELINK_FLOW_CTRL_BOTH;
13346 break;
13347 default:
13348 phy->req_flow_ctrl = ELINK_FLOW_CTRL_NONE;
13349 break;
13350 }
13351 }
13352 #endif /* EXCLUDE_COMMON_INIT */
13353
elink_phy_selection(struct elink_params * params)13354 u32 elink_phy_selection(struct elink_params *params)
13355 {
13356 u32 phy_config_swapped, prio_cfg;
13357 u32 return_cfg = PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT;
13358
13359 phy_config_swapped = params->multi_phy_config &
13360 PORT_HW_CFG_PHY_SWAPPED_ENABLED;
13361
13362 prio_cfg = params->multi_phy_config &
13363 PORT_HW_CFG_PHY_SELECTION_MASK;
13364
13365 if (phy_config_swapped) {
13366 switch (prio_cfg) {
13367 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
13368 return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY;
13369 break;
13370 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
13371 return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY;
13372 break;
13373 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
13374 return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
13375 break;
13376 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
13377 return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
13378 break;
13379 }
13380 } else
13381 return_cfg = prio_cfg;
13382
13383 return return_cfg;
13384 }
13385
13386 #ifndef EXCLUDE_COMMON_INIT
elink_phy_probe(struct elink_params * params)13387 elink_status_t elink_phy_probe(struct elink_params *params)
13388 {
13389 u8 phy_index, actual_phy_idx;
13390 u32 phy_config_swapped, sync_offset, media_types;
13391 struct elink_dev *cb = params->cb;
13392 struct elink_phy *phy;
13393 params->num_phys = 0;
13394 ELINK_DEBUG_P0(cb, "Begin phy probe\n");
13395 #ifdef ELINK_INCLUDE_EMUL
13396 if (CHIP_REV_IS_EMUL(params->chip_id))
13397 return ELINK_STATUS_OK;
13398 #endif
13399 phy_config_swapped = params->multi_phy_config &
13400 PORT_HW_CFG_PHY_SWAPPED_ENABLED;
13401
13402 for (phy_index = ELINK_INT_PHY; phy_index < ELINK_MAX_PHYS;
13403 phy_index++) {
13404 actual_phy_idx = phy_index;
13405 if (phy_config_swapped) {
13406 if (phy_index == ELINK_EXT_PHY1)
13407 actual_phy_idx = ELINK_EXT_PHY2;
13408 else if (phy_index == ELINK_EXT_PHY2)
13409 actual_phy_idx = ELINK_EXT_PHY1;
13410 }
13411 ELINK_DEBUG_P3(cb, "phy_config_swapped %x, phy_index %x,"
13412 " actual_phy_idx %x\n", phy_config_swapped,
13413 phy_index, actual_phy_idx);
13414 phy = ¶ms->phy[actual_phy_idx];
13415 if (elink_populate_phy(cb, phy_index, params->shmem_base,
13416 params->shmem2_base, params->port,
13417 phy) != ELINK_STATUS_OK) {
13418 params->num_phys = 0;
13419 ELINK_DEBUG_P1(cb, "phy probe failed in phy index %d\n",
13420 phy_index);
13421 for (phy_index = ELINK_INT_PHY;
13422 phy_index < ELINK_MAX_PHYS;
13423 phy_index++)
13424 *phy = phy_null;
13425 return ELINK_STATUS_ERROR;
13426 }
13427 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
13428 break;
13429
13430 if (params->feature_config_flags &
13431 ELINK_FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET)
13432 phy->flags &= ~ELINK_FLAGS_TX_ERROR_CHECK;
13433
13434 if (!(params->feature_config_flags &
13435 ELINK_FEATURE_CONFIG_MT_SUPPORT))
13436 phy->flags |= ELINK_FLAGS_MDC_MDIO_WA_G;
13437
13438 sync_offset = params->shmem_base +
13439 OFFSETOF(struct shmem_region,
13440 dev_info.port_hw_config[params->port].media_type);
13441 media_types = REG_RD(cb, sync_offset);
13442
13443 /* Update media type for non-PMF sync only for the first time
13444 * In case the media type changes afterwards, it will be updated
13445 * using the update_status function
13446 */
13447 if ((media_types & (PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
13448 (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
13449 actual_phy_idx))) == 0) {
13450 media_types |= ((phy->media_type &
13451 PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
13452 (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
13453 actual_phy_idx));
13454 }
13455 REG_WR(cb, sync_offset, media_types);
13456
13457 elink_phy_def_cfg(params, phy, phy_index);
13458 params->num_phys++;
13459 }
13460
13461 ELINK_DEBUG_P1(cb, "End phy probe. #phys found %x\n", params->num_phys);
13462 return ELINK_STATUS_OK;
13463 }
13464 #endif /* EXCLUDE_COMMON_INIT */
13465
13466 #ifdef ELINK_AUX_POWER
elink_phy_is_temperature_support(struct elink_params * params)13467 u8 elink_phy_is_temperature_support(struct elink_params *params)
13468 {
13469 u8 phy_index;
13470 struct elink_phy *phy;
13471
13472 /* This function check that at least one of the phy's supports
13473 * temperature read.
13474 */
13475 for (phy_index = ELINK_INT_PHY; phy_index < params->num_phys;
13476 phy_index++) {
13477 phy = ¶ms->phy[phy_index];
13478 if (phy->flags & ELINK_FLAGS_TEMPERATURE)
13479 return 1;
13480 }
13481 return 0;
13482 }
13483 #endif /* ELINK_AUX_POWER */
13484 #ifdef ELINK_INCLUDE_EMUL
elink_init_e3_emul_mac(struct elink_params * params,struct elink_vars * vars)13485 static elink_status_t elink_init_e3_emul_mac(struct elink_params *params,
13486 struct elink_vars *vars)
13487 {
13488 struct elink_dev *cb = params->cb;
13489 vars->line_speed = params->req_line_speed[0];
13490 /* In case link speed is auto, set speed the highest as possible */
13491 if (params->req_line_speed[0] == ELINK_SPEED_AUTO_NEG) {
13492 if (params->feature_config_flags &
13493 ELINK_FEATURE_CONFIG_EMUL_DISABLE_XMAC)
13494 vars->line_speed = ELINK_SPEED_2500;
13495 else if (elink_is_4_port_mode(cb))
13496 vars->line_speed = ELINK_SPEED_10000;
13497 else
13498 vars->line_speed = ELINK_SPEED_20000;
13499 }
13500 if (vars->line_speed < ELINK_SPEED_10000) {
13501 if ((params->feature_config_flags &
13502 ELINK_FEATURE_CONFIG_EMUL_DISABLE_UMAC)) {
13503 ELINK_DEBUG_P1(cb, "Invalid line speed %d while UMAC is"
13504 " disabled!\n", params->req_line_speed[0]);
13505 return ELINK_STATUS_ERROR;
13506 }
13507 switch (vars->line_speed) {
13508 case ELINK_SPEED_10:
13509 vars->link_status = ELINK_LINK_10TFD;
13510 break;
13511 case ELINK_SPEED_100:
13512 vars->link_status = ELINK_LINK_100TXFD;
13513 break;
13514 case ELINK_SPEED_1000:
13515 vars->link_status = ELINK_LINK_1000TFD;
13516 break;
13517 case ELINK_SPEED_2500:
13518 vars->link_status = ELINK_LINK_2500TFD;
13519 break;
13520 default:
13521 ELINK_DEBUG_P1(cb, "Invalid line speed %d for UMAC\n",
13522 vars->line_speed);
13523 return ELINK_STATUS_ERROR;
13524 }
13525 vars->link_status |= LINK_STATUS_LINK_UP;
13526
13527 if (params->loopback_mode == ELINK_LOOPBACK_UMAC)
13528 elink_umac_enable(params, vars, 1);
13529 else
13530 elink_umac_enable(params, vars, 0);
13531 } else {
13532 /* Link speed >= 10000 requires XMAC enabled */
13533 if (params->feature_config_flags &
13534 ELINK_FEATURE_CONFIG_EMUL_DISABLE_XMAC) {
13535 ELINK_DEBUG_P1(cb, "Invalid line speed %d while XMAC is"
13536 " disabled!\n", params->req_line_speed[0]);
13537 return ELINK_STATUS_ERROR;
13538 }
13539 /* Check link speed */
13540 switch (vars->line_speed) {
13541 case ELINK_SPEED_10000:
13542 vars->link_status = ELINK_LINK_10GTFD;
13543 break;
13544 case ELINK_SPEED_20000:
13545 vars->link_status = ELINK_LINK_20GTFD;
13546 break;
13547 default:
13548 ELINK_DEBUG_P1(cb, "Invalid line speed %d for XMAC\n",
13549 vars->line_speed);
13550 return ELINK_STATUS_ERROR;
13551 }
13552 vars->link_status |= LINK_STATUS_LINK_UP;
13553 if (params->loopback_mode == ELINK_LOOPBACK_XMAC)
13554 elink_xmac_enable(params, vars, 1);
13555 else
13556 elink_xmac_enable(params, vars, 0);
13557 }
13558 return ELINK_STATUS_OK;
13559 }
13560
elink_init_emul(struct elink_params * params,struct elink_vars * vars)13561 static elink_status_t elink_init_emul(struct elink_params *params,
13562 struct elink_vars *vars)
13563 {
13564 struct elink_dev *cb = params->cb;
13565 if (CHIP_IS_E3(params->chip_id)) {
13566 if (elink_init_e3_emul_mac(params, vars) !=
13567 ELINK_STATUS_OK)
13568 return ELINK_STATUS_ERROR;
13569 } else {
13570 if (params->feature_config_flags &
13571 ELINK_FEATURE_CONFIG_EMUL_DISABLE_BMAC) {
13572 vars->line_speed = ELINK_SPEED_1000;
13573 vars->link_status = (LINK_STATUS_LINK_UP |
13574 ELINK_LINK_1000XFD);
13575 if (params->loopback_mode ==
13576 ELINK_LOOPBACK_EMAC)
13577 elink_emac_enable(params, vars, 1);
13578 else
13579 elink_emac_enable(params, vars, 0);
13580 } else {
13581 vars->line_speed = ELINK_SPEED_10000;
13582 vars->link_status = (LINK_STATUS_LINK_UP |
13583 ELINK_LINK_10GTFD);
13584 if (params->loopback_mode ==
13585 ELINK_LOOPBACK_BMAC)
13586 elink_bmac_enable(params, vars, 1, 1);
13587 else
13588 elink_bmac_enable(params, vars, 0, 1);
13589 }
13590 }
13591 vars->link_up = 1;
13592 vars->duplex = DUPLEX_FULL;
13593 vars->flow_ctrl = ELINK_FLOW_CTRL_NONE;
13594
13595 #ifndef ELINK_AUX_POWER
13596 if (CHIP_IS_E1X(params->chip_id))
13597 elink_pbf_update(params, vars->flow_ctrl,
13598 vars->line_speed);
13599 #endif /* ELINK_AUX_POWER */
13600 /* Disable drain */
13601 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
13602
13603 /* update shared memory */
13604 elink_update_mng(params, vars->link_status);
13605 return ELINK_STATUS_OK;
13606 }
13607 #endif // ELINK_INCLUDE_EMUL
13608 #ifdef ELINK_INCLUDE_FPGA
elink_init_fpga(struct elink_params * params,struct elink_vars * vars)13609 static elink_status_t elink_init_fpga(struct elink_params *params,
13610 struct elink_vars *vars)
13611 {
13612 /* Enable on E1.5 FPGA */
13613 struct elink_dev *cb = params->cb;
13614 vars->duplex = DUPLEX_FULL;
13615 vars->flow_ctrl = ELINK_FLOW_CTRL_NONE;
13616 if (!(CHIP_IS_E1(params->chip_id))) {
13617 vars->flow_ctrl = (ELINK_FLOW_CTRL_TX |
13618 ELINK_FLOW_CTRL_RX);
13619 vars->link_status |= (LINK_STATUS_TX_FLOW_CONTROL_ENABLED |
13620 LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
13621 }
13622 if (CHIP_IS_E3(params->chip_id)) {
13623 vars->line_speed = params->req_line_speed[0];
13624 switch (vars->line_speed) {
13625 case ELINK_SPEED_AUTO_NEG:
13626 vars->line_speed = ELINK_SPEED_2500;
13627 case ELINK_SPEED_2500:
13628 vars->link_status = ELINK_LINK_2500TFD;
13629 break;
13630 case ELINK_SPEED_1000:
13631 vars->link_status = ELINK_LINK_1000XFD;
13632 break;
13633 case ELINK_SPEED_100:
13634 vars->link_status = ELINK_LINK_100TXFD;
13635 break;
13636 case ELINK_SPEED_10:
13637 vars->link_status = ELINK_LINK_10TFD;
13638 break;
13639 default:
13640 ELINK_DEBUG_P1(cb, "Invalid link speed %d\n",
13641 params->req_line_speed[0]);
13642 return ELINK_STATUS_ERROR;
13643 }
13644 vars->link_status |= LINK_STATUS_LINK_UP;
13645 if (params->loopback_mode == ELINK_LOOPBACK_UMAC)
13646 elink_umac_enable(params, vars, 1);
13647 else
13648 elink_umac_enable(params, vars, 0);
13649 } else {
13650 vars->line_speed = ELINK_SPEED_10000;
13651 vars->link_status = (LINK_STATUS_LINK_UP | ELINK_LINK_10GTFD);
13652 if (params->loopback_mode == ELINK_LOOPBACK_EMAC)
13653 elink_emac_enable(params, vars, 1);
13654 else
13655 elink_emac_enable(params, vars, 0);
13656 }
13657 vars->link_up = 1;
13658
13659 #ifndef ELINK_AUX_POWER
13660 if (CHIP_IS_E1X(params->chip_id))
13661 elink_pbf_update(params, vars->flow_ctrl,
13662 vars->line_speed);
13663 #endif /* ELINK_AUX_POWER */
13664 /* Disable drain */
13665 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
13666
13667 /* Update shared memory */
13668 elink_update_mng(params, vars->link_status);
13669 return ELINK_STATUS_OK;
13670 }
13671 #endif // #ifdef ELINK_INCLUDE_FPGA
13672 #ifdef ELINK_INCLUDE_LOOPBACK
elink_init_bmac_loopback(struct elink_params * params,struct elink_vars * vars)13673 static void elink_init_bmac_loopback(struct elink_params *params,
13674 struct elink_vars *vars)
13675 {
13676 struct elink_dev *cb = params->cb;
13677 vars->link_up = 1;
13678 vars->line_speed = ELINK_SPEED_10000;
13679 vars->duplex = DUPLEX_FULL;
13680 vars->flow_ctrl = ELINK_FLOW_CTRL_NONE;
13681 vars->mac_type = ELINK_MAC_TYPE_BMAC;
13682
13683 vars->phy_flags = PHY_XGXS_FLAG;
13684
13685 elink_xgxs_deassert(params);
13686
13687 /* Set bmac loopback */
13688 elink_bmac_enable(params, vars, 1, 1);
13689
13690 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
13691 }
13692
elink_init_emac_loopback(struct elink_params * params,struct elink_vars * vars)13693 static void elink_init_emac_loopback(struct elink_params *params,
13694 struct elink_vars *vars)
13695 {
13696 struct elink_dev *cb = params->cb;
13697 vars->link_up = 1;
13698 vars->line_speed = ELINK_SPEED_1000;
13699 vars->duplex = DUPLEX_FULL;
13700 vars->flow_ctrl = ELINK_FLOW_CTRL_NONE;
13701 vars->mac_type = ELINK_MAC_TYPE_EMAC;
13702
13703 vars->phy_flags = PHY_XGXS_FLAG;
13704
13705 elink_xgxs_deassert(params);
13706 /* Set bmac loopback */
13707 elink_emac_enable(params, vars, 1);
13708 elink_emac_program(params, vars);
13709 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
13710 }
13711
elink_init_xmac_loopback(struct elink_params * params,struct elink_vars * vars)13712 static void elink_init_xmac_loopback(struct elink_params *params,
13713 struct elink_vars *vars)
13714 {
13715 struct elink_dev *cb = params->cb;
13716 vars->link_up = 1;
13717 if (!params->req_line_speed[0])
13718 vars->line_speed = ELINK_SPEED_10000;
13719 else
13720 vars->line_speed = params->req_line_speed[0];
13721 vars->duplex = DUPLEX_FULL;
13722 vars->flow_ctrl = ELINK_FLOW_CTRL_NONE;
13723 vars->mac_type = ELINK_MAC_TYPE_XMAC;
13724 vars->phy_flags = PHY_XGXS_FLAG;
13725 /* Set WC to loopback mode since link is required to provide clock
13726 * to the XMAC in 20G mode
13727 */
13728 elink_set_aer_mmd(params, ¶ms->phy[0]);
13729 elink_warpcore_reset_lane(cb, ¶ms->phy[0], 0);
13730 params->phy[ELINK_INT_PHY].config_loopback(
13731 ¶ms->phy[ELINK_INT_PHY],
13732 params);
13733
13734 elink_xmac_enable(params, vars, 1);
13735 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
13736 }
13737
elink_init_umac_loopback(struct elink_params * params,struct elink_vars * vars)13738 static void elink_init_umac_loopback(struct elink_params *params,
13739 struct elink_vars *vars)
13740 {
13741 struct elink_dev *cb = params->cb;
13742 vars->link_up = 1;
13743 vars->line_speed = ELINK_SPEED_1000;
13744 vars->duplex = DUPLEX_FULL;
13745 vars->flow_ctrl = ELINK_FLOW_CTRL_NONE;
13746 vars->mac_type = ELINK_MAC_TYPE_UMAC;
13747 vars->phy_flags = PHY_XGXS_FLAG;
13748 elink_umac_enable(params, vars, 1);
13749
13750 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
13751 }
13752
elink_init_xgxs_loopback(struct elink_params * params,struct elink_vars * vars)13753 static void elink_init_xgxs_loopback(struct elink_params *params,
13754 struct elink_vars *vars)
13755 {
13756 struct elink_dev *cb = params->cb;
13757 struct elink_phy *int_phy = ¶ms->phy[ELINK_INT_PHY];
13758 vars->link_up = 1;
13759 vars->flow_ctrl = ELINK_FLOW_CTRL_NONE;
13760 vars->duplex = DUPLEX_FULL;
13761 if (params->req_line_speed[0] == ELINK_SPEED_1000)
13762 vars->line_speed = ELINK_SPEED_1000;
13763 else if ((params->req_line_speed[0] == ELINK_SPEED_20000) ||
13764 (int_phy->flags & ELINK_FLAGS_WC_DUAL_MODE))
13765 vars->line_speed = ELINK_SPEED_20000;
13766 else
13767 vars->line_speed = ELINK_SPEED_10000;
13768
13769 if (!ELINK_USES_WARPCORE(params->chip_id))
13770 elink_xgxs_deassert(params);
13771 elink_link_initialize(params, vars);
13772
13773 if (params->req_line_speed[0] == ELINK_SPEED_1000) {
13774 if (ELINK_USES_WARPCORE(params->chip_id))
13775 elink_umac_enable(params, vars, 0);
13776 else {
13777 elink_emac_program(params, vars);
13778 elink_emac_enable(params, vars, 0);
13779 }
13780 } else {
13781 if (ELINK_USES_WARPCORE(params->chip_id))
13782 elink_xmac_enable(params, vars, 0);
13783 else
13784 elink_bmac_enable(params, vars, 0, 1);
13785 }
13786
13787 if (params->loopback_mode == ELINK_LOOPBACK_XGXS) {
13788 /* Set 10G XGXS loopback */
13789 int_phy->config_loopback(int_phy, params);
13790 } else {
13791 /* Set external phy loopback */
13792 u8 phy_index;
13793 for (phy_index = ELINK_EXT_PHY1;
13794 phy_index < params->num_phys; phy_index++)
13795 if (params->phy[phy_index].config_loopback)
13796 params->phy[phy_index].config_loopback(
13797 ¶ms->phy[phy_index],
13798 params);
13799 }
13800 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
13801
13802 elink_set_led(params, vars, ELINK_LED_MODE_OPER, vars->line_speed);
13803 }
13804 #endif // #ifdef ELINK_INCLUDE_LOOPBACK
13805
13806 #ifdef ELINK_ENHANCEMENTS
elink_set_rx_filter(struct elink_params * params,u8 en)13807 void elink_set_rx_filter(struct elink_params *params, u8 en)
13808 {
13809 struct elink_dev *cb = params->cb;
13810 u8 val = en * 0x1F;
13811
13812 /* Open / close the gate between the NIG and the BRB */
13813 if (!CHIP_IS_E1X(params->chip_id))
13814 val |= en * 0x20;
13815 REG_WR(cb, NIG_REG_LLH0_BRB1_DRV_MASK + params->port*4, val);
13816
13817 if (!CHIP_IS_E1(params->chip_id)) {
13818 REG_WR(cb, NIG_REG_LLH0_BRB1_DRV_MASK_MF + params->port*4,
13819 en*0x3);
13820 }
13821
13822 REG_WR(cb, (params->port ? NIG_REG_LLH1_BRB1_NOT_MCP :
13823 NIG_REG_LLH0_BRB1_NOT_MCP), en);
13824 }
13825 #endif /* #ifdef ELINK_ENHANCEMENTS */
13826 #ifndef EXCLUDE_NON_COMMON_INIT
elink_avoid_link_flap(struct elink_params * params,struct elink_vars * vars)13827 static elink_status_t elink_avoid_link_flap(struct elink_params *params,
13828 struct elink_vars *vars)
13829 {
13830 u32 phy_idx;
13831 u32 dont_clear_stat, lfa_sts;
13832 struct elink_dev *cb = params->cb;
13833
13834 elink_set_mdio_emac_per_phy(cb, params);
13835 /* Sync the link parameters */
13836 elink_link_status_update(params, vars);
13837
13838 /*
13839 * The module verification was already done by previous link owner,
13840 * so this call is meant only to get warning message
13841 */
13842
13843 for (phy_idx = ELINK_INT_PHY; phy_idx < params->num_phys; phy_idx++) {
13844 struct elink_phy *phy = ¶ms->phy[phy_idx];
13845 if (phy->phy_specific_func) {
13846 ELINK_DEBUG_P0(cb, "Calling PHY specific func\n");
13847 phy->phy_specific_func(phy, params, ELINK_PHY_INIT);
13848 }
13849 #ifdef ELINK_ENHANCEMENTS
13850 if ((phy->media_type == ELINK_ETH_PHY_SFPP_10G_FIBER) ||
13851 (phy->media_type == ELINK_ETH_PHY_SFP_1G_FIBER) ||
13852 (phy->media_type == ELINK_ETH_PHY_DA_TWINAX))
13853 elink_verify_sfp_module(phy, params);
13854 #endif
13855 }
13856 lfa_sts = REG_RD(cb, params->lfa_base +
13857 OFFSETOF(struct shmem_lfa,
13858 lfa_sts));
13859
13860 dont_clear_stat = lfa_sts & SHMEM_LFA_DONT_CLEAR_STAT;
13861
13862 /* Re-enable the NIG/MAC */
13863 if (CHIP_IS_E3(params->chip_id)) {
13864 #ifndef EXCLUDE_WARPCORE
13865 if (!dont_clear_stat) {
13866 REG_WR(cb, GRCBASE_MISC +
13867 MISC_REGISTERS_RESET_REG_2_CLEAR,
13868 (MISC_REGISTERS_RESET_REG_2_MSTAT0 <<
13869 params->port));
13870 REG_WR(cb, GRCBASE_MISC +
13871 MISC_REGISTERS_RESET_REG_2_SET,
13872 (MISC_REGISTERS_RESET_REG_2_MSTAT0 <<
13873 params->port));
13874 }
13875 if (vars->line_speed < ELINK_SPEED_10000)
13876 elink_umac_enable(params, vars, 0);
13877 else
13878 elink_xmac_enable(params, vars, 0);
13879 #endif
13880 } else {
13881 #ifndef EXCLUDE_BMAC2
13882 if (vars->line_speed < ELINK_SPEED_10000)
13883 elink_emac_enable(params, vars, 0);
13884 else
13885 elink_bmac_enable(params, vars, 0, !dont_clear_stat);
13886 #endif
13887 }
13888
13889 /* Increment LFA count */
13890 lfa_sts = ((lfa_sts & ~LINK_FLAP_AVOIDANCE_COUNT_MASK) |
13891 (((((lfa_sts & LINK_FLAP_AVOIDANCE_COUNT_MASK) >>
13892 LINK_FLAP_AVOIDANCE_COUNT_OFFSET) + 1) & 0xff)
13893 << LINK_FLAP_AVOIDANCE_COUNT_OFFSET));
13894 /* Clear link flap reason */
13895 lfa_sts &= ~LFA_LINK_FLAP_REASON_MASK;
13896
13897 REG_WR(cb, params->lfa_base +
13898 OFFSETOF(struct shmem_lfa, lfa_sts), lfa_sts);
13899
13900 /* Disable NIG DRAIN */
13901 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
13902
13903 /* Enable interrupts */
13904 elink_link_int_enable(params);
13905 return ELINK_STATUS_OK;
13906 }
13907
elink_cannot_avoid_link_flap(struct elink_params * params,struct elink_vars * vars,int lfa_status)13908 static void elink_cannot_avoid_link_flap(struct elink_params *params,
13909 struct elink_vars *vars,
13910 int lfa_status)
13911 {
13912 u32 lfa_sts, cfg_idx, tmp_val;
13913 struct elink_dev *cb = params->cb;
13914
13915 elink_link_reset(params, vars, 1);
13916
13917 if (!params->lfa_base)
13918 return;
13919 /* Store the new link parameters */
13920 REG_WR(cb, params->lfa_base +
13921 OFFSETOF(struct shmem_lfa, req_duplex),
13922 params->req_duplex[0] | (params->req_duplex[1] << 16));
13923
13924 REG_WR(cb, params->lfa_base +
13925 OFFSETOF(struct shmem_lfa, req_flow_ctrl),
13926 params->req_flow_ctrl[0] | (params->req_flow_ctrl[1] << 16));
13927
13928 REG_WR(cb, params->lfa_base +
13929 OFFSETOF(struct shmem_lfa, req_line_speed),
13930 params->req_line_speed[0] | (params->req_line_speed[1] << 16));
13931
13932 for (cfg_idx = 0; cfg_idx < SHMEM_LINK_CONFIG_SIZE; cfg_idx++) {
13933 REG_WR(cb, params->lfa_base +
13934 OFFSETOF(struct shmem_lfa,
13935 speed_cap_mask[cfg_idx]),
13936 params->speed_cap_mask[cfg_idx]);
13937 }
13938
13939 tmp_val = REG_RD(cb, params->lfa_base +
13940 OFFSETOF(struct shmem_lfa, additional_config));
13941 tmp_val &= ~REQ_FC_AUTO_ADV_MASK;
13942 tmp_val |= params->req_fc_auto_adv;
13943
13944 REG_WR(cb, params->lfa_base +
13945 OFFSETOF(struct shmem_lfa, additional_config), tmp_val);
13946
13947 lfa_sts = REG_RD(cb, params->lfa_base +
13948 OFFSETOF(struct shmem_lfa, lfa_sts));
13949
13950 /* Clear the "Don't Clear Statistics" bit, and set reason */
13951 lfa_sts &= ~SHMEM_LFA_DONT_CLEAR_STAT;
13952
13953 /* Set link flap reason */
13954 lfa_sts &= ~LFA_LINK_FLAP_REASON_MASK;
13955 lfa_sts |= ((lfa_status & LFA_LINK_FLAP_REASON_MASK) <<
13956 LFA_LINK_FLAP_REASON_OFFSET);
13957
13958 /* Increment link flap counter */
13959 lfa_sts = ((lfa_sts & ~LINK_FLAP_COUNT_MASK) |
13960 (((((lfa_sts & LINK_FLAP_COUNT_MASK) >>
13961 LINK_FLAP_COUNT_OFFSET) + 1) & 0xff)
13962 << LINK_FLAP_COUNT_OFFSET));
13963 REG_WR(cb, params->lfa_base +
13964 OFFSETOF(struct shmem_lfa, lfa_sts), lfa_sts);
13965 /* Proceed with regular link initialization */
13966 }
13967
elink_phy_init(struct elink_params * params,struct elink_vars * vars)13968 elink_status_t elink_phy_init(struct elink_params *params, struct elink_vars *vars)
13969 {
13970 int lfa_status;
13971 struct elink_dev *cb = params->cb;
13972 ELINK_DEBUG_P0(cb, "Phy Initialization started\n");
13973 ELINK_DEBUG_P2(cb, "(1) req_speed %d, req_flowctrl %d\n",
13974 params->req_line_speed[0], params->req_flow_ctrl[0]);
13975 ELINK_DEBUG_P2(cb, "(2) req_speed %d, req_flowctrl %d\n",
13976 params->req_line_speed[1], params->req_flow_ctrl[1]);
13977 ELINK_DEBUG_P1(cb, "req_adv_flow_ctrl 0x%x\n", params->req_fc_auto_adv);
13978 vars->link_status = 0;
13979 vars->phy_link_up = 0;
13980 vars->link_up = 0;
13981 vars->line_speed = 0;
13982 vars->duplex = DUPLEX_FULL;
13983 vars->flow_ctrl = ELINK_FLOW_CTRL_NONE;
13984 vars->mac_type = ELINK_MAC_TYPE_NONE;
13985 vars->phy_flags = 0;
13986 vars->check_kr2_recovery_cnt = 0;
13987 params->link_flags = ELINK_PHY_INITIALIZED;
13988 #ifdef ELINK_ENHANCEMENTS
13989 /* Driver opens NIG-BRB filters */
13990 elink_set_rx_filter(params, 1);
13991 #endif
13992 elink_chng_link_count(params, 1);
13993 /* Check if link flap can be avoided */
13994 lfa_status = elink_check_lfa(params);
13995
13996 if (lfa_status == 0) {
13997 ELINK_DEBUG_P0(cb, "Link Flap Avoidance in progress\n");
13998 return elink_avoid_link_flap(params, vars);
13999 }
14000
14001 ELINK_DEBUG_P1(cb, "Cannot avoid link flap lfa_sta=0x%x\n",
14002 lfa_status);
14003 elink_cannot_avoid_link_flap(params, vars, lfa_status);
14004
14005 /* Disable attentions */
14006 elink_bits_dis(cb, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
14007 (ELINK_NIG_MASK_XGXS0_LINK_STATUS |
14008 ELINK_NIG_MASK_XGXS0_LINK10G |
14009 ELINK_NIG_MASK_SERDES0_LINK_STATUS |
14010 ELINK_NIG_MASK_MI_INT));
14011 #ifdef ELINK_INCLUDE_EMUL
14012 if (!(params->feature_config_flags &
14013 ELINK_FEATURE_CONFIG_EMUL_DISABLE_EMAC))
14014 #endif //ELINK_INCLUDE_EMUL
14015
14016 elink_emac_init(params, vars);
14017
14018 if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED)
14019 vars->link_status |= LINK_STATUS_PFC_ENABLED;
14020
14021 if ((params->num_phys == 0) &&
14022 !CHIP_REV_IS_SLOW(params->chip_id)) {
14023 ELINK_DEBUG_P0(cb, "No phy found for initialization !!\n");
14024 return ELINK_STATUS_ERROR;
14025 }
14026 set_phy_vars(params, vars);
14027
14028 ELINK_DEBUG_P1(cb, "Num of phys on board: %d\n", params->num_phys);
14029 #ifdef ELINK_INCLUDE_FPGA
14030 if (CHIP_REV_IS_FPGA(params->chip_id)) {
14031 return elink_init_fpga(params, vars);
14032 } else
14033 #endif /* ELINK_INCLUDE_FPGA */
14034 #ifdef ELINK_INCLUDE_EMUL
14035 if (CHIP_REV_IS_EMUL(params->chip_id)) {
14036 return elink_init_emul(params, vars);
14037 } else
14038 #endif /* ELINK_INCLUDE_EMUL */
14039 #ifdef ELINK_INCLUDE_LOOPBACK
14040 switch (params->loopback_mode) {
14041 case ELINK_LOOPBACK_BMAC:
14042 elink_init_bmac_loopback(params, vars);
14043 break;
14044 case ELINK_LOOPBACK_EMAC:
14045 elink_init_emac_loopback(params, vars);
14046 break;
14047 case ELINK_LOOPBACK_XMAC:
14048 elink_init_xmac_loopback(params, vars);
14049 break;
14050 case ELINK_LOOPBACK_UMAC:
14051 elink_init_umac_loopback(params, vars);
14052 break;
14053 case ELINK_LOOPBACK_XGXS:
14054 case ELINK_LOOPBACK_EXT_PHY:
14055 elink_init_xgxs_loopback(params, vars);
14056 break;
14057 default:
14058 #endif /* ELINK_INCLUDE_LOOPBACK */
14059 #ifndef EXCLUDE_XGXS
14060 if (!CHIP_IS_E3(params->chip_id)) {
14061 if (params->switch_cfg == ELINK_SWITCH_CFG_10G)
14062 elink_xgxs_deassert(params);
14063 #ifndef EXCLUDE_SERDES
14064 else
14065 elink_serdes_deassert(cb, params->port);
14066 #endif // EXCLUDE_SERDES
14067 }
14068 #endif /* EXCLUDE_XGXS */
14069 elink_link_initialize(params, vars);
14070 MSLEEP(cb, 30);
14071 elink_link_int_enable(params);
14072 #ifdef ELINK_INCLUDE_LOOPBACK
14073 break;
14074 }
14075 #endif // ELINK_INCLUDE_LOOPBACK
14076 elink_update_mng(params, vars->link_status);
14077
14078 #ifndef EXCLUDE_WARPCORE
14079 elink_update_mng_eee(params, vars->eee_status);
14080 #endif /* #ifndef EXCLUDE_BCM84833 */
14081 return ELINK_STATUS_OK;
14082 }
14083
14084 #ifndef EXCLUDE_LINK_RESET
elink_link_reset(struct elink_params * params,struct elink_vars * vars,u8 reset_ext_phy)14085 elink_status_t elink_link_reset(struct elink_params *params, struct elink_vars *vars,
14086 u8 reset_ext_phy)
14087 {
14088 struct elink_dev *cb = params->cb;
14089 u8 phy_index, port = params->port, clear_latch_ind = 0;
14090 ELINK_DEBUG_P1(cb, "Resetting the link of port %d\n", port);
14091 /* Disable attentions */
14092 vars->link_status = 0;
14093 elink_chng_link_count(params, 1);
14094 elink_update_mng(params, vars->link_status);
14095 #ifndef EXCLUDE_WARPCORE
14096 vars->eee_status &= ~(SHMEM_EEE_LP_ADV_STATUS_MASK |
14097 SHMEM_EEE_ACTIVE_BIT);
14098 elink_update_mng_eee(params, vars->eee_status);
14099 #endif /* #ifndef EXCLUDE_BCM84833 */
14100 elink_bits_dis(cb, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
14101 (ELINK_NIG_MASK_XGXS0_LINK_STATUS |
14102 ELINK_NIG_MASK_XGXS0_LINK10G |
14103 ELINK_NIG_MASK_SERDES0_LINK_STATUS |
14104 ELINK_NIG_MASK_MI_INT));
14105
14106 /* Activate nig drain */
14107 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
14108
14109 /* Disable nig egress interface */
14110 if (!CHIP_IS_E3(params->chip_id)) {
14111 REG_WR(cb, NIG_REG_BMAC0_OUT_EN + port*4, 0);
14112 REG_WR(cb, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
14113 }
14114
14115 #ifdef ELINK_INCLUDE_EMUL
14116 /* Stop BigMac rx */
14117 if (!(params->feature_config_flags &
14118 ELINK_FEATURE_CONFIG_EMUL_DISABLE_BMAC))
14119 #endif // ELINK_INCLUDE_EMUL
14120 #if !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1)
14121 if (!CHIP_IS_E3(params->chip_id))
14122 elink_set_bmac_rx(cb, params->chip_id, port, 0);
14123 #endif // !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1)
14124 #ifndef EXCLUDE_WARPCORE
14125 #ifdef ELINK_INCLUDE_EMUL
14126 /* Stop XMAC/UMAC rx */
14127 if (!(params->feature_config_flags &
14128 ELINK_FEATURE_CONFIG_EMUL_DISABLE_XMAC))
14129 #endif // ELINK_INCLUDE_EMUL
14130 if (CHIP_IS_E3(params->chip_id) &&
14131 !CHIP_REV_IS_FPGA(params->chip_id)) {
14132 elink_set_xmac_rxtx(params, 0);
14133 elink_set_umac_rxtx(params, 0);
14134 }
14135 #endif // EXCLUDE_WARPCORE
14136 /* Disable emac */
14137 if (!CHIP_IS_E3(params->chip_id))
14138 REG_WR(cb, NIG_REG_NIG_EMAC0_EN + port*4, 0);
14139
14140 MSLEEP(cb, 10);
14141 /* The PHY reset is controlled by GPIO 1
14142 * Hold it as vars low
14143 */
14144 /* Clear link led */
14145 elink_set_mdio_emac_per_phy(cb, params);
14146 elink_set_led(params, vars, ELINK_LED_MODE_OFF, 0);
14147
14148 if (reset_ext_phy && (!CHIP_REV_IS_SLOW(params->chip_id))) {
14149 for (phy_index = ELINK_EXT_PHY1; phy_index < params->num_phys;
14150 phy_index++) {
14151 if (params->phy[phy_index].link_reset) {
14152 elink_set_aer_mmd(params,
14153 ¶ms->phy[phy_index]);
14154 params->phy[phy_index].link_reset(
14155 ¶ms->phy[phy_index],
14156 params);
14157 }
14158 if (params->phy[phy_index].flags &
14159 ELINK_FLAGS_REARM_LATCH_SIGNAL)
14160 clear_latch_ind = 1;
14161 }
14162 }
14163
14164 if (clear_latch_ind) {
14165 /* Clear latching indication */
14166 elink_rearm_latch_signal(cb, port, 0);
14167 elink_bits_dis(cb, NIG_REG_LATCH_BC_0 + port*4,
14168 1 << ELINK_NIG_LATCH_BC_ENABLE_MI_INT);
14169 }
14170 #if defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA)
14171 if (!CHIP_REV_IS_SLOW(params->chip_id))
14172 #endif
14173 if (params->phy[ELINK_INT_PHY].link_reset)
14174 params->phy[ELINK_INT_PHY].link_reset(
14175 ¶ms->phy[ELINK_INT_PHY], params);
14176
14177 /* Disable nig ingress interface */
14178 if (!CHIP_IS_E3(params->chip_id)) {
14179 /* Reset BigMac */
14180 REG_WR(cb, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
14181 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
14182 REG_WR(cb, NIG_REG_BMAC0_IN_EN + port*4, 0);
14183 REG_WR(cb, NIG_REG_EMAC0_IN_EN + port*4, 0);
14184 } else {
14185 #ifndef EXCLUDE_WARPCORE
14186 u32 xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
14187 elink_set_xumac_nig(params, 0, 0);
14188 if (REG_RD(cb, MISC_REG_RESET_REG_2) &
14189 MISC_REGISTERS_RESET_REG_2_XMAC)
14190 REG_WR(cb, xmac_base + XMAC_REG_CTRL,
14191 XMAC_CTRL_REG_SOFT_RESET);
14192 #endif // EXCLUDE_WARPCORE
14193 }
14194 vars->link_up = 0;
14195 vars->phy_flags = 0;
14196 return ELINK_STATUS_OK;
14197 }
14198 #endif // EXCLUDE_LINK_RESET
14199 #ifndef ELINK_AUX_POWER
elink_lfa_reset(struct elink_params * params,struct elink_vars * vars)14200 elink_status_t elink_lfa_reset(struct elink_params *params,
14201 struct elink_vars *vars)
14202 {
14203 struct elink_dev *cb = params->cb;
14204 vars->link_up = 0;
14205 vars->phy_flags = 0;
14206 params->link_flags &= ~ELINK_PHY_INITIALIZED;
14207 if (!params->lfa_base)
14208 return elink_link_reset(params, vars, 1);
14209 /*
14210 * Activate NIG drain so that during this time the device won't send
14211 * anything while it is unable to response.
14212 */
14213 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 1);
14214
14215 /*
14216 * Close gracefully the gate from BMAC to NIG such that no half packets
14217 * are passed.
14218 */
14219 if (!CHIP_IS_E3(params->chip_id))
14220 elink_set_bmac_rx(cb, params->chip_id, params->port, 0);
14221
14222 if (CHIP_IS_E3(params->chip_id)) {
14223 elink_set_xmac_rxtx(params, 0);
14224 elink_set_umac_rxtx(params, 0);
14225 }
14226 /* Wait 10ms for the pipe to clean up*/
14227 MSLEEP(cb, 10);
14228
14229 #ifdef ELINK_ENHANCEMENTS
14230 /* Clean the NIG-BRB using the network filters in a way that will
14231 * not cut a packet in the middle.
14232 */
14233 elink_set_rx_filter(params, 0);
14234 #endif
14235
14236 /*
14237 * Re-open the gate between the BMAC and the NIG, after verifying the
14238 * gate to the BRB is closed, otherwise packets may arrive to the
14239 * firmware before driver had initialized it. The target is to achieve
14240 * minimum management protocol down time.
14241 */
14242 if (!CHIP_IS_E3(params->chip_id))
14243 elink_set_bmac_rx(cb, params->chip_id, params->port, 1);
14244
14245 if (CHIP_IS_E3(params->chip_id)) {
14246 elink_set_xmac_rxtx(params, 1);
14247 elink_set_umac_rxtx(params, 1);
14248 }
14249 /* Disable NIG drain */
14250 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
14251 return ELINK_STATUS_OK;
14252 }
14253 #endif /* ELINK_AUX_POWER */
14254 #endif // EXCLUDE_NON_COMMON_INIT
14255
14256 /****************************************************************************/
14257 /* Common function */
14258 /****************************************************************************/
14259 #ifndef EXCLUDE_COMMON_INIT
14260 #ifndef ELINK_EMUL_ONLY
14261 #ifndef EXCLUDE_BCM8727_BCM8073
elink_8073_common_init_phy(struct elink_dev * cb,u32 shmem_base_path[],u32 shmem2_base_path[],u8 phy_index,u32 chip_id)14262 static elink_status_t elink_8073_common_init_phy(struct elink_dev *cb,
14263 u32 shmem_base_path[],
14264 u32 shmem2_base_path[], u8 phy_index,
14265 u32 chip_id)
14266 {
14267 struct elink_phy phy[PORT_MAX];
14268 struct elink_phy *phy_blk[PORT_MAX];
14269 u16 val;
14270 s8 port = 0;
14271 s8 port_of_path = 0;
14272 u32 swap_val, swap_override;
14273 swap_val = REG_RD(cb, NIG_REG_PORT_SWAP);
14274 swap_override = REG_RD(cb, NIG_REG_STRAP_OVERRIDE);
14275 port ^= (swap_val && swap_override);
14276 elink_ext_phy_hw_reset(cb, port);
14277 /* PART1 - Reset both phys */
14278 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
14279 u32 shmem_base, shmem2_base;
14280 /* In E2, same phy is using for port0 of the two paths */
14281 if (CHIP_IS_E1X(chip_id)) {
14282 shmem_base = shmem_base_path[0];
14283 shmem2_base = shmem2_base_path[0];
14284 port_of_path = port;
14285 } else {
14286 shmem_base = shmem_base_path[port];
14287 shmem2_base = shmem2_base_path[port];
14288 port_of_path = 0;
14289 }
14290
14291 /* Extract the ext phy address for the port */
14292 if (elink_populate_phy(cb, phy_index, shmem_base, shmem2_base,
14293 port_of_path, &phy[port]) !=
14294 ELINK_STATUS_OK) {
14295 ELINK_DEBUG_P0(cb, "populate_phy failed\n");
14296 return ELINK_STATUS_ERROR;
14297 }
14298 /* Disable attentions */
14299 elink_bits_dis(cb, NIG_REG_MASK_INTERRUPT_PORT0 +
14300 port_of_path*4,
14301 (ELINK_NIG_MASK_XGXS0_LINK_STATUS |
14302 ELINK_NIG_MASK_XGXS0_LINK10G |
14303 ELINK_NIG_MASK_SERDES0_LINK_STATUS |
14304 ELINK_NIG_MASK_MI_INT));
14305
14306 /* Need to take the phy out of low power mode in order
14307 * to write to access its registers
14308 */
14309 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_2,
14310 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
14311 port);
14312
14313 /* Reset the phy */
14314 elink_cl45_write(cb, &phy[port],
14315 MDIO_PMA_DEVAD,
14316 MDIO_PMA_REG_CTRL,
14317 1<<15);
14318 }
14319
14320 /* Add delay of 150ms after reset */
14321 MSLEEP(cb, 150);
14322
14323 if (phy[PORT_0].addr & 0x1) {
14324 phy_blk[PORT_0] = &(phy[PORT_1]);
14325 phy_blk[PORT_1] = &(phy[PORT_0]);
14326 } else {
14327 phy_blk[PORT_0] = &(phy[PORT_0]);
14328 phy_blk[PORT_1] = &(phy[PORT_1]);
14329 }
14330
14331 /* PART2 - Download firmware to both phys */
14332 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
14333 if (CHIP_IS_E1X(chip_id))
14334 port_of_path = port;
14335 else
14336 port_of_path = 0;
14337
14338 ELINK_DEBUG_P1(cb, "Loading spirom for phy address 0x%x\n",
14339 phy_blk[port]->addr);
14340 if (elink_8073_8727_external_rom_boot(cb, phy_blk[port],
14341 port_of_path))
14342 return ELINK_STATUS_ERROR;
14343
14344 /* Only set bit 10 = 1 (Tx power down) */
14345 elink_cl45_read(cb, phy_blk[port],
14346 MDIO_PMA_DEVAD,
14347 MDIO_PMA_REG_TX_POWER_DOWN, &val);
14348
14349 /* Phase1 of TX_POWER_DOWN reset */
14350 elink_cl45_write(cb, phy_blk[port],
14351 MDIO_PMA_DEVAD,
14352 MDIO_PMA_REG_TX_POWER_DOWN,
14353 (val | 1<<10));
14354 }
14355
14356 /* Toggle Transmitter: Power down and then up with 600ms delay
14357 * between
14358 */
14359 MSLEEP(cb, 600);
14360
14361 /* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low */
14362 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
14363 /* Phase2 of POWER_DOWN_RESET */
14364 /* Release bit 10 (Release Tx power down) */
14365 elink_cl45_read(cb, phy_blk[port],
14366 MDIO_PMA_DEVAD,
14367 MDIO_PMA_REG_TX_POWER_DOWN, &val);
14368
14369 elink_cl45_write(cb, phy_blk[port],
14370 MDIO_PMA_DEVAD,
14371 MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
14372 MSLEEP(cb, 15);
14373
14374 /* Read modify write the SPI-ROM version select register */
14375 elink_cl45_read(cb, phy_blk[port],
14376 MDIO_PMA_DEVAD,
14377 MDIO_PMA_REG_EDC_FFE_MAIN, &val);
14378 elink_cl45_write(cb, phy_blk[port],
14379 MDIO_PMA_DEVAD,
14380 MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
14381
14382 /* set GPIO2 back to LOW */
14383 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_2,
14384 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
14385 }
14386 return ELINK_STATUS_OK;
14387 }
14388 #endif /* EXCLUDE_BCM8727_BCM8073 */
14389 #ifndef EXCLUDE_BCM87x6
elink_8726_common_init_phy(struct elink_dev * cb,u32 shmem_base_path[],u32 shmem2_base_path[],u8 phy_index,u32 chip_id)14390 static elink_status_t elink_8726_common_init_phy(struct elink_dev *cb,
14391 u32 shmem_base_path[],
14392 u32 shmem2_base_path[], u8 phy_index,
14393 u32 chip_id)
14394 {
14395 u32 val;
14396 s8 port;
14397 struct elink_phy phy;
14398 /* Use port1 because of the static port-swap */
14399 /* Enable the module detection interrupt */
14400 val = REG_RD(cb, MISC_REG_GPIO_EVENT_EN);
14401 val |= ((1<<MISC_REGISTERS_GPIO_3)|
14402 (1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT)));
14403 REG_WR(cb, MISC_REG_GPIO_EVENT_EN, val);
14404
14405 elink_ext_phy_hw_reset(cb, 0);
14406 MSLEEP(cb, 5);
14407 for (port = 0; port < PORT_MAX; port++) {
14408 u32 shmem_base, shmem2_base;
14409
14410 /* In E2, same phy is using for port0 of the two paths */
14411 if (CHIP_IS_E1X(chip_id)) {
14412 shmem_base = shmem_base_path[0];
14413 shmem2_base = shmem2_base_path[0];
14414 } else {
14415 shmem_base = shmem_base_path[port];
14416 shmem2_base = shmem2_base_path[port];
14417 }
14418 /* Extract the ext phy address for the port */
14419 if (elink_populate_phy(cb, phy_index, shmem_base, shmem2_base,
14420 port, &phy) !=
14421 ELINK_STATUS_OK) {
14422 ELINK_DEBUG_P0(cb, "populate phy failed\n");
14423 return ELINK_STATUS_ERROR;
14424 }
14425
14426 /* Reset phy*/
14427 elink_cl45_write(cb, &phy,
14428 MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x0001);
14429
14430
14431 /* Set fault module detected LED on */
14432 ELINK_SET_GPIO(cb, MISC_REGISTERS_GPIO_0,
14433 MISC_REGISTERS_GPIO_HIGH,
14434 port);
14435 }
14436
14437 return ELINK_STATUS_OK;
14438 }
14439 #endif /* #ifndef EXCLUDE_BCM87x6 */
14440 #ifndef EXCLUDE_BCM8727_BCM8073
elink_get_ext_phy_reset_gpio(struct elink_dev * cb,u32 shmem_base,u8 * io_gpio,u8 * io_port)14441 static void elink_get_ext_phy_reset_gpio(struct elink_dev *cb, u32 shmem_base,
14442 u8 *io_gpio, u8 *io_port)
14443 {
14444
14445 u32 phy_gpio_reset = REG_RD(cb, shmem_base +
14446 OFFSETOF(struct shmem_region,
14447 dev_info.port_hw_config[PORT_0].default_cfg));
14448 switch (phy_gpio_reset) {
14449 case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0:
14450 *io_gpio = 0;
14451 *io_port = 0;
14452 break;
14453 case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0:
14454 *io_gpio = 1;
14455 *io_port = 0;
14456 break;
14457 case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0:
14458 *io_gpio = 2;
14459 *io_port = 0;
14460 break;
14461 case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0:
14462 *io_gpio = 3;
14463 *io_port = 0;
14464 break;
14465 case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1:
14466 *io_gpio = 0;
14467 *io_port = 1;
14468 break;
14469 case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1:
14470 *io_gpio = 1;
14471 *io_port = 1;
14472 break;
14473 case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1:
14474 *io_gpio = 2;
14475 *io_port = 1;
14476 break;
14477 case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1:
14478 *io_gpio = 3;
14479 *io_port = 1;
14480 break;
14481 default:
14482 /* Don't override the io_gpio and io_port */
14483 break;
14484 }
14485 }
14486
elink_8727_common_init_phy(struct elink_dev * cb,u32 shmem_base_path[],u32 shmem2_base_path[],u8 phy_index,u32 chip_id)14487 static elink_status_t elink_8727_common_init_phy(struct elink_dev *cb,
14488 u32 shmem_base_path[],
14489 u32 shmem2_base_path[], u8 phy_index,
14490 u32 chip_id)
14491 {
14492 s8 port, reset_gpio;
14493 u32 swap_val, swap_override;
14494 struct elink_phy phy[PORT_MAX];
14495 struct elink_phy *phy_blk[PORT_MAX];
14496 s8 port_of_path;
14497 swap_val = REG_RD(cb, NIG_REG_PORT_SWAP);
14498 swap_override = REG_RD(cb, NIG_REG_STRAP_OVERRIDE);
14499
14500 reset_gpio = MISC_REGISTERS_GPIO_1;
14501 port = 1;
14502
14503 /* Retrieve the reset gpio/port which control the reset.
14504 * Default is GPIO1, PORT1
14505 */
14506 elink_get_ext_phy_reset_gpio(cb, shmem_base_path[0],
14507 (u8 *)&reset_gpio, (u8 *)&port);
14508
14509 /* Calculate the port based on port swap */
14510 port ^= (swap_val && swap_override);
14511
14512 /* Initiate PHY reset*/
14513 ELINK_SET_GPIO(cb, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_LOW,
14514 port);
14515 MSLEEP(cb, 1);
14516 ELINK_SET_GPIO(cb, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_HIGH,
14517 port);
14518
14519 MSLEEP(cb, 5);
14520
14521 /* PART1 - Reset both phys */
14522 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
14523 u32 shmem_base, shmem2_base;
14524
14525 /* In E2, same phy is using for port0 of the two paths */
14526 if (CHIP_IS_E1X(chip_id)) {
14527 shmem_base = shmem_base_path[0];
14528 shmem2_base = shmem2_base_path[0];
14529 port_of_path = port;
14530 } else {
14531 shmem_base = shmem_base_path[port];
14532 shmem2_base = shmem2_base_path[port];
14533 port_of_path = 0;
14534 }
14535
14536 /* Extract the ext phy address for the port */
14537 if (elink_populate_phy(cb, phy_index, shmem_base, shmem2_base,
14538 port_of_path, &phy[port]) !=
14539 ELINK_STATUS_OK) {
14540 ELINK_DEBUG_P0(cb, "populate phy failed\n");
14541 return ELINK_STATUS_ERROR;
14542 }
14543 /* disable attentions */
14544 elink_bits_dis(cb, NIG_REG_MASK_INTERRUPT_PORT0 +
14545 port_of_path*4,
14546 (ELINK_NIG_MASK_XGXS0_LINK_STATUS |
14547 ELINK_NIG_MASK_XGXS0_LINK10G |
14548 ELINK_NIG_MASK_SERDES0_LINK_STATUS |
14549 ELINK_NIG_MASK_MI_INT));
14550
14551
14552 /* Reset the phy */
14553 elink_cl45_write(cb, &phy[port],
14554 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
14555 }
14556
14557 /* Add delay of 150ms after reset */
14558 MSLEEP(cb, 150);
14559 if (phy[PORT_0].addr & 0x1) {
14560 phy_blk[PORT_0] = &(phy[PORT_1]);
14561 phy_blk[PORT_1] = &(phy[PORT_0]);
14562 } else {
14563 phy_blk[PORT_0] = &(phy[PORT_0]);
14564 phy_blk[PORT_1] = &(phy[PORT_1]);
14565 }
14566 /* PART2 - Download firmware to both phys */
14567 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
14568 if (CHIP_IS_E1X(chip_id))
14569 port_of_path = port;
14570 else
14571 port_of_path = 0;
14572 ELINK_DEBUG_P1(cb, "Loading spirom for phy address 0x%x\n",
14573 phy_blk[port]->addr);
14574 if (elink_8073_8727_external_rom_boot(cb, phy_blk[port],
14575 port_of_path))
14576 return ELINK_STATUS_ERROR;
14577 /* Disable PHY transmitter output */
14578 elink_cl45_write(cb, phy_blk[port],
14579 MDIO_PMA_DEVAD,
14580 MDIO_PMA_REG_TX_DISABLE, 1);
14581
14582 }
14583 return ELINK_STATUS_OK;
14584 }
14585 #endif /* EXCLUDE_BCM8727_BCM8073 */
14586
14587 #ifndef EXCLUDE_BCM84833
elink_84833_common_init_phy(struct elink_dev * cb,u32 shmem_base_path[],u32 shmem2_base_path[],u8 phy_index,u32 chip_id)14588 static elink_status_t elink_84833_common_init_phy(struct elink_dev *cb,
14589 u32 shmem_base_path[],
14590 u32 shmem2_base_path[],
14591 u8 phy_index,
14592 u32 chip_id)
14593 {
14594 u8 reset_gpios;
14595 reset_gpios = elink_84833_get_reset_gpios(cb, shmem_base_path, chip_id);
14596 #ifndef EDEBUG
14597 ELINK_SET_MULT_GPIO(cb, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
14598 USLEEP(cb, 10);
14599 ELINK_SET_MULT_GPIO(cb, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH);
14600 ELINK_DEBUG_P1(cb, "84833 reset pulse on pin values 0x%x\n",
14601 reset_gpios);
14602 #endif
14603 return ELINK_STATUS_OK;
14604 }
14605 #ifndef EXCLUDE_FROM_BNX2X
elink_84833_pre_init_phy(struct elink_dev * cb,struct elink_phy * phy,u8 port)14606 static elink_status_t elink_84833_pre_init_phy(struct elink_dev *cb,
14607 struct elink_phy *phy,
14608 u8 port)
14609 {
14610 u16 val, cnt;
14611 /* Wait for FW completing its initialization. */
14612 for (cnt = 0; cnt < 1500; cnt++) {
14613 elink_cl45_read(cb, phy,
14614 MDIO_PMA_DEVAD,
14615 MDIO_PMA_REG_CTRL, &val);
14616 if (!(val & (1<<15)))
14617 break;
14618 MSLEEP(cb, 1);
14619 }
14620 if (cnt >= 1500) {
14621 ELINK_DEBUG_P0(cb, "84833 reset timeout\n");
14622 return ELINK_STATUS_ERROR;
14623 }
14624
14625 /* Put the port in super isolate mode. */
14626 elink_cl45_read(cb, phy,
14627 MDIO_CTL_DEVAD,
14628 MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
14629 val |= MDIO_84833_SUPER_ISOLATE;
14630 elink_cl45_write(cb, phy,
14631 MDIO_CTL_DEVAD,
14632 MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
14633
14634 /* Save spirom version */
14635 elink_save_848xx_spirom_version(phy, cb, port);
14636 return ELINK_STATUS_OK;
14637 }
14638
elink_pre_init_phy(struct elink_dev * cb,u32 shmem_base,u32 shmem2_base,u32 chip_id,u8 port)14639 elink_status_t elink_pre_init_phy(struct elink_dev *cb,
14640 u32 shmem_base,
14641 u32 shmem2_base,
14642 u32 chip_id,
14643 u8 port)
14644 {
14645 elink_status_t rc = ELINK_STATUS_OK;
14646 struct elink_phy phy;
14647 if (elink_populate_phy(cb, ELINK_EXT_PHY1, shmem_base, shmem2_base,
14648 port, &phy) != ELINK_STATUS_OK) {
14649 ELINK_DEBUG_P0(cb, "populate_phy failed\n");
14650 return ELINK_STATUS_ERROR;
14651 }
14652 elink_set_mdio_clk(cb, chip_id, phy.mdio_ctrl);
14653 switch (phy.type) {
14654 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
14655 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
14656 rc = elink_84833_pre_init_phy(cb, &phy, port);
14657 break;
14658 default:
14659 break;
14660 }
14661 return rc;
14662 }
14663 #endif /* EXCLUDE_FROM_BNX2X */
14664 #endif /* EXCLUDE_BCM84833 */
elink_ext_phy_common_init(struct elink_dev * cb,u32 shmem_base_path[],u32 shmem2_base_path[],u8 phy_index,u32 ext_phy_type,u32 chip_id)14665 static elink_status_t elink_ext_phy_common_init(struct elink_dev *cb, u32 shmem_base_path[],
14666 u32 shmem2_base_path[], u8 phy_index,
14667 u32 ext_phy_type, u32 chip_id)
14668 {
14669 elink_status_t rc = ELINK_STATUS_OK;
14670
14671 switch (ext_phy_type) {
14672 #ifndef EXCLUDE_BCM8727_BCM8073
14673 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
14674 rc = elink_8073_common_init_phy(cb, shmem_base_path,
14675 shmem2_base_path,
14676 phy_index, chip_id);
14677 break;
14678 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
14679 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
14680 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
14681 rc = elink_8727_common_init_phy(cb, shmem_base_path,
14682 shmem2_base_path,
14683 phy_index, chip_id);
14684 break;
14685
14686 #endif
14687 #ifndef EXCLUDE_BCM87x6
14688 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
14689 /* GPIO1 affects both ports, so there's need to pull
14690 * it for single port alone
14691 */
14692 rc = elink_8726_common_init_phy(cb, shmem_base_path,
14693 shmem2_base_path,
14694 phy_index, chip_id);
14695 break;
14696 #endif /* #ifndef EXCLUDE_BCM87x6 */
14697 #ifndef EXCLUDE_BCM84833
14698 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
14699 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
14700 /* GPIO3's are linked, and so both need to be toggled
14701 * to obtain required 2us pulse.
14702 */
14703 rc = elink_84833_common_init_phy(cb, shmem_base_path,
14704 shmem2_base_path,
14705 phy_index, chip_id);
14706 break;
14707 #endif
14708 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
14709 rc = ELINK_STATUS_ERROR;
14710 break;
14711 default:
14712 ELINK_DEBUG_P1(cb,
14713 "ext_phy 0x%x common init not required\n",
14714 ext_phy_type);
14715 break;
14716 }
14717
14718 if (rc != ELINK_STATUS_OK)
14719 elink_cb_event_log(cb, ELINK_LOG_ID_PHY_UNINITIALIZED, 0); // "Warning: PHY was not initialized,"
14720 // " Port %d\n",
14721
14722 return rc;
14723 }
14724
14725 #ifdef INCLUDE_WARPCORE_UC_LOAD
elink_warpcore_common_init(struct elink_dev * cb,u32 shmem_base_path[],u32 shmem2_base_path[],u8 phy_index,u32 chip_id,u8 one_port_enabled)14726 static elink_status_t elink_warpcore_common_init(struct elink_dev *cb,
14727 u32 shmem_base_path[],
14728 u32 shmem2_base_path[],
14729 u8 phy_index,
14730 u32 chip_id,
14731 u8 one_port_enabled)
14732 {
14733 struct elink_phy phy;
14734 u32 wc_lane_config;
14735 u16 val;
14736 elink_status_t rc;
14737
14738 REG_WR(cb, MISC_REG_LCPLL_E40_PWRDWN, 0);
14739 /* Procedure to bring the LCPLL out of reset. */
14740 MSLEEP(cb, 1);
14741 REG_WR(cb, MISC_REG_LCPLL_E40_RESETB_ANA, 1);
14742 MSLEEP(cb, 1);
14743 REG_WR(cb, MISC_REG_LCPLL_E40_RESETB_DIG, 1);
14744
14745 ELINK_DEBUG_P0(cb, "Resetting Warpcore\n");
14746
14747 if (elink_reset_warpcore(cb) != ELINK_STATUS_OK)
14748 return ELINK_STATUS_ERROR;
14749
14750 /* Extract the ext phy address for the port */
14751 if (elink_populate_phy(cb, phy_index, shmem_base_path[0],
14752 shmem2_base_path[0],
14753 0, &phy) != ELINK_STATUS_OK) {
14754 ELINK_DEBUG_P0(cb, "populate phy failed\n");
14755 return ELINK_STATUS_ERROR;
14756 }
14757
14758 /* Set WC to use CL45 */
14759 REG_WR(cb, MISC_REG_WC0_CTRL_MD_ST, 0);
14760 /* Set swap lanes and polarity */
14761 wc_lane_config = REG_RD(cb, shmem_base_path[0] +
14762 OFFSETOF(struct shmem_region, dev_info.
14763 shared_hw_config.wc_lane_config));
14764
14765 /* Power down warpcore lanes */
14766 if (one_port_enabled)
14767 elink_warpcore_powerdown_secondport_lanes(cb, &phy);
14768
14769 /* Disable sequencer */
14770 elink_warpcore_sequencer(cb, &phy, 0);
14771
14772 elink_warpcore_set_lane_swap(cb, &phy, wc_lane_config);
14773 elink_warpcore_set_lane_polarity(cb, &phy, wc_lane_config);
14774
14775 if (phy.flags & ELINK_FLAGS_WC_DUAL_MODE)
14776 elink_warpcore_set_dual_mode(cb, &phy, shmem_base_path[0]);
14777 else
14778 elink_warpcore_set_quad_mode(cb, &phy);
14779
14780 /* Load Warpcore microcode */
14781 rc = elink_warpcore_load_uc(cb, &phy);
14782 if (rc != ELINK_STATUS_OK)
14783 return rc;
14784
14785 /* RX traffic and TX traffic requires clock sync.
14786 * When transmiting we send data + clock to the Warpcore.
14787 * This clock is provided by lane 0 of the Warpcore.
14788 * So we need to configure this lane to supply us the correct clock
14789 * which will be use for transmit on all lanes
14790 */
14791
14792 CL22_WR_OVER_CL45(cb, &phy, MDIO_REG_BANK_AER_BLOCK,
14793 MDIO_AER_BLOCK_AER_REG, 0);
14794 elink_cl45_read(cb, &phy, MDIO_WC_DEVAD,
14795 MDIO_WC_REG_XGXS_X2_CONTROL2, &val);
14796 val &= 0xDE1F;
14797 if (phy.flags & ELINK_FLAGS_WC_DUAL_MODE) {
14798 val |= (1<<11);
14799 val |= (9<<5);
14800 /* To force tx_wclk33 to txckp[0] */
14801 if (phy.supported & ELINK_SUPPORTED_20000baseKR2_Full)
14802 val |= (1<<13);
14803
14804 /* Dual mode - lanes 0,1 use same clocks/resets - from lane 0
14805 * Lanes 2,3 use same clocks/resets - from lane 2
14806 */
14807 elink_cl45_write(cb, &phy, MDIO_WC_DEVAD,
14808 MDIO_WC_REG_XGXS_X2_CONTROL3, 0x7);
14809 } else
14810 val |= 0x2800;
14811
14812 elink_cl45_write(cb, &phy, MDIO_WC_DEVAD,
14813 MDIO_WC_REG_XGXS_X2_CONTROL2, val);
14814
14815 /* Enable sequencer */
14816 elink_warpcore_sequencer(cb, &phy, 1);
14817
14818 return ELINK_STATUS_OK;
14819 }
14820
14821 #endif /* INCLUDE_WARPCORE_UC_LOAD */
14822 #endif /* ELINK_EMUL_ONLY */
elink_common_init_phy(struct elink_dev * cb,u32 shmem_base_path[],u32 shmem2_base_path[],u32 chip_id,u8 one_port_enabled)14823 elink_status_t elink_common_init_phy(struct elink_dev *cb, u32 shmem_base_path[],
14824 u32 shmem2_base_path[], u32 chip_id,
14825 u8 one_port_enabled)
14826 {
14827 elink_status_t rc = ELINK_STATUS_OK;
14828 u32 phy_ver, val;
14829 #ifndef ELINK_EMUL_ONLY
14830 u8 phy_index = 0;
14831 u32 ext_phy_type, ext_phy_config;
14832 #endif
14833 #if defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA)
14834 if (CHIP_REV_IS_EMUL(chip_id) || CHIP_REV_IS_FPGA(chip_id))
14835 return ELINK_STATUS_OK;
14836 #endif
14837
14838 elink_set_mdio_clk(cb, chip_id, GRCBASE_EMAC0);
14839 elink_set_mdio_clk(cb, chip_id, GRCBASE_EMAC1);
14840 ELINK_DEBUG_P0(cb, "Begin common phy init\n");
14841 if (CHIP_IS_E3(chip_id)) {
14842 /* Enable EPIO */
14843 val = REG_RD(cb, MISC_REG_GEN_PURP_HWG);
14844 REG_WR(cb, MISC_REG_GEN_PURP_HWG, val | 1);
14845 }
14846 #ifndef ELINK_EMUL_ONLY
14847 /* Check if common init was already done */
14848 phy_ver = REG_RD(cb, shmem_base_path[0] +
14849 OFFSETOF(struct shmem_region,
14850 port_mb[PORT_0].ext_phy_fw_version));
14851 if (phy_ver) {
14852 ELINK_DEBUG_P1(cb, "Not doing common init; phy ver is 0x%x\n",
14853 phy_ver);
14854 return ELINK_STATUS_OK;
14855 }
14856
14857 #ifdef INCLUDE_WARPCORE_UC_LOAD
14858 if (ELINK_USES_WARPCORE(chip_id)) {
14859 rc |= elink_warpcore_common_init(cb, shmem_base_path,
14860 shmem2_base_path, phy_index,
14861 chip_id, one_port_enabled);
14862 }
14863 #endif
14864 /* Read the ext_phy_type for arbitrary port(0) */
14865 for (phy_index = ELINK_EXT_PHY1; phy_index < ELINK_MAX_PHYS;
14866 phy_index++) {
14867 ext_phy_config = elink_get_ext_phy_config(cb,
14868 shmem_base_path[0],
14869 phy_index, 0);
14870 ext_phy_type = ELINK_XGXS_EXT_PHY_TYPE(ext_phy_config);
14871 rc |= elink_ext_phy_common_init(cb, shmem_base_path,
14872 shmem2_base_path,
14873 phy_index, ext_phy_type,
14874 chip_id);
14875 }
14876 #endif /* ELINK_EMUL_ONLY */
14877 return rc;
14878 }
14879 #endif // #ifndef EXCLUDE_COMMON_INIT
14880
14881 #ifndef EXCLUDE_NON_COMMON_INIT
14882 #ifndef EXCLUDE_WARPCORE
elink_check_over_curr(struct elink_params * params,struct elink_vars * vars)14883 static void elink_check_over_curr(struct elink_params *params,
14884 struct elink_vars *vars)
14885 {
14886 struct elink_dev *cb = params->cb;
14887 u32 cfg_pin;
14888 u8 port = params->port;
14889 u32 pin_val;
14890
14891 cfg_pin = (REG_RD(cb, params->shmem_base +
14892 OFFSETOF(struct shmem_region,
14893 dev_info.port_hw_config[port].e3_cmn_pin_cfg1)) &
14894 PORT_HW_CFG_E3_OVER_CURRENT_MASK) >>
14895 PORT_HW_CFG_E3_OVER_CURRENT_SHIFT;
14896
14897 /* Ignore check if no external input PIN available */
14898 if (elink_get_cfg_pin(cb, cfg_pin, &pin_val) != ELINK_STATUS_OK)
14899 return;
14900
14901 if (!pin_val) {
14902 if ((vars->phy_flags & PHY_OVER_CURRENT_FLAG) == 0) {
14903 #ifndef ELINK_AUX_POWER
14904 elink_cb_event_log(cb, ELINK_LOG_ID_OVER_CURRENT, params->port); //"Error: Power fault on Port %d has"
14905 // " been detected and the power to "
14906 // "that SFP+ module has been removed"
14907 // " to prevent failure of the card."
14908 // " Please remove the SFP+ module and"
14909 // " restart the system to clear this"
14910 // " error.\n",
14911 #endif /* ELINK_AUX_POWER */
14912 vars->phy_flags |= PHY_OVER_CURRENT_FLAG;
14913 elink_warpcore_power_module(params, 0);
14914 }
14915 } else
14916 vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG;
14917 }
14918 #endif // EXCLUDE_WARPCORE
14919
14920 /* Returns 0 if no change occured since last check; 1 otherwise. */
elink_analyze_link_error(struct elink_params * params,struct elink_vars * vars,u32 status,u32 phy_flag,u32 link_flag,u8 notify)14921 static u8 elink_analyze_link_error(struct elink_params *params,
14922 struct elink_vars *vars, u32 status,
14923 u32 phy_flag, u32 link_flag, u8 notify)
14924 {
14925 struct elink_dev *cb = params->cb;
14926 /* Compare new value with previous value */
14927 u8 led_mode;
14928 u32 old_status = (vars->phy_flags & phy_flag) ? 1 : 0;
14929
14930 if ((status ^ old_status) == 0)
14931 return 0;
14932
14933 /* If values differ */
14934 switch (phy_flag) {
14935 case PHY_HALF_OPEN_CONN_FLAG:
14936 ELINK_DEBUG_P0(cb, "Analyze Remote Fault\n");
14937 break;
14938 case PHY_SFP_TX_FAULT_FLAG:
14939 ELINK_DEBUG_P0(cb, "Analyze TX Fault\n");
14940 break;
14941 default:
14942 ELINK_DEBUG_P0(cb, "Analyze UNKNOWN\n");
14943 }
14944 ELINK_DEBUG_P3(cb, "Link changed:[%x %x]->%x\n", vars->link_up,
14945 old_status, status);
14946
14947 /* Do not touch the link in case physical link down */
14948 if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
14949 return 1;
14950
14951 /* a. Update shmem->link_status accordingly
14952 * b. Update elink_vars->link_up
14953 */
14954 if (status) {
14955 vars->link_status &= ~LINK_STATUS_LINK_UP;
14956 vars->link_status |= link_flag;
14957 vars->link_up = 0;
14958 vars->phy_flags |= phy_flag;
14959
14960 /* activate nig drain */
14961 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 1);
14962 /* Set LED mode to off since the PHY doesn't know about these
14963 * errors
14964 */
14965 led_mode = ELINK_LED_MODE_OFF;
14966 } else {
14967 vars->link_status |= LINK_STATUS_LINK_UP;
14968 vars->link_status &= ~link_flag;
14969 vars->link_up = 1;
14970 vars->phy_flags &= ~phy_flag;
14971 led_mode = ELINK_LED_MODE_OPER;
14972
14973 /* Clear nig drain */
14974 REG_WR(cb, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
14975 }
14976 #ifndef ELINK_AUX_POWER
14977 #ifdef ELINK_57711E_SUPPORT
14978 elink_sync_link(params, vars);
14979 #endif // ELINK_57711E_SUPPORT
14980 #endif // ELINK_AUX_POWER
14981 /* Update the LED according to the link state */
14982 elink_set_led(params, vars, led_mode, ELINK_SPEED_10000);
14983
14984 /* Update link status in the shared memory */
14985 elink_update_mng(params, vars->link_status);
14986
14987 /* C. Trigger General Attention */
14988 vars->periodic_flags |= ELINK_PERIODIC_FLAGS_LINK_EVENT;
14989 #ifndef EDEBUG
14990 if (notify)
14991 elink_cb_notify_link_changed(cb);
14992 #endif // EDEBUG
14993
14994 return 1;
14995 }
14996
14997 /******************************************************************************
14998 * Description:
14999 * This function checks for half opened connection change indication.
15000 * When such change occurs, it calls the elink_analyze_link_error
15001 * to check if Remote Fault is set or cleared. Reception of remote fault
15002 * status message in the MAC indicates that the peer's MAC has detected
15003 * a fault, for example, due to break in the TX side of fiber.
15004 *
15005 ******************************************************************************/
15006 #ifdef BNX2X_ADD /* BNX2X_ADD */
15007 static
15008 #endif
elink_check_half_open_conn(struct elink_params * params,struct elink_vars * vars,u8 notify)15009 elink_status_t elink_check_half_open_conn(struct elink_params *params,
15010 struct elink_vars *vars,
15011 u8 notify)
15012 {
15013 struct elink_dev *cb = params->cb;
15014 u32 lss_status = 0;
15015 u32 mac_base;
15016 /* In case link status is physically up @ 10G do */
15017 if (((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0) ||
15018 (REG_RD(cb, NIG_REG_EGRESS_EMAC0_PORT + params->port*4)))
15019 return ELINK_STATUS_OK;
15020
15021 if (CHIP_IS_E3(params->chip_id) &&
15022 (REG_RD(cb, MISC_REG_RESET_REG_2) &
15023 (MISC_REGISTERS_RESET_REG_2_XMAC))) {
15024 /* Check E3 XMAC */
15025 /* Note that link speed cannot be queried here, since it may be
15026 * zero while link is down. In case UMAC is active, LSS will
15027 * simply not be set
15028 */
15029 mac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
15030
15031 /* Clear stick bits (Requires rising edge) */
15032 REG_WR(cb, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0);
15033 REG_WR(cb, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS,
15034 XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS |
15035 XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS);
15036 if (REG_RD(cb, mac_base + XMAC_REG_RX_LSS_STATUS))
15037 lss_status = 1;
15038
15039 elink_analyze_link_error(params, vars, lss_status,
15040 PHY_HALF_OPEN_CONN_FLAG,
15041 LINK_STATUS_NONE, notify);
15042 } else if (REG_RD(cb, MISC_REG_RESET_REG_2) &
15043 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) {
15044 /* Check E1X / E2 BMAC */
15045 u32 lss_status_reg;
15046 u32 wb_data[2];
15047 mac_base = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
15048 NIG_REG_INGRESS_BMAC0_MEM;
15049 /* Read BIGMAC_REGISTER_RX_LSS_STATUS */
15050 if (CHIP_IS_E2(params->chip_id))
15051 lss_status_reg = BIGMAC2_REGISTER_RX_LSS_STAT;
15052 else
15053 lss_status_reg = BIGMAC_REGISTER_RX_LSS_STATUS;
15054
15055 REG_RD_DMAE(cb, mac_base + lss_status_reg, wb_data, 2);
15056 lss_status = (wb_data[0] > 0);
15057
15058 elink_analyze_link_error(params, vars, lss_status,
15059 PHY_HALF_OPEN_CONN_FLAG,
15060 LINK_STATUS_NONE, notify);
15061 }
15062 return ELINK_STATUS_OK;
15063 }
15064 #ifdef ELINK_ENHANCEMENTS
elink_sfp_tx_fault_detection(struct elink_phy * phy,struct elink_params * params,struct elink_vars * vars)15065 static void elink_sfp_tx_fault_detection(struct elink_phy *phy,
15066 struct elink_params *params,
15067 struct elink_vars *vars)
15068 {
15069 struct elink_dev *cb = params->cb;
15070 u32 cfg_pin, value = 0;
15071 u8 led_change, port = params->port;
15072
15073 /* Get The SFP+ TX_Fault controlling pin ([eg]pio) */
15074 cfg_pin = (REG_RD(cb, params->shmem_base + OFFSETOF(struct shmem_region,
15075 dev_info.port_hw_config[port].e3_cmn_pin_cfg)) &
15076 PORT_HW_CFG_E3_TX_FAULT_MASK) >>
15077 PORT_HW_CFG_E3_TX_FAULT_SHIFT;
15078
15079 if (elink_get_cfg_pin(cb, cfg_pin, &value)) {
15080 ELINK_DEBUG_P1(cb, "Failed to read pin 0x%02x\n", cfg_pin);
15081 return;
15082 }
15083
15084 led_change = elink_analyze_link_error(params, vars, value,
15085 PHY_SFP_TX_FAULT_FLAG,
15086 LINK_STATUS_SFP_TX_FAULT, 1);
15087
15088 if (led_change) {
15089 /* Change TX_Fault led, set link status for further syncs */
15090 u8 led_mode;
15091
15092 if (vars->phy_flags & PHY_SFP_TX_FAULT_FLAG) {
15093 led_mode = MISC_REGISTERS_GPIO_HIGH;
15094 vars->link_status |= LINK_STATUS_SFP_TX_FAULT;
15095 } else {
15096 led_mode = MISC_REGISTERS_GPIO_LOW;
15097 vars->link_status &= ~LINK_STATUS_SFP_TX_FAULT;
15098 }
15099
15100 /* If module is unapproved, led should be on regardless */
15101 if (!(phy->flags & ELINK_FLAGS_SFP_NOT_APPROVED)) {
15102 ELINK_DEBUG_P1(cb, "Change TX_Fault LED: ->%x\n",
15103 led_mode);
15104 elink_set_e3_module_fault_led(params, led_mode);
15105 }
15106 }
15107 }
15108 #endif
15109 #ifndef EXCLUDE_WARPCORE
elink_kr2_recovery(struct elink_params * params,struct elink_vars * vars,struct elink_phy * phy)15110 static void elink_kr2_recovery(struct elink_params *params,
15111 struct elink_vars *vars,
15112 struct elink_phy *phy)
15113 {
15114 #ifdef ELINK_DEBUG
15115 struct elink_dev *cb = params->cb;
15116 ELINK_DEBUG_P0(cb, "KR2 recovery\n");
15117 #endif // ELINK_DEBUG
15118 elink_warpcore_enable_AN_KR2(phy, params, vars);
15119 elink_warpcore_restart_AN_KR(phy, params);
15120 }
15121
elink_check_kr2_wa(struct elink_params * params,struct elink_vars * vars,struct elink_phy * phy)15122 static void elink_check_kr2_wa(struct elink_params *params,
15123 struct elink_vars *vars,
15124 struct elink_phy *phy)
15125 {
15126 struct elink_dev *cb = params->cb;
15127 u16 base_page, next_page, not_kr2_device, lane;
15128 int sigdet;
15129
15130 /* Once KR2 was disabled, wait 5 seconds before checking KR2 recovery
15131 * Since some switches tend to reinit the AN process and clear the
15132 * the advertised BP/NP after ~2 seconds causing the KR2 to be disabled
15133 * and recovered many times
15134 */
15135 if (vars->check_kr2_recovery_cnt > 0) {
15136 vars->check_kr2_recovery_cnt--;
15137 return;
15138 }
15139
15140 sigdet = elink_warpcore_get_sigdet(phy, params);
15141 if (!sigdet) {
15142 if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
15143 elink_kr2_recovery(params, vars, phy);
15144 ELINK_DEBUG_P0(cb, "No sigdet\n");
15145 }
15146 return;
15147 }
15148
15149 lane = elink_get_warpcore_lane(phy, params);
15150 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
15151 MDIO_AER_BLOCK_AER_REG, lane);
15152 elink_cl45_read(cb, phy, MDIO_AN_DEVAD,
15153 MDIO_AN_REG_LP_AUTO_NEG, &base_page);
15154 elink_cl45_read(cb, phy, MDIO_AN_DEVAD,
15155 MDIO_AN_REG_LP_AUTO_NEG2, &next_page);
15156 elink_set_aer_mmd(params, phy);
15157
15158 /* CL73 has not begun yet */
15159 if (base_page == 0) {
15160 if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
15161 elink_kr2_recovery(params, vars, phy);
15162 ELINK_DEBUG_P0(cb, "No BP\n");
15163 }
15164 return;
15165 }
15166
15167 /* In case NP bit is not set in the BasePage, or it is set,
15168 * but only KX is advertised, declare this link partner as non-KR2
15169 * device.
15170 */
15171 not_kr2_device = (((base_page & 0x8000) == 0) ||
15172 (((base_page & 0x8000) &&
15173 ((next_page & 0xe0) == 0x20))));
15174
15175 /* In case KR2 is already disabled, check if we need to re-enable it */
15176 if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
15177 if (!not_kr2_device) {
15178 ELINK_DEBUG_P2(cb, "BP=0x%x, NP=0x%x\n", base_page,
15179 next_page);
15180 elink_kr2_recovery(params, vars, phy);
15181 }
15182 return;
15183 }
15184 /* KR2 is enabled, but not KR2 device */
15185 if (not_kr2_device) {
15186 /* Disable KR2 on both lanes */
15187 ELINK_DEBUG_P2(cb, "BP=0x%x, NP=0x%x\n", base_page, next_page);
15188 elink_disable_kr2(params, vars, phy);
15189 /* Restart AN on leading lane */
15190 elink_warpcore_restart_AN_KR(phy, params);
15191 return;
15192 }
15193 }
15194 #endif
15195
elink_period_func(struct elink_params * params,struct elink_vars * vars)15196 void elink_period_func(struct elink_params *params, struct elink_vars *vars)
15197 {
15198 u16 phy_idx;
15199 #if defined(ELINK_DEBUG) || defined(ELINK_ENHANCEMENTS)
15200 struct elink_dev *cb = params->cb;
15201 #endif
15202 for (phy_idx = ELINK_INT_PHY; phy_idx < ELINK_MAX_PHYS; phy_idx++) {
15203 if (params->phy[phy_idx].flags & ELINK_FLAGS_TX_ERROR_CHECK) {
15204 elink_set_aer_mmd(params, ¶ms->phy[phy_idx]);
15205 if (elink_check_half_open_conn(params, vars, 1) !=
15206 ELINK_STATUS_OK)
15207 ELINK_DEBUG_P0(cb, "Fault detection failed\n");
15208 break;
15209 }
15210 }
15211
15212 #ifndef EXCLUDE_WARPCORE
15213 if (CHIP_IS_E3(params->chip_id)) {
15214 struct elink_phy *phy = ¶ms->phy[ELINK_INT_PHY];
15215 elink_set_aer_mmd(params, phy);
15216 if ((phy->supported & ELINK_SUPPORTED_20000baseKR2_Full) &&
15217 (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G))
15218 elink_check_kr2_wa(params, vars, phy);
15219 #ifdef ELINK_AUX_POWER
15220 if ((phy->flags & ELINK_FLAGS_SFP_MODULE_PLUGGED_IN_WC) == 0) {
15221 if (elink_is_sfp_module_plugged(phy, params)) {
15222 phy->flags |=
15223 ELINK_FLAGS_SFP_MODULE_PLUGGED_IN_WC;
15224 elink_sfp_module_detection(phy, params);
15225 }
15226 } else {
15227 if (!elink_is_sfp_module_plugged(phy, params)) {
15228 elink_sfp_set_transmitter(params, phy, 1);
15229 phy->flags &=
15230 ~ELINK_FLAGS_SFP_MODULE_PLUGGED_IN_WC;
15231 }
15232 }
15233 #endif // ELINK_AUX_POWER
15234 elink_check_over_curr(params, vars);
15235 #ifdef ELINK_ENHANCEMENTS
15236 if (vars->rx_tx_asic_rst)
15237 elink_warpcore_config_runtime(phy, params, vars);
15238
15239 if ((REG_RD(cb, params->shmem_base +
15240 OFFSETOF(struct shmem_region, dev_info.
15241 port_hw_config[params->port].default_cfg))
15242 & PORT_HW_CFG_NET_SERDES_IF_MASK) ==
15243 PORT_HW_CFG_NET_SERDES_IF_SFI) {
15244 if (elink_is_sfp_module_plugged(phy, params)) {
15245 elink_sfp_tx_fault_detection(phy, params, vars);
15246 } else if (vars->link_status &
15247 LINK_STATUS_SFP_TX_FAULT) {
15248 /* Clean trail, interrupt corrects the leds */
15249 vars->link_status &= ~LINK_STATUS_SFP_TX_FAULT;
15250 vars->phy_flags &= ~PHY_SFP_TX_FAULT_FLAG;
15251 /* Update link status in the shared memory */
15252 elink_update_mng(params, vars->link_status);
15253 }
15254 }
15255 #endif // ELINK_ENHANCEMENTS
15256 }
15257 #endif /* EXCLUDE_WARPCORE */
15258 }
15259
15260 #ifdef ELINK_ENHANCEMENTS
elink_fan_failure_det_req(struct elink_dev * cb,u32 shmem_base,u32 shmem2_base,u8 port)15261 u8 elink_fan_failure_det_req(struct elink_dev *cb,
15262 u32 shmem_base,
15263 u32 shmem2_base,
15264 u8 port)
15265 {
15266 u8 phy_index, fan_failure_det_req = 0;
15267 struct elink_phy phy;
15268 for (phy_index = ELINK_EXT_PHY1; phy_index < ELINK_MAX_PHYS;
15269 phy_index++) {
15270 if (elink_populate_phy(cb, phy_index, shmem_base, shmem2_base,
15271 port, &phy)
15272 != ELINK_STATUS_OK) {
15273 ELINK_DEBUG_P0(cb, "populate phy failed\n");
15274 return 0;
15275 }
15276 fan_failure_det_req |= (phy.flags &
15277 ELINK_FLAGS_FAN_FAILURE_DET_REQ);
15278 }
15279 return fan_failure_det_req;
15280 }
15281 #endif // ELINK_ENHANCEMENTS
15282 #ifdef ELINK_AUX_POWER
elink_enable_pmd_tx(struct elink_params * params)15283 void elink_enable_pmd_tx(struct elink_params *params)
15284 {
15285 u8 phy_index;
15286 elink_set_mdio_emac_per_phy(params->cb, params);
15287
15288 for (phy_index = ELINK_EXT_PHY1; phy_index < ELINK_MAX_PHYS;
15289 phy_index++) {
15290 switch (params->phy[phy_index].type) {
15291 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
15292 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
15293 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
15294 elink_cl45_write(params->cb, ¶ms->phy[phy_index],
15295 MDIO_PMA_DEVAD,
15296 MDIO_PMA_REG_TX_DISABLE, 0);
15297 default:
15298 break;
15299 }
15300 }
15301 }
15302 #endif // ELINK_AUX_POWER
15303
elink_hw_reset_phy(struct elink_params * params)15304 void elink_hw_reset_phy(struct elink_params *params)
15305 {
15306 u8 phy_index;
15307 struct elink_dev *cb = params->cb;
15308 elink_update_mng(params, 0);
15309 elink_bits_dis(cb, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
15310 (ELINK_NIG_MASK_XGXS0_LINK_STATUS |
15311 ELINK_NIG_MASK_XGXS0_LINK10G |
15312 ELINK_NIG_MASK_SERDES0_LINK_STATUS |
15313 ELINK_NIG_MASK_MI_INT));
15314
15315 for (phy_index = ELINK_INT_PHY; phy_index < ELINK_MAX_PHYS;
15316 phy_index++) {
15317 if (params->phy[phy_index].hw_reset) {
15318 params->phy[phy_index].hw_reset(
15319 ¶ms->phy[phy_index],
15320 params);
15321 params->phy[phy_index] = phy_null;
15322 }
15323 }
15324 }
15325
15326 #ifdef ELINK_ENHANCEMENTS
elink_init_mod_abs_int(struct elink_dev * cb,struct elink_vars * vars,u32 chip_id,u32 shmem_base,u32 shmem2_base,u8 port)15327 void elink_init_mod_abs_int(struct elink_dev *cb, struct elink_vars *vars,
15328 u32 chip_id, u32 shmem_base, u32 shmem2_base,
15329 u8 port)
15330 {
15331 u8 gpio_num = 0xff, gpio_port = 0xff, phy_index;
15332 u32 val;
15333 u32 offset, aeu_mask, swap_val, swap_override, sync_offset;
15334 if (CHIP_IS_E3(chip_id)) {
15335 if (elink_get_mod_abs_int_cfg(cb, chip_id,
15336 shmem_base,
15337 port,
15338 &gpio_num,
15339 &gpio_port) != ELINK_STATUS_OK)
15340 return;
15341 } else {
15342 struct elink_phy phy;
15343 for (phy_index = ELINK_EXT_PHY1; phy_index < ELINK_MAX_PHYS;
15344 phy_index++) {
15345 if (elink_populate_phy(cb, phy_index, shmem_base,
15346 shmem2_base, port, &phy)
15347 != ELINK_STATUS_OK) {
15348 ELINK_DEBUG_P0(cb, "populate phy failed\n");
15349 return;
15350 }
15351 if (phy.type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) {
15352 gpio_num = MISC_REGISTERS_GPIO_3;
15353 gpio_port = port;
15354 break;
15355 }
15356 }
15357 }
15358
15359 if (gpio_num == 0xff)
15360 return;
15361
15362 /* Set GPIO3 to trigger SFP+ module insertion/removal */
15363 ELINK_SET_GPIO(cb, gpio_num, MISC_REGISTERS_GPIO_INPUT_HI_Z, gpio_port);
15364
15365 swap_val = REG_RD(cb, NIG_REG_PORT_SWAP);
15366 swap_override = REG_RD(cb, NIG_REG_STRAP_OVERRIDE);
15367 gpio_port ^= (swap_val && swap_override);
15368
15369 vars->aeu_int_mask = AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0 <<
15370 (gpio_num + (gpio_port << 2));
15371
15372 sync_offset = shmem_base +
15373 OFFSETOF(struct shmem_region,
15374 dev_info.port_hw_config[port].aeu_int_mask);
15375 REG_WR(cb, sync_offset, vars->aeu_int_mask);
15376
15377 ELINK_DEBUG_P3(cb, "Setting MOD_ABS (GPIO%d_P%d) AEU to 0x%x\n",
15378 gpio_num, gpio_port, vars->aeu_int_mask);
15379
15380 if (port == 0)
15381 offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
15382 else
15383 offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
15384
15385 /* Open appropriate AEU for interrupts */
15386 aeu_mask = REG_RD(cb, offset);
15387 aeu_mask |= vars->aeu_int_mask;
15388 REG_WR(cb, offset, aeu_mask);
15389
15390 /* Enable the GPIO to trigger interrupt */
15391 val = REG_RD(cb, MISC_REG_GPIO_EVENT_EN);
15392 val |= 1 << (gpio_num + (gpio_port << 2));
15393 REG_WR(cb, MISC_REG_GPIO_EVENT_EN, val);
15394 }
15395 #endif // ELINK_ENHANCEMENTS
15396 #endif // EXCLUDE_NON_COMMON_INIT
15397
15398 #ifdef ELINK_AUX_POWER
elink_adjust_phy_func_ptr(struct elink_params * params)15399 void elink_adjust_phy_func_ptr(struct elink_params *params)
15400 {
15401 u32 phy_idx;
15402 struct elink_phy phy, *cur_phy;
15403 for (phy_idx = ELINK_INT_PHY; phy_idx < ELINK_MAX_PHYS; phy_idx++) {
15404 cur_phy = ¶ms->phy[phy_idx];
15405 /* Select the phy type */
15406 switch (cur_phy->type) {
15407 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
15408 #ifndef EXCLUDE_WARPCORE
15409 phy = phy_warpcore;
15410 #else
15411 phy = phy_xgxs;
15412 #endif
15413 break;
15414 #ifndef EXCLUDE_BCM8727_BCM8073
15415 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
15416 phy = phy_8073;
15417 break;
15418 #endif
15419 #ifndef EXCLUDE_BCM8705
15420 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
15421 phy = phy_8705;
15422 break;
15423 #endif
15424 #ifndef EXCLUDE_BCM87x6
15425 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
15426 phy = phy_8706;
15427 break;
15428 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
15429 phy = phy_8726;
15430 break;
15431 #endif /* EXCLUDE_BCM87x6 */
15432 #ifndef EXCLUDE_BCM8727_BCM8073
15433 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
15434 phy = phy_8727;
15435 break;
15436 #endif
15437 #ifndef EXCLUDE_BCM8481
15438 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
15439 phy = phy_8481;
15440 break;
15441 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
15442 phy = phy_84823;
15443 break;
15444 #endif
15445 #ifndef EXCLUDE_BCM84833
15446 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
15447 phy = phy_84833;
15448 break;
15449 #endif
15450 #ifndef EXCLUDE_BCM54618SE
15451 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE:
15452 phy = phy_54618se;
15453 break;
15454 #endif
15455 #ifndef EXCLUDE_SFX7101
15456 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
15457 phy = phy_7101;
15458 break;
15459 #endif
15460 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
15461 phy = phy_null;
15462 return;
15463 default:
15464 phy = phy_null;
15465 continue;
15466 }
15467 cur_phy->config_init = phy.config_init;
15468 cur_phy->read_status = phy.read_status;
15469 cur_phy->link_reset = phy.link_reset;
15470 cur_phy->config_loopback = phy.config_loopback;
15471 cur_phy->format_fw_ver = phy.format_fw_ver;
15472 cur_phy->hw_reset = phy.hw_reset;
15473 cur_phy->set_link_led = phy.set_link_led;
15474 cur_phy->phy_specific_func = phy.phy_specific_func;
15475 }
15476 }
15477
15478 #ifndef EXCLUDE_COMMON_INIT
elink_get_phy_temperature(struct elink_params * params,u32 * temp_reading,u8 path,u8 port)15479 elink_status_t elink_get_phy_temperature(struct elink_params *params,
15480 u32 *temp_reading, u8 path, u8 port)
15481 {
15482 /* The temperature returned from this function is expected
15483 * to be degree C. Any conversion from hardware value to
15484 * degree C will be performed here.
15485 */
15486
15487 struct elink_phy *phy;
15488 u16 cmd_args[PHY84833_CMDHDLR_MAX_ARGS];
15489 elink_status_t rc;
15490 u8 idx;
15491
15492 for (idx = 0; idx < PHY84833_CMDHDLR_MAX_ARGS; idx++)
15493 cmd_args[idx] = 0;
15494 for (idx = 0; idx < params->num_phys; idx++) {
15495 phy = ¶ms->phy[idx];
15496 if (phy->flags & ELINK_FLAGS_TEMPERATURE) {
15497 rc = elink_84833_cmd_hdlr(phy, params,
15498 PHY84833_CMD_GET_CURRENT_TEMP,
15499 cmd_args,
15500 PHY84833_CMDHDLR_MAX_ARGS);
15501 if ((path == 0) && (cmd_args[1] == 0))
15502 cmd_args[1] = cmd_args[0] + 5;
15503 if (cmd_args[0] > cmd_args[1])
15504 *temp_reading = (u32)cmd_args[0];
15505 else
15506 *temp_reading = (u32)cmd_args[1];
15507
15508 return rc;
15509 }
15510 }
15511
15512 return ELINK_STATUS_ERROR;
15513 }
15514 #ifndef EXCLUDE_WARPCORE
set_cfg_pin(struct elink_dev * cb,u32 pin_cfg,u32 val)15515 void set_cfg_pin(struct elink_dev *cb, u32 pin_cfg, u32 val)
15516 {
15517 elink_set_cfg_pin(cb, pin_cfg, val);
15518 }
get_cfg_pin(struct elink_dev * cb,u32 pin_cfg,u32 * val)15519 int get_cfg_pin(struct elink_dev *cb, u32 pin_cfg, u32 *val)
15520 {
15521 return elink_get_cfg_pin(cb, pin_cfg, val);
15522 }
15523
elink_force_link(struct elink_params * params,int enable)15524 void elink_force_link(struct elink_params *params, int enable) {
15525 struct elink_phy *phy = ¶ms->phy[ELINK_INT_PHY];
15526 struct elink_dev *cb = params->cb;
15527 u8 lane = elink_get_warpcore_lane(phy, params);
15528 u16 val;
15529
15530 /* Global register - operate on lane 0 */
15531 CL22_WR_OVER_CL45(cb, phy, MDIO_REG_BANK_AER_BLOCK,
15532 MDIO_AER_BLOCK_AER_REG, 0);
15533
15534 elink_cl45_read(cb, phy, MDIO_PMA_DEVAD,
15535 MDIO_WC_REG_XGXSBLK2_LANE_RESET, &val);
15536 if (enable)
15537 val &= ~(0x11 << lane);
15538 else
15539 val |= (0x11 << lane);
15540 elink_cl45_write(cb, phy, MDIO_PMA_DEVAD,
15541 MDIO_WC_REG_XGXSBLK2_LANE_RESET,
15542 val);
15543
15544 /* Restore AER */
15545 elink_set_aer_mmd(params, phy);
15546 }
15547
15548 #endif /* EXCLUDE_WARPCORE */
15549 #endif /* #ifndef EXCLUDE_COMMON_INIT */
15550 #endif
15551