144961713Sgirish /* 244961713Sgirish * CDDL HEADER START 344961713Sgirish * 444961713Sgirish * The contents of this file are subject to the terms of the 544961713Sgirish * Common Development and Distribution License (the "License"). 644961713Sgirish * You may not use this file except in compliance with the License. 744961713Sgirish * 844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 944961713Sgirish * or http://www.opensolaris.org/os/licensing. 1044961713Sgirish * See the License for the specific language governing permissions 1144961713Sgirish * and limitations under the License. 1244961713Sgirish * 1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each 1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the 1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 1844961713Sgirish * 1944961713Sgirish * CDDL HEADER END 2044961713Sgirish */ 2144961713Sgirish /* 22e759c33aSMichael Speer * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2344961713Sgirish * Use is subject to license terms. 2444961713Sgirish */ 2544961713Sgirish 2644961713Sgirish #include <sys/nxge/nxge_impl.h> 2744961713Sgirish #include <sys/nxge/nxge_mac.h> 28678453a8Sspeer #include <sys/nxge/nxge_hio.h> 2944961713Sgirish 3098ecde52Stm #define LINK_MONITOR_PERIOD (1000 * 1000) 3198ecde52Stm #define LM_WAIT_MULTIPLIER 8 3298ecde52Stm 33321febdeSsbehera #define SERDES_RDY_WT_INTERVAL 50 34321febdeSsbehera #define MAX_SERDES_RDY_RETRIES 10 35321febdeSsbehera 3600161856Syc #define TN1010_SPEED_1G 1 3700161856Syc #define TN1010_SPEED_10G 0 3800161856Syc #define TN1010_AN_IN_PROG 0 /* Auto negotiation in progress */ 3900161856Syc #define TN1010_AN_COMPLETE 1 4000161856Syc #define TN1010_AN_RSVD 2 4100161856Syc #define TN1010_AN_FAILED 3 4200161856Syc 4344961713Sgirish extern uint32_t nxge_no_link_notify; 4459ac0c16Sdavemq extern boolean_t nxge_no_msg; 4544961713Sgirish extern uint32_t nxge_lb_dbg; 464202ea4bSsbehera extern uint32_t nxge_jumbo_mtu; 4744961713Sgirish 4898ecde52Stm typedef enum { 4998ecde52Stm CHECK_LINK_RESCHEDULE, 5098ecde52Stm CHECK_LINK_STOP 5198ecde52Stm } check_link_state_t; 5298ecde52Stm 5398ecde52Stm static check_link_state_t nxge_check_link_stop(nxge_t *); 5498ecde52Stm 5544961713Sgirish /* 5644961713Sgirish * Ethernet broadcast address definition. 5744961713Sgirish */ 5844961713Sgirish static ether_addr_st etherbroadcastaddr = 5944961713Sgirish {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 6059ac0c16Sdavemq /* 6159ac0c16Sdavemq * Ethernet zero address definition. 6259ac0c16Sdavemq */ 6356d930aeSspeer static ether_addr_st etherzeroaddr = 6456d930aeSspeer {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 6559ac0c16Sdavemq /* 6659ac0c16Sdavemq * Supported chip types 6759ac0c16Sdavemq */ 6852cdd236Ssbehera static uint32_t nxge_supported_cl45_ids[] = { 6952cdd236Ssbehera BCM8704_DEV_ID, 7052cdd236Ssbehera MARVELL_88X_201X_DEV_ID, 7100161856Syc BCM8706_DEV_ID, 7200161856Syc TN1010_DEV_ID 7352cdd236Ssbehera }; 7452cdd236Ssbehera 75b1000363Sml static uint32_t nxge_supported_cl22_ids[] = { 76b1000363Sml BCM5464R_PHY_ID, 77b1000363Sml BCM5482_PHY_ID 78b1000363Sml }; 7959ac0c16Sdavemq 8059ac0c16Sdavemq #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 8159ac0c16Sdavemq sizeof (uint32_t)) 8259ac0c16Sdavemq #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 8359ac0c16Sdavemq sizeof (uint32_t)) 8459ac0c16Sdavemq /* 8559ac0c16Sdavemq * static functions 8659ac0c16Sdavemq */ 872e59129aSraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int); 882e59129aSraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int); 892e59129aSraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int); 9059ac0c16Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t); 912d17280bSsbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t); 9259ac0c16Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t); 93*4df55fdeSJanie Lu static nxge_status_t nxge_n2_kt_serdes_init(p_nxge_t); 9459ac0c16Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t); 9559ac0c16Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t); 9659ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t); 9759ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t); 9859ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t); 9959ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t); 10059ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t); 10159ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t); 10259ac0c16Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t); 10359ac0c16Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t); 10459ac0c16Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t); 1052d17280bSsbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t); 1062d17280bSsbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t); 10759ac0c16Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t); 10859ac0c16Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t); 10900161856Syc static nxge_status_t nxge_check_mrvl88x2011_link(p_nxge_t, boolean_t *); 11052cdd236Ssbehera static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t); 11100161856Syc static nxge_status_t nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id, 11200161856Syc uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui); 11300161856Syc static nxge_status_t nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed); 11400161856Syc static nxge_status_t nxge_set_tn1010_param(p_nxge_t nxgep); 11500161856Syc static nxge_status_t nxge_tn1010_check(p_nxge_t nxgep, 11600161856Syc nxge_link_state_t *link_up); 11700161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep); 11800161856Syc static nxge_status_t nxge_tn1010_xcvr_init(p_nxge_t nxgep); 11900161856Syc 12000161856Syc nxge_status_t nxge_mac_init(p_nxge_t); 12100161856Syc static nxge_status_t nxge_mii_get_link_mode(p_nxge_t); 12200161856Syc 12300161856Syc #ifdef NXGE_DEBUG 12400161856Syc static void nxge_mii_dump(p_nxge_t); 12500161856Syc static nxge_status_t nxge_tn1010_reset(p_nxge_t nxgep); 12600161856Syc static void nxge_dump_tn1010_status_regs(p_nxge_t nxgep); 12700161856Syc #endif 12859ac0c16Sdavemq 12959ac0c16Sdavemq /* 13059ac0c16Sdavemq * xcvr tables for supported transceivers 13159ac0c16Sdavemq */ 13259ac0c16Sdavemq 13300161856Syc /* 13400161856Syc * nxge_n2_10G_table is for 10G fiber or serdes on N2-NIU systems. 13500161856Syc * The Teranetics TN1010 based copper XAUI card can also be used 13600161856Syc * on N2-NIU systems in 10G mode, but it uses its own table 13700161856Syc * nxge_n2_10G_tn1010_table below. 13800161856Syc */ 1392e59129aSraghus static nxge_xcvr_table_t nxge_n2_10G_table = { 14059ac0c16Sdavemq nxge_n2_serdes_init, 14159ac0c16Sdavemq nxge_10G_xcvr_init, 14259ac0c16Sdavemq nxge_10G_link_intr_stop, 14359ac0c16Sdavemq nxge_10G_link_intr_start, 14459ac0c16Sdavemq nxge_check_10g_link, 1452d17280bSsbehera PCS_XCVR 14659ac0c16Sdavemq }; 14759ac0c16Sdavemq 14800161856Syc /* 14900161856Syc * For the Teranetics TN1010 based copper XAUI card 15000161856Syc */ 15100161856Syc static nxge_xcvr_table_t nxge_n2_10G_tn1010_table = { 15200161856Syc nxge_n2_serdes_init, /* Handle both 1G and 10G */ 15300161856Syc nxge_tn1010_xcvr_init, /* Handle both 1G and 10G */ 15400161856Syc nxge_10G_link_intr_stop, 15500161856Syc nxge_10G_link_intr_start, 15600161856Syc nxge_check_tn1010_link, /* Will figure out speed */ 15700161856Syc XPCS_XCVR 15800161856Syc }; 15900161856Syc 1602e59129aSraghus static nxge_xcvr_table_t nxge_n2_1G_table = { 1612e59129aSraghus nxge_n2_serdes_init, 1622e59129aSraghus nxge_1G_xcvr_init, 1632e59129aSraghus nxge_1G_fiber_link_intr_stop, 1642e59129aSraghus nxge_1G_fiber_link_intr_start, 1652e59129aSraghus nxge_check_mii_link, 1662d17280bSsbehera PCS_XCVR 1672e59129aSraghus }; 1682e59129aSraghus 16900161856Syc static nxge_xcvr_table_t nxge_n2_1G_tn1010_table = { 17000161856Syc nxge_n2_serdes_init, 17100161856Syc nxge_tn1010_xcvr_init, 17200161856Syc nxge_1G_fiber_link_intr_stop, /* TN1010 is a Cu PHY, but it uses */ 17300161856Syc nxge_1G_fiber_link_intr_start, /* PCS for 1G, so call fiber func */ 17400161856Syc nxge_check_tn1010_link, 17500161856Syc PCS_XCVR 17600161856Syc }; 17700161856Syc 17800161856Syc static nxge_xcvr_table_t nxge_10G_tn1010_table = { 17900161856Syc nxge_neptune_10G_serdes_init, 18000161856Syc nxge_tn1010_xcvr_init, 18100161856Syc nxge_10G_link_intr_stop, 18200161856Syc nxge_10G_link_intr_start, 18300161856Syc nxge_check_tn1010_link, 18400161856Syc XPCS_XCVR 18500161856Syc }; 18600161856Syc 18700161856Syc static nxge_xcvr_table_t nxge_1G_tn1010_table = { 18800161856Syc nxge_1G_serdes_init, 18900161856Syc nxge_tn1010_xcvr_init, 19000161856Syc nxge_1G_fiber_link_intr_stop, 19100161856Syc nxge_1G_fiber_link_intr_start, 19200161856Syc nxge_check_tn1010_link, 19300161856Syc PCS_XCVR 19400161856Syc }; 19500161856Syc 19659ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = { 19759ac0c16Sdavemq nxge_neptune_10G_serdes_init, 19859ac0c16Sdavemq nxge_10G_xcvr_init, 19959ac0c16Sdavemq nxge_10G_link_intr_stop, 20059ac0c16Sdavemq nxge_10G_link_intr_start, 20159ac0c16Sdavemq nxge_check_10g_link, 2022d17280bSsbehera PCS_XCVR 20359ac0c16Sdavemq }; 20459ac0c16Sdavemq 20559ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = { 20659ac0c16Sdavemq NULL, 20759ac0c16Sdavemq nxge_1G_xcvr_init, 20859ac0c16Sdavemq nxge_1G_copper_link_intr_stop, 20959ac0c16Sdavemq nxge_1G_copper_link_intr_start, 21059ac0c16Sdavemq nxge_check_mii_link, 2112d17280bSsbehera INT_MII_XCVR 21259ac0c16Sdavemq }; 21359ac0c16Sdavemq 21400161856Syc /* This table is for Neptune portmode == PORT_1G_SERDES cases */ 21559ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = { 21659ac0c16Sdavemq nxge_1G_serdes_init, 21759ac0c16Sdavemq nxge_1G_xcvr_init, 21859ac0c16Sdavemq nxge_1G_fiber_link_intr_stop, 21959ac0c16Sdavemq nxge_1G_fiber_link_intr_start, 22059ac0c16Sdavemq nxge_check_mii_link, 2212d17280bSsbehera PCS_XCVR 22259ac0c16Sdavemq }; 22359ac0c16Sdavemq 22459ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = { 22559ac0c16Sdavemq nxge_neptune_10G_serdes_init, 22659ac0c16Sdavemq NULL, 22759ac0c16Sdavemq NULL, 22859ac0c16Sdavemq NULL, 2292e59129aSraghus NULL, 2302d17280bSsbehera PCS_XCVR 23159ac0c16Sdavemq }; 23244961713Sgirish 23300161856Syc /* 23400161856Syc * NXGE_PORT_TN1010 is defined as, 23500161856Syc * NXGE_PORT_SPD_NONE | (NXGE_PHY_TN1010 << NXGE_PHY_SHIFT) 23600161856Syc * = 0 | 5 << 16 = 0x50000 23700161856Syc * 23800161856Syc * So NEPTUNE_2_TN1010 = 23900161856Syc * (NXGE_PORT_TN1010 | 24000161856Syc * (NXGE_PORT_TN1010 << 4) | 24100161856Syc * (NXGE_PORT_NONE << 8) | 24200161856Syc * (NXGE_PORT_NONE << 12)), 24300161856Syc * = 0x50000 | (0x50000 << 4) 24400161856Syc * = 0x550000 24500161856Syc * 24600161856Syc * This function partitions nxgep->nxge_hw_p->niu_type (which may have 24700161856Syc * value NEPTUNE_2_TN1010) and checks if a port has type = NXGE_PORT_TN1010 24800161856Syc * = 0x50000 24900161856Syc */ 25000161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep) 25100161856Syc { 25200161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 25300161856Syc 25400161856Syc if (((nxgep->nxge_hw_p->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn)) 25500161856Syc & NXGE_PHY_MASK) == NXGE_PORT_TN1010) { 25600161856Syc return (B_TRUE); 25700161856Syc } else { 25800161856Syc return (B_FALSE); 25900161856Syc } 26000161856Syc } 26144961713Sgirish 262d81011f0Ssbehera 26300161856Syc /* 26400161856Syc * Figure out nxgep->mac.portmode from nxge.conf, OBP's device properties, 26500161856Syc * serial EEPROM or VPD if possible. Note that not all systems could get 26600161856Syc * the portmode information by calling this function. For example, the 26700161856Syc * Maramba system figures out the portmode information by calling function 26800161856Syc * nxge_setup_xcvr_table. 26900161856Syc */ 2702e59129aSraghus nxge_status_t 2712e59129aSraghus nxge_get_xcvr_type(p_nxge_t nxgep) 2722e59129aSraghus { 2732e59129aSraghus nxge_status_t status = NXGE_OK; 2742e59129aSraghus char *phy_type; 2752e59129aSraghus char *prop_val; 27600161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 2771c7408c9Stc uint32_t val; 2781c7408c9Stc npi_status_t rs; 2791c7408c9Stc 2801c7408c9Stc /* For Opus NEM, skip xcvr checking if 10G Serdes link is up */ 2811c7408c9Stc if (nxgep->mac.portmode == PORT_10G_SERDES && 2821c7408c9Stc nxgep->statsp->mac_stats.link_up) { 2831c7408c9Stc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2841c7408c9Stc return (status); 2851c7408c9Stc } 2862e59129aSraghus 2872e59129aSraghus nxgep->mac.portmode = 0; 2882d17280bSsbehera nxgep->xcvr_addr = 0; 2892e59129aSraghus 2902d17280bSsbehera /* 2912d17280bSsbehera * First check for hot swappable phy property. 2922d17280bSsbehera */ 2932d17280bSsbehera if (nxgep->hot_swappable_phy == B_TRUE) { 2942d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 2952d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 2962d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable")); 2972d17280bSsbehera } else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 2982d17280bSsbehera DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 2992d17280bSsbehera "hot-swappable-phy") == 1) { 3002d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 3012d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 3022d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable")); 3032d17280bSsbehera } else if (nxgep->niu_type == N2_NIU && 3042d17280bSsbehera ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0, 3052d17280bSsbehera "hot-swappable-phy") == 1) { 3062d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 3072d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 3082d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable")); 3092d17280bSsbehera } 3102d17280bSsbehera 3112d17280bSsbehera /* 3122d17280bSsbehera * MDIO polling support for Monza RTM card, Goa NEM card 3132d17280bSsbehera */ 3142d17280bSsbehera if (nxgep->mac.portmode == PORT_HSP_MODE) { 3152d17280bSsbehera nxgep->hot_swappable_phy = B_TRUE; 316ef523517SMichael Speer if (portn > 1) { 317ef523517SMichael Speer return (NXGE_ERROR); 318ef523517SMichael Speer } 319ef523517SMichael Speer 3202d17280bSsbehera /* 3212d17280bSsbehera * If this is the 2nd NIU port, then check 2 addresses 3222d17280bSsbehera * to take care of the Goa NEM card. Port 1 can have addr 17 3232d17280bSsbehera * (in the eval board) or 20 (in the P0 board). 3242d17280bSsbehera */ 3252d17280bSsbehera if (portn == 1) { 3262d17280bSsbehera if (nxge_is_phy_present(nxgep, 32700161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR, BCM8706_DEV_ID, 3282d17280bSsbehera BCM_PHY_ID_MASK)) { 3292d17280bSsbehera nxgep->xcvr_addr = 33000161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR; 3312d17280bSsbehera goto found_phy; 3322d17280bSsbehera } 3332d17280bSsbehera } 3342d17280bSsbehera if (nxge_is_phy_present(nxgep, 33500161856Syc GOA_CLAUSE45_PORT_ADDR_BASE + portn, 3362d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 33700161856Syc nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE + 3382d17280bSsbehera portn; 3392d17280bSsbehera goto found_phy; 3402d17280bSsbehera } 3412d17280bSsbehera 3422d17280bSsbehera nxgep->phy_absent = B_TRUE; 3431c7408c9Stc 3441c7408c9Stc /* Check Serdes link to detect Opus NEM */ 3451c7408c9Stc rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 3461c7408c9Stc XPCS_REG_STATUS, &val); 3471c7408c9Stc 3481c7408c9Stc if (rs == 0 && val & XPCS_STATUS_LANE_ALIGN) { 3491c7408c9Stc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3501c7408c9Stc nxgep->mac.portmode = PORT_10G_SERDES; 3511c7408c9Stc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3521c7408c9Stc "HSP 10G Serdes FOUND!!")); 3531c7408c9Stc } 3542d17280bSsbehera goto check_phy_done; 3552d17280bSsbehera found_phy: 3562d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3572d17280bSsbehera nxgep->mac.portmode = PORT_10G_FIBER; 3582d17280bSsbehera nxgep->phy_absent = B_FALSE; 3592d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr " 3602d17280bSsbehera "found for hot swappable phy")); 3612d17280bSsbehera check_phy_done: 3622d17280bSsbehera return (status); 3632d17280bSsbehera } 3642d17280bSsbehera 36500161856Syc /* Get phy-type property (May have been set by nxge.conf) */ 3662e59129aSraghus if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 3672e59129aSraghus DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 3682e59129aSraghus "phy-type", &prop_val)) == DDI_PROP_SUCCESS) { 3692e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3702e59129aSraghus "found conf file: phy-type %s", prop_val)); 3712e59129aSraghus if (strcmp("xgsd", prop_val) == 0) { 3722e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3732e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 3742e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3752e59129aSraghus "found: 10G Serdes")); 3762e59129aSraghus } else if (strcmp("gsd", prop_val) == 0) { 3772e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3782e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 3792e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes")); 3802e59129aSraghus } else if (strcmp("mif", prop_val) == 0) { 3812e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 3822e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 3832e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr")); 3842e59129aSraghus } else if (strcmp("pcs", prop_val) == 0) { 3852e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3862e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 3872e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr")); 388321febdeSsbehera } else if (strcmp("xgf", prop_val) == 0) { 38900161856Syc /* 39000161856Syc * Before OBP supports new phy-type property 39100161856Syc * value "xgc", the 10G copper XAUI may carry 39200161856Syc * "xgf" instead of "xgc". If the OBP is 39300161856Syc * upgraded to a newer version which supports 39400161856Syc * "xgc", then the TN1010 related code in this 39500161856Syc * "xgf" case will not be used anymore. 39600161856Syc */ 39700161856Syc if (nxge_is_tn1010_phy(nxgep)) { 39800161856Syc if ((status = nxge_set_tn1010_param(nxgep)) 39900161856Syc != NXGE_OK) { 40000161856Syc return (status); 40100161856Syc } 40200161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 40300161856Syc } else { /* For Fiber XAUI */ 40400161856Syc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 40500161856Syc nxgep->mac.portmode = PORT_10G_FIBER; 40600161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 40700161856Syc "10G Fiber Xcvr")); 40800161856Syc } 40900161856Syc } else if (strcmp("xgc", prop_val) == 0) { 41000161856Syc if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK) 41100161856Syc return (status); 41200161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 4132e59129aSraghus } 4142e59129aSraghus 4152e59129aSraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 4162e59129aSraghus "phy-type", prop_val); 4172e59129aSraghus ddi_prop_free(prop_val); 4182e59129aSraghus 4192e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 4202e59129aSraghus "Got phy type [0x%x] from conf file", 4212e59129aSraghus nxgep->mac.portmode)); 4222e59129aSraghus 4232e59129aSraghus return (NXGE_OK); 4242e59129aSraghus } 4252d17280bSsbehera 4262d17280bSsbehera /* Get phy-type property from OBP */ 4272e59129aSraghus if (nxgep->niu_type == N2_NIU) { 4282e59129aSraghus if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 4292e59129aSraghus "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 4302e59129aSraghus if (strcmp("xgf", prop_val) == 0) { 43100161856Syc /* 43200161856Syc * Before OBP supports new phy-type property 43300161856Syc * value "xgc", the 10G copper XAUI may carry 43400161856Syc * "xgf" instead of "xgc". If the OBP is 43500161856Syc * upgraded to a newer version which supports 43600161856Syc * "xgc", then the TN1010 related code in this 43700161856Syc * "xgf" case will not be used anymore. 43800161856Syc */ 43900161856Syc if (nxge_is_tn1010_phy(nxgep)) { 44000161856Syc if ((status = 44100161856Syc nxge_set_tn1010_param(nxgep)) 44200161856Syc != NXGE_OK) { 44300161856Syc return (status); 44400161856Syc } 44500161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44600161856Syc "TN1010 Xcvr")); 44700161856Syc } else { /* For Fiber XAUI */ 44800161856Syc nxgep->statsp->mac_stats.xcvr_inuse 44900161856Syc = XPCS_XCVR; 45000161856Syc nxgep->mac.portmode = PORT_10G_FIBER; 45100161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 45200161856Syc "10G Fiber Xcvr")); 45300161856Syc } 4542e59129aSraghus } else if (strcmp("mif", prop_val) == 0) { 4552e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = 4562e59129aSraghus INT_MII_XCVR; 4572e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 4582e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4592e59129aSraghus "1G Copper Xcvr")); 4602e59129aSraghus } else if (strcmp("pcs", prop_val) == 0) { 4612e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 4622e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 4632e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4642e59129aSraghus "1G Fiber Xcvr")); 4652e59129aSraghus } else if (strcmp("xgc", prop_val) == 0) { 46600161856Syc status = nxge_set_tn1010_param(nxgep); 46700161856Syc if (status != NXGE_OK) 46800161856Syc return (status); 46900161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 4702e59129aSraghus } else if (strcmp("xgsd", prop_val) == 0) { 4712e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 4722e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 4732e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4742e59129aSraghus "OBP: 10G Serdes")); 4752e59129aSraghus } else if (strcmp("gsd", prop_val) == 0) { 4762e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 4772e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 4782e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4792e59129aSraghus "OBP: 1G Serdes")); 4802e59129aSraghus } else { 4812e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4822e59129aSraghus "Unknown phy-type: %s", prop_val)); 4832e59129aSraghus ddi_prop_free(prop_val); 4842e59129aSraghus return (NXGE_ERROR); 4852e59129aSraghus } 4862e59129aSraghus status = NXGE_OK; 4872e59129aSraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, 4882e59129aSraghus nxgep->dip, "phy-type", prop_val); 4892e59129aSraghus ddi_prop_free(prop_val); 4902e59129aSraghus 4912e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 4922e59129aSraghus "Got phy type [0x%x] from OBP", 4932e59129aSraghus nxgep->mac.portmode)); 4942e59129aSraghus 4952e59129aSraghus return (status); 4962e59129aSraghus } else { 4972e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4982e59129aSraghus "Exiting...phy-type property not found")); 4992e59129aSraghus return (NXGE_ERROR); 5002e59129aSraghus } 5012e59129aSraghus } 5022e59129aSraghus 5032e59129aSraghus 5042e59129aSraghus if (!nxgep->vpd_info.present) { 5052e59129aSraghus return (NXGE_OK); 5062e59129aSraghus } 5072e59129aSraghus 5082e59129aSraghus if (!nxgep->vpd_info.ver_valid) { 5092e59129aSraghus goto read_seeprom; 5102e59129aSraghus } 5112e59129aSraghus 5122e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5132e59129aSraghus "Reading phy type from expansion ROM")); 5142e59129aSraghus /* 5152e59129aSraghus * Try to read the phy type from the vpd data read off the 5162e59129aSraghus * expansion ROM. 5172e59129aSraghus */ 5182e59129aSraghus phy_type = nxgep->vpd_info.phy_type; 5192e59129aSraghus 520d81011f0Ssbehera if (strncmp(phy_type, "mif", 3) == 0) { 5212e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 5222e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 523d81011f0Ssbehera } else if (strncmp(phy_type, "xgf", 3) == 0) { 5242e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 5252e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 526d81011f0Ssbehera } else if (strncmp(phy_type, "pcs", 3) == 0) { 5272e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 5282e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 529d81011f0Ssbehera } else if (strncmp(phy_type, "xgc", 3) == 0) { 53000161856Syc status = nxge_set_tn1010_param(nxgep); 53100161856Syc if (status != NXGE_OK) { 53200161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 53300161856Syc "nxge_get_xcvr_type: Failed to set TN1010 param")); 53400161856Syc goto read_seeprom; 53500161856Syc } 536d81011f0Ssbehera } else if (strncmp(phy_type, "xgsd", 4) == 0) { 537d81011f0Ssbehera nxgep->mac.portmode = PORT_10G_SERDES; 538d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 539d81011f0Ssbehera } else if (strncmp(phy_type, "gsd", 3) == 0) { 540d81011f0Ssbehera nxgep->mac.portmode = PORT_1G_SERDES; 541d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 5422e59129aSraghus } else { 543d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5442e59129aSraghus "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 5452e59129aSraghus phy_type[0], phy_type[1], phy_type[2])); 5462e59129aSraghus goto read_seeprom; 5472e59129aSraghus } 5482e59129aSraghus 5492e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 5502e59129aSraghus "Got phy type [0x%x] from VPD", nxgep->mac.portmode)); 5512e59129aSraghus 5522e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 5532e59129aSraghus return (status); 5542e59129aSraghus 5552e59129aSraghus read_seeprom: 5562e59129aSraghus /* 5572e59129aSraghus * read the phy type from the SEEPROM - NCR registers 5582e59129aSraghus */ 5592e59129aSraghus status = nxge_espc_phy_type_get(nxgep); 5602e59129aSraghus if (status != NXGE_OK) { 5612e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5622e59129aSraghus "Failed to get phy type")); 5632e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 5642e59129aSraghus "[%s] invalid...please update", nxgep->vpd_info.ver)); 5652e59129aSraghus } 5662e59129aSraghus 5672e59129aSraghus return (status); 5682e59129aSraghus 5692e59129aSraghus } 5702e59129aSraghus 57159ac0c16Sdavemq /* Set up the PHY specific values. */ 57259ac0c16Sdavemq 57359ac0c16Sdavemq nxge_status_t 57459ac0c16Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep) 57559ac0c16Sdavemq { 57659ac0c16Sdavemq nxge_status_t status = NXGE_OK; 57759ac0c16Sdavemq uint32_t port_type; 57859ac0c16Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 5792e59129aSraghus uint32_t pcs_id = 0; 5802e59129aSraghus uint32_t pma_pmd_id = 0; 5812e59129aSraghus uint32_t phy_id = 0; 5822d17280bSsbehera uint16_t chip_id = 0; 58359ac0c16Sdavemq 58459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>", 58559ac0c16Sdavemq portn)); 58659ac0c16Sdavemq 5872e59129aSraghus switch (nxgep->niu_type) { 5882e59129aSraghus case N2_NIU: 5892e59129aSraghus switch (nxgep->mac.portmode) { 5902e59129aSraghus case PORT_1G_FIBER: 5912e59129aSraghus case PORT_1G_SERDES: 5922e59129aSraghus nxgep->xcvr = nxge_n2_1G_table; 5932d17280bSsbehera nxgep->xcvr_addr = portn; 5942e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr", 5952e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" : 5962e59129aSraghus "Serdes")); 5972e59129aSraghus break; 5982e59129aSraghus case PORT_10G_FIBER: 5992e59129aSraghus case PORT_10G_SERDES: 6002e59129aSraghus nxgep->xcvr = nxge_n2_10G_table; 6012d17280bSsbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 6022d17280bSsbehera nxgep->xcvr_addr = 6032d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 6042d17280bSsbehera } 6052e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr", 6062e59129aSraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" : 6072e59129aSraghus "Serdes")); 6082e59129aSraghus break; 60900161856Syc case PORT_1G_TN1010: 61000161856Syc nxgep->xcvr = nxge_n2_1G_tn1010_table; 61100161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 61200161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61300161856Syc "TN1010 Copper Xcvr in 1G")); 61400161856Syc break; 61500161856Syc case PORT_10G_TN1010: 61600161856Syc nxgep->xcvr = nxge_n2_10G_tn1010_table; 61700161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 61800161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61900161856Syc "TN1010 Copper Xcvr in 10G")); 62000161856Syc break; 6212d17280bSsbehera case PORT_HSP_MODE: 6222d17280bSsbehera nxgep->xcvr = nxge_n2_10G_table; 6232d17280bSsbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 6242d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot " 6252d17280bSsbehera "Swappable Xcvr (not present)")); 6262d17280bSsbehera break; 6272e59129aSraghus default: 6282e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6292e59129aSraghus "<== nxge_setup_xcvr_table: " 6302e59129aSraghus "Unable to determine NIU portmode")); 6312e59129aSraghus return (NXGE_ERROR); 6322e59129aSraghus } 6332e59129aSraghus break; 6342e59129aSraghus default: 6352e59129aSraghus if (nxgep->mac.portmode == 0) { 6362e59129aSraghus /* 6372e59129aSraghus * Would be the case for platforms like Maramba 6382e59129aSraghus * in which the phy type could not be got from conf 6392e59129aSraghus * file, OBP, VPD or Serial PROM. 6402e59129aSraghus */ 6412e59129aSraghus if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 6422e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6432e59129aSraghus "<== nxge_setup_xcvr_table:" 6442e59129aSraghus " Invalid Neptune type [0x%x]", 6452e59129aSraghus nxgep->niu_type)); 6462e59129aSraghus return (NXGE_ERROR); 6472e59129aSraghus } 6482e59129aSraghus 6492e59129aSraghus port_type = nxgep->niu_type >> 6502e59129aSraghus (NXGE_PORT_TYPE_SHIFT * portn); 6512e59129aSraghus port_type = port_type & (NXGE_PORT_TYPE_MASK); 6522e59129aSraghus 6532e59129aSraghus switch (port_type) { 6542e59129aSraghus 6552e59129aSraghus case NXGE_PORT_1G_COPPER: 6562e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 6572e59129aSraghus break; 6582e59129aSraghus case NXGE_PORT_10G_COPPER: 6592e59129aSraghus nxgep->mac.portmode = PORT_10G_COPPER; 6602e59129aSraghus break; 6612e59129aSraghus case NXGE_PORT_1G_FIBRE: 6622e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 6632e59129aSraghus break; 6642e59129aSraghus case NXGE_PORT_10G_FIBRE: 6652e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 6662e59129aSraghus break; 6672e59129aSraghus case NXGE_PORT_1G_SERDES: 6682e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 6692e59129aSraghus break; 6702e59129aSraghus case NXGE_PORT_10G_SERDES: 6712e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 6722e59129aSraghus break; 67300161856Syc /* Ports 2 and 3 of Alonso or ARTM */ 6742e59129aSraghus case NXGE_PORT_1G_RGMII_FIBER: 6752e59129aSraghus nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 6762e59129aSraghus break; 67700161856Syc case NXGE_PORT_TN1010: 67800161856Syc /* 67900161856Syc * If this port uses the TN1010 copper 68000161856Syc * PHY, then its speed is not known yet 68100161856Syc * because nxge_scan_ports_phy could only 68200161856Syc * figure out the vendor of the PHY but 68300161856Syc * not its speed. nxge_set_tn1010_param 68400161856Syc * will read the PHY speed and set 68500161856Syc * portmode accordingly. 68600161856Syc */ 68700161856Syc if ((status = nxge_set_tn1010_param(nxgep)) 68800161856Syc != NXGE_OK) { 68900161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 69000161856Syc "nxge_set_tn1010_param failed")); 69100161856Syc return (status); 69200161856Syc } 69300161856Syc break; 6942e59129aSraghus default: 6952e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6962e59129aSraghus "<== nxge_setup_xcvr_table: " 6972e59129aSraghus "Unknown port-type: 0x%x", port_type)); 6982e59129aSraghus return (NXGE_ERROR); 6992e59129aSraghus } 7002e59129aSraghus } 7012e59129aSraghus 70200161856Syc /* 70300161856Syc * Above switch has figured out nxge->mac.portmode, now set 70400161856Syc * nxgep->xcvr (the table) and nxgep->xcvr_addr according 70500161856Syc * to portmode. 70600161856Syc */ 7072e59129aSraghus switch (nxgep->mac.portmode) { 7082e59129aSraghus case PORT_1G_COPPER: 7092e59129aSraghus case PORT_1G_RGMII_FIBER: 71059ac0c16Sdavemq nxgep->xcvr = nxge_1G_copper_table; 7112d17280bSsbehera nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 71259ac0c16Sdavemq /* 71359ac0c16Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 71459ac0c16Sdavemq * swapped with ethernet port number. This is 7152e59129aSraghus * designed for better signal integrity in 7162e59129aSraghus * routing. This is also the case for the 7172e59129aSraghus * on-board Neptune copper ports on the Maramba 7182e59129aSraghus * platform. 71959ac0c16Sdavemq */ 7202e59129aSraghus switch (nxgep->platform_type) { 7212e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 7222e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 7232e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 7242e59129aSraghus switch (portn) { 7252e59129aSraghus case 0: 7262d17280bSsbehera nxgep->xcvr_addr += 3; 7272e59129aSraghus break; 7282e59129aSraghus case 1: 7292d17280bSsbehera nxgep->xcvr_addr += 1; 7302e59129aSraghus break; 7312e59129aSraghus case 2: 7322d17280bSsbehera nxgep->xcvr_addr -= 1; 7332e59129aSraghus break; 7342e59129aSraghus case 3: 7352d17280bSsbehera nxgep->xcvr_addr -= 3; 7362e59129aSraghus break; 7372e59129aSraghus default: 7382e59129aSraghus return (NXGE_ERROR); 7392e59129aSraghus } 74059ac0c16Sdavemq break; 74159ac0c16Sdavemq default: 7422e59129aSraghus break; 74359ac0c16Sdavemq } 744d81011f0Ssbehera 7452e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 7462e59129aSraghus (nxgep->mac.portmode == PORT_1G_COPPER) ? 7472e59129aSraghus "Copper" : "RGMII Fiber")); 74859ac0c16Sdavemq break; 74900161856Syc 7502e59129aSraghus case PORT_10G_COPPER: 75159ac0c16Sdavemq nxgep->xcvr = nxge_10G_copper_table; 75259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr")); 75359ac0c16Sdavemq break; 75400161856Syc 75500161856Syc case PORT_1G_TN1010: 75600161856Syc nxgep->xcvr = nxge_1G_tn1010_table; 75700161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 75800161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 75900161856Syc "1G TN1010 copper Xcvr")); 76000161856Syc break; 76100161856Syc 76200161856Syc case PORT_10G_TN1010: 76300161856Syc nxgep->xcvr = nxge_10G_tn1010_table; 76400161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 76500161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 76600161856Syc "10G TN1010 copper Xcvr")); 76700161856Syc break; 76800161856Syc 7692e59129aSraghus case PORT_1G_FIBER: 7702e59129aSraghus case PORT_1G_SERDES: 77159ac0c16Sdavemq nxgep->xcvr = nxge_1G_fiber_table; 7722d17280bSsbehera nxgep->xcvr_addr = portn; 7732e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 7742e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? 7752e59129aSraghus "Fiber" : "Serdes")); 77659ac0c16Sdavemq break; 7772e59129aSraghus case PORT_10G_FIBER: 7782e59129aSraghus case PORT_10G_SERDES: 77959ac0c16Sdavemq nxgep->xcvr = nxge_10G_fiber_table; 7802d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr " 7812d17280bSsbehera "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] " 7822d17280bSsbehera "nxgep->xcvr_addr = [%d]", 7832d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn], 7842d17280bSsbehera nxgep->xcvr_addr)); 7852d17280bSsbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 7862d17280bSsbehera nxgep->xcvr_addr = 7872d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 7882d17280bSsbehera } 7892e59129aSraghus switch (nxgep->platform_type) { 7902e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 7912e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 79259ac0c16Sdavemq /* 79359ac0c16Sdavemq * Switch off LED for corresponding copper 79459ac0c16Sdavemq * port 79559ac0c16Sdavemq */ 79659ac0c16Sdavemq nxge_bcm5464_link_led_off(nxgep); 7972e59129aSraghus break; 7982e59129aSraghus default: 7992e59129aSraghus break; 80059ac0c16Sdavemq } 8012e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr", 8022e59129aSraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? 8032e59129aSraghus "Fiber" : "Serdes")); 80459ac0c16Sdavemq break; 8052d17280bSsbehera 8062d17280bSsbehera case PORT_HSP_MODE: 8072d17280bSsbehera nxgep->xcvr = nxge_10G_fiber_table; 8082d17280bSsbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 8092d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot " 8102d17280bSsbehera "Swappable Xcvr (not present)")); 8112d17280bSsbehera break; 81259ac0c16Sdavemq default: 81359ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 81459ac0c16Sdavemq "Unknown port-type: 0x%x", port_type)); 81559ac0c16Sdavemq return (NXGE_ERROR); 81659ac0c16Sdavemq } 81759ac0c16Sdavemq } 81859ac0c16Sdavemq 8192d17280bSsbehera if (nxgep->mac.portmode == PORT_10G_FIBER) { 82052cdd236Ssbehera uint32_t pma_pmd_id; 82152cdd236Ssbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, 82252cdd236Ssbehera nxgep->xcvr_addr); 82352cdd236Ssbehera if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) { 82452cdd236Ssbehera chip_id = MRVL88X201X_CHIP_ID; 82552cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 82652cdd236Ssbehera "nxge_setup_xcvr_table: " 82752cdd236Ssbehera "Chip ID MARVELL [0x%x] for 10G xcvr", chip_id)); 82852cdd236Ssbehera } else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr, 8292d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG, 8302d17280bSsbehera &chip_id)) == NXGE_OK) { 8312d17280bSsbehera 8322d17280bSsbehera switch (chip_id) { 8332d17280bSsbehera case BCM8704_CHIP_ID: 8342d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8352d17280bSsbehera "nxge_setup_xcvr_table: " 8362d17280bSsbehera "Chip ID 8704 [0x%x] for 10G xcvr", 8372d17280bSsbehera chip_id)); 8382d17280bSsbehera break; 8392d17280bSsbehera case BCM8706_CHIP_ID: 8402d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8412d17280bSsbehera "nxge_setup_xcvr_table: " 8422d17280bSsbehera "Chip ID 8706 [0x%x] for 10G xcvr", 8432d17280bSsbehera chip_id)); 8442d17280bSsbehera break; 8452d17280bSsbehera default: 8462d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8472d17280bSsbehera "nxge_setup_xcvr_table: " 8482d17280bSsbehera "Unknown Chip ID [0x%x] for 10G xcvr", 8492d17280bSsbehera chip_id)); 8502d17280bSsbehera break; 8512d17280bSsbehera } 8522d17280bSsbehera } 8532d17280bSsbehera } 8542d17280bSsbehera 85559ac0c16Sdavemq nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse; 8562d17280bSsbehera nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr; 8572d17280bSsbehera nxgep->chip_id = chip_id; 8582e59129aSraghus 8592e59129aSraghus /* 8602e59129aSraghus * Get the actual device ID value returned by MDIO read. 8612e59129aSraghus */ 8622e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = 0; 8632e59129aSraghus 8642d17280bSsbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr); 8652e59129aSraghus if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) { 8662e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id; 8672e59129aSraghus } else { 8682d17280bSsbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr); 8692e59129aSraghus if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) { 8702e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = pcs_id; 8712e59129aSraghus } else { 8722e59129aSraghus phy_id = nxge_get_cl22_phy_id(nxgep, 8732d17280bSsbehera nxgep->xcvr_addr); 8742e59129aSraghus if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 8752e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = phy_id; 8762e59129aSraghus } 8772e59129aSraghus } 8782e59129aSraghus } 8792e59129aSraghus 88059ac0c16Sdavemq nxgep->mac.linkchkmode = LINKCHK_TIMER; 88159ac0c16Sdavemq 8822e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type" 88323b952a3SSantwona Behera "[0x%x] platform type[0x%x] xcvr_addr[%d]", nxgep->niu_type, 8842d17280bSsbehera nxgep->platform_type, nxgep->xcvr_addr)); 8852e59129aSraghus 88659ac0c16Sdavemq return (status); 88759ac0c16Sdavemq } 88859ac0c16Sdavemq 88944961713Sgirish /* Initialize the entire MAC and physical layer */ 89044961713Sgirish 89144961713Sgirish nxge_status_t 89244961713Sgirish nxge_mac_init(p_nxge_t nxgep) 89344961713Sgirish { 89444961713Sgirish uint8_t portn; 89544961713Sgirish nxge_status_t status = NXGE_OK; 89644961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 89744961713Sgirish 89844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 89944961713Sgirish 90044961713Sgirish nxgep->mac.portnum = portn; 90144961713Sgirish nxgep->mac.porttype = PORT_TYPE_XMAC; 90244961713Sgirish 90344961713Sgirish if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 90444961713Sgirish nxgep->mac.porttype = PORT_TYPE_BMAC; 90544961713Sgirish 90600161856Syc 90744961713Sgirish /* Initialize XIF to configure a network mode */ 90844961713Sgirish if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 90944961713Sgirish goto fail; 91044961713Sgirish } 91144961713Sgirish 91244961713Sgirish if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 91344961713Sgirish goto fail; 91444961713Sgirish } 91544961713Sgirish 91644961713Sgirish /* Initialize TX and RX MACs */ 91744961713Sgirish /* 91844961713Sgirish * Always perform XIF init first, before TX and RX MAC init 91944961713Sgirish */ 92044961713Sgirish if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 92144961713Sgirish goto fail; 92244961713Sgirish 92344961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 92444961713Sgirish goto fail; 92544961713Sgirish 92644961713Sgirish if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 92744961713Sgirish goto fail; 92844961713Sgirish 92944961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 93044961713Sgirish goto fail; 93144961713Sgirish 93244961713Sgirish if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 93344961713Sgirish goto fail; 93444961713Sgirish 935e759c33aSMichael Speer if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 936e759c33aSMichael Speer if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 937e759c33aSMichael Speer goto fail; 938e759c33aSMichael Speer } 93944961713Sgirish 940cb9d3ae6Smisaki /* Initialize MAC control configuration */ 941cb9d3ae6Smisaki if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) { 942cb9d3ae6Smisaki goto fail; 943cb9d3ae6Smisaki } 944cb9d3ae6Smisaki 94544961713Sgirish nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 94644961713Sgirish 947d81011f0Ssbehera /* The Neptune Serdes needs to be reinitialized again */ 948d81011f0Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 949d81011f0Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 95000161856Syc (nxgep->mac.portmode == PORT_1G_TN1010) || 951d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 952d81011f0Ssbehera ((portn == 0) || (portn == 1))) { 953d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 954d81011f0Ssbehera "nxge_mac_init: reinit Neptune 1G Serdes ")); 955d81011f0Ssbehera if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) { 956d81011f0Ssbehera goto fail; 957d81011f0Ssbehera } 958d81011f0Ssbehera } 959d81011f0Ssbehera 9602e59129aSraghus 96144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 96244961713Sgirish 96344961713Sgirish return (NXGE_OK); 96444961713Sgirish fail: 96544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 96652ccf843Smisaki "nxge_mac_init: failed to initialize MAC port<%d>", portn)); 96744961713Sgirish return (status); 96844961713Sgirish } 96944961713Sgirish 97044961713Sgirish /* Initialize the Ethernet Link */ 97144961713Sgirish 97244961713Sgirish nxge_status_t 97344961713Sgirish nxge_link_init(p_nxge_t nxgep) 97444961713Sgirish { 97544961713Sgirish nxge_status_t status = NXGE_OK; 9762e59129aSraghus nxge_port_mode_t portmode; 97744961713Sgirish #ifdef NXGE_DEBUG 97844961713Sgirish uint8_t portn; 97944961713Sgirish 98044961713Sgirish portn = nxgep->mac.portnum; 98144961713Sgirish 98244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 98344961713Sgirish #endif 9841c7408c9Stc /* For Opus NEM, Serdes always needs to be initialized */ 98544961713Sgirish 9862e59129aSraghus portmode = nxgep->mac.portmode; 9872d17280bSsbehera 98800161856Syc /* 98900161856Syc * Workaround to get link up in both NIU ports. Some portmodes require 99000161856Syc * that the xcvr be initialized twice, the first time before calling 99100161856Syc * nxge_serdes_init. 99200161856Syc */ 9932e59129aSraghus if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) && 99400161856Syc (portmode != PORT_10G_TN1010) && 99500161856Syc (portmode != PORT_1G_TN1010) && 9962e59129aSraghus (portmode != PORT_1G_SERDES)) { 9972e59129aSraghus if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) { 99844961713Sgirish goto fail; 9992e59129aSraghus } 100044961713Sgirish } 100100161856Syc 100244961713Sgirish NXGE_DELAY(200000); 100344961713Sgirish /* Initialize internal serdes */ 100444961713Sgirish if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 100544961713Sgirish goto fail; 100644961713Sgirish NXGE_DELAY(200000); 100744961713Sgirish if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 100844961713Sgirish goto fail; 100944961713Sgirish 101044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 101144961713Sgirish 101244961713Sgirish return (NXGE_OK); 101344961713Sgirish 101444961713Sgirish fail: 101552ccf843Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_link_init: ", 101652ccf843Smisaki "failed to initialize Ethernet link on port<%d>", portn)); 101744961713Sgirish 101844961713Sgirish return (status); 101944961713Sgirish } 102044961713Sgirish 102144961713Sgirish 102244961713Sgirish /* Initialize the XIF sub-block within the MAC */ 102344961713Sgirish 102444961713Sgirish nxge_status_t 102544961713Sgirish nxge_xif_init(p_nxge_t nxgep) 102644961713Sgirish { 102744961713Sgirish uint32_t xif_cfg = 0; 102844961713Sgirish npi_attr_t ap; 102944961713Sgirish uint8_t portn; 103044961713Sgirish nxge_port_t portt; 103144961713Sgirish nxge_port_mode_t portmode; 103244961713Sgirish p_nxge_stats_t statsp; 103344961713Sgirish npi_status_t rs = NPI_SUCCESS; 103444961713Sgirish npi_handle_t handle; 103544961713Sgirish 103644961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 103744961713Sgirish 103844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 103944961713Sgirish 104044961713Sgirish handle = nxgep->npi_handle; 104144961713Sgirish portmode = nxgep->mac.portmode; 104244961713Sgirish portt = nxgep->mac.porttype; 104344961713Sgirish statsp = nxgep->statsp; 104444961713Sgirish 1045d81011f0Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 1046d81011f0Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 104700161856Syc (nxgep->mac.portmode == PORT_1G_TN1010) || 1048d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 1049d81011f0Ssbehera ((portn == 0) || (portn == 1))) { 1050d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1051d81011f0Ssbehera "nxge_xcvr_init: set ATCA mode")); 1052d81011f0Ssbehera npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE); 1053d81011f0Ssbehera } 1054d81011f0Ssbehera 105544961713Sgirish if (portt == PORT_TYPE_XMAC) { 105644961713Sgirish 105744961713Sgirish /* Setup XIF Configuration for XMAC */ 105844961713Sgirish 105944961713Sgirish if ((portmode == PORT_10G_FIBER) || 10602e59129aSraghus (portmode == PORT_10G_COPPER) || 106100161856Syc (portmode == PORT_10G_TN1010) || 10621c7408c9Stc (portmode == PORT_HSP_MODE) || 10632e59129aSraghus (portmode == PORT_10G_SERDES)) 106444961713Sgirish xif_cfg |= CFG_XMAC_XIF_LFS; 106544961713Sgirish 106600161856Syc /* Bypass PCS so that RGMII will be used */ 106744961713Sgirish if (portmode == PORT_1G_COPPER) { 106844961713Sgirish xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 106944961713Sgirish } 107044961713Sgirish 107144961713Sgirish /* Set MAC Internal Loopback if necessary */ 107244961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 107344961713Sgirish xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 107444961713Sgirish 107544961713Sgirish if (statsp->mac_stats.link_speed == 100) 107644961713Sgirish xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 107744961713Sgirish 107844961713Sgirish xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 107944961713Sgirish 10802e59129aSraghus if ((portmode == PORT_10G_FIBER) || 108100161856Syc (portmode == PORT_10G_TN1010) || 108200161856Syc (portmode == PORT_1G_TN1010) || 10831c7408c9Stc (portmode == PORT_HSP_MODE) || 10842e59129aSraghus (portmode == PORT_10G_SERDES)) { 108500161856Syc /* Assume LED same for 1G and 10G */ 108644961713Sgirish if (statsp->mac_stats.link_up) { 108744961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 108844961713Sgirish } else { 108944961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 109044961713Sgirish } 109144961713Sgirish } 109244961713Sgirish 109344961713Sgirish rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 109444961713Sgirish if (rs != NPI_SUCCESS) 109544961713Sgirish goto fail; 109644961713Sgirish 109744961713Sgirish nxgep->mac.xif_config = xif_cfg; 109844961713Sgirish 109944961713Sgirish /* Set Port Mode */ 110044961713Sgirish if ((portmode == PORT_10G_FIBER) || 11012e59129aSraghus (portmode == PORT_10G_COPPER) || 110200161856Syc (portmode == PORT_10G_TN1010) || 11031c7408c9Stc (portmode == PORT_HSP_MODE) || 11042e59129aSraghus (portmode == PORT_10G_SERDES)) { 110544961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 110652ccf843Smisaki MAC_XGMII_MODE, rs); 110744961713Sgirish if (rs != NPI_SUCCESS) 110844961713Sgirish goto fail; 110944961713Sgirish if (statsp->mac_stats.link_up) { 111044961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 111144961713Sgirish goto fail; 111244961713Sgirish } else { 111344961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 111444961713Sgirish goto fail; 111544961713Sgirish } 111644961713Sgirish } else if ((portmode == PORT_1G_FIBER) || 11172e59129aSraghus (portmode == PORT_1G_COPPER) || 1118d81011f0Ssbehera (portmode == PORT_1G_SERDES) || 111900161856Syc (portmode == PORT_1G_TN1010) || 1120d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 1121d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1122d81011f0Ssbehera "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]", 1123d81011f0Ssbehera portn, portmode, statsp->mac_stats.link_speed)); 112444961713Sgirish if (statsp->mac_stats.link_speed == 1000) { 112544961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 112652ccf843Smisaki MAC_GMII_MODE, rs); 112744961713Sgirish } else { 112844961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 112952ccf843Smisaki MAC_MII_MODE, rs); 113044961713Sgirish } 113144961713Sgirish if (rs != NPI_SUCCESS) 113244961713Sgirish goto fail; 113344961713Sgirish } else { 113444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 113552ccf843Smisaki "nxge_xif_init: Unknown port mode (%d)" 113652ccf843Smisaki " for port<%d>", portmode, portn)); 113744961713Sgirish goto fail; 113844961713Sgirish } 113944961713Sgirish 1140d81011f0Ssbehera /* Enable ATCA mode */ 1141d81011f0Ssbehera 114244961713Sgirish } else if (portt == PORT_TYPE_BMAC) { 114344961713Sgirish 114444961713Sgirish /* Setup XIF Configuration for BMAC */ 114544961713Sgirish 1146d81011f0Ssbehera if ((portmode == PORT_1G_COPPER) || 1147d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 114844961713Sgirish if (statsp->mac_stats.link_speed == 100) 114944961713Sgirish xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 115044961713Sgirish } 115144961713Sgirish 115244961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 115344961713Sgirish xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 115444961713Sgirish 115544961713Sgirish if (statsp->mac_stats.link_speed == 1000) 115644961713Sgirish xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 115744961713Sgirish 115844961713Sgirish xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 115944961713Sgirish 116044961713Sgirish rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 116144961713Sgirish if (rs != NPI_SUCCESS) 116244961713Sgirish goto fail; 116344961713Sgirish nxgep->mac.xif_config = xif_cfg; 116444961713Sgirish } 116544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 116644961713Sgirish return (NXGE_OK); 116744961713Sgirish fail: 116844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 116952ccf843Smisaki "nxge_xif_init: Failed to initialize XIF port<%d>", portn)); 117044961713Sgirish return (NXGE_ERROR | rs); 117144961713Sgirish } 117244961713Sgirish 117344961713Sgirish 117400161856Syc /* 117500161856Syc * Initialize the PCS sub-block in the MAC. Note that PCS does not 117600161856Syc * support loopback like XPCS. 117700161856Syc */ 117844961713Sgirish nxge_status_t 117944961713Sgirish nxge_pcs_init(p_nxge_t nxgep) 118044961713Sgirish { 118144961713Sgirish pcs_cfg_t pcs_cfg; 118244961713Sgirish uint32_t val; 118344961713Sgirish uint8_t portn; 118444961713Sgirish nxge_port_mode_t portmode; 118544961713Sgirish npi_handle_t handle; 118644961713Sgirish p_nxge_stats_t statsp; 118700161856Syc pcs_ctrl_t pcs_ctrl; 118844961713Sgirish npi_status_t rs = NPI_SUCCESS; 118900161856Syc uint8_t i; 119044961713Sgirish 119144961713Sgirish handle = nxgep->npi_handle; 119244961713Sgirish portmode = nxgep->mac.portmode; 119344961713Sgirish portn = nxgep->mac.portnum; 119444961713Sgirish statsp = nxgep->statsp; 119544961713Sgirish 119644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 119744961713Sgirish 119800161856Syc if (portmode == PORT_1G_FIBER || 119900161856Syc portmode == PORT_1G_TN1010 || 120000161856Syc portmode == PORT_1G_SERDES) { 120100161856Syc if (portmode == PORT_1G_TN1010) { 120200161856Syc /* Reset PCS multiple time in PORT_1G_TN1010 mode */ 120300161856Syc for (i = 0; i < 6; i ++) { 120400161856Syc if ((rs = npi_mac_pcs_reset(handle, portn)) 120500161856Syc != NPI_SUCCESS) { 120600161856Syc goto fail; 120700161856Syc } 120800161856Syc } 120900161856Syc } else { 121000161856Syc if ((rs = npi_mac_pcs_reset(handle, portn)) 121100161856Syc != NPI_SUCCESS) 121200161856Syc goto fail; 12132e59129aSraghus } 12142e59129aSraghus 121544961713Sgirish /* Initialize port's PCS */ 121644961713Sgirish pcs_cfg.value = 0; 121744961713Sgirish pcs_cfg.bits.w0.enable = 1; 121844961713Sgirish pcs_cfg.bits.w0.mask = 1; 121944961713Sgirish PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 122044961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 122144961713Sgirish 12222e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12232e59129aSraghus "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx", 12242e59129aSraghus portn, pcs_cfg.value)); 122500161856Syc 122600161856Syc if (portmode == PORT_1G_TN1010) { 122700161856Syc /* 122800161856Syc * Must disable PCS auto-negotiation when the the driver 122900161856Syc * is driving the TN1010 based XAUI card Otherwise the 123000161856Syc * autonegotiation between the PCS and the TN1010 PCS 123100161856Syc * will never complete and the Neptune/NIU will not work 123200161856Syc */ 123300161856Syc pcs_ctrl.value = 0; 123400161856Syc PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG, 123500161856Syc pcs_ctrl.value); 123600161856Syc } 123700161856Syc } else if (portmode == PORT_10G_FIBER || 123800161856Syc portmode == PORT_10G_COPPER || 123900161856Syc portmode == PORT_10G_TN1010 || 12401c7408c9Stc portmode == PORT_HSP_MODE || 124100161856Syc portmode == PORT_10G_SERDES) { 124244961713Sgirish /* Use internal XPCS, bypass 1G PCS */ 124344961713Sgirish XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 124444961713Sgirish val &= ~XMAC_XIF_XPCS_BYPASS; 124544961713Sgirish XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 124644961713Sgirish 124744961713Sgirish if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 124844961713Sgirish goto fail; 124944961713Sgirish 125044961713Sgirish /* Set XPCS Internal Loopback if necessary */ 125144961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 125252ccf843Smisaki XPCS_REG_CONTROL1, &val)) != NPI_SUCCESS) 125344961713Sgirish goto fail; 125400161856Syc 125544961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 125652ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 125744961713Sgirish val |= XPCS_CTRL1_LOOPBK; 125844961713Sgirish else 125944961713Sgirish val &= ~XPCS_CTRL1_LOOPBK; 126044961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 126152ccf843Smisaki XPCS_REG_CONTROL1, val)) != NPI_SUCCESS) 126244961713Sgirish goto fail; 126344961713Sgirish 126444961713Sgirish /* Clear descw errors */ 126544961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 126652ccf843Smisaki XPCS_REG_DESCWERR_COUNTER, 0)) != NPI_SUCCESS) 126744961713Sgirish goto fail; 126844961713Sgirish /* Clear symbol errors */ 126944961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 127052ccf843Smisaki XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) != NPI_SUCCESS) 127144961713Sgirish goto fail; 127244961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 127352ccf843Smisaki XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) != NPI_SUCCESS) 127444961713Sgirish goto fail; 127544961713Sgirish 1276d81011f0Ssbehera } else if ((portmode == PORT_1G_COPPER) || 1277d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 1278d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1279d81011f0Ssbehera "==> nxge_pcs_init: (1G) copper port<%d>", portn)); 128044961713Sgirish if (portn < 4) { 128144961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 128252ccf843Smisaki PCS_DATAPATH_MODE_MII); 128344961713Sgirish } 128444961713Sgirish if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 128544961713Sgirish goto fail; 128644961713Sgirish 128744961713Sgirish } else { 128844961713Sgirish goto fail; 128944961713Sgirish } 129044961713Sgirish pass: 129144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 129244961713Sgirish return (NXGE_OK); 129344961713Sgirish fail: 129444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 129552ccf843Smisaki "nxge_pcs_init: Failed to initialize PCS port<%d>", portn)); 129644961713Sgirish return (NXGE_ERROR | rs); 129744961713Sgirish } 129844961713Sgirish 1299cb9d3ae6Smisaki /* 1300cb9d3ae6Smisaki * Initialize the MAC CTRL sub-block within the MAC 1301cb9d3ae6Smisaki * Only the receive-pause-cap is supported. 1302cb9d3ae6Smisaki */ 1303cb9d3ae6Smisaki nxge_status_t 1304cb9d3ae6Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep) 1305cb9d3ae6Smisaki { 1306cb9d3ae6Smisaki uint8_t portn; 1307cb9d3ae6Smisaki nxge_port_t portt; 1308cb9d3ae6Smisaki p_nxge_stats_t statsp; 1309cb9d3ae6Smisaki npi_handle_t handle; 1310cb9d3ae6Smisaki uint32_t val; 1311cb9d3ae6Smisaki 1312cb9d3ae6Smisaki portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1313cb9d3ae6Smisaki 1314cb9d3ae6Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>", 1315cb9d3ae6Smisaki portn)); 1316cb9d3ae6Smisaki 1317cb9d3ae6Smisaki handle = nxgep->npi_handle; 1318cb9d3ae6Smisaki portt = nxgep->mac.porttype; 1319cb9d3ae6Smisaki statsp = nxgep->statsp; 1320cb9d3ae6Smisaki 1321cb9d3ae6Smisaki if (portt == PORT_TYPE_XMAC) { 132200161856Syc /* Reading the current XMAC Config Register for XMAC */ 1323cb9d3ae6Smisaki XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 1324cb9d3ae6Smisaki 1325cb9d3ae6Smisaki /* 1326cb9d3ae6Smisaki * Setup XMAC Configuration for XMAC 1327cb9d3ae6Smisaki * XMAC only supports receive-pause 1328cb9d3ae6Smisaki */ 1329cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 1330cb9d3ae6Smisaki if (!statsp->mac_stats.adv_cap_pause) { 1331cb9d3ae6Smisaki /* 1332cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1333cb9d3ae6Smisaki * is 0, enable receive pause. 1334cb9d3ae6Smisaki */ 1335cb9d3ae6Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 1336cb9d3ae6Smisaki } else { 1337cb9d3ae6Smisaki /* 1338cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1339cb9d3ae6Smisaki * is 1, disable receive pause. Send pause is 1340cb9d3ae6Smisaki * not supported. 1341cb9d3ae6Smisaki */ 1342cb9d3ae6Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1343cb9d3ae6Smisaki } 1344cb9d3ae6Smisaki } else { 13451bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13461bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: pause", 13471bd6825cSml portn)); 1348cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 13491bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13501bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: " 13511bd6825cSml "enable pause", portn)); 1352cb9d3ae6Smisaki /* 1353cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1354cb9d3ae6Smisaki * is 1, enable receive pause. 1355cb9d3ae6Smisaki */ 1356cb9d3ae6Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 1357cb9d3ae6Smisaki } else { 1358cb9d3ae6Smisaki /* 1359cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1360cb9d3ae6Smisaki * is 0, disable receive pause. Send pause is 1361cb9d3ae6Smisaki * not supported 1362cb9d3ae6Smisaki */ 13631bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13641bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: " 13651bd6825cSml "disable pause", portn)); 1366cb9d3ae6Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1367cb9d3ae6Smisaki } 1368cb9d3ae6Smisaki } 1369cb9d3ae6Smisaki XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 1370cb9d3ae6Smisaki } else if (portt == PORT_TYPE_BMAC) { 137100161856Syc /* Reading the current MAC CTRL Config Register for BMAC */ 1372cb9d3ae6Smisaki BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val); 1373cb9d3ae6Smisaki 1374cb9d3ae6Smisaki /* Setup MAC CTRL Configuration for BMAC */ 1375cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 1376cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 1377cb9d3ae6Smisaki /* 1378cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1379cb9d3ae6Smisaki * is 1, disable receive pause. Send pause 1380cb9d3ae6Smisaki * is not supported 1381cb9d3ae6Smisaki */ 1382cb9d3ae6Smisaki val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN; 1383cb9d3ae6Smisaki } else { 1384cb9d3ae6Smisaki /* 1385cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1386cb9d3ae6Smisaki * is 0, enable receive pause and disable 1387cb9d3ae6Smisaki * send pause. 1388cb9d3ae6Smisaki */ 1389cb9d3ae6Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1390cb9d3ae6Smisaki val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN; 1391cb9d3ae6Smisaki } 1392cb9d3ae6Smisaki } else { 1393cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 1394cb9d3ae6Smisaki /* 1395cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1396cb9d3ae6Smisaki * is 1, enable receive pause. Send pause is 1397cb9d3ae6Smisaki * not supported. 1398cb9d3ae6Smisaki */ 1399cb9d3ae6Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1400cb9d3ae6Smisaki } else { 1401cb9d3ae6Smisaki /* 1402cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1403cb9d3ae6Smisaki * is 0, pause capability is not available in 1404cb9d3ae6Smisaki * either direction. 1405cb9d3ae6Smisaki */ 1406cb9d3ae6Smisaki val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN & 140752ccf843Smisaki ~MAC_CTRL_CFG_RECV_PAUSE_EN); 1408cb9d3ae6Smisaki } 1409cb9d3ae6Smisaki } 1410cb9d3ae6Smisaki BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val); 1411cb9d3ae6Smisaki } 1412cb9d3ae6Smisaki 1413cb9d3ae6Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>", 1414cb9d3ae6Smisaki portn)); 1415cb9d3ae6Smisaki 1416cb9d3ae6Smisaki return (NXGE_OK); 1417cb9d3ae6Smisaki } 1418cb9d3ae6Smisaki 141944961713Sgirish /* Initialize the Internal Serdes */ 142044961713Sgirish 142144961713Sgirish nxge_status_t 142244961713Sgirish nxge_serdes_init(p_nxge_t nxgep) 142344961713Sgirish { 142444961713Sgirish p_nxge_stats_t statsp; 142544961713Sgirish #ifdef NXGE_DEBUG 142644961713Sgirish uint8_t portn; 142744961713Sgirish #endif 142844961713Sgirish nxge_status_t status = NXGE_OK; 142944961713Sgirish 143044961713Sgirish #ifdef NXGE_DEBUG 143144961713Sgirish portn = nxgep->mac.portnum; 143244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 143359ac0c16Sdavemq "==> nxge_serdes_init port<%d>", portn)); 143444961713Sgirish #endif 143544961713Sgirish 143659ac0c16Sdavemq if (nxgep->xcvr.serdes_init) { 143759ac0c16Sdavemq statsp = nxgep->statsp; 143859ac0c16Sdavemq status = nxgep->xcvr.serdes_init(nxgep); 143959ac0c16Sdavemq if (status != NXGE_OK) 144044961713Sgirish goto fail; 144159ac0c16Sdavemq statsp->mac_stats.serdes_inits++; 144244961713Sgirish } 144344961713Sgirish 144444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 144559ac0c16Sdavemq portn)); 144644961713Sgirish 144744961713Sgirish return (NXGE_OK); 144844961713Sgirish 144944961713Sgirish fail: 145044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 145159ac0c16Sdavemq "nxge_serdes_init: Failed to initialize serdes for port<%d>", 145259ac0c16Sdavemq portn)); 145344961713Sgirish 145444961713Sgirish return (status); 145544961713Sgirish } 145644961713Sgirish 145744961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 145844961713Sgirish 145959ac0c16Sdavemq static nxge_status_t 146044961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep) 146144961713Sgirish { 146244961713Sgirish uint8_t portn; 146344961713Sgirish int chan; 146444961713Sgirish esr_ti_cfgpll_l_t pll_cfg_l; 14652e59129aSraghus esr_ti_cfgpll_l_t pll_sts_l; 146644961713Sgirish esr_ti_cfgrx_l_t rx_cfg_l; 146744961713Sgirish esr_ti_cfgrx_h_t rx_cfg_h; 146844961713Sgirish esr_ti_cfgtx_l_t tx_cfg_l; 146944961713Sgirish esr_ti_cfgtx_h_t tx_cfg_h; 14702e59129aSraghus #ifdef NXGE_DEBUG 14712e59129aSraghus esr_ti_testcfg_t cfg; 14722e59129aSraghus #endif 147344961713Sgirish esr_ti_testcfg_t test_cfg; 147444961713Sgirish nxge_status_t status = NXGE_OK; 147544961713Sgirish 147644961713Sgirish portn = nxgep->mac.portnum; 147744961713Sgirish 147844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 147952ccf843Smisaki portn)); 1480*4df55fdeSJanie Lu if (nxgep->niu_hw_type == NIU_HW_TYPE_RF) { 1481*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1482*4df55fdeSJanie Lu "==> nxge_n2_serdes_init port<%d>: KT-NIU", portn)); 1483*4df55fdeSJanie Lu return (nxge_n2_kt_serdes_init(nxgep)); 1484*4df55fdeSJanie Lu } 148544961713Sgirish 148644961713Sgirish tx_cfg_l.value = 0; 148744961713Sgirish tx_cfg_h.value = 0; 148844961713Sgirish rx_cfg_l.value = 0; 148944961713Sgirish rx_cfg_h.value = 0; 149044961713Sgirish pll_cfg_l.value = 0; 14912e59129aSraghus pll_sts_l.value = 0; 149244961713Sgirish test_cfg.value = 0; 149344961713Sgirish 149400161856Syc /* 149500161856Syc * If the nxge driver has been plumbed without a link, then it will 149600161856Syc * detect a link up when a cable connecting to an anto-negotiation 149700161856Syc * partner is plugged into the port. Because the TN1010 PHY supports 149800161856Syc * both 1G and 10G speeds, the driver must re-configure the 149900161856Syc * Neptune/NIU according to the negotiated speed. nxge_n2_serdes_init 150000161856Syc * is called at the post-link-up reconfiguration time. Here it calls 150100161856Syc * nxge_set_tn1010_param to set portmode before re-initializing 150200161856Syc * the serdes. 150300161856Syc */ 150400161856Syc if (nxgep->mac.portmode == PORT_1G_TN1010 || 150500161856Syc nxgep->mac.portmode == PORT_10G_TN1010) { 150600161856Syc if (nxge_set_tn1010_param(nxgep) != NXGE_OK) { 150700161856Syc goto fail; 150800161856Syc } 150900161856Syc } 151000161856Syc 151100161856Syc if (nxgep->mac.portmode == PORT_10G_FIBER || 151200161856Syc nxgep->mac.portmode == PORT_10G_TN1010 || 15131c7408c9Stc nxgep->mac.portmode == PORT_HSP_MODE || 151400161856Syc nxgep->mac.portmode == PORT_10G_SERDES) { 151544961713Sgirish /* 0x0E01 */ 151644961713Sgirish tx_cfg_l.bits.entx = 1; 151744961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 151844961713Sgirish 151944961713Sgirish /* 0x9101 */ 152044961713Sgirish rx_cfg_l.bits.enrx = 1; 152144961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 152244961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 152344961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 152444961713Sgirish 152544961713Sgirish /* 0x0008 */ 152644961713Sgirish rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 152744961713Sgirish 152844961713Sgirish /* Set loopback mode if necessary */ 152944961713Sgirish if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 153044961713Sgirish tx_cfg_l.bits.entest = 1; 153144961713Sgirish rx_cfg_l.bits.entest = 1; 153244961713Sgirish test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 153344961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 153452ccf843Smisaki ESR_N2_DEV_ADDR, 153552ccf843Smisaki ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) 153644961713Sgirish goto fail; 153744961713Sgirish } 153844961713Sgirish 153900161856Syc /* Initialize PLL for 10G */ 154000161856Syc pll_cfg_l.bits.mpy = CFGPLL_MPY_10X; 154100161856Syc pll_cfg_l.bits.enpll = 1; 154200161856Syc pll_sts_l.bits.enpll = 1; 154300161856Syc if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 154400161856Syc ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK) 154500161856Syc goto fail; 154600161856Syc 154700161856Syc if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 154800161856Syc ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 154900161856Syc goto fail; 155044961713Sgirish 155100161856Syc #ifdef NXGE_DEBUG 155200161856Syc nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 155300161856Syc ESR_N2_PLL_CFG_L_REG, &cfg.value); 155400161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 155500161856Syc "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 155600161856Syc portn, pll_cfg_l.value, cfg.value)); 155744961713Sgirish 155800161856Syc nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 155900161856Syc ESR_N2_PLL_STS_L_REG, &cfg.value); 156000161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 156100161856Syc "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 156200161856Syc portn, pll_sts_l.value, cfg.value)); 156300161856Syc #endif 156400161856Syc } else if (nxgep->mac.portmode == PORT_1G_FIBER || 156500161856Syc nxgep->mac.portmode == PORT_1G_TN1010 || 156600161856Syc nxgep->mac.portmode == PORT_1G_SERDES) { 156744961713Sgirish /* 0x0E21 */ 156844961713Sgirish tx_cfg_l.bits.entx = 1; 156944961713Sgirish tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 157044961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 157144961713Sgirish 157244961713Sgirish /* 0x9121 */ 157344961713Sgirish rx_cfg_l.bits.enrx = 1; 157444961713Sgirish rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 157544961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 157644961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 157744961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 157844961713Sgirish 15792e59129aSraghus if (portn == 0) { 15802e59129aSraghus /* 0x8 */ 15812e59129aSraghus rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 15822e59129aSraghus } 158344961713Sgirish 158400161856Syc /* Initialize PLL for 1G */ 158544961713Sgirish pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 158644961713Sgirish pll_cfg_l.bits.enpll = 1; 15872e59129aSraghus pll_sts_l.bits.enpll = 1; 158844961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 158952ccf843Smisaki ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK) 159044961713Sgirish goto fail; 15912e59129aSraghus 15922e59129aSraghus if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 15932e59129aSraghus ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 15942e59129aSraghus goto fail; 15952e59129aSraghus 15962e59129aSraghus #ifdef NXGE_DEBUG 15972e59129aSraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 15982e59129aSraghus ESR_N2_PLL_CFG_L_REG, &cfg.value); 15992e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16002e59129aSraghus "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 16012e59129aSraghus portn, pll_cfg_l.value, cfg.value)); 16022e59129aSraghus 16032e59129aSraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 16042e59129aSraghus ESR_N2_PLL_STS_L_REG, &cfg.value); 16052e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16062e59129aSraghus "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 16072e59129aSraghus portn, pll_sts_l.value, cfg.value)); 16082e59129aSraghus #endif 16092e59129aSraghus 16102e59129aSraghus /* Set loopback mode if necessary */ 16112e59129aSraghus if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 16122e59129aSraghus tx_cfg_l.bits.entest = 1; 16132e59129aSraghus rx_cfg_l.bits.entest = 1; 16142e59129aSraghus test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 16152e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16162e59129aSraghus "==> nxge_n2_serdes_init port<%d>: loopback 0x%x", 16172e59129aSraghus portn, test_cfg.value)); 16182e59129aSraghus if ((status = nxge_mdio_write(nxgep, portn, 16192e59129aSraghus ESR_N2_DEV_ADDR, 16202e59129aSraghus ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 16212e59129aSraghus goto fail; 16222e59129aSraghus } 16232e59129aSraghus } 162444961713Sgirish } else { 162544961713Sgirish goto fail; 162644961713Sgirish } 162744961713Sgirish 162844961713Sgirish /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 162944961713Sgirish 163044961713Sgirish NXGE_DELAY(20); 163144961713Sgirish 163244961713Sgirish /* init TX channels */ 163344961713Sgirish for (chan = 0; chan < 4; chan++) { 163444961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 163552ccf843Smisaki ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK) 163644961713Sgirish goto fail; 163744961713Sgirish 163844961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 163952ccf843Smisaki ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK) 164044961713Sgirish goto fail; 16412e59129aSraghus 16422e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16432e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x", 16442e59129aSraghus portn, chan, tx_cfg_l.value)); 16452e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16462e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x", 16472e59129aSraghus portn, chan, tx_cfg_h.value)); 164844961713Sgirish } 164944961713Sgirish 165044961713Sgirish /* init RX channels */ 165144961713Sgirish for (chan = 0; chan < 4; chan++) { 165244961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 165352ccf843Smisaki ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) != NXGE_OK) 165444961713Sgirish goto fail; 165544961713Sgirish 165644961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 165752ccf843Smisaki ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) != NXGE_OK) 165844961713Sgirish goto fail; 16592e59129aSraghus 16602e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16612e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x", 16622e59129aSraghus portn, chan, rx_cfg_l.value)); 166300161856Syc 16642e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16652e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x", 16662e59129aSraghus portn, chan, rx_cfg_h.value)); 166744961713Sgirish } 166844961713Sgirish 166944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 167052ccf843Smisaki portn)); 167144961713Sgirish 167244961713Sgirish return (NXGE_OK); 167344961713Sgirish fail: 16742d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16752d17280bSsbehera "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 16762d17280bSsbehera portn)); 167744961713Sgirish 167844961713Sgirish return (status); 1679*4df55fdeSJanie Lu 1680*4df55fdeSJanie Lu } 1681*4df55fdeSJanie Lu 1682*4df55fdeSJanie Lu /* Initialize the TI Hedwig Internal Serdes (N2-KT-NIU only) */ 1683*4df55fdeSJanie Lu 1684*4df55fdeSJanie Lu static nxge_status_t 1685*4df55fdeSJanie Lu nxge_n2_kt_serdes_init(p_nxge_t nxgep) 1686*4df55fdeSJanie Lu { 1687*4df55fdeSJanie Lu uint8_t portn; 1688*4df55fdeSJanie Lu int chan; 1689*4df55fdeSJanie Lu k_esr_ti_cfgpll_l_t pll_cfg_l; 1690*4df55fdeSJanie Lu k_esr_ti_cfgrx_l_t rx_cfg_l; 1691*4df55fdeSJanie Lu k_esr_ti_cfgrx_h_t rx_cfg_h; 1692*4df55fdeSJanie Lu k_esr_ti_cfgtx_l_t tx_cfg_l; 1693*4df55fdeSJanie Lu k_esr_ti_cfgtx_h_t tx_cfg_h; 1694*4df55fdeSJanie Lu #ifdef NXGE_DEBUG 1695*4df55fdeSJanie Lu k_esr_ti_testcfg_t cfg; 1696*4df55fdeSJanie Lu #endif 1697*4df55fdeSJanie Lu k_esr_ti_testcfg_t test_cfg; 1698*4df55fdeSJanie Lu nxge_status_t status = NXGE_OK; 1699*4df55fdeSJanie Lu boolean_t mode_1g = B_FALSE; 1700*4df55fdeSJanie Lu 1701*4df55fdeSJanie Lu portn = nxgep->mac.portnum; 1702*4df55fdeSJanie Lu 1703*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1704*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>", portn)); 1705*4df55fdeSJanie Lu 1706*4df55fdeSJanie Lu tx_cfg_l.value = 0; 1707*4df55fdeSJanie Lu tx_cfg_h.value = 0; 1708*4df55fdeSJanie Lu rx_cfg_l.value = 0; 1709*4df55fdeSJanie Lu rx_cfg_h.value = 0; 1710*4df55fdeSJanie Lu pll_cfg_l.value = 0; 1711*4df55fdeSJanie Lu test_cfg.value = 0; 1712*4df55fdeSJanie Lu 1713*4df55fdeSJanie Lu /* 1714*4df55fdeSJanie Lu * The following setting assumes the reference clock frquency 1715*4df55fdeSJanie Lu * is 156.25 MHz. 1716*4df55fdeSJanie Lu */ 1717*4df55fdeSJanie Lu /* 1718*4df55fdeSJanie Lu * If the nxge driver has been plumbed without a link, then it will 1719*4df55fdeSJanie Lu * detect a link up when a cable connecting to an anto-negotiation 1720*4df55fdeSJanie Lu * partner is plugged into the port. Because the TN1010 PHY supports 1721*4df55fdeSJanie Lu * both 1G and 10G speeds, the driver must re-configure the 1722*4df55fdeSJanie Lu * Neptune/NIU according to the negotiated speed. nxge_n2_serdes_init 1723*4df55fdeSJanie Lu * is called at the post-link-up reconfiguration time. Here it calls 1724*4df55fdeSJanie Lu * nxge_set_tn1010_param to set portmode before re-initializing 1725*4df55fdeSJanie Lu * the serdes. 1726*4df55fdeSJanie Lu */ 1727*4df55fdeSJanie Lu if (nxgep->mac.portmode == PORT_1G_TN1010 || 1728*4df55fdeSJanie Lu nxgep->mac.portmode == PORT_10G_TN1010) { 1729*4df55fdeSJanie Lu if (nxge_set_tn1010_param(nxgep) != NXGE_OK) { 1730*4df55fdeSJanie Lu goto fail; 1731*4df55fdeSJanie Lu } 1732*4df55fdeSJanie Lu } 1733*4df55fdeSJanie Lu if (nxgep->mac.portmode == PORT_10G_FIBER || 1734*4df55fdeSJanie Lu nxgep->mac.portmode == PORT_10G_TN1010 || 1735*4df55fdeSJanie Lu nxgep->mac.portmode == PORT_10G_SERDES) { 1736*4df55fdeSJanie Lu tx_cfg_l.bits.entx = K_CFGTX_ENABLE_TX; 1737*4df55fdeSJanie Lu /* 0x1e21 */ 1738*4df55fdeSJanie Lu tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV; 1739*4df55fdeSJanie Lu tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF; 1740*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1741*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x", 1742*4df55fdeSJanie Lu portn, tx_cfg_l.value)); 1743*4df55fdeSJanie Lu 1744*4df55fdeSJanie Lu /* channel 0: enable syn. master */ 1745*4df55fdeSJanie Lu /* 0x40 */ 1746*4df55fdeSJanie Lu tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC; 1747*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1748*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x", 1749*4df55fdeSJanie Lu portn, tx_cfg_h.value)); 1750*4df55fdeSJanie Lu /* 0x4821 */ 1751*4df55fdeSJanie Lu rx_cfg_l.bits.enrx = K_CFGRX_ENABLE_RX; 1752*4df55fdeSJanie Lu rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF; 1753*4df55fdeSJanie Lu rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN; 1754*4df55fdeSJanie Lu rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE; 1755*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1756*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x", 1757*4df55fdeSJanie Lu portn, rx_cfg_l.value)); 1758*4df55fdeSJanie Lu 1759*4df55fdeSJanie Lu /* 0x0008 */ 1760*4df55fdeSJanie Lu rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE; 1761*4df55fdeSJanie Lu 1762*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1763*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_h 0x%x", 1764*4df55fdeSJanie Lu portn, rx_cfg_h.value)); 1765*4df55fdeSJanie Lu 1766*4df55fdeSJanie Lu /* Set loopback mode if necessary */ 1767*4df55fdeSJanie Lu if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 1768*4df55fdeSJanie Lu tx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK; 1769*4df55fdeSJanie Lu rx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK; 1770*4df55fdeSJanie Lu rx_cfg_l.bits.los = 0; 1771*4df55fdeSJanie Lu 1772*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1773*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 1774*4df55fdeSJanie Lu "loopback 0x%x", portn, tx_cfg_h.value)); 1775*4df55fdeSJanie Lu } 1776*4df55fdeSJanie Lu /* 0xa1: Initialize PLL for 10G */ 1777*4df55fdeSJanie Lu pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X; 1778*4df55fdeSJanie Lu pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL; 1779*4df55fdeSJanie Lu 1780*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1781*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x", 1782*4df55fdeSJanie Lu portn, pll_cfg_l.value)); 1783*4df55fdeSJanie Lu 1784*4df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1785*4df55fdeSJanie Lu ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK) 1786*4df55fdeSJanie Lu goto fail; 1787*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1788*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x", 1789*4df55fdeSJanie Lu portn, pll_cfg_l.value)); 1790*4df55fdeSJanie Lu #ifdef NXGE_DEBUG 1791*4df55fdeSJanie Lu nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1792*4df55fdeSJanie Lu ESR_N2_PLL_CFG_L_REG, &cfg.value); 1793*4df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1794*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 1795*4df55fdeSJanie Lu "PLL cfg.l 0x%x (0x%x)", 1796*4df55fdeSJanie Lu portn, pll_cfg_l.value, cfg.value)); 1797*4df55fdeSJanie Lu 1798*4df55fdeSJanie Lu nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1799*4df55fdeSJanie Lu ESR_N2_PLL_STS_L_REG, &cfg.value); 1800*4df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1801*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)", 1802*4df55fdeSJanie Lu portn, cfg.value)); 1803*4df55fdeSJanie Lu #endif 1804*4df55fdeSJanie Lu } else if (nxgep->mac.portmode == PORT_1G_FIBER || 1805*4df55fdeSJanie Lu nxgep->mac.portmode == PORT_1G_TN1010 || 1806*4df55fdeSJanie Lu nxgep->mac.portmode == PORT_1G_SERDES) { 1807*4df55fdeSJanie Lu mode_1g = B_TRUE; 1808*4df55fdeSJanie Lu /* 0x1e41 */ 1809*4df55fdeSJanie Lu tx_cfg_l.bits.entx = 1; 1810*4df55fdeSJanie Lu tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF; 1811*4df55fdeSJanie Lu tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV; 1812*4df55fdeSJanie Lu 1813*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1814*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x", 1815*4df55fdeSJanie Lu portn, tx_cfg_l.value)); 1816*4df55fdeSJanie Lu 1817*4df55fdeSJanie Lu 1818*4df55fdeSJanie Lu /* channel 0: enable syn. master */ 1819*4df55fdeSJanie Lu tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC; 1820*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1821*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x", 1822*4df55fdeSJanie Lu portn, tx_cfg_h.value)); 1823*4df55fdeSJanie Lu 1824*4df55fdeSJanie Lu 1825*4df55fdeSJanie Lu /* 0x4841 */ 1826*4df55fdeSJanie Lu rx_cfg_l.bits.enrx = 1; 1827*4df55fdeSJanie Lu rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF; 1828*4df55fdeSJanie Lu rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN; 1829*4df55fdeSJanie Lu rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE; 1830*4df55fdeSJanie Lu 1831*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1832*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x", 1833*4df55fdeSJanie Lu portn, rx_cfg_l.value)); 1834*4df55fdeSJanie Lu 1835*4df55fdeSJanie Lu /* 0x0008 */ 1836*4df55fdeSJanie Lu rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE_LF_365MHZ_ZF; 1837*4df55fdeSJanie Lu 1838*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1839*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x", 1840*4df55fdeSJanie Lu portn, rx_cfg_h.value)); 1841*4df55fdeSJanie Lu 1842*4df55fdeSJanie Lu /* 0xa1: Initialize PLL for 1G */ 1843*4df55fdeSJanie Lu pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X; 1844*4df55fdeSJanie Lu pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL; 1845*4df55fdeSJanie Lu 1846*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1847*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x", 1848*4df55fdeSJanie Lu portn, pll_cfg_l.value)); 1849*4df55fdeSJanie Lu 1850*4df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1851*4df55fdeSJanie Lu ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 1852*4df55fdeSJanie Lu != NXGE_OK) 1853*4df55fdeSJanie Lu goto fail; 1854*4df55fdeSJanie Lu 1855*4df55fdeSJanie Lu 1856*4df55fdeSJanie Lu #ifdef NXGE_DEBUG 1857*4df55fdeSJanie Lu nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1858*4df55fdeSJanie Lu ESR_N2_PLL_CFG_L_REG, &cfg.value); 1859*4df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1860*4df55fdeSJanie Lu "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 1861*4df55fdeSJanie Lu portn, pll_cfg_l.value, cfg.value)); 1862*4df55fdeSJanie Lu 1863*4df55fdeSJanie Lu nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1864*4df55fdeSJanie Lu ESR_N2_PLL_STS_L_REG, &cfg.value); 1865*4df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1866*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)", 1867*4df55fdeSJanie Lu portn, cfg.value)); 1868*4df55fdeSJanie Lu #endif 1869*4df55fdeSJanie Lu 1870*4df55fdeSJanie Lu /* Set loopback mode if necessary */ 1871*4df55fdeSJanie Lu if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1872*4df55fdeSJanie Lu tx_cfg_h.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 1873*4df55fdeSJanie Lu 1874*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1875*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 1876*4df55fdeSJanie Lu "loopback 0x%x", portn, test_cfg.value)); 1877*4df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, 1878*4df55fdeSJanie Lu ESR_N2_DEV_ADDR, 1879*4df55fdeSJanie Lu ESR_N2_TX_CFG_L_REG_ADDR(0), 1880*4df55fdeSJanie Lu tx_cfg_h.value)) != NXGE_OK) { 1881*4df55fdeSJanie Lu goto fail; 1882*4df55fdeSJanie Lu } 1883*4df55fdeSJanie Lu } 1884*4df55fdeSJanie Lu } else { 1885*4df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1886*4df55fdeSJanie Lu "nxge_n2_kt_serdes_init:port<%d> - " 1887*4df55fdeSJanie Lu "unsupported port mode %d", 1888*4df55fdeSJanie Lu portn, nxgep->mac.portmode)); 1889*4df55fdeSJanie Lu goto fail; 1890*4df55fdeSJanie Lu } 1891*4df55fdeSJanie Lu 1892*4df55fdeSJanie Lu NXGE_DELAY(20); 1893*4df55fdeSJanie Lu /* Clear the test register (offset 0x8004) */ 1894*4df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1895*4df55fdeSJanie Lu ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 1896*4df55fdeSJanie Lu goto fail; 1897*4df55fdeSJanie Lu } 1898*4df55fdeSJanie Lu NXGE_DELAY(20); 1899*4df55fdeSJanie Lu 1900*4df55fdeSJanie Lu /* init TX channels */ 1901*4df55fdeSJanie Lu for (chan = 0; chan < 4; chan++) { 1902*4df55fdeSJanie Lu if (mode_1g) 1903*4df55fdeSJanie Lu tx_cfg_l.value = 0; 1904*4df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1905*4df55fdeSJanie Lu ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK) 1906*4df55fdeSJanie Lu goto fail; 1907*4df55fdeSJanie Lu 1908*4df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1909*4df55fdeSJanie Lu ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK) 1910*4df55fdeSJanie Lu goto fail; 1911*4df55fdeSJanie Lu 1912*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1913*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 1914*4df55fdeSJanie Lu "chan %d tx_cfg_l 0x%x", portn, chan, tx_cfg_l.value)); 1915*4df55fdeSJanie Lu 1916*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1917*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 1918*4df55fdeSJanie Lu "chan %d tx_cfg_h 0x%x", portn, chan, tx_cfg_h.value)); 1919*4df55fdeSJanie Lu } 1920*4df55fdeSJanie Lu 1921*4df55fdeSJanie Lu /* init RX channels */ 1922*4df55fdeSJanie Lu /* 1G mode only write to the first channel */ 1923*4df55fdeSJanie Lu for (chan = 0; chan < 4; chan++) { 1924*4df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1925*4df55fdeSJanie Lu ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 1926*4df55fdeSJanie Lu != NXGE_OK) 1927*4df55fdeSJanie Lu goto fail; 1928*4df55fdeSJanie Lu 1929*4df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1930*4df55fdeSJanie Lu ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 1931*4df55fdeSJanie Lu != NXGE_OK) 1932*4df55fdeSJanie Lu goto fail; 1933*4df55fdeSJanie Lu 1934*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1935*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 1936*4df55fdeSJanie Lu "chan %d rx_cfg_l 0x%x", portn, chan, rx_cfg_l.value)); 1937*4df55fdeSJanie Lu 1938*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1939*4df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 1940*4df55fdeSJanie Lu "chan %d rx_cfg_h 0x%x", portn, chan, rx_cfg_h.value)); 1941*4df55fdeSJanie Lu } 1942*4df55fdeSJanie Lu 1943*4df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1944*4df55fdeSJanie Lu "<== nxge_n2_kt_serdes_init port<%d>", portn)); 1945*4df55fdeSJanie Lu 1946*4df55fdeSJanie Lu return (NXGE_OK); 1947*4df55fdeSJanie Lu fail: 1948*4df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1949*4df55fdeSJanie Lu "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 1950*4df55fdeSJanie Lu portn)); 1951*4df55fdeSJanie Lu 1952*4df55fdeSJanie Lu return (status); 195344961713Sgirish } 195444961713Sgirish 195559ac0c16Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */ 195644961713Sgirish 195759ac0c16Sdavemq static nxge_status_t 195859ac0c16Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep) 195944961713Sgirish { 196044961713Sgirish npi_handle_t handle; 196144961713Sgirish uint8_t portn; 1962321febdeSsbehera int chan, i; 196344961713Sgirish sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 196444961713Sgirish sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 196544961713Sgirish sr_glue_ctrl0_l_t glue_ctrl0_l; 196644961713Sgirish sr_glue_ctrl0_h_t glue_ctrl0_h; 196744961713Sgirish uint64_t val; 196844961713Sgirish uint16_t val16l; 196944961713Sgirish uint16_t val16h; 197044961713Sgirish nxge_status_t status = NXGE_OK; 197144961713Sgirish 197244961713Sgirish portn = nxgep->mac.portnum; 197344961713Sgirish 197444961713Sgirish if ((portn != 0) && (portn != 1)) 197544961713Sgirish return (NXGE_OK); 197644961713Sgirish 197759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 197859ac0c16Sdavemq "==> nxge_neptune_10G_serdes_init port<%d>", portn)); 197944961713Sgirish handle = nxgep->npi_handle; 198059ac0c16Sdavemq switch (portn) { 198159ac0c16Sdavemq case 0: 19824202ea4bSsbehera /* Reset Serdes */ 19834202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0); 19844202ea4bSsbehera NXGE_DELAY(20); 19854202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 19864202ea4bSsbehera NXGE_DELAY(2000); 19874202ea4bSsbehera 19884202ea4bSsbehera /* Configure Serdes to 10G mode */ 19894202ea4bSsbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 19904202ea4bSsbehera ESR_PLL_CFG_10G_SERDES); 19914202ea4bSsbehera 199259ac0c16Sdavemq ESR_REG_WR(handle, ESR_0_CONTROL_REG, 199359ac0c16Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 199459ac0c16Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 199559ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 199659ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 199759ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 199859ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 199959ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 200059ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 200159ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 200259ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 200359ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 200459ac0c16Sdavemq 200559ac0c16Sdavemq /* Set Serdes0 Internal Loopback if necessary */ 200659ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 200759ac0c16Sdavemq ESR_REG_WR(handle, 200859ac0c16Sdavemq ESR_0_TEST_CONFIG_REG, 200959ac0c16Sdavemq ESR_PAD_LOOPBACK_CH3 | 201059ac0c16Sdavemq ESR_PAD_LOOPBACK_CH2 | 201159ac0c16Sdavemq ESR_PAD_LOOPBACK_CH1 | 201259ac0c16Sdavemq ESR_PAD_LOOPBACK_CH0); 201359ac0c16Sdavemq } else { 201459ac0c16Sdavemq ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 201544961713Sgirish } 201659ac0c16Sdavemq break; 201759ac0c16Sdavemq case 1: 20184202ea4bSsbehera /* Reset Serdes */ 20194202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1); 20204202ea4bSsbehera NXGE_DELAY(20); 20214202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 20224202ea4bSsbehera NXGE_DELAY(2000); 20234202ea4bSsbehera 20244202ea4bSsbehera /* Configure Serdes to 10G mode */ 20254202ea4bSsbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 20264202ea4bSsbehera ESR_PLL_CFG_10G_SERDES); 20274202ea4bSsbehera 202859ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_CONTROL_REG, 202959ac0c16Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 203059ac0c16Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 203159ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 203259ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 203359ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 203459ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 203559ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 203659ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 203759ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 203859ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 203959ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 204059ac0c16Sdavemq 204159ac0c16Sdavemq /* Set Serdes1 Internal Loopback if necessary */ 204259ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 204359ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 204459ac0c16Sdavemq ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 | 204559ac0c16Sdavemq ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0); 204659ac0c16Sdavemq } else { 204759ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 204844961713Sgirish } 204959ac0c16Sdavemq break; 205059ac0c16Sdavemq default: 205159ac0c16Sdavemq /* Nothing to do here */ 205259ac0c16Sdavemq goto done; 205359ac0c16Sdavemq } 205444961713Sgirish 205559ac0c16Sdavemq /* init TX RX channels */ 205659ac0c16Sdavemq for (chan = 0; chan < 4; chan++) { 205759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 205859ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 205959ac0c16Sdavemq &rx_tx_ctrl_l.value)) != NXGE_OK) 206044961713Sgirish goto fail; 206159ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 206259ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 206359ac0c16Sdavemq &rx_tx_ctrl_h.value)) != NXGE_OK) 206444961713Sgirish goto fail; 206559ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 206659ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 206759ac0c16Sdavemq &glue_ctrl0_l.value)) != NXGE_OK) 206859ac0c16Sdavemq goto fail; 206959ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 207059ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 207159ac0c16Sdavemq &glue_ctrl0_h.value)) != NXGE_OK) 207259ac0c16Sdavemq goto fail; 207359ac0c16Sdavemq rx_tx_ctrl_l.bits.enstretch = 1; 207459ac0c16Sdavemq rx_tx_ctrl_h.bits.vmuxlo = 2; 207559ac0c16Sdavemq rx_tx_ctrl_h.bits.vpulselo = 2; 207659ac0c16Sdavemq glue_ctrl0_l.bits.rxlosenable = 1; 207759ac0c16Sdavemq glue_ctrl0_l.bits.samplerate = 0xF; 207859ac0c16Sdavemq glue_ctrl0_l.bits.thresholdcount = 0xFF; 207959ac0c16Sdavemq glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 208044961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 208159ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 208259ac0c16Sdavemq rx_tx_ctrl_l.value)) != NXGE_OK) 208344961713Sgirish goto fail; 208444961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 208559ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 208659ac0c16Sdavemq rx_tx_ctrl_h.value)) != NXGE_OK) 208744961713Sgirish goto fail; 208859ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 208959ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 209059ac0c16Sdavemq glue_ctrl0_l.value)) != NXGE_OK) 209144961713Sgirish goto fail; 209259ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 209359ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 209459ac0c16Sdavemq glue_ctrl0_h.value)) != NXGE_OK) 209544961713Sgirish goto fail; 209644961713Sgirish } 209744961713Sgirish 209859ac0c16Sdavemq /* Apply Tx core reset */ 209959ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 210059ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 210159ac0c16Sdavemq (uint16_t)0)) != NXGE_OK) 210259ac0c16Sdavemq goto fail; 210359ac0c16Sdavemq 210459ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 210559ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 210659ac0c16Sdavemq NXGE_OK) 210759ac0c16Sdavemq goto fail; 210859ac0c16Sdavemq 210959ac0c16Sdavemq NXGE_DELAY(200); 211059ac0c16Sdavemq 211159ac0c16Sdavemq /* Apply Rx core reset */ 211259ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 211359ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 211459ac0c16Sdavemq NXGE_OK) 211559ac0c16Sdavemq goto fail; 211659ac0c16Sdavemq 211759ac0c16Sdavemq NXGE_DELAY(200); 211859ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 211959ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) 212059ac0c16Sdavemq goto fail; 212159ac0c16Sdavemq 212259ac0c16Sdavemq NXGE_DELAY(200); 212359ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 212459ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 212559ac0c16Sdavemq &val16l)) != NXGE_OK) 212659ac0c16Sdavemq goto fail; 212759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 212859ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) 212959ac0c16Sdavemq goto fail; 213059ac0c16Sdavemq if ((val16l != 0) || (val16h != 0)) { 213159ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2132d81011f0Ssbehera "Failed to reset port<%d> XAUI Serdes " 2133d81011f0Ssbehera "(val16l 0x%x val16h 0x%x)", 2134d81011f0Ssbehera portn, val16l, val16h)); 213559ac0c16Sdavemq } 213659ac0c16Sdavemq 213759ac0c16Sdavemq if (portn == 0) { 2138321febdeSsbehera /* Wait for serdes to be ready */ 2139321febdeSsbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 2140321febdeSsbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2141321febdeSsbehera if ((val & ESR_SIG_P0_BITS_MASK) != 2142321febdeSsbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 2143321febdeSsbehera ESR_SIG_XSERDES_RDY_P0 | 2144321febdeSsbehera ESR_SIG_XDETECT_P0_CH3 | 2145321febdeSsbehera ESR_SIG_XDETECT_P0_CH2 | 2146321febdeSsbehera ESR_SIG_XDETECT_P0_CH1 | 2147321febdeSsbehera ESR_SIG_XDETECT_P0_CH0)) 2148321febdeSsbehera 2149321febdeSsbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 2150321febdeSsbehera else 2151321febdeSsbehera break; 2152321febdeSsbehera } 2153321febdeSsbehera 2154321febdeSsbehera if (i == MAX_SERDES_RDY_RETRIES) { 2155ab6abb7aSjoycey /* 2156ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 2157ab6abb7aSjoycey * external PHY, it is not an error condition. But still 2158ab6abb7aSjoycey * print the message for the debugging purpose when link 2159ab6abb7aSjoycey * stays down 2160ab6abb7aSjoycey */ 2161321febdeSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2162321febdeSsbehera "nxge_neptune_10G_serdes_init: " 2163321febdeSsbehera "Serdes/signal for port<%d> not ready", portn)); 216400161856Syc goto done; 216559ac0c16Sdavemq } 216659ac0c16Sdavemq } else if (portn == 1) { 2167321febdeSsbehera /* Wait for serdes to be ready */ 2168321febdeSsbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 2169321febdeSsbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2170321febdeSsbehera if ((val & ESR_SIG_P1_BITS_MASK) != 2171321febdeSsbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 2172321febdeSsbehera ESR_SIG_XSERDES_RDY_P1 | 2173321febdeSsbehera ESR_SIG_XDETECT_P1_CH3 | 2174321febdeSsbehera ESR_SIG_XDETECT_P1_CH2 | 2175321febdeSsbehera ESR_SIG_XDETECT_P1_CH1 | 2176321febdeSsbehera ESR_SIG_XDETECT_P1_CH0)) 2177321febdeSsbehera 2178321febdeSsbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 2179321febdeSsbehera else 2180321febdeSsbehera break; 2181321febdeSsbehera } 2182321febdeSsbehera 2183321febdeSsbehera if (i == MAX_SERDES_RDY_RETRIES) { 2184ab6abb7aSjoycey /* 2185ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 2186ab6abb7aSjoycey * external PHY, it is not an error condition. But still 2187ab6abb7aSjoycey * print the message for the debugging purpose when link 2188ab6abb7aSjoycey * stays down 2189ab6abb7aSjoycey */ 2190321febdeSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2191321febdeSsbehera "nxge_neptune_10G_serdes_init: " 2192321febdeSsbehera "Serdes/signal for port<%d> not ready", portn)); 219300161856Syc goto done; 219444961713Sgirish } 219544961713Sgirish } 219644961713Sgirish 219744961713Sgirish done: 219859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 219959ac0c16Sdavemq "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 220059ac0c16Sdavemq 220144961713Sgirish return (NXGE_OK); 220244961713Sgirish fail: 22032d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 220459ac0c16Sdavemq "nxge_neptune_10G_serdes_init: " 220559ac0c16Sdavemq "Failed to initialize Neptune serdes for port<%d>", portn)); 220644961713Sgirish 220744961713Sgirish return (status); 220844961713Sgirish } 220944961713Sgirish 221059ac0c16Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 221144961713Sgirish 221259ac0c16Sdavemq static nxge_status_t 221359ac0c16Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep) 221444961713Sgirish { 221559ac0c16Sdavemq npi_handle_t handle; 221659ac0c16Sdavemq uint8_t portn; 2217d81011f0Ssbehera int chan; 2218d81011f0Ssbehera sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 2219d81011f0Ssbehera sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 2220d81011f0Ssbehera sr_glue_ctrl0_l_t glue_ctrl0_l; 2221d81011f0Ssbehera sr_glue_ctrl0_h_t glue_ctrl0_h; 222259ac0c16Sdavemq uint64_t val; 2223d81011f0Ssbehera uint16_t val16l; 2224d81011f0Ssbehera uint16_t val16h; 2225d81011f0Ssbehera nxge_status_t status = NXGE_OK; 222644961713Sgirish 222744961713Sgirish portn = nxgep->mac.portnum; 222844961713Sgirish 222959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 223059ac0c16Sdavemq "==> nxge_1G_serdes_init port<%d>", portn)); 223144961713Sgirish 223259ac0c16Sdavemq handle = nxgep->npi_handle; 223344961713Sgirish 223459ac0c16Sdavemq switch (portn) { 223559ac0c16Sdavemq case 0: 2236d81011f0Ssbehera /* Assert the reset register */ 2237d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 2238d81011f0Ssbehera val |= ESR_RESET_0; 2239d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 2240d81011f0Ssbehera 2241d81011f0Ssbehera /* Set the PLL register to 0x79 */ 2242d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 2243d81011f0Ssbehera ESR_PLL_CFG_1G_SERDES); 2244d81011f0Ssbehera 2245d81011f0Ssbehera /* Set the control register to 0x249249f */ 2246d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES); 2247d81011f0Ssbehera 2248d81011f0Ssbehera /* Set Serdes0 Internal Loopback if necessary */ 2249d81011f0Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 2250d81011f0Ssbehera /* Set pad loopback modes 0xaa */ 2251d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 2252d81011f0Ssbehera ESR_TSTCFG_LBTEST_PAD); 2253d81011f0Ssbehera } else { 2254d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 2255d81011f0Ssbehera } 2256d81011f0Ssbehera 2257d81011f0Ssbehera /* Deassert the reset register */ 2258d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 2259d81011f0Ssbehera val &= ~ESR_RESET_0; 2260d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 226159ac0c16Sdavemq break; 2262d81011f0Ssbehera 226359ac0c16Sdavemq case 1: 2264d81011f0Ssbehera /* Assert the reset register */ 2265d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 2266d81011f0Ssbehera val |= ESR_RESET_1; 2267d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 2268d81011f0Ssbehera 2269d81011f0Ssbehera /* Set PLL register to 0x79 */ 2270d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 2271d81011f0Ssbehera ESR_PLL_CFG_1G_SERDES); 2272d81011f0Ssbehera 2273d81011f0Ssbehera /* Set the control register to 0x249249f */ 2274d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES); 2275d81011f0Ssbehera 2276d81011f0Ssbehera /* Set Serdes1 Internal Loopback if necessary */ 2277d81011f0Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 2278d81011f0Ssbehera /* Set pad loopback mode 0xaa */ 2279d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 2280d81011f0Ssbehera ESR_TSTCFG_LBTEST_PAD); 2281d81011f0Ssbehera } else { 2282d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 2283d81011f0Ssbehera } 2284d81011f0Ssbehera 2285d81011f0Ssbehera /* Deassert the reset register */ 2286d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 2287d81011f0Ssbehera val &= ~ESR_RESET_1; 2288d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 228959ac0c16Sdavemq break; 2290d81011f0Ssbehera 229159ac0c16Sdavemq default: 2292d81011f0Ssbehera /* Nothing to do here */ 2293d81011f0Ssbehera goto done; 2294d81011f0Ssbehera } 2295d81011f0Ssbehera 2296d81011f0Ssbehera /* init TX RX channels */ 2297d81011f0Ssbehera for (chan = 0; chan < 4; chan++) { 2298d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2299d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2300d81011f0Ssbehera &rx_tx_ctrl_l.value)) != NXGE_OK) { 2301d81011f0Ssbehera goto fail; 2302d81011f0Ssbehera } 2303d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2304d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2305d81011f0Ssbehera &rx_tx_ctrl_h.value)) != NXGE_OK) { 2306d81011f0Ssbehera goto fail; 2307d81011f0Ssbehera } 2308d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2309d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2310d81011f0Ssbehera &glue_ctrl0_l.value)) != NXGE_OK) { 2311d81011f0Ssbehera goto fail; 2312d81011f0Ssbehera } 2313d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2314d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2315d81011f0Ssbehera &glue_ctrl0_h.value)) != NXGE_OK) { 2316d81011f0Ssbehera goto fail; 2317d81011f0Ssbehera } 2318d81011f0Ssbehera 2319d81011f0Ssbehera rx_tx_ctrl_l.bits.enstretch = 1; 2320d81011f0Ssbehera rx_tx_ctrl_h.bits.vmuxlo = 2; 2321d81011f0Ssbehera rx_tx_ctrl_h.bits.vpulselo = 2; 2322d81011f0Ssbehera glue_ctrl0_l.bits.rxlosenable = 1; 2323d81011f0Ssbehera glue_ctrl0_l.bits.samplerate = 0xF; 2324d81011f0Ssbehera glue_ctrl0_l.bits.thresholdcount = 0xFF; 2325d81011f0Ssbehera glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 2326d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2327d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2328d81011f0Ssbehera rx_tx_ctrl_l.value)) != NXGE_OK) { 2329d81011f0Ssbehera goto fail; 2330d81011f0Ssbehera } 2331d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2332d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2333d81011f0Ssbehera rx_tx_ctrl_h.value)) != NXGE_OK) { 2334d81011f0Ssbehera goto fail; 2335d81011f0Ssbehera } 2336d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2337d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2338d81011f0Ssbehera glue_ctrl0_l.value)) != NXGE_OK) { 2339d81011f0Ssbehera goto fail; 2340d81011f0Ssbehera } 2341d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2342d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2343d81011f0Ssbehera glue_ctrl0_h.value)) != NXGE_OK) { 2344d81011f0Ssbehera goto fail; 2345d81011f0Ssbehera } 2346d81011f0Ssbehera } 2347d81011f0Ssbehera 2348d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2349d81011f0Ssbehera ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) { 2350d81011f0Ssbehera goto fail; 2351d81011f0Ssbehera } 2352d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2353d81011f0Ssbehera ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 2354d81011f0Ssbehera goto fail; 2355d81011f0Ssbehera } 2356d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2357d81011f0Ssbehera ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) { 2358d81011f0Ssbehera goto fail; 2359d81011f0Ssbehera } 2360d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2361d81011f0Ssbehera ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 236259ac0c16Sdavemq goto fail; 236344961713Sgirish } 236444961713Sgirish 2365d81011f0Ssbehera /* Apply Tx core reset */ 2366d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2367d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) { 2368d81011f0Ssbehera goto fail; 2369d81011f0Ssbehera } 2370d81011f0Ssbehera 2371d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2372d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 2373d81011f0Ssbehera NXGE_OK) { 2374d81011f0Ssbehera goto fail; 2375d81011f0Ssbehera } 2376d81011f0Ssbehera 2377d81011f0Ssbehera NXGE_DELAY(200); 2378d81011f0Ssbehera 2379d81011f0Ssbehera /* Apply Rx core reset */ 2380d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2381d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 2382d81011f0Ssbehera NXGE_OK) { 2383d81011f0Ssbehera goto fail; 2384d81011f0Ssbehera } 2385d81011f0Ssbehera 2386d81011f0Ssbehera NXGE_DELAY(200); 2387d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2388d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) { 2389d81011f0Ssbehera goto fail; 2390d81011f0Ssbehera } 2391d81011f0Ssbehera 2392d81011f0Ssbehera NXGE_DELAY(200); 2393d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2394d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) { 2395d81011f0Ssbehera goto fail; 2396d81011f0Ssbehera } 2397d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2398d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) { 2399d81011f0Ssbehera goto fail; 2400d81011f0Ssbehera } 2401d81011f0Ssbehera if ((val16l != 0) || (val16h != 0)) { 2402d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2403d81011f0Ssbehera "Failed to reset port<%d> XAUI Serdes " 2404d81011f0Ssbehera "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h)); 2405d81011f0Ssbehera status = NXGE_ERROR; 2406d81011f0Ssbehera goto fail; 2407d81011f0Ssbehera } 2408d81011f0Ssbehera 2409d81011f0Ssbehera NXGE_DELAY(200); 2410d81011f0Ssbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2411d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2412d81011f0Ssbehera "nxge_neptune_serdes_init: read internal signal reg port<%d> " 2413d81011f0Ssbehera "val 0x%x", portn, val)); 2414d81011f0Ssbehera if (portn == 0) { 2415d81011f0Ssbehera if ((val & ESR_SIG_P0_BITS_MASK_1G) != 2416d81011f0Ssbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) { 2417ab6abb7aSjoycey /* 2418ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 2419ab6abb7aSjoycey * external PHY, it is not an error condition. But still 2420ab6abb7aSjoycey * print the message for the debugging purpose when link 2421ab6abb7aSjoycey * stays down 2422ab6abb7aSjoycey */ 2423d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2424ab6abb7aSjoycey "nxge_neptune_1G_serdes_init: " 2425ab6abb7aSjoycey "Serdes/signal for port<%d> not ready", portn)); 242600161856Syc goto done; 2427d81011f0Ssbehera } 2428d81011f0Ssbehera } else if (portn == 1) { 2429d81011f0Ssbehera if ((val & ESR_SIG_P1_BITS_MASK_1G) != 2430d81011f0Ssbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) { 2431ab6abb7aSjoycey /* 2432ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 2433ab6abb7aSjoycey * external PHY, it is not an error condition. But still 2434ab6abb7aSjoycey * print the message for the debugging purpose when link 2435ab6abb7aSjoycey * stays down 2436ab6abb7aSjoycey */ 2437d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2438ab6abb7aSjoycey "nxge_neptune_1G_serdes_init: " 2439ab6abb7aSjoycey "Serdes/signal for port<%d> not ready", portn)); 244000161856Syc goto done; 244100161856Syc 2442d81011f0Ssbehera } 2443d81011f0Ssbehera } 2444d81011f0Ssbehera done: 244559ac0c16Sdavemq 244659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 244759ac0c16Sdavemq "<== nxge_1G_serdes_init port<%d>", portn)); 244844961713Sgirish return (NXGE_OK); 244959ac0c16Sdavemq fail: 2450d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 245159ac0c16Sdavemq "nxge_1G_serdes_init: " 245259ac0c16Sdavemq "Failed to initialize Neptune serdes for port<%d>", 245359ac0c16Sdavemq portn)); 245459ac0c16Sdavemq 2455d81011f0Ssbehera return (status); 245644961713Sgirish } 245744961713Sgirish 24582d17280bSsbehera /* Initialize the BCM 8704 xcvr */ 245944961713Sgirish 246059ac0c16Sdavemq static nxge_status_t 24612d17280bSsbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep) 246244961713Sgirish { 246344961713Sgirish uint16_t val; 246444961713Sgirish #ifdef NXGE_DEBUG 246514ea4bb7Ssd uint8_t portn; 246644961713Sgirish uint16_t val1; 246744961713Sgirish #endif 246844961713Sgirish uint8_t phy_port_addr; 246944961713Sgirish pmd_tx_control_t tx_ctl; 247044961713Sgirish control_t ctl; 247144961713Sgirish phyxs_control_t phyxs_ctl; 247244961713Sgirish pcs_control_t pcs_ctl; 247344961713Sgirish uint32_t delay = 0; 247444961713Sgirish optics_dcntr_t op_ctr; 247544961713Sgirish nxge_status_t status = NXGE_OK; 247614ea4bb7Ssd #ifdef NXGE_DEBUG 247744961713Sgirish portn = nxgep->mac.portnum; 247814ea4bb7Ssd #endif 24792d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 248059ac0c16Sdavemq portn)); 248144961713Sgirish 248259ac0c16Sdavemq phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 248359ac0c16Sdavemq 248459ac0c16Sdavemq /* Reset the transceiver */ 248559ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 248659ac0c16Sdavemq BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 248759ac0c16Sdavemq goto fail; 248859ac0c16Sdavemq 248959ac0c16Sdavemq phyxs_ctl.bits.reset = 1; 249059ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 249159ac0c16Sdavemq BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 249259ac0c16Sdavemq goto fail; 249359ac0c16Sdavemq 249459ac0c16Sdavemq do { 249559ac0c16Sdavemq drv_usecwait(500); 249659ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 249759ac0c16Sdavemq BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 249859ac0c16Sdavemq &phyxs_ctl.value)) != NXGE_OK) 249959ac0c16Sdavemq goto fail; 250059ac0c16Sdavemq delay++; 250159ac0c16Sdavemq } while ((phyxs_ctl.bits.reset) && (delay < 100)); 250259ac0c16Sdavemq if (delay == 100) { 250359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 250459ac0c16Sdavemq "failed to reset Transceiver on port<%d>", portn)); 250559ac0c16Sdavemq status = NXGE_ERROR; 250659ac0c16Sdavemq goto fail; 250759ac0c16Sdavemq } 250844961713Sgirish 250959ac0c16Sdavemq /* Set to 0x7FBF */ 251059ac0c16Sdavemq ctl.value = 0; 251159ac0c16Sdavemq ctl.bits.res1 = 0x3F; 251259ac0c16Sdavemq ctl.bits.optxon_lvl = 1; 251359ac0c16Sdavemq ctl.bits.oprxflt_lvl = 1; 251459ac0c16Sdavemq ctl.bits.optrxlos_lvl = 1; 251559ac0c16Sdavemq ctl.bits.optxflt_lvl = 1; 251659ac0c16Sdavemq ctl.bits.opprflt_lvl = 1; 251759ac0c16Sdavemq ctl.bits.obtmpflt_lvl = 1; 251859ac0c16Sdavemq ctl.bits.opbiasflt_lvl = 1; 251959ac0c16Sdavemq ctl.bits.optxrst_lvl = 1; 252059ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 252159ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 252259ac0c16Sdavemq != NXGE_OK) 252359ac0c16Sdavemq goto fail; 252459ac0c16Sdavemq 252559ac0c16Sdavemq /* Set to 0x164 */ 252659ac0c16Sdavemq tx_ctl.value = 0; 252759ac0c16Sdavemq tx_ctl.bits.tsck_lpwren = 1; 252859ac0c16Sdavemq tx_ctl.bits.tx_dac_txck = 0x2; 252959ac0c16Sdavemq tx_ctl.bits.tx_dac_txd = 0x1; 253059ac0c16Sdavemq tx_ctl.bits.xfp_clken = 1; 253159ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 253259ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 253359ac0c16Sdavemq tx_ctl.value)) != NXGE_OK) 253459ac0c16Sdavemq goto fail; 253544961713Sgirish /* 253659ac0c16Sdavemq * According to Broadcom's instruction, SW needs to read 253759ac0c16Sdavemq * back these registers twice after written. 253844961713Sgirish */ 253959ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 254059ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 254159ac0c16Sdavemq != NXGE_OK) 254259ac0c16Sdavemq goto fail; 254344961713Sgirish 254459ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 254559ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 254659ac0c16Sdavemq != NXGE_OK) 254759ac0c16Sdavemq goto fail; 254844961713Sgirish 254959ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 255059ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 255159ac0c16Sdavemq != NXGE_OK) 255259ac0c16Sdavemq goto fail; 255344961713Sgirish 255459ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 255559ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 255659ac0c16Sdavemq != NXGE_OK) 255759ac0c16Sdavemq goto fail; 255844961713Sgirish 255959ac0c16Sdavemq /* Enable Tx and Rx LEDs to be driven by traffic */ 256059ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 256159ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 256259ac0c16Sdavemq &op_ctr.value)) != NXGE_OK) 256359ac0c16Sdavemq goto fail; 2564cb9d3ae6Smisaki if (NXGE_IS_XAUI_PLATFORM(nxgep)) { 2565cb9d3ae6Smisaki op_ctr.bits.gpio_sel = 0x1; 2566cb9d3ae6Smisaki } else { 2567cb9d3ae6Smisaki op_ctr.bits.gpio_sel = 0x3; 2568cb9d3ae6Smisaki } 256959ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 257059ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 257159ac0c16Sdavemq op_ctr.value)) != NXGE_OK) 257259ac0c16Sdavemq goto fail; 257344961713Sgirish 257459ac0c16Sdavemq NXGE_DELAY(1000000); 257544961713Sgirish 257659ac0c16Sdavemq /* Set BCM8704 Internal Loopback mode if necessary */ 257759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 257859ac0c16Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 257959ac0c16Sdavemq != NXGE_OK) 258059ac0c16Sdavemq goto fail; 258159ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 258259ac0c16Sdavemq pcs_ctl.bits.loopback = 1; 258359ac0c16Sdavemq else 258459ac0c16Sdavemq pcs_ctl.bits.loopback = 0; 258559ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 258659ac0c16Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 258759ac0c16Sdavemq != NXGE_OK) 258859ac0c16Sdavemq goto fail; 258944961713Sgirish 259059ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 259159ac0c16Sdavemq if (status != NXGE_OK) 259259ac0c16Sdavemq goto fail; 259359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 259459ac0c16Sdavemq "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 259559ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 259659ac0c16Sdavemq if (status != NXGE_OK) 259759ac0c16Sdavemq goto fail; 259859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 259959ac0c16Sdavemq "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 260059ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 260159ac0c16Sdavemq if (status != NXGE_OK) 260259ac0c16Sdavemq goto fail; 260359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 260459ac0c16Sdavemq "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 260544961713Sgirish 260659ac0c16Sdavemq #ifdef NXGE_DEBUG 260759ac0c16Sdavemq /* Diagnose link issue if link is not up */ 260859ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 260959ac0c16Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 261059ac0c16Sdavemq &val); 261159ac0c16Sdavemq if (status != NXGE_OK) 261259ac0c16Sdavemq goto fail; 261344961713Sgirish 261459ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 261552ccf843Smisaki BCM8704_USER_DEV3_ADDR, BCM8704_USER_ANALOG_STATUS0_REG, &val); 261659ac0c16Sdavemq if (status != NXGE_OK) 261759ac0c16Sdavemq goto fail; 261844961713Sgirish 261959ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 262052ccf843Smisaki BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1); 262159ac0c16Sdavemq if (status != NXGE_OK) 262259ac0c16Sdavemq goto fail; 262344961713Sgirish 262459ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 262552ccf843Smisaki BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1); 262659ac0c16Sdavemq if (status != NXGE_OK) 262759ac0c16Sdavemq goto fail; 262844961713Sgirish 262959ac0c16Sdavemq if (val != 0x3FC) { 263059ac0c16Sdavemq if ((val == 0x43BC) && (val1 != 0)) { 263159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 263259ac0c16Sdavemq "Cable not connected to peer or bad" 263359ac0c16Sdavemq " cable on port<%d>\n", portn)); 263459ac0c16Sdavemq } else if (val == 0x639C) { 263559ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 263659ac0c16Sdavemq "Optical module (XFP) is bad or absent" 263759ac0c16Sdavemq " on port<%d>\n", portn)); 263859ac0c16Sdavemq } 263959ac0c16Sdavemq } 264059ac0c16Sdavemq #endif 264144961713Sgirish 26422d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 26432d17280bSsbehera portn)); 26442d17280bSsbehera return (NXGE_OK); 26452d17280bSsbehera 26462d17280bSsbehera fail: 26472d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 26482d17280bSsbehera "nxge_BCM8704_xcvr_init: failed to initialize transceiver for " 26492d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 26502d17280bSsbehera return (NXGE_ERROR); 26512d17280bSsbehera } 26522d17280bSsbehera 26532d17280bSsbehera /* Initialize the BCM 8706 Transceiver */ 26542d17280bSsbehera 26552d17280bSsbehera static nxge_status_t 26562d17280bSsbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep) 26572d17280bSsbehera { 26582d17280bSsbehera uint8_t phy_port_addr; 26592d17280bSsbehera phyxs_control_t phyxs_ctl; 26602d17280bSsbehera pcs_control_t pcs_ctl; 26612d17280bSsbehera uint32_t delay = 0; 26622d17280bSsbehera optics_dcntr_t op_ctr; 26632d17280bSsbehera nxge_status_t status = NXGE_OK; 26642d17280bSsbehera #ifdef NXGE_DEBUG 26652d17280bSsbehera uint8_t portn = nxgep->mac.portnum; 26662d17280bSsbehera #endif 26672d17280bSsbehera 26682d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 26692d17280bSsbehera portn)); 26702d17280bSsbehera 26712d17280bSsbehera phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 26722d17280bSsbehera 26732d17280bSsbehera /* Reset the transceiver */ 26742d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 26752d17280bSsbehera BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 26762d17280bSsbehera goto fail; 26772d17280bSsbehera 26782d17280bSsbehera phyxs_ctl.bits.reset = 1; 26792d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 26802d17280bSsbehera BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 26812d17280bSsbehera goto fail; 26822d17280bSsbehera do { 26832d17280bSsbehera drv_usecwait(500); 26842d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 26852d17280bSsbehera BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 26862d17280bSsbehera &phyxs_ctl.value)) != NXGE_OK) 26872d17280bSsbehera goto fail; 26882d17280bSsbehera delay++; 26892d17280bSsbehera } while ((phyxs_ctl.bits.reset) && (delay < 100)); 26902d17280bSsbehera 26912d17280bSsbehera if (delay == 100) { 26922d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 26932d17280bSsbehera "failed to reset Transceiver on port<%d>", portn)); 26942d17280bSsbehera status = NXGE_ERROR; 26952d17280bSsbehera goto fail; 26962d17280bSsbehera } 26972d17280bSsbehera 26982d17280bSsbehera NXGE_DELAY(1000000); 26992d17280bSsbehera 27002d17280bSsbehera /* Set BCM8706 Internal Loopback mode if necessary */ 27012d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 27022d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 27032d17280bSsbehera != NXGE_OK) 27042d17280bSsbehera goto fail; 27052d17280bSsbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 27062d17280bSsbehera pcs_ctl.bits.loopback = 1; 27072d17280bSsbehera else 27082d17280bSsbehera pcs_ctl.bits.loopback = 0; 27092d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 27102d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 27112d17280bSsbehera != NXGE_OK) 27122d17280bSsbehera goto fail; 27132d17280bSsbehera 27142d17280bSsbehera /* Enable Tx and Rx LEDs to be driven by traffic */ 27152d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 27162d17280bSsbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 27172d17280bSsbehera &op_ctr.value)) != NXGE_OK) 27182d17280bSsbehera goto fail; 27192d17280bSsbehera op_ctr.bits.gpio_sel = 0x3; 27202d17280bSsbehera op_ctr.bits.res2 = 0x1; 27212d17280bSsbehera 27222d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 27232d17280bSsbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 27242d17280bSsbehera op_ctr.value)) != NXGE_OK) 27252d17280bSsbehera goto fail; 27262d17280bSsbehera 27272d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 27282d17280bSsbehera portn)); 27292d17280bSsbehera return (NXGE_OK); 27302d17280bSsbehera 27312d17280bSsbehera fail: 27322d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27332d17280bSsbehera "nxge_BCM8706_xcvr_init: failed to initialize transceiver for " 27342d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 27352d17280bSsbehera return (status); 27362d17280bSsbehera } 27372d17280bSsbehera 273852cdd236Ssbehera #define CHK_STAT(x) status = (x); if (status != NXGE_OK) goto fail 273952cdd236Ssbehera 274052cdd236Ssbehera #define MRVL88X2011_RD(nxgep, port, d, r, p) \ 274152cdd236Ssbehera CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p)) 274252cdd236Ssbehera 274352cdd236Ssbehera #define MRVL88X2011_WR(nxgep, port, d, r, p) \ 274452cdd236Ssbehera CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p)) 274552cdd236Ssbehera 274652cdd236Ssbehera 274752cdd236Ssbehera static void 274852cdd236Ssbehera nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate) 274952cdd236Ssbehera { 275052cdd236Ssbehera uint16_t value; 275152cdd236Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 275252cdd236Ssbehera 275352cdd236Ssbehera if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 275452cdd236Ssbehera MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) { 275552cdd236Ssbehera value &= ~MRVL_88X2011_LED_BLK_MASK; 275652cdd236Ssbehera value |= (rate << MRVL_88X2011_LED_BLK_SHIFT); 275752cdd236Ssbehera (void) nxge_mdio_write(nxgep, phy, 275852cdd236Ssbehera MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL, 275952cdd236Ssbehera value); 276052cdd236Ssbehera } 276152cdd236Ssbehera } 276252cdd236Ssbehera 276352cdd236Ssbehera static nxge_status_t 276452cdd236Ssbehera nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep) 276552cdd236Ssbehera { 276652cdd236Ssbehera nxge_status_t status; 276752cdd236Ssbehera pcs_control_t pcs_ctl; 276852cdd236Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 276952cdd236Ssbehera 277052cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 277152cdd236Ssbehera MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value); 277252cdd236Ssbehera 277352cdd236Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 277452cdd236Ssbehera pcs_ctl.bits.loopback = 1; 277552cdd236Ssbehera else 277652cdd236Ssbehera pcs_ctl.bits.loopback = 0; 277752cdd236Ssbehera 277852cdd236Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 277952cdd236Ssbehera MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value); 278052cdd236Ssbehera 278152cdd236Ssbehera fail: 278252cdd236Ssbehera return (status); 278352cdd236Ssbehera } 278452cdd236Ssbehera 278552cdd236Ssbehera 278652cdd236Ssbehera static void 278752cdd236Ssbehera nxge_mrvl88x2011_led(p_nxge_t nxgep, uint16_t val) 278852cdd236Ssbehera { 278952cdd236Ssbehera uint16_t val2; 279052cdd236Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 279152cdd236Ssbehera 279252cdd236Ssbehera val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 279352cdd236Ssbehera val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, 279452cdd236Ssbehera MRVL_88X2011_LED_CTL_MASK); 279552cdd236Ssbehera val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 279652cdd236Ssbehera 279752cdd236Ssbehera if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 279852cdd236Ssbehera MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) { 279952cdd236Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 280052cdd236Ssbehera "nxge_mrvl88x2011_led: nxge_mdio_write failed!!")); 280152cdd236Ssbehera } 280252cdd236Ssbehera } 280352cdd236Ssbehera 280452cdd236Ssbehera 280552cdd236Ssbehera static nxge_status_t 280652cdd236Ssbehera nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep) 280752cdd236Ssbehera { 280852cdd236Ssbehera uint8_t phy; 280952cdd236Ssbehera nxge_status_t status; 281052cdd236Ssbehera uint16_t clk; 281152cdd236Ssbehera 281252cdd236Ssbehera phy = nxgep->statsp->mac_stats.xcvr_portn; 281352cdd236Ssbehera 281452cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 281552cdd236Ssbehera "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>", 281652cdd236Ssbehera nxgep->mac.portnum, phy)); 281752cdd236Ssbehera 281852cdd236Ssbehera /* Set LED functions */ 281952cdd236Ssbehera nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS); 282052cdd236Ssbehera /* PCS activity */ 282152cdd236Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT); 282252cdd236Ssbehera 282352cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 282452cdd236Ssbehera MRVL_88X2011_GEN_CTL, &clk); 282552cdd236Ssbehera clk |= MRVL_88X2011_ENA_XFPREFCLK; 282652cdd236Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 282752cdd236Ssbehera MRVL_88X2011_GEN_CTL, clk); 282852cdd236Ssbehera 282952cdd236Ssbehera /* Set internal loopback mode if necessary */ 283052cdd236Ssbehera 283152cdd236Ssbehera CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep)); 283252cdd236Ssbehera 283352cdd236Ssbehera /* Enable PMD */ 283452cdd236Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 283552cdd236Ssbehera MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX); 283652cdd236Ssbehera 283752cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK")); 283852cdd236Ssbehera 283952cdd236Ssbehera fail: 284052cdd236Ssbehera return (status); 284152cdd236Ssbehera } 284252cdd236Ssbehera 284352cdd236Ssbehera 284452cdd236Ssbehera 28452d17280bSsbehera /* Initialize the 10G Transceiver */ 28462d17280bSsbehera 28472d17280bSsbehera static nxge_status_t 28482d17280bSsbehera nxge_10G_xcvr_init(p_nxge_t nxgep) 28492d17280bSsbehera { 28502d17280bSsbehera p_nxge_stats_t statsp; 28511bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 28522d17280bSsbehera nxge_status_t status = NXGE_OK; 28532d17280bSsbehera #ifdef NXGE_DEBUG 28542d17280bSsbehera uint8_t portn = nxgep->mac.portnum; 28552d17280bSsbehera #endif 28562d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 28572d17280bSsbehera portn)); 28582d17280bSsbehera 28592d17280bSsbehera statsp = nxgep->statsp; 28602d17280bSsbehera 28611c7408c9Stc /* Disable Link LEDs, with or without PHY */ 28621c7408c9Stc if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 28632d17280bSsbehera goto done; 28642d17280bSsbehera 28651c7408c9Stc /* Skip MDIO, if PHY absent */ 28661c7408c9Stc if (nxgep->mac.portmode == PORT_10G_SERDES || nxgep->phy_absent) { 28671c7408c9Stc goto done; 28681c7408c9Stc } 28692d17280bSsbehera 28702d17280bSsbehera /* Set Clause 45 */ 28712d17280bSsbehera npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 28722d17280bSsbehera 28732d17280bSsbehera switch (nxgep->chip_id) { 28742d17280bSsbehera case BCM8704_CHIP_ID: 287500161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 28762d17280bSsbehera "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id)); 28772d17280bSsbehera status = nxge_BCM8704_xcvr_init(nxgep); 28782d17280bSsbehera break; 28792d17280bSsbehera case BCM8706_CHIP_ID: 288000161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 28812d17280bSsbehera "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 28822d17280bSsbehera status = nxge_BCM8706_xcvr_init(nxgep); 28832d17280bSsbehera break; 288452cdd236Ssbehera case MRVL88X201X_CHIP_ID: 288500161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 288652cdd236Ssbehera "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 288752cdd236Ssbehera status = nxge_mrvl88x2011_xcvr_init(nxgep); 288852cdd236Ssbehera break; 28892d17280bSsbehera default: 28902d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: " 28912d17280bSsbehera "Unknown chip ID 0x%x for 10G xcvr addr[%d]", 28922d17280bSsbehera nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn)); 28932d17280bSsbehera goto fail; 28942d17280bSsbehera } 28952d17280bSsbehera 28962d17280bSsbehera if (status != NXGE_OK) { 28972d17280bSsbehera goto fail; 28982d17280bSsbehera } 28992e59129aSraghus done: 290059ac0c16Sdavemq statsp->mac_stats.cap_10gfdx = 1; 290159ac0c16Sdavemq statsp->mac_stats.lp_cap_10gfdx = 1; 29021bd6825cSml statsp->mac_stats.adv_cap_asmpause = 29031bd6825cSml param_arr[param_anar_asmpause].value; 29041bd6825cSml statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 290544961713Sgirish 290659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 290759ac0c16Sdavemq portn)); 290859ac0c16Sdavemq return (NXGE_OK); 290944961713Sgirish 291059ac0c16Sdavemq fail: 29112d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 291259ac0c16Sdavemq "nxge_10G_xcvr_init: failed to initialize transceiver for " 29132d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 29142d17280bSsbehera return (NXGE_ERROR); 291559ac0c16Sdavemq } 291644961713Sgirish 291759ac0c16Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */ 291844961713Sgirish 291959ac0c16Sdavemq static nxge_status_t 292059ac0c16Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep) 292159ac0c16Sdavemq { 292259ac0c16Sdavemq p_nxge_param_t param_arr = nxgep->param_arr; 292359ac0c16Sdavemq p_nxge_stats_t statsp = nxgep->statsp; 292459ac0c16Sdavemq nxge_status_t status = NXGE_OK; 292544961713Sgirish 29262e59129aSraghus if (nxgep->mac.portmode == PORT_1G_SERDES) { 29272e59129aSraghus statsp->mac_stats.cap_1000fdx = 29282e59129aSraghus param_arr[param_anar_1000fdx].value; 29292e59129aSraghus goto done; 29302e59129aSraghus } 29312e59129aSraghus 293259ac0c16Sdavemq /* Set Clause 22 */ 293359ac0c16Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 293444961713Sgirish 293559ac0c16Sdavemq /* Set capability flags */ 293659ac0c16Sdavemq statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 29372e59129aSraghus if ((nxgep->mac.portmode == PORT_1G_COPPER) || 29382e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER)) { 29392e59129aSraghus statsp->mac_stats.cap_100fdx = 29402e59129aSraghus param_arr[param_anar_100fdx].value; 29412e59129aSraghus statsp->mac_stats.cap_10fdx = 29422e59129aSraghus param_arr[param_anar_10fdx].value; 29432e59129aSraghus } 294444961713Sgirish 294559ac0c16Sdavemq status = nxge_mii_xcvr_init(nxgep); 29462e59129aSraghus done: 294759ac0c16Sdavemq return (status); 294859ac0c16Sdavemq } 294959ac0c16Sdavemq 295000161856Syc /* 295100161856Syc * Although the Teranetics copper transceiver (TN1010) does not need 295200161856Syc * to be initialized by the driver for passing packets, this funtion 295300161856Syc * initializes the members of nxgep->statsp->mac_stats struct for 295400161856Syc * kstat based on the value of nxgep->statsp->ports_stats.lb_mode. 295500161856Syc * It also configures the TN1010 for PHY loopback to support SunVTS. 295600161856Syc * 295700161856Syc * TN1010 only has the option to disable advertisement for the 10G 295800161856Syc * mode. So we can set it to either Dual Mode or 1G Only mode but 295900161856Syc * can't set it to 10G Only mode. 296000161856Syc * 296100161856Syc * ndd -set command can set the following 6 speed/duplex related parameters. 296200161856Syc * 296300161856Syc * ---------------------------------------------------------------- 296400161856Syc * ndd -set /dev/nxgeX param n kstat nxge:X | grep param 296500161856Syc * ---------------------------------------------------------------- 296600161856Syc * adv_autoneg_cap kstat nxge:1 | grep adv_cap_autoneg 296700161856Syc * adv_10gfdx_cap 296800161856Syc * adv_1000fdx_cap kstat nxge:1 | grep adv_cap_1000fdx 296900161856Syc * adv_100fdx_cap kstat nxge:1 | grep adv_cap_100fdx 297000161856Syc * adv_10fdx_cap kstat nxge:1 | grep adv_cap_10fdx 297100161856Syc * adv_pause_cap kstat nxge:1 | grep adv_cap_pause 297200161856Syc * ---------------------------------------------------------------- 297300161856Syc */ 297400161856Syc static nxge_status_t 297500161856Syc nxge_tn1010_xcvr_init(p_nxge_t nxgep) 297600161856Syc { 297700161856Syc p_nxge_param_t param_arr; 297800161856Syc p_nxge_stats_t statsp; 297900161856Syc tn1010_pcs_ctrl_t tn1010_pcs_ctrl; 298000161856Syc uint16_t speed; 298100161856Syc uint8_t phy_port_addr; 298200161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 298300161856Syc int status = NXGE_OK; 298400161856Syc 298500161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init")); 298600161856Syc 298700161856Syc param_arr = nxgep->param_arr; 298800161856Syc statsp = nxgep->statsp; 298900161856Syc 299000161856Syc /* 299100161856Syc * Initialize the xcvr statistics which are NOT controlled by ndd 299200161856Syc */ 299300161856Syc statsp->mac_stats.cap_autoneg = 1; /* TN1010 autoneg is always on */ 299400161856Syc statsp->mac_stats.cap_100T4 = 0; 299500161856Syc 299600161856Syc /* 299700161856Syc * Read the TN1010 link speed and initialize capabilities kstat. Note 299800161856Syc * that function nxge_check_tn1010_link repeatedly invoked by the 299900161856Syc * timer will update link_speed real time. 300000161856Syc */ 300100161856Syc if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 300200161856Syc goto fail; 300300161856Syc } 300400161856Syc if (speed == TN1010_SPEED_1G) { 300500161856Syc statsp->mac_stats.cap_10gfdx = 0; 300600161856Syc } else { 300700161856Syc statsp->mac_stats.cap_10gfdx = 1; 300800161856Syc } 300900161856Syc 301000161856Syc /* Whether we are in 1G or 10G mode, we always have the 1G capability */ 301100161856Syc statsp->mac_stats.cap_1000fdx = 1; 301200161856Syc 301300161856Syc /* TN1010 is not able to operate in the following states */ 301400161856Syc statsp->mac_stats.cap_1000hdx = 0; 301500161856Syc statsp->mac_stats.cap_100fdx = 0; 301600161856Syc statsp->mac_stats.cap_100hdx = 0; 301700161856Syc statsp->mac_stats.cap_10fdx = 0; 301800161856Syc statsp->mac_stats.cap_10hdx = 0; 301900161856Syc 302000161856Syc /* param_anar_pause can be modified by ndd -set */ 302100161856Syc statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 302200161856Syc 302300161856Syc /* 302400161856Syc * The following 4 lines actually overwrites what ever the ndd command 302500161856Syc * has set. For example, by command 302600161856Syc * ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1) 302700161856Syc * we could set param_arr[param_autoneg].value to n. However, because 302800161856Syc * here we assign constants to these parameters, whatever we set with 302900161856Syc * the "ndd -set" command will be replaced. So command 303000161856Syc * kstat nxge:X | grep param 303100161856Syc * will always show those constant values. In other words, the 303200161856Syc * "ndd -set" command can NOT change the values of these 4 parameters 303300161856Syc * even though the command appears to be successful. 303400161856Syc * 303500161856Syc * Note: TN1010 auto negotiation is always enabled. 303600161856Syc */ 303700161856Syc statsp->mac_stats.adv_cap_autoneg 303800161856Syc = param_arr[param_autoneg].value = 1; 303900161856Syc statsp->mac_stats.adv_cap_1000fdx 304000161856Syc = param_arr[param_anar_1000fdx].value = 1; 304100161856Syc statsp->mac_stats.adv_cap_100fdx 304200161856Syc = param_arr[param_anar_100fdx].value = 0; 304300161856Syc statsp->mac_stats.adv_cap_10fdx 304400161856Syc = param_arr[param_anar_10fdx].value = 0; 304500161856Syc 304600161856Syc /* 304700161856Syc * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as 304800161856Syc * defined in nxge_param_arr[], therefore they are not seen by the 304900161856Syc * "ndd -get" command and can not be changed by ndd. We just set 305000161856Syc * them (both ndd param and kstat values) to constant 0 because TN1010 305100161856Syc * does not support those speeds. 305200161856Syc */ 305300161856Syc statsp->mac_stats.adv_cap_100T4 305400161856Syc = param_arr[param_anar_100T4].value = 0; 305500161856Syc statsp->mac_stats.adv_cap_1000hdx 305600161856Syc = param_arr[param_anar_1000hdx].value = 0; 305700161856Syc statsp->mac_stats.adv_cap_100hdx 305800161856Syc = param_arr[param_anar_100hdx].value = 0; 305900161856Syc statsp->mac_stats.adv_cap_10hdx 306000161856Syc = param_arr[param_anar_10hdx].value = 0; 306100161856Syc 306200161856Syc /* 306300161856Syc * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified 306400161856Syc * by ndd 306500161856Syc */ 306600161856Syc statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 306700161856Syc 306800161856Syc /* 306900161856Syc * nxge_param_arr[] defines the adv_cap_asmpause with type 307000161856Syc * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the 307100161856Syc * "ndd -get" command and can not be changed by ndd. Here we do not 307200161856Syc * assign a constant to it so the default value defined in 307300161856Syc * nxge_param_arr[] will be used to set the parameter and 307400161856Syc * will be shown by the kstat. 307500161856Syc */ 307600161856Syc statsp->mac_stats.adv_cap_asmpause 307700161856Syc = param_arr[param_anar_asmpause].value; 307800161856Syc 307900161856Syc /* 308000161856Syc * Initialize the link statistics. 308100161856Syc */ 308200161856Syc statsp->mac_stats.link_T4 = 0; 308300161856Syc statsp->mac_stats.link_asmpause = 0; 308400161856Syc statsp->mac_stats.link_pause = 0; 308500161856Syc if (speed == TN1010_SPEED_1G) { 308600161856Syc statsp->mac_stats.link_speed = 1000; 308700161856Syc statsp->mac_stats.link_duplex = 2; /* Full duplex */ 308800161856Syc statsp->mac_stats.link_up = 1; 308900161856Syc } else { 309000161856Syc statsp->mac_stats.link_speed = 10000; 309100161856Syc statsp->mac_stats.link_duplex = 2; 309200161856Syc statsp->mac_stats.link_up = 1; 309300161856Syc } 309400161856Syc 309500161856Syc /* 309600161856Syc * Because TN1010 does not have a link partner register, to 309700161856Syc * figure out the link partner's capabilities is tricky. Here we 309800161856Syc * just set the kstat based on our knowledge about the partner 309900161856Syc * (The partner must support auto-neg because auto-negotiation 310000161856Syc * has completed, it must support 1G or 10G because that is the 310100161856Syc * negotiated speed we are using.) 310200161856Syc * 310300161856Syc * Note: Current kstat does not show lp_cap_10gfdx and 310400161856Syc * lp_cap_10ghdx. 310500161856Syc */ 310600161856Syc if (speed == TN1010_SPEED_1G) { 310700161856Syc statsp->mac_stats.lp_cap_1000fdx = 1; 310800161856Syc statsp->mac_stats.lp_cap_10gfdx = 0; 310900161856Syc } else { 311000161856Syc statsp->mac_stats.lp_cap_1000fdx = 0; 311100161856Syc statsp->mac_stats.lp_cap_10gfdx = 1; 311200161856Syc } 311300161856Syc statsp->mac_stats.lp_cap_10ghdx = 0; 311400161856Syc statsp->mac_stats.lp_cap_1000hdx = 0; 311500161856Syc statsp->mac_stats.lp_cap_100fdx = 0; 311600161856Syc statsp->mac_stats.lp_cap_100hdx = 0; 311700161856Syc statsp->mac_stats.lp_cap_10fdx = 0; 311800161856Syc statsp->mac_stats.lp_cap_10hdx = 0; 311900161856Syc statsp->mac_stats.lp_cap_10gfdx = 0; 312000161856Syc statsp->mac_stats.lp_cap_10ghdx = 0; 312100161856Syc statsp->mac_stats.lp_cap_100T4 = 0; 312200161856Syc statsp->mac_stats.lp_cap_autoneg = 1; 312300161856Syc statsp->mac_stats.lp_cap_asmpause = 0; 312400161856Syc statsp->mac_stats.lp_cap_pause = 0; 312500161856Syc 312600161856Syc /* Handle PHY loopback for SunVTS loopback test */ 312700161856Syc npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 312800161856Syc phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 312900161856Syc 313000161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 313100161856Syc TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG, 313200161856Syc &tn1010_pcs_ctrl.value)) != NXGE_OK) { 313300161856Syc goto fail; 313400161856Syc } 313500161856Syc if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) || 313600161856Syc (statsp->port_stats.lb_mode == nxge_lb_phy10g)) { 313700161856Syc tn1010_pcs_ctrl.bits.loopback = 1; 313800161856Syc } else { 313900161856Syc tn1010_pcs_ctrl.bits.loopback = 0; 314000161856Syc } 314100161856Syc if ((status = nxge_mdio_write(nxgep, phy_port_addr, 314200161856Syc TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG, 314300161856Syc tn1010_pcs_ctrl.value)) != NXGE_OK) { 314400161856Syc goto fail; 314500161856Syc } 314600161856Syc 314700161856Syc statsp->mac_stats.xcvr_inits++; 314800161856Syc 314900161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 315000161856Syc "<== nxge_1G_tn1010_xcvr_init status 0x%x", status)); 315100161856Syc return (status); 315200161856Syc fail: 315300161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 315400161856Syc "<== nxge_1G_tn1010_xcvr_init status 0x%x", status)); 315500161856Syc return (status); 315600161856Syc } 315700161856Syc 315859ac0c16Sdavemq /* Initialize transceiver */ 315959ac0c16Sdavemq 316059ac0c16Sdavemq nxge_status_t 316159ac0c16Sdavemq nxge_xcvr_init(p_nxge_t nxgep) 316259ac0c16Sdavemq { 316359ac0c16Sdavemq p_nxge_stats_t statsp; 316459ac0c16Sdavemq #ifdef NXGE_DEBUG 316559ac0c16Sdavemq uint8_t portn; 316644961713Sgirish #endif 316744961713Sgirish 316859ac0c16Sdavemq nxge_status_t status = NXGE_OK; 316959ac0c16Sdavemq #ifdef NXGE_DEBUG 317059ac0c16Sdavemq portn = nxgep->mac.portnum; 317159ac0c16Sdavemq #endif 317259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 317359ac0c16Sdavemq statsp = nxgep->statsp; 317444961713Sgirish 317559ac0c16Sdavemq /* 317600161856Syc * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will 317700161856Syc * modify mac_stats. 317859ac0c16Sdavemq */ 317959ac0c16Sdavemq statsp->mac_stats.cap_autoneg = 0; 318059ac0c16Sdavemq statsp->mac_stats.cap_100T4 = 0; 318159ac0c16Sdavemq statsp->mac_stats.cap_100fdx = 0; 318259ac0c16Sdavemq statsp->mac_stats.cap_100hdx = 0; 318359ac0c16Sdavemq statsp->mac_stats.cap_10fdx = 0; 318459ac0c16Sdavemq statsp->mac_stats.cap_10hdx = 0; 318559ac0c16Sdavemq statsp->mac_stats.cap_asmpause = 0; 318659ac0c16Sdavemq statsp->mac_stats.cap_pause = 0; 318759ac0c16Sdavemq statsp->mac_stats.cap_1000fdx = 0; 318859ac0c16Sdavemq statsp->mac_stats.cap_1000hdx = 0; 318959ac0c16Sdavemq statsp->mac_stats.cap_10gfdx = 0; 319059ac0c16Sdavemq statsp->mac_stats.cap_10ghdx = 0; 319159ac0c16Sdavemq 319259ac0c16Sdavemq /* 319359ac0c16Sdavemq * Initialize the link statistics. 319459ac0c16Sdavemq */ 319559ac0c16Sdavemq statsp->mac_stats.link_T4 = 0; 319659ac0c16Sdavemq statsp->mac_stats.link_asmpause = 0; 319759ac0c16Sdavemq statsp->mac_stats.link_pause = 0; 319844961713Sgirish 319959ac0c16Sdavemq if (nxgep->xcvr.xcvr_init) { 320059ac0c16Sdavemq status = nxgep->xcvr.xcvr_init(nxgep); 320159ac0c16Sdavemq if (status != NXGE_OK) 320244961713Sgirish goto fail; 320359ac0c16Sdavemq statsp->mac_stats.xcvr_inits++; 320444961713Sgirish } 320544961713Sgirish 320659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 320759ac0c16Sdavemq portn)); 320844961713Sgirish return (NXGE_OK); 320944961713Sgirish 321044961713Sgirish fail: 321144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 321259ac0c16Sdavemq "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 321359ac0c16Sdavemq portn)); 321444961713Sgirish return (status); 321544961713Sgirish } 321644961713Sgirish 32172e59129aSraghus /* Look for transceiver type */ 32182e59129aSraghus 32192e59129aSraghus nxge_status_t 32202e59129aSraghus nxge_xcvr_find(p_nxge_t nxgep) 32212e59129aSraghus { 3222d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", 3223d81011f0Ssbehera nxgep->mac.portnum)); 32242e59129aSraghus 32252e59129aSraghus if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 32262e59129aSraghus return (NXGE_ERROR); 32272e59129aSraghus 32282e59129aSraghus if (nxge_setup_xcvr_table(nxgep) != NXGE_OK) 32292e59129aSraghus return (NXGE_ERROR); 32302e59129aSraghus 32312e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 32322e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse)); 32332e59129aSraghus return (NXGE_OK); 32342e59129aSraghus } 323544961713Sgirish 323644961713Sgirish /* Initialize the TxMAC sub-block */ 323744961713Sgirish 323844961713Sgirish nxge_status_t 323944961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep) 324044961713Sgirish { 324144961713Sgirish npi_attr_t ap; 324244961713Sgirish uint8_t portn; 324344961713Sgirish nxge_port_mode_t portmode; 324444961713Sgirish nxge_port_t portt; 324544961713Sgirish npi_handle_t handle; 324644961713Sgirish npi_status_t rs = NPI_SUCCESS; 324744961713Sgirish 324844961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 324944961713Sgirish portt = nxgep->mac.porttype; 325044961713Sgirish handle = nxgep->npi_handle; 325144961713Sgirish portmode = nxgep->mac.portmode; 325244961713Sgirish 325344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 325452ccf843Smisaki portn)); 325544961713Sgirish /* Set Max and Min Frame Size */ 32561bd6825cSml /* 32571bd6825cSml * Use maxframesize to configure the hardware maxframe size 325800161856Syc * and minframesize to configure the hardware minframe size. 32591bd6825cSml */ 32601bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 32611bd6825cSml "==> nxge_tx_mac_init: port<%d> " 32621bd6825cSml "min framesize %d max framesize %d ", 32631bd6825cSml nxgep->mac.minframesize, 32641bd6825cSml nxgep->mac.maxframesize, 32651bd6825cSml portn)); 326644961713Sgirish 32671bd6825cSml SET_MAC_ATTR2(handle, ap, portn, 32681bd6825cSml MAC_PORT_FRAME_SIZE, 32691bd6825cSml nxgep->mac.minframesize, 32701bd6825cSml nxgep->mac.maxframesize, 32711bd6825cSml rs); 327244961713Sgirish if (rs != NPI_SUCCESS) 327344961713Sgirish goto fail; 327444961713Sgirish 327544961713Sgirish if (portt == PORT_TYPE_XMAC) { 327644961713Sgirish if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 327752ccf843Smisaki 0)) != NPI_SUCCESS) 327844961713Sgirish goto fail; 327944961713Sgirish nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 328044961713Sgirish if ((portmode == PORT_10G_FIBER) || 32812e59129aSraghus (portmode == PORT_10G_COPPER) || 328200161856Syc (portmode == PORT_10G_TN1010) || 32831c7408c9Stc (portmode == PORT_HSP_MODE) || 32842e59129aSraghus (portmode == PORT_10G_SERDES)) { 328544961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 328652ccf843Smisaki XGMII_IPG_12_15, rs); 328744961713Sgirish if (rs != NPI_SUCCESS) 328844961713Sgirish goto fail; 328944961713Sgirish nxgep->mac.ipg[0] = XGMII_IPG_12_15; 329044961713Sgirish } else { 329144961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 329252ccf843Smisaki MII_GMII_IPG_12, rs); 329344961713Sgirish if (rs != NPI_SUCCESS) 329444961713Sgirish goto fail; 329544961713Sgirish nxgep->mac.ipg[0] = MII_GMII_IPG_12; 329644961713Sgirish } 329744961713Sgirish if ((rs = npi_xmac_tx_config(handle, INIT, portn, 329852ccf843Smisaki CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 329944961713Sgirish goto fail; 330044961713Sgirish nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 330144961713Sgirish nxgep->mac.maxburstsize = 0; /* not programmable */ 330244961713Sgirish nxgep->mac.ctrltype = 0; /* not programmable */ 330344961713Sgirish nxgep->mac.pa_size = 0; /* not programmable */ 330444961713Sgirish 330544961713Sgirish if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 330652ccf843Smisaki != NPI_SUCCESS) 330744961713Sgirish goto fail; 330844961713Sgirish 330944961713Sgirish } else { 331044961713Sgirish if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 331152ccf843Smisaki 0)) != NPI_SUCCESS) 331244961713Sgirish goto fail; 331344961713Sgirish nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 331444961713Sgirish 331544961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 331652ccf843Smisaki rs); 331744961713Sgirish if (rs != NPI_SUCCESS) 331844961713Sgirish goto fail; 331944961713Sgirish nxgep->mac.ctrltype = 0x8808; 332044961713Sgirish 332144961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 332244961713Sgirish if (rs != NPI_SUCCESS) 332344961713Sgirish goto fail; 332444961713Sgirish nxgep->mac.pa_size = 0x7; 332544961713Sgirish 332644961713Sgirish if ((rs = npi_bmac_tx_config(handle, INIT, portn, 332752ccf843Smisaki CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 332844961713Sgirish goto fail; 332944961713Sgirish nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 333044961713Sgirish } 333144961713Sgirish 333244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 333352ccf843Smisaki portn)); 333444961713Sgirish 333544961713Sgirish return (NXGE_OK); 333644961713Sgirish fail: 333744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 333852ccf843Smisaki "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn)); 333944961713Sgirish 334044961713Sgirish return (NXGE_ERROR | rs); 334144961713Sgirish } 334244961713Sgirish 3343678453a8Sspeer 334444961713Sgirish /* Initialize the RxMAC sub-block */ 334544961713Sgirish 334644961713Sgirish nxge_status_t 334744961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep) 334844961713Sgirish { 334944961713Sgirish npi_attr_t ap; 335044961713Sgirish uint32_t i; 335144961713Sgirish uint16_t hashtab_e; 335244961713Sgirish p_hash_filter_t hash_filter; 335344961713Sgirish nxge_port_t portt; 335444961713Sgirish uint8_t portn; 335544961713Sgirish npi_handle_t handle; 335644961713Sgirish npi_status_t rs = NPI_SUCCESS; 335744961713Sgirish uint16_t *addr16p; 335844961713Sgirish uint16_t addr0, addr1, addr2; 335944961713Sgirish xmac_rx_config_t xconfig; 336044961713Sgirish bmac_rx_config_t bconfig; 336144961713Sgirish 336244961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 336344961713Sgirish 336444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 336552ccf843Smisaki portn)); 336644961713Sgirish handle = nxgep->npi_handle; 336744961713Sgirish portt = nxgep->mac.porttype; 336844961713Sgirish 336944961713Sgirish addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 337044961713Sgirish addr0 = ntohs(addr16p[2]); 337144961713Sgirish addr1 = ntohs(addr16p[1]); 337244961713Sgirish addr2 = ntohs(addr16p[0]); 337344961713Sgirish SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 337452ccf843Smisaki rs); 337544961713Sgirish 337644961713Sgirish if (rs != NPI_SUCCESS) 337744961713Sgirish goto fail; 337844961713Sgirish SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 337944961713Sgirish if (rs != NPI_SUCCESS) 338044961713Sgirish goto fail; 338144961713Sgirish SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 338244961713Sgirish if (rs != NPI_SUCCESS) 338344961713Sgirish goto fail; 338444961713Sgirish 338544961713Sgirish /* 338644961713Sgirish * Load the multicast hash filter bits. 338744961713Sgirish */ 338844961713Sgirish hash_filter = nxgep->hash_filter; 338944961713Sgirish for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 339044961713Sgirish if (hash_filter != NULL) { 339144961713Sgirish hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 339252ccf843Smisaki (NMCFILTER_REGS - 1) - i]; 339344961713Sgirish } else { 339444961713Sgirish hashtab_e = 0; 339544961713Sgirish } 339644961713Sgirish 339744961713Sgirish if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 339852ccf843Smisaki (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 339944961713Sgirish goto fail; 340044961713Sgirish } 340144961713Sgirish 340244961713Sgirish if (portt == PORT_TYPE_XMAC) { 340344961713Sgirish if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 340452ccf843Smisaki 0)) != NPI_SUCCESS) 340544961713Sgirish goto fail; 340644961713Sgirish nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 340744961713Sgirish 340844961713Sgirish (void) nxge_fflp_init_hostinfo(nxgep); 340944961713Sgirish 341044961713Sgirish xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 341152ccf843Smisaki CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 341252ccf843Smisaki ~CFG_XMAC_RX_STRIP_CRC; 341344961713Sgirish 341444961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 341544961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUS; 341644961713Sgirish 341744961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 341844961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 341944961713Sgirish 342044961713Sgirish xconfig |= CFG_XMAC_RX_HASH_FILTER; 342144961713Sgirish 342244961713Sgirish if ((rs = npi_xmac_rx_config(handle, INIT, portn, 342352ccf843Smisaki xconfig)) != NPI_SUCCESS) 342444961713Sgirish goto fail; 342544961713Sgirish nxgep->mac.rx_config = xconfig; 342644961713Sgirish 342744961713Sgirish /* Comparison of mac unique address is always enabled on XMAC */ 342844961713Sgirish 342944961713Sgirish if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 343052ccf843Smisaki != NPI_SUCCESS) 343144961713Sgirish goto fail; 343244961713Sgirish } else { 343344961713Sgirish (void) nxge_fflp_init_hostinfo(nxgep); 343444961713Sgirish 343544961713Sgirish if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 343652ccf843Smisaki 0) != NPI_SUCCESS) 343744961713Sgirish goto fail; 343844961713Sgirish nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 343944961713Sgirish 3440a3c5bd6dSspeer bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 344152ccf843Smisaki ~CFG_BMAC_RX_STRIP_CRC; 344244961713Sgirish 344344961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 344444961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUS; 344544961713Sgirish 344644961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 344744961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 344844961713Sgirish 344944961713Sgirish bconfig |= CFG_BMAC_RX_HASH_FILTER; 345044961713Sgirish if ((rs = npi_bmac_rx_config(handle, INIT, portn, 345152ccf843Smisaki bconfig)) != NPI_SUCCESS) 345244961713Sgirish goto fail; 345344961713Sgirish nxgep->mac.rx_config = bconfig; 345444961713Sgirish 345544961713Sgirish /* Always enable comparison of mac unique address */ 345644961713Sgirish if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 345752ccf843Smisaki != NPI_SUCCESS) 345844961713Sgirish goto fail; 345944961713Sgirish } 346044961713Sgirish 346144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 346252ccf843Smisaki portn)); 346344961713Sgirish 346444961713Sgirish return (NXGE_OK); 346544961713Sgirish 346644961713Sgirish fail: 346744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 346852ccf843Smisaki "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn)); 346944961713Sgirish 347044961713Sgirish return (NXGE_ERROR | rs); 347144961713Sgirish } 347244961713Sgirish 347344961713Sgirish /* Enable TXMAC */ 347444961713Sgirish 347544961713Sgirish nxge_status_t 347644961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep) 347744961713Sgirish { 347844961713Sgirish npi_handle_t handle; 347944961713Sgirish npi_status_t rs = NPI_SUCCESS; 348044961713Sgirish nxge_status_t status = NXGE_OK; 348144961713Sgirish 348244961713Sgirish handle = nxgep->npi_handle; 348344961713Sgirish 348444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 348552ccf843Smisaki nxgep->mac.portnum)); 348644961713Sgirish 348744961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 348844961713Sgirish goto fail; 348944961713Sgirish 349044961713Sgirish /* based on speed */ 349144961713Sgirish nxgep->msg_min = ETHERMIN; 349244961713Sgirish 349344961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 349444961713Sgirish if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 349552ccf843Smisaki CFG_XMAC_TX)) != NPI_SUCCESS) 349644961713Sgirish goto fail; 349744961713Sgirish } else { 349844961713Sgirish if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 349952ccf843Smisaki CFG_BMAC_TX)) != NPI_SUCCESS) 350044961713Sgirish goto fail; 350144961713Sgirish } 350244961713Sgirish 350344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 350452ccf843Smisaki nxgep->mac.portnum)); 350544961713Sgirish 350644961713Sgirish return (NXGE_OK); 350744961713Sgirish fail: 350844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 350952ccf843Smisaki "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 351052ccf843Smisaki nxgep->mac.portnum)); 351144961713Sgirish if (rs != NPI_SUCCESS) 351244961713Sgirish return (NXGE_ERROR | rs); 351344961713Sgirish else 351444961713Sgirish return (status); 351544961713Sgirish } 351644961713Sgirish 351744961713Sgirish /* Disable TXMAC */ 351844961713Sgirish 351944961713Sgirish nxge_status_t 352044961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep) 352144961713Sgirish { 352244961713Sgirish npi_handle_t handle; 352344961713Sgirish npi_status_t rs = NPI_SUCCESS; 352444961713Sgirish 3525678453a8Sspeer if (isLDOMguest(nxgep)) 3526678453a8Sspeer return (NXGE_OK); 3527678453a8Sspeer 352844961713Sgirish handle = nxgep->npi_handle; 352944961713Sgirish 353044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 353152ccf843Smisaki nxgep->mac.portnum)); 353244961713Sgirish 353344961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 353444961713Sgirish if ((rs = npi_xmac_tx_config(handle, DISABLE, 353552ccf843Smisaki nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 353644961713Sgirish goto fail; 353744961713Sgirish } else { 353844961713Sgirish if ((rs = npi_bmac_tx_config(handle, DISABLE, 353952ccf843Smisaki nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 354044961713Sgirish goto fail; 354144961713Sgirish } 354244961713Sgirish 354344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 354452ccf843Smisaki nxgep->mac.portnum)); 354544961713Sgirish return (NXGE_OK); 354644961713Sgirish fail: 354744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 354852ccf843Smisaki "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 354952ccf843Smisaki nxgep->mac.portnum)); 355044961713Sgirish return (NXGE_ERROR | rs); 355144961713Sgirish } 355244961713Sgirish 355344961713Sgirish /* Enable RXMAC */ 355444961713Sgirish 355544961713Sgirish nxge_status_t 355644961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep) 355744961713Sgirish { 355844961713Sgirish npi_handle_t handle; 355944961713Sgirish uint8_t portn; 356044961713Sgirish npi_status_t rs = NPI_SUCCESS; 356144961713Sgirish nxge_status_t status = NXGE_OK; 356244961713Sgirish 3563678453a8Sspeer /* This is a service-domain-only activity. */ 3564678453a8Sspeer if (isLDOMguest(nxgep)) 3565678453a8Sspeer return (status); 3566678453a8Sspeer 356744961713Sgirish handle = nxgep->npi_handle; 356844961713Sgirish portn = nxgep->mac.portnum; 356944961713Sgirish 357044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 357152ccf843Smisaki portn)); 357244961713Sgirish 357344961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 357444961713Sgirish goto fail; 357544961713Sgirish 357644961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 357744961713Sgirish if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 3578678453a8Sspeer CFG_XMAC_RX)) != NPI_SUCCESS) 357944961713Sgirish goto fail; 358044961713Sgirish } else { 358144961713Sgirish if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 3582678453a8Sspeer CFG_BMAC_RX)) != NPI_SUCCESS) 358344961713Sgirish goto fail; 358444961713Sgirish } 358544961713Sgirish 3586678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3587678453a8Sspeer "<== nxge_rx_mac_enable: port<%d>", portn)); 358844961713Sgirish 358944961713Sgirish return (NXGE_OK); 359044961713Sgirish fail: 359144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3592678453a8Sspeer "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn)); 359344961713Sgirish 359444961713Sgirish if (rs != NPI_SUCCESS) 359544961713Sgirish return (NXGE_ERROR | rs); 359644961713Sgirish else 359744961713Sgirish return (status); 359844961713Sgirish } 359944961713Sgirish 360044961713Sgirish /* Disable RXMAC */ 360144961713Sgirish 360244961713Sgirish nxge_status_t 360344961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep) 360444961713Sgirish { 360544961713Sgirish npi_handle_t handle; 360644961713Sgirish uint8_t portn; 360744961713Sgirish npi_status_t rs = NPI_SUCCESS; 360844961713Sgirish 3609678453a8Sspeer /* If we are a guest domain driver, don't bother. */ 3610678453a8Sspeer if (isLDOMguest(nxgep)) 3611678453a8Sspeer return (NXGE_OK); 3612678453a8Sspeer 361344961713Sgirish handle = nxgep->npi_handle; 361444961713Sgirish portn = nxgep->mac.portnum; 361544961713Sgirish 361644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 361752ccf843Smisaki portn)); 361844961713Sgirish 361944961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 362044961713Sgirish if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 362152ccf843Smisaki CFG_XMAC_RX)) != NPI_SUCCESS) 362244961713Sgirish goto fail; 362344961713Sgirish } else { 362444961713Sgirish if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 362552ccf843Smisaki CFG_BMAC_RX)) != NPI_SUCCESS) 362644961713Sgirish goto fail; 362744961713Sgirish } 362844961713Sgirish 362944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 363052ccf843Smisaki portn)); 363144961713Sgirish return (NXGE_OK); 363244961713Sgirish fail: 363344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 363452ccf843Smisaki "nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn)); 363544961713Sgirish 363644961713Sgirish return (NXGE_ERROR | rs); 363744961713Sgirish } 363844961713Sgirish 363944961713Sgirish /* Reset TXMAC */ 364044961713Sgirish 364144961713Sgirish nxge_status_t 364244961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep) 364344961713Sgirish { 364444961713Sgirish npi_handle_t handle; 364544961713Sgirish uint8_t portn; 364644961713Sgirish npi_status_t rs = NPI_SUCCESS; 364744961713Sgirish 364844961713Sgirish handle = nxgep->npi_handle; 364944961713Sgirish portn = nxgep->mac.portnum; 365044961713Sgirish 365144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 365252ccf843Smisaki portn)); 365344961713Sgirish 365444961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 365544961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 365644961713Sgirish != NPI_SUCCESS) 365744961713Sgirish goto fail; 365844961713Sgirish } else { 365944961713Sgirish if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 366052ccf843Smisaki != NPI_SUCCESS) 366144961713Sgirish goto fail; 366244961713Sgirish } 366344961713Sgirish 366444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 366552ccf843Smisaki portn)); 366644961713Sgirish 366744961713Sgirish return (NXGE_OK); 366844961713Sgirish fail: 366944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 367052ccf843Smisaki "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn)); 367144961713Sgirish 367244961713Sgirish return (NXGE_ERROR | rs); 367344961713Sgirish } 367444961713Sgirish 367544961713Sgirish /* Reset RXMAC */ 367644961713Sgirish 367744961713Sgirish nxge_status_t 367844961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep) 367944961713Sgirish { 368044961713Sgirish npi_handle_t handle; 368144961713Sgirish uint8_t portn; 368244961713Sgirish npi_status_t rs = NPI_SUCCESS; 368344961713Sgirish 368444961713Sgirish handle = nxgep->npi_handle; 368544961713Sgirish portn = nxgep->mac.portnum; 368644961713Sgirish 368744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 368852ccf843Smisaki portn)); 368944961713Sgirish 369044961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 369144961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 369244961713Sgirish != NPI_SUCCESS) 369344961713Sgirish goto fail; 369444961713Sgirish } else { 369544961713Sgirish if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 369652ccf843Smisaki != NPI_SUCCESS) 369744961713Sgirish goto fail; 369844961713Sgirish } 369944961713Sgirish 370044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 370152ccf843Smisaki portn)); 370244961713Sgirish 370359ac0c16Sdavemq return (NXGE_OK); 370459ac0c16Sdavemq fail: 370559ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 370652ccf843Smisaki "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn)); 370759ac0c16Sdavemq return (NXGE_ERROR | rs); 370859ac0c16Sdavemq } 370959ac0c16Sdavemq 371059ac0c16Sdavemq /* 10G fiber link interrupt start routine */ 371159ac0c16Sdavemq 371259ac0c16Sdavemq static nxge_status_t 371359ac0c16Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep) 371459ac0c16Sdavemq { 371559ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 371659ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 371759ac0c16Sdavemq 371859ac0c16Sdavemq rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 371959ac0c16Sdavemq 372059ac0c16Sdavemq if (rs != NPI_SUCCESS) 372159ac0c16Sdavemq return (NXGE_ERROR | rs); 372259ac0c16Sdavemq else 372359ac0c16Sdavemq return (NXGE_OK); 372459ac0c16Sdavemq } 372559ac0c16Sdavemq 372659ac0c16Sdavemq /* 10G fiber link interrupt stop routine */ 372759ac0c16Sdavemq 372859ac0c16Sdavemq static nxge_status_t 372959ac0c16Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep) 373059ac0c16Sdavemq { 373159ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 373259ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 373359ac0c16Sdavemq 373459ac0c16Sdavemq rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 373559ac0c16Sdavemq 373659ac0c16Sdavemq if (rs != NPI_SUCCESS) 373759ac0c16Sdavemq return (NXGE_ERROR | rs); 373859ac0c16Sdavemq else 373959ac0c16Sdavemq return (NXGE_OK); 374059ac0c16Sdavemq } 374159ac0c16Sdavemq 374259ac0c16Sdavemq /* 1G fiber link interrupt start routine */ 374359ac0c16Sdavemq 374459ac0c16Sdavemq static nxge_status_t 374559ac0c16Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 374659ac0c16Sdavemq { 374759ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 374859ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 374959ac0c16Sdavemq 375059ac0c16Sdavemq rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 375159ac0c16Sdavemq if (rs != NPI_SUCCESS) 375259ac0c16Sdavemq return (NXGE_ERROR | rs); 375359ac0c16Sdavemq else 375459ac0c16Sdavemq return (NXGE_OK); 375559ac0c16Sdavemq } 375659ac0c16Sdavemq 375759ac0c16Sdavemq /* 1G fiber link interrupt stop routine */ 375859ac0c16Sdavemq 375959ac0c16Sdavemq static nxge_status_t 376059ac0c16Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 376159ac0c16Sdavemq { 376259ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 376359ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 376459ac0c16Sdavemq 376559ac0c16Sdavemq rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 376659ac0c16Sdavemq 376759ac0c16Sdavemq if (rs != NPI_SUCCESS) 376859ac0c16Sdavemq return (NXGE_ERROR | rs); 376959ac0c16Sdavemq else 377059ac0c16Sdavemq return (NXGE_OK); 377159ac0c16Sdavemq } 377259ac0c16Sdavemq 377359ac0c16Sdavemq /* 1G copper link interrupt start routine */ 377459ac0c16Sdavemq 377559ac0c16Sdavemq static nxge_status_t 377659ac0c16Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 377759ac0c16Sdavemq { 377859ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 377959ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 378059ac0c16Sdavemq 378159ac0c16Sdavemq rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 37826b438925Ssbehera MII_STATUS, MII_STATUS_LINKUP); 378359ac0c16Sdavemq 378459ac0c16Sdavemq if (rs != NPI_SUCCESS) 378559ac0c16Sdavemq return (NXGE_ERROR | rs); 378659ac0c16Sdavemq else 378759ac0c16Sdavemq return (NXGE_OK); 378844961713Sgirish } 378944961713Sgirish 379059ac0c16Sdavemq /* 1G copper link interrupt stop routine */ 379159ac0c16Sdavemq 379259ac0c16Sdavemq static nxge_status_t 379359ac0c16Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 379459ac0c16Sdavemq { 379559ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 379659ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 379759ac0c16Sdavemq 379859ac0c16Sdavemq rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 379959ac0c16Sdavemq 380059ac0c16Sdavemq if (rs != NPI_SUCCESS) 380159ac0c16Sdavemq return (NXGE_ERROR | rs); 380259ac0c16Sdavemq else 380359ac0c16Sdavemq return (NXGE_OK); 380459ac0c16Sdavemq } 380544961713Sgirish 380659ac0c16Sdavemq /* Enable/Disable Link Status change interrupt */ 380744961713Sgirish 380844961713Sgirish nxge_status_t 380944961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 381044961713Sgirish { 381159ac0c16Sdavemq uint8_t portn; 381259ac0c16Sdavemq nxge_status_t status = NXGE_OK; 381344961713Sgirish 381444961713Sgirish portn = nxgep->mac.portnum; 381544961713Sgirish 381644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 381759ac0c16Sdavemq if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 381859ac0c16Sdavemq return (NXGE_OK); 381944961713Sgirish 382059ac0c16Sdavemq if (enable == LINK_INTR_START) 382159ac0c16Sdavemq status = nxgep->xcvr.link_intr_start(nxgep); 382259ac0c16Sdavemq else if (enable == LINK_INTR_STOP) 382359ac0c16Sdavemq status = nxgep->xcvr.link_intr_stop(nxgep); 382459ac0c16Sdavemq if (status != NXGE_OK) 382559ac0c16Sdavemq goto fail; 382644961713Sgirish 382744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 382844961713Sgirish 382944961713Sgirish return (NXGE_OK); 383044961713Sgirish fail: 383144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 383252ccf843Smisaki "nxge_link_intr: Failed to set port<%d> mif intr mode", portn)); 383344961713Sgirish 383459ac0c16Sdavemq return (status); 383544961713Sgirish } 383644961713Sgirish 383744961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 383844961713Sgirish 383944961713Sgirish nxge_status_t 384044961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep) 384144961713Sgirish { 384244961713Sgirish p_nxge_param_t param_arr; 384344961713Sgirish p_nxge_stats_t statsp; 384444961713Sgirish uint8_t xcvr_portn; 384544961713Sgirish p_mii_regs_t mii_regs; 384644961713Sgirish mii_bmcr_t bmcr; 384744961713Sgirish mii_bmsr_t bmsr; 384844961713Sgirish mii_anar_t anar; 384944961713Sgirish mii_gcr_t gcr; 385044961713Sgirish mii_esr_t esr; 385144961713Sgirish mii_aux_ctl_t bcm5464r_aux; 385244961713Sgirish int status = NXGE_OK; 385344961713Sgirish 385444961713Sgirish uint_t delay; 385544961713Sgirish 385644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 385744961713Sgirish 385844961713Sgirish param_arr = nxgep->param_arr; 385944961713Sgirish statsp = nxgep->statsp; 386044961713Sgirish xcvr_portn = statsp->mac_stats.xcvr_portn; 386144961713Sgirish 386244961713Sgirish mii_regs = NULL; 386344961713Sgirish 386444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 386552ccf843Smisaki "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 386644961713Sgirish 3867d81011f0Ssbehera /* 3868d81011f0Ssbehera * The mif phy mode may be connected to either a copper link 3869d81011f0Ssbehera * or fiber link. Read the mode control register to get the fiber 3870d81011f0Ssbehera * configuration if it is hard-wired to fiber link. 3871d81011f0Ssbehera */ 3872d81011f0Ssbehera (void) nxge_mii_get_link_mode(nxgep); 3873d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 3874d81011f0Ssbehera return (nxge_mii_xcvr_fiber_init(nxgep)); 3875d81011f0Ssbehera } 3876d81011f0Ssbehera 387744961713Sgirish /* 387844961713Sgirish * Reset the transceiver. 387944961713Sgirish */ 388044961713Sgirish delay = 0; 388144961713Sgirish bmcr.value = 0; 388244961713Sgirish bmcr.bits.reset = 1; 388344961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3884adfcba55Sjoycey #if defined(__i386) 388552ccf843Smisaki (uint8_t)(uint32_t)&mii_regs->bmcr, 3886adfcba55Sjoycey #else 388752ccf843Smisaki (uint8_t)(uint64_t)&mii_regs->bmcr, 3888adfcba55Sjoycey #endif 388952ccf843Smisaki bmcr.value)) != NXGE_OK) 389044961713Sgirish goto fail; 389144961713Sgirish do { 389244961713Sgirish drv_usecwait(500); 389344961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3894adfcba55Sjoycey #if defined(__i386) 389552ccf843Smisaki (uint8_t)(uint32_t)&mii_regs->bmcr, 3896adfcba55Sjoycey #else 389752ccf843Smisaki (uint8_t)(uint64_t)&mii_regs->bmcr, 3898adfcba55Sjoycey #endif 389952ccf843Smisaki &bmcr.value)) != NXGE_OK) 390044961713Sgirish goto fail; 390144961713Sgirish delay++; 390244961713Sgirish } while ((bmcr.bits.reset) && (delay < 1000)); 390344961713Sgirish if (delay == 1000) { 390444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 390544961713Sgirish goto fail; 390644961713Sgirish } 390744961713Sgirish 390844961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3909adfcba55Sjoycey #if defined(__i386) 391052ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmsr), 3911adfcba55Sjoycey #else 391252ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmsr), 3913adfcba55Sjoycey #endif 391452ccf843Smisaki &bmsr.value)) != NXGE_OK) 391544961713Sgirish goto fail; 391644961713Sgirish 391744961713Sgirish param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 391844961713Sgirish param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 391944961713Sgirish param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 392044961713Sgirish param_arr[param_anar_100hdx].value = 0; 392144961713Sgirish param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 392244961713Sgirish param_arr[param_anar_10hdx].value = 0; 392344961713Sgirish 392444961713Sgirish /* 392558324dfcSspeer * Initialize the xcvr statistics. 392644961713Sgirish */ 392744961713Sgirish statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 392844961713Sgirish statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 392944961713Sgirish statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 393044961713Sgirish statsp->mac_stats.cap_100hdx = 0; 393144961713Sgirish statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 393244961713Sgirish statsp->mac_stats.cap_10hdx = 0; 393344961713Sgirish statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 393444961713Sgirish statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 393544961713Sgirish 393644961713Sgirish /* 393700161856Syc * Initialize the xcvr advertised capability statistics. 393844961713Sgirish */ 393944961713Sgirish statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 394044961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 394144961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 394244961713Sgirish statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 394344961713Sgirish statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 394444961713Sgirish statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 394544961713Sgirish statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 394644961713Sgirish statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 394744961713Sgirish statsp->mac_stats.adv_cap_asmpause = 394852ccf843Smisaki param_arr[param_anar_asmpause].value; 394944961713Sgirish statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 395044961713Sgirish 395144961713Sgirish 395244961713Sgirish /* 395344961713Sgirish * Check for extended status just in case we're 395444961713Sgirish * running a Gigibit phy. 395544961713Sgirish */ 395644961713Sgirish if (bmsr.bits.extend_status) { 395744961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3958adfcba55Sjoycey #if defined(__i386) 395952ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->esr), 3960adfcba55Sjoycey #else 396152ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->esr), 3962adfcba55Sjoycey #endif 396352ccf843Smisaki &esr.value)) != NXGE_OK) 396444961713Sgirish goto fail; 396552ccf843Smisaki param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx; 396644961713Sgirish param_arr[param_anar_1000hdx].value = 0; 396744961713Sgirish 396844961713Sgirish statsp->mac_stats.cap_1000fdx = 396952ccf843Smisaki (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 397044961713Sgirish statsp->mac_stats.cap_1000hdx = 0; 397144961713Sgirish } else { 397244961713Sgirish param_arr[param_anar_1000fdx].value = 0; 397344961713Sgirish param_arr[param_anar_1000hdx].value = 0; 397444961713Sgirish } 397544961713Sgirish 397644961713Sgirish /* 397744961713Sgirish * Initialize 1G Statistics once the capability is established. 397844961713Sgirish */ 397944961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 398044961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 398144961713Sgirish 398244961713Sgirish /* 398300161856Syc * Initialize the link statistics. 398444961713Sgirish */ 398544961713Sgirish statsp->mac_stats.link_T4 = 0; 398644961713Sgirish statsp->mac_stats.link_asmpause = 0; 398744961713Sgirish statsp->mac_stats.link_pause = 0; 398844961713Sgirish statsp->mac_stats.link_speed = 0; 398944961713Sgirish statsp->mac_stats.link_duplex = 0; 399044961713Sgirish statsp->mac_stats.link_up = 0; 399144961713Sgirish 399244961713Sgirish /* 399344961713Sgirish * Switch off Auto-negotiation, 100M and full duplex. 399444961713Sgirish */ 399544961713Sgirish bmcr.value = 0; 399644961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3997adfcba55Sjoycey #if defined(__i386) 399852ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmcr), 3999adfcba55Sjoycey #else 400052ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmcr), 4001adfcba55Sjoycey #endif 400252ccf843Smisaki bmcr.value)) != NXGE_OK) 400344961713Sgirish goto fail; 400444961713Sgirish 400544961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 400652ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 400744961713Sgirish bmcr.bits.loopback = 1; 400844961713Sgirish bmcr.bits.enable_autoneg = 0; 400944961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 401044961713Sgirish bmcr.bits.speed_1000_sel = 1; 401144961713Sgirish bmcr.bits.duplex_mode = 1; 401244961713Sgirish param_arr[param_autoneg].value = 0; 401344961713Sgirish } else { 401444961713Sgirish bmcr.bits.loopback = 0; 401544961713Sgirish } 401644961713Sgirish 401744961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 401852ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_ext100) || 401952ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 402044961713Sgirish param_arr[param_autoneg].value = 0; 402144961713Sgirish bcm5464r_aux.value = 0; 402244961713Sgirish bcm5464r_aux.bits.ext_lb = 1; 402344961713Sgirish bcm5464r_aux.bits.write_1 = 1; 402444961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 402552ccf843Smisaki BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 402644961713Sgirish goto fail; 402744961713Sgirish } 402844961713Sgirish 402900161856Syc /* If auto-negotiation is desired */ 403044961713Sgirish if (param_arr[param_autoneg].value) { 403144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 403252ccf843Smisaki "Restarting Auto-negotiation.")); 403344961713Sgirish /* 403444961713Sgirish * Setup our Auto-negotiation advertisement register. 403544961713Sgirish */ 403644961713Sgirish anar.value = 0; 403744961713Sgirish anar.bits.selector = 1; 403844961713Sgirish anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 403944961713Sgirish anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 404044961713Sgirish anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 404144961713Sgirish anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 404244961713Sgirish anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 404344961713Sgirish anar.bits.cap_asmpause = 0; 404444961713Sgirish anar.bits.cap_pause = 0; 404544961713Sgirish if (param_arr[param_anar_1000fdx].value || 404652ccf843Smisaki param_arr[param_anar_100fdx].value || 404752ccf843Smisaki param_arr[param_anar_10fdx].value) { 404844961713Sgirish anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 404944961713Sgirish anar.bits.cap_pause = statsp->mac_stats.cap_pause; 405044961713Sgirish } 405144961713Sgirish 405200161856Syc /* Write to the auto-negotiation advertisement register */ 405344961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4054adfcba55Sjoycey #if defined(__i386) 405552ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->anar), 4056adfcba55Sjoycey #else 405752ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->anar), 4058adfcba55Sjoycey #endif 405952ccf843Smisaki anar.value)) != NXGE_OK) 406044961713Sgirish goto fail; 406144961713Sgirish if (bmsr.bits.extend_status) { 406244961713Sgirish gcr.value = 0; 406344961713Sgirish gcr.bits.ms_mode_en = 406452ccf843Smisaki param_arr[param_master_cfg_enable].value; 406544961713Sgirish gcr.bits.master = 406652ccf843Smisaki param_arr[param_master_cfg_value].value; 406744961713Sgirish gcr.bits.link_1000fdx = 406852ccf843Smisaki param_arr[param_anar_1000fdx].value; 406944961713Sgirish gcr.bits.link_1000hdx = 407052ccf843Smisaki param_arr[param_anar_1000hdx].value; 407144961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4072adfcba55Sjoycey #if defined(__i386) 407352ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gcr), 4074adfcba55Sjoycey #else 407552ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gcr), 4076adfcba55Sjoycey #endif 407752ccf843Smisaki gcr.value)) != NXGE_OK) 407844961713Sgirish goto fail; 407944961713Sgirish } 408044961713Sgirish 408144961713Sgirish bmcr.bits.enable_autoneg = 1; 408244961713Sgirish bmcr.bits.restart_autoneg = 1; 408344961713Sgirish 408444961713Sgirish } else { 408544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 408644961713Sgirish bmcr.bits.speed_1000_sel = 408752ccf843Smisaki param_arr[param_anar_1000fdx].value | 408852ccf843Smisaki param_arr[param_anar_1000hdx].value; 408944961713Sgirish bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 409052ccf843Smisaki (param_arr[param_anar_100fdx].value | 409152ccf843Smisaki param_arr[param_anar_100hdx].value); 409200161856Syc 409300161856Syc /* Force to 1G */ 409444961713Sgirish if (bmcr.bits.speed_1000_sel) { 409544961713Sgirish statsp->mac_stats.link_speed = 1000; 409644961713Sgirish gcr.value = 0; 409744961713Sgirish gcr.bits.ms_mode_en = 409852ccf843Smisaki param_arr[param_master_cfg_enable].value; 409944961713Sgirish gcr.bits.master = 410052ccf843Smisaki param_arr[param_master_cfg_value].value; 410144961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4102adfcba55Sjoycey #if defined(__i386) 410352ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gcr), 4104adfcba55Sjoycey #else 410552ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gcr), 4106adfcba55Sjoycey #endif 410752ccf843Smisaki gcr.value)) != NXGE_OK) 410844961713Sgirish goto fail; 410944961713Sgirish if (param_arr[param_anar_1000fdx].value) { 411044961713Sgirish bmcr.bits.duplex_mode = 1; 411144961713Sgirish statsp->mac_stats.link_duplex = 2; 411244961713Sgirish } else 411344961713Sgirish statsp->mac_stats.link_duplex = 1; 411400161856Syc 411500161856Syc /* Force to 100M */ 411644961713Sgirish } else if (bmcr.bits.speed_sel) { 411744961713Sgirish statsp->mac_stats.link_speed = 100; 411844961713Sgirish if (param_arr[param_anar_100fdx].value) { 411944961713Sgirish bmcr.bits.duplex_mode = 1; 412044961713Sgirish statsp->mac_stats.link_duplex = 2; 412144961713Sgirish } else 412244961713Sgirish statsp->mac_stats.link_duplex = 1; 412300161856Syc 412400161856Syc /* Force to 10M */ 412544961713Sgirish } else { 412644961713Sgirish statsp->mac_stats.link_speed = 10; 412744961713Sgirish if (param_arr[param_anar_10fdx].value) { 412844961713Sgirish bmcr.bits.duplex_mode = 1; 412944961713Sgirish statsp->mac_stats.link_duplex = 2; 413044961713Sgirish } else 413144961713Sgirish statsp->mac_stats.link_duplex = 1; 413244961713Sgirish } 413344961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 413444961713Sgirish statsp->mac_stats.link_asmpause = 413552ccf843Smisaki statsp->mac_stats.cap_asmpause; 413644961713Sgirish statsp->mac_stats.link_pause = 413752ccf843Smisaki statsp->mac_stats.cap_pause; 413844961713Sgirish } 413944961713Sgirish 414044961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 414152ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_ext100) || 414252ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 414344961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 414444961713Sgirish /* BCM5464R 1000mbps external loopback mode */ 414544961713Sgirish gcr.value = 0; 414644961713Sgirish gcr.bits.ms_mode_en = 1; 414744961713Sgirish gcr.bits.master = 1; 414844961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4149adfcba55Sjoycey #if defined(__i386) 415052ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gcr), 4151adfcba55Sjoycey #else 415252ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gcr), 4153adfcba55Sjoycey #endif 415452ccf843Smisaki gcr.value)) != NXGE_OK) 415544961713Sgirish goto fail; 415644961713Sgirish bmcr.value = 0; 415744961713Sgirish bmcr.bits.speed_1000_sel = 1; 415844961713Sgirish statsp->mac_stats.link_speed = 1000; 415944961713Sgirish } else if (statsp->port_stats.lb_mode 416044961713Sgirish == nxge_lb_ext100) { 416144961713Sgirish /* BCM5464R 100mbps external loopback mode */ 416244961713Sgirish bmcr.value = 0; 416344961713Sgirish bmcr.bits.speed_sel = 1; 416444961713Sgirish bmcr.bits.duplex_mode = 1; 416544961713Sgirish statsp->mac_stats.link_speed = 100; 416644961713Sgirish } else if (statsp->port_stats.lb_mode 416744961713Sgirish == nxge_lb_ext10) { 416844961713Sgirish /* BCM5464R 10mbps external loopback mode */ 416944961713Sgirish bmcr.value = 0; 417044961713Sgirish bmcr.bits.duplex_mode = 1; 417144961713Sgirish statsp->mac_stats.link_speed = 10; 417244961713Sgirish } 417344961713Sgirish } 417444961713Sgirish } 417544961713Sgirish 417644961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4177adfcba55Sjoycey #if defined(__i386) 417852ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmcr), 4179adfcba55Sjoycey #else 418052ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmcr), 4181adfcba55Sjoycey #endif 418252ccf843Smisaki bmcr.value)) != NXGE_OK) 418344961713Sgirish goto fail; 418444961713Sgirish 418544961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 4186adfcba55Sjoycey #if defined(__i386) 418752ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmcr), 4188adfcba55Sjoycey #else 418952ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmcr), 4190adfcba55Sjoycey #endif 419152ccf843Smisaki &bmcr.value)) != NXGE_OK) 419244961713Sgirish goto fail; 419344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 419444961713Sgirish 419544961713Sgirish /* 419644961713Sgirish * Initialize the xcvr status kept in the context structure. 419744961713Sgirish */ 419844961713Sgirish nxgep->soft_bmsr.value = 0; 419944961713Sgirish 420044961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 4201adfcba55Sjoycey #if defined(__i386) 420252ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmsr), 4203adfcba55Sjoycey #else 420452ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmsr), 4205adfcba55Sjoycey #endif 420652ccf843Smisaki &nxgep->bmsr.value)) != NXGE_OK) 420744961713Sgirish goto fail; 420844961713Sgirish 420944961713Sgirish statsp->mac_stats.xcvr_inits++; 421044961713Sgirish nxgep->bmsr.value = 0; 421144961713Sgirish 421244961713Sgirish fail: 421344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 421452ccf843Smisaki "<== nxge_mii_xcvr_init status 0x%x", status)); 421544961713Sgirish return (status); 421644961713Sgirish } 421744961713Sgirish 4218d81011f0Ssbehera nxge_status_t 4219d81011f0Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep) 4220d81011f0Ssbehera { 4221d81011f0Ssbehera p_nxge_param_t param_arr; 4222d81011f0Ssbehera p_nxge_stats_t statsp; 4223d81011f0Ssbehera uint8_t xcvr_portn; 4224d81011f0Ssbehera p_mii_regs_t mii_regs; 4225d81011f0Ssbehera mii_bmcr_t bmcr; 4226d81011f0Ssbehera mii_bmsr_t bmsr; 4227d81011f0Ssbehera mii_gcr_t gcr; 4228d81011f0Ssbehera mii_esr_t esr; 4229d81011f0Ssbehera mii_aux_ctl_t bcm5464r_aux; 4230d81011f0Ssbehera int status = NXGE_OK; 4231d81011f0Ssbehera 4232d81011f0Ssbehera uint_t delay; 4233d81011f0Ssbehera 4234d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init")); 4235d81011f0Ssbehera 4236d81011f0Ssbehera param_arr = nxgep->param_arr; 4237d81011f0Ssbehera statsp = nxgep->statsp; 4238d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 4239d81011f0Ssbehera 4240d81011f0Ssbehera mii_regs = NULL; 4241d81011f0Ssbehera 4242d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4243d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: " 4244d81011f0Ssbehera "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 4245d81011f0Ssbehera 4246d81011f0Ssbehera /* 4247d81011f0Ssbehera * Reset the transceiver. 4248d81011f0Ssbehera */ 4249d81011f0Ssbehera delay = 0; 4250d81011f0Ssbehera bmcr.value = 0; 4251d81011f0Ssbehera bmcr.bits.reset = 1; 4252d81011f0Ssbehera 4253d81011f0Ssbehera #if defined(__i386) 4254d81011f0Ssbehera 4255d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4256d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4257d81011f0Ssbehera goto fail; 4258d81011f0Ssbehera #else 4259d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4260d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4261d81011f0Ssbehera goto fail; 4262d81011f0Ssbehera #endif 4263d81011f0Ssbehera do { 4264d81011f0Ssbehera drv_usecwait(500); 4265d81011f0Ssbehera #if defined(__i386) 4266d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4267d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) 4268d81011f0Ssbehera != NXGE_OK) 4269d81011f0Ssbehera goto fail; 4270d81011f0Ssbehera #else 4271d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4272d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) 4273d81011f0Ssbehera != NXGE_OK) 4274d81011f0Ssbehera goto fail; 4275d81011f0Ssbehera #endif 4276d81011f0Ssbehera delay++; 4277d81011f0Ssbehera } while ((bmcr.bits.reset) && (delay < 1000)); 4278d81011f0Ssbehera if (delay == 1000) { 4279d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 4280d81011f0Ssbehera goto fail; 4281d81011f0Ssbehera } 4282d81011f0Ssbehera 4283d81011f0Ssbehera #if defined(__i386) 4284d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4285d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 4286d81011f0Ssbehera goto fail; 4287d81011f0Ssbehera #else 4288d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4289d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 4290d81011f0Ssbehera goto fail; 4291d81011f0Ssbehera #endif 4292d81011f0Ssbehera 4293d81011f0Ssbehera param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 4294d81011f0Ssbehera param_arr[param_anar_100T4].value = 0; 4295d81011f0Ssbehera param_arr[param_anar_100fdx].value = 0; 4296d81011f0Ssbehera param_arr[param_anar_100hdx].value = 0; 4297d81011f0Ssbehera param_arr[param_anar_10fdx].value = 0; 4298d81011f0Ssbehera param_arr[param_anar_10hdx].value = 0; 4299d81011f0Ssbehera 4300d81011f0Ssbehera /* 4301d81011f0Ssbehera * Initialize the xcvr statistics. 4302d81011f0Ssbehera */ 4303d81011f0Ssbehera statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 4304d81011f0Ssbehera statsp->mac_stats.cap_100T4 = 0; 4305d81011f0Ssbehera statsp->mac_stats.cap_100fdx = 0; 4306d81011f0Ssbehera statsp->mac_stats.cap_100hdx = 0; 4307d81011f0Ssbehera statsp->mac_stats.cap_10fdx = 0; 4308d81011f0Ssbehera statsp->mac_stats.cap_10hdx = 0; 4309d81011f0Ssbehera statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 4310d81011f0Ssbehera statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 4311d81011f0Ssbehera 4312d81011f0Ssbehera /* 4313d81011f0Ssbehera * Initialize the xcvr advertised capability statistics. 4314d81011f0Ssbehera */ 4315d81011f0Ssbehera statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 4316d81011f0Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 4317d81011f0Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 4318d81011f0Ssbehera statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 4319d81011f0Ssbehera statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 4320d81011f0Ssbehera statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 4321d81011f0Ssbehera statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 4322d81011f0Ssbehera statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 4323d81011f0Ssbehera statsp->mac_stats.adv_cap_asmpause = 4324d81011f0Ssbehera param_arr[param_anar_asmpause].value; 4325d81011f0Ssbehera statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 4326d81011f0Ssbehera 4327d81011f0Ssbehera /* 4328d81011f0Ssbehera * Check for extended status just in case we're 4329d81011f0Ssbehera * running a Gigibit phy. 4330d81011f0Ssbehera */ 4331d81011f0Ssbehera if (bmsr.bits.extend_status) { 4332d81011f0Ssbehera #if defined(__i386) 4333d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4334d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) != 4335d81011f0Ssbehera NXGE_OK) 4336d81011f0Ssbehera goto fail; 4337d81011f0Ssbehera #else 4338d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4339d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) != 4340d81011f0Ssbehera NXGE_OK) 4341d81011f0Ssbehera goto fail; 4342d81011f0Ssbehera #endif 4343d81011f0Ssbehera param_arr[param_anar_1000fdx].value &= 4344d81011f0Ssbehera esr.bits.link_1000fdx; 4345d81011f0Ssbehera param_arr[param_anar_1000hdx].value = 0; 4346d81011f0Ssbehera 4347d81011f0Ssbehera statsp->mac_stats.cap_1000fdx = 4348d81011f0Ssbehera (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 4349d81011f0Ssbehera statsp->mac_stats.cap_1000hdx = 0; 4350d81011f0Ssbehera } else { 4351d81011f0Ssbehera param_arr[param_anar_1000fdx].value = 0; 4352d81011f0Ssbehera param_arr[param_anar_1000hdx].value = 0; 4353d81011f0Ssbehera } 4354d81011f0Ssbehera 4355d81011f0Ssbehera /* 4356d81011f0Ssbehera * Initialize 1G Statistics once the capability is established. 4357d81011f0Ssbehera */ 4358d81011f0Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 4359d81011f0Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 4360d81011f0Ssbehera 4361d81011f0Ssbehera /* 4362d81011f0Ssbehera * Initialize the link statistics. 4363d81011f0Ssbehera */ 4364d81011f0Ssbehera statsp->mac_stats.link_T4 = 0; 4365d81011f0Ssbehera statsp->mac_stats.link_asmpause = 0; 4366d81011f0Ssbehera statsp->mac_stats.link_pause = 0; 4367d81011f0Ssbehera statsp->mac_stats.link_speed = 0; 4368d81011f0Ssbehera statsp->mac_stats.link_duplex = 0; 4369d81011f0Ssbehera statsp->mac_stats.link_up = 0; 4370d81011f0Ssbehera 4371d81011f0Ssbehera /* 4372d81011f0Ssbehera * Switch off Auto-negotiation, 100M and full duplex. 4373d81011f0Ssbehera */ 4374d81011f0Ssbehera bmcr.value = 0; 4375d81011f0Ssbehera #if defined(__i386) 4376d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4377d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4378d81011f0Ssbehera goto fail; 4379d81011f0Ssbehera #else 4380d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4381d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4382d81011f0Ssbehera goto fail; 4383d81011f0Ssbehera #endif 4384d81011f0Ssbehera 4385d81011f0Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 4386d81011f0Ssbehera (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 4387d81011f0Ssbehera bmcr.bits.loopback = 1; 4388d81011f0Ssbehera bmcr.bits.enable_autoneg = 0; 4389d81011f0Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 4390d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 4391d81011f0Ssbehera bmcr.bits.duplex_mode = 1; 4392d81011f0Ssbehera param_arr[param_autoneg].value = 0; 4393d81011f0Ssbehera } else { 4394d81011f0Ssbehera bmcr.bits.loopback = 0; 4395d81011f0Ssbehera } 4396d81011f0Ssbehera 4397d81011f0Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 4398d81011f0Ssbehera param_arr[param_autoneg].value = 0; 4399d81011f0Ssbehera bcm5464r_aux.value = 0; 4400d81011f0Ssbehera bcm5464r_aux.bits.ext_lb = 1; 4401d81011f0Ssbehera bcm5464r_aux.bits.write_1 = 1; 4402d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4403d81011f0Ssbehera BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 4404d81011f0Ssbehera goto fail; 4405d81011f0Ssbehera } 4406d81011f0Ssbehera 4407d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 4408d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 4409d81011f0Ssbehera bmcr.bits.speed_sel = 0; 4410d81011f0Ssbehera bmcr.bits.duplex_mode = 1; 4411d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 4412d81011f0Ssbehera statsp->mac_stats.link_duplex = 2; 4413d81011f0Ssbehera 4414d81011f0Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) { 4415d81011f0Ssbehera /* BCM5464R 1000mbps external loopback mode */ 4416d81011f0Ssbehera gcr.value = 0; 4417d81011f0Ssbehera gcr.bits.ms_mode_en = 1; 4418d81011f0Ssbehera gcr.bits.master = 1; 4419d81011f0Ssbehera #if defined(__i386) 4420d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4421d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->gcr), 4422d81011f0Ssbehera gcr.value)) != NXGE_OK) 4423d81011f0Ssbehera goto fail; 4424d81011f0Ssbehera #else 4425d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4426d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->gcr), 4427d81011f0Ssbehera gcr.value)) != NXGE_OK) 4428d81011f0Ssbehera goto fail; 4429d81011f0Ssbehera #endif 4430d81011f0Ssbehera bmcr.value = 0; 4431d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 4432d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 4433d81011f0Ssbehera } 4434d81011f0Ssbehera 4435d81011f0Ssbehera #if defined(__i386) 4436d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4437d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), 4438d81011f0Ssbehera bmcr.value)) != NXGE_OK) 4439d81011f0Ssbehera goto fail; 4440d81011f0Ssbehera #else 4441d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4442d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), 4443d81011f0Ssbehera bmcr.value)) != NXGE_OK) 4444d81011f0Ssbehera goto fail; 4445d81011f0Ssbehera #endif 4446d81011f0Ssbehera 4447d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4448d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x", 4449d81011f0Ssbehera bmcr.value)); 4450d81011f0Ssbehera 4451d81011f0Ssbehera #if defined(__i386) 4452d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4453d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 4454d81011f0Ssbehera goto fail; 4455d81011f0Ssbehera #else 4456d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4457d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 4458d81011f0Ssbehera goto fail; 4459d81011f0Ssbehera #endif 4460d81011f0Ssbehera 4461d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4462d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value)); 4463d81011f0Ssbehera 4464d81011f0Ssbehera /* 4465d81011f0Ssbehera * Initialize the xcvr status kept in the context structure. 4466d81011f0Ssbehera */ 4467d81011f0Ssbehera nxgep->soft_bmsr.value = 0; 4468d81011f0Ssbehera #if defined(__i386) 4469d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4470d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), 4471d81011f0Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 4472d81011f0Ssbehera goto fail; 4473d81011f0Ssbehera #else 4474d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4475d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), 4476d81011f0Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 4477d81011f0Ssbehera goto fail; 4478d81011f0Ssbehera #endif 4479d81011f0Ssbehera 4480d81011f0Ssbehera statsp->mac_stats.xcvr_inits++; 4481d81011f0Ssbehera nxgep->bmsr.value = 0; 4482d81011f0Ssbehera 4483d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4484d81011f0Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 4485d81011f0Ssbehera return (status); 4486d81011f0Ssbehera 4487d81011f0Ssbehera fail: 4488d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4489d81011f0Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 4490d81011f0Ssbehera return (status); 4491d81011f0Ssbehera } 4492d81011f0Ssbehera 449344961713Sgirish /* Read from a MII compliant register */ 449444961713Sgirish 449544961713Sgirish nxge_status_t 449644961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 449744961713Sgirish uint16_t *value) 449844961713Sgirish { 449944961713Sgirish npi_status_t rs = NPI_SUCCESS; 450044961713Sgirish 450144961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 450252ccf843Smisaki "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 450344961713Sgirish 4504321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 450544961713Sgirish 4506d81011f0Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 4507d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 450844961713Sgirish if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 450952ccf843Smisaki xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 451044961713Sgirish goto fail; 45112e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 45122e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 451344961713Sgirish if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 451452ccf843Smisaki xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 451544961713Sgirish goto fail; 451644961713Sgirish } else 451744961713Sgirish goto fail; 451844961713Sgirish 4519321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 452044961713Sgirish 452144961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 452252ccf843Smisaki "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value)); 452344961713Sgirish return (NXGE_OK); 452444961713Sgirish fail: 4525321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 452644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 452752ccf843Smisaki "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn)); 452844961713Sgirish 452944961713Sgirish return (NXGE_ERROR | rs); 453044961713Sgirish } 453144961713Sgirish 453244961713Sgirish /* Write to a MII compliant Register */ 453344961713Sgirish 453444961713Sgirish nxge_status_t 453544961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 453644961713Sgirish uint16_t value) 453744961713Sgirish { 453844961713Sgirish npi_status_t rs = NPI_SUCCESS; 453944961713Sgirish 454044961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 454152ccf843Smisaki "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value)); 454244961713Sgirish 4543321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 454444961713Sgirish 4545d81011f0Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 4546d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 454744961713Sgirish if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 454852ccf843Smisaki xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 454944961713Sgirish goto fail; 45502e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 45512e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 455244961713Sgirish if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 455352ccf843Smisaki xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 455444961713Sgirish goto fail; 455544961713Sgirish } else 455644961713Sgirish goto fail; 455744961713Sgirish 4558321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 455944961713Sgirish 456044961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 456152ccf843Smisaki "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 456244961713Sgirish return (NXGE_OK); 456344961713Sgirish fail: 4564321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 456544961713Sgirish 456644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 456752ccf843Smisaki "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn)); 456844961713Sgirish 456944961713Sgirish return (NXGE_ERROR | rs); 457044961713Sgirish } 457144961713Sgirish 457200161856Syc /* 457300161856Syc * Perform write to Clause45 serdes / transceiver device 457400161856Syc * Arguments: 457500161856Syc * xcvr_portn: The IEEE 802.3 Clause45 PHYAD, it is the same as port 457600161856Syc * number if nxge_mdio_write is used for accessing the 457700161856Syc * internal LSIL serdes. Otherwise PHYAD is different 457800161856Syc * for different platforms. 457900161856Syc * device: With each PHYAD, the driver can use MDIO to control 458000161856Syc * multiple devices inside the PHY, here "device" is an 458100161856Syc * MMD (MDIO managable device). 458200161856Syc * xcvr_reg: Each device has multiple registers. xcvr_reg specifies 458300161856Syc * the register which the driver will write value to. 458400161856Syc * value: The register value will be filled in. 458500161856Syc */ 458644961713Sgirish nxge_status_t 458744961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 458844961713Sgirish uint16_t xcvr_reg, uint16_t *value) 458944961713Sgirish { 459044961713Sgirish npi_status_t rs = NPI_SUCCESS; 459144961713Sgirish 459244961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 459352ccf843Smisaki xcvr_portn)); 459444961713Sgirish 459553560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 459644961713Sgirish 459744961713Sgirish if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 459852ccf843Smisaki xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 459944961713Sgirish goto fail; 460044961713Sgirish 460153560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 460244961713Sgirish 460344961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 460452ccf843Smisaki xcvr_portn)); 460544961713Sgirish return (NXGE_OK); 460644961713Sgirish fail: 460753560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 460844961713Sgirish 460944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 461052ccf843Smisaki "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn)); 461144961713Sgirish 461244961713Sgirish return (NXGE_ERROR | rs); 461344961713Sgirish } 461444961713Sgirish 461544961713Sgirish /* Perform write to Clause45 serdes / transceiver device */ 461644961713Sgirish 461744961713Sgirish nxge_status_t 461844961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 461944961713Sgirish uint16_t xcvr_reg, uint16_t value) 462044961713Sgirish { 462144961713Sgirish npi_status_t rs = NPI_SUCCESS; 462244961713Sgirish 462344961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 462452ccf843Smisaki xcvr_portn)); 462544961713Sgirish 462653560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 462744961713Sgirish 462844961713Sgirish if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 462952ccf843Smisaki xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 463044961713Sgirish goto fail; 463144961713Sgirish 463253560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 463344961713Sgirish 463444961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 463552ccf843Smisaki xcvr_portn)); 463644961713Sgirish return (NXGE_OK); 463744961713Sgirish fail: 463853560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 463944961713Sgirish 464044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 464152ccf843Smisaki "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn)); 464244961713Sgirish 464344961713Sgirish return (NXGE_ERROR | rs); 464444961713Sgirish } 464544961713Sgirish 464644961713Sgirish 464744961713Sgirish /* Check MII to see if there is any link status change */ 464844961713Sgirish 464944961713Sgirish nxge_status_t 4650a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 4651a3c5bd6dSspeer nxge_link_state_t *link_up) 465244961713Sgirish { 465344961713Sgirish p_nxge_param_t param_arr; 465444961713Sgirish p_nxge_stats_t statsp; 465544961713Sgirish p_mii_regs_t mii_regs; 465644961713Sgirish p_mii_bmsr_t soft_bmsr; 465744961713Sgirish mii_anar_t anar; 465844961713Sgirish mii_anlpar_t anlpar; 465944961713Sgirish mii_anar_t an_common; 466044961713Sgirish mii_aner_t aner; 466144961713Sgirish mii_gsr_t gsr; 466244961713Sgirish nxge_status_t status = NXGE_OK; 466344961713Sgirish 466444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 466544961713Sgirish 466644961713Sgirish mii_regs = NULL; 466744961713Sgirish param_arr = nxgep->param_arr; 466844961713Sgirish statsp = nxgep->statsp; 466944961713Sgirish soft_bmsr = &nxgep->soft_bmsr; 4670a3c5bd6dSspeer *link_up = LINK_NO_CHANGE; 467144961713Sgirish 4672d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4673d81011f0Ssbehera "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x", 4674d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 4675d81011f0Ssbehera 467644961713Sgirish if (bmsr_ints.bits.link_status) { 4677d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4678d81011f0Ssbehera "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x", 4679d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 468044961713Sgirish if (bmsr.bits.link_status) { 468144961713Sgirish soft_bmsr->bits.link_status = 1; 4682d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4683d81011f0Ssbehera "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int " 4684d81011f0Ssbehera "0x%x", bmsr.value, bmsr_ints.value)); 468544961713Sgirish } else { 468644961713Sgirish statsp->mac_stats.link_up = 0; 468744961713Sgirish soft_bmsr->bits.link_status = 0; 468844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 468952ccf843Smisaki "Link down cable problem")); 4690a3c5bd6dSspeer *link_up = LINK_IS_DOWN; 469144961713Sgirish } 469244961713Sgirish } 469344961713Sgirish 4694d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 4695d81011f0Ssbehera param_arr[param_autoneg].value) { 469644961713Sgirish if (bmsr_ints.bits.auto_neg_complete) { 469744961713Sgirish if (bmsr.bits.auto_neg_complete) 469844961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 469944961713Sgirish else 470044961713Sgirish soft_bmsr->bits.auto_neg_complete = 0; 470144961713Sgirish } 470244961713Sgirish if (soft_bmsr->bits.link_status == 0) { 470344961713Sgirish statsp->mac_stats.link_T4 = 0; 470444961713Sgirish statsp->mac_stats.link_speed = 0; 470544961713Sgirish statsp->mac_stats.link_duplex = 0; 470644961713Sgirish statsp->mac_stats.link_asmpause = 0; 470744961713Sgirish statsp->mac_stats.link_pause = 0; 470844961713Sgirish statsp->mac_stats.lp_cap_autoneg = 0; 470944961713Sgirish statsp->mac_stats.lp_cap_100T4 = 0; 471044961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 0; 471144961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 0; 471244961713Sgirish statsp->mac_stats.lp_cap_100fdx = 0; 471344961713Sgirish statsp->mac_stats.lp_cap_100hdx = 0; 471444961713Sgirish statsp->mac_stats.lp_cap_10fdx = 0; 471544961713Sgirish statsp->mac_stats.lp_cap_10hdx = 0; 471644961713Sgirish statsp->mac_stats.lp_cap_10gfdx = 0; 471744961713Sgirish statsp->mac_stats.lp_cap_10ghdx = 0; 471844961713Sgirish statsp->mac_stats.lp_cap_asmpause = 0; 471944961713Sgirish statsp->mac_stats.lp_cap_pause = 0; 472044961713Sgirish } 472144961713Sgirish } else 472244961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 472344961713Sgirish 472444961713Sgirish if ((bmsr_ints.bits.link_status || 472552ccf843Smisaki bmsr_ints.bits.auto_neg_complete) && 472652ccf843Smisaki soft_bmsr->bits.link_status && 472752ccf843Smisaki soft_bmsr->bits.auto_neg_complete) { 472844961713Sgirish statsp->mac_stats.link_up = 1; 4729d81011f0Ssbehera 4730d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4731d81011f0Ssbehera "==> nxge_mii_check " 4732d81011f0Ssbehera "(auto negotiation complete or link up) " 4733d81011f0Ssbehera "soft bmsr 0x%x bmsr_int 0x%x", 4734d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 4735d81011f0Ssbehera 4736d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 4737d81011f0Ssbehera param_arr[param_autoneg].value) { 473844961713Sgirish if ((status = nxge_mii_read(nxgep, 473952ccf843Smisaki statsp->mac_stats.xcvr_portn, 4740adfcba55Sjoycey #if defined(__i386) 474152ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->anar), 4742adfcba55Sjoycey #else 474352ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->anar), 4744adfcba55Sjoycey #endif 474552ccf843Smisaki &anar.value)) != NXGE_OK) 474644961713Sgirish goto fail; 474744961713Sgirish if ((status = nxge_mii_read(nxgep, 474852ccf843Smisaki statsp->mac_stats.xcvr_portn, 4749adfcba55Sjoycey #if defined(__i386) 475052ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->anlpar), 4751adfcba55Sjoycey #else 475252ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->anlpar), 4753adfcba55Sjoycey #endif 475452ccf843Smisaki &anlpar.value)) != NXGE_OK) 475544961713Sgirish goto fail; 475644961713Sgirish if ((status = nxge_mii_read(nxgep, 475752ccf843Smisaki statsp->mac_stats.xcvr_portn, 4758adfcba55Sjoycey #if defined(__i386) 475952ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->aner), 4760adfcba55Sjoycey #else 476152ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->aner), 4762adfcba55Sjoycey #endif 476352ccf843Smisaki &aner.value)) != NXGE_OK) 476444961713Sgirish goto fail; 476544961713Sgirish statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 476644961713Sgirish statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 476744961713Sgirish statsp->mac_stats.lp_cap_100fdx = 476852ccf843Smisaki anlpar.bits.cap_100fdx; 476944961713Sgirish statsp->mac_stats.lp_cap_100hdx = 477052ccf843Smisaki anlpar.bits.cap_100hdx; 477144961713Sgirish statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 477244961713Sgirish statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 477344961713Sgirish statsp->mac_stats.lp_cap_asmpause = 477452ccf843Smisaki anlpar.bits.cap_asmpause; 477544961713Sgirish statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 477644961713Sgirish an_common.value = anar.value & anlpar.value; 477744961713Sgirish if (param_arr[param_anar_1000fdx].value || 477852ccf843Smisaki param_arr[param_anar_1000hdx].value) { 477944961713Sgirish if ((status = nxge_mii_read(nxgep, 478052ccf843Smisaki statsp->mac_stats.xcvr_portn, 4781adfcba55Sjoycey #if defined(__i386) 478252ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gsr), 4783adfcba55Sjoycey #else 478452ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gsr), 4785adfcba55Sjoycey #endif 478652ccf843Smisaki &gsr.value)) != NXGE_OK) 478744961713Sgirish goto fail; 478844961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 478952ccf843Smisaki gsr.bits.link_1000fdx; 479044961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 479152ccf843Smisaki gsr.bits.link_1000hdx; 479244961713Sgirish if (param_arr[param_anar_1000fdx].value && 479352ccf843Smisaki gsr.bits.link_1000fdx) { 479444961713Sgirish statsp->mac_stats.link_speed = 1000; 479544961713Sgirish statsp->mac_stats.link_duplex = 2; 479644961713Sgirish } else if ( 479752ccf843Smisaki param_arr[param_anar_1000hdx].value && 479852ccf843Smisaki gsr.bits.link_1000hdx) { 479944961713Sgirish statsp->mac_stats.link_speed = 1000; 480044961713Sgirish statsp->mac_stats.link_duplex = 1; 480144961713Sgirish } 480244961713Sgirish } 480344961713Sgirish if ((an_common.value != 0) && 480452ccf843Smisaki !(statsp->mac_stats.link_speed)) { 480544961713Sgirish if (an_common.bits.cap_100T4) { 480644961713Sgirish statsp->mac_stats.link_T4 = 1; 480744961713Sgirish statsp->mac_stats.link_speed = 100; 480844961713Sgirish statsp->mac_stats.link_duplex = 1; 480944961713Sgirish } else if (an_common.bits.cap_100fdx) { 481044961713Sgirish statsp->mac_stats.link_speed = 100; 481144961713Sgirish statsp->mac_stats.link_duplex = 2; 481244961713Sgirish } else if (an_common.bits.cap_100hdx) { 481344961713Sgirish statsp->mac_stats.link_speed = 100; 481444961713Sgirish statsp->mac_stats.link_duplex = 1; 481544961713Sgirish } else if (an_common.bits.cap_10fdx) { 481644961713Sgirish statsp->mac_stats.link_speed = 10; 481744961713Sgirish statsp->mac_stats.link_duplex = 2; 481844961713Sgirish } else if (an_common.bits.cap_10hdx) { 481944961713Sgirish statsp->mac_stats.link_speed = 10; 482044961713Sgirish statsp->mac_stats.link_duplex = 1; 482144961713Sgirish } else { 482244961713Sgirish goto fail; 482344961713Sgirish } 482444961713Sgirish } 482544961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 482652ccf843Smisaki int link_pause; 482752ccf843Smisaki int cp, lcp; 482852ccf843Smisaki 482944961713Sgirish statsp->mac_stats.link_asmpause = 483052ccf843Smisaki an_common.bits.cap_asmpause; 483152ccf843Smisaki cp = statsp->mac_stats.cap_pause; 483252ccf843Smisaki lcp = statsp->mac_stats.lp_cap_pause; 483352ccf843Smisaki if (statsp->mac_stats.link_asmpause) { 483452ccf843Smisaki if ((cp == 0) && (lcp == 1)) { 483552ccf843Smisaki link_pause = 0; 483652ccf843Smisaki } else { 483752ccf843Smisaki link_pause = 1; 483852ccf843Smisaki } 483952ccf843Smisaki } else { 484052ccf843Smisaki link_pause = an_common.bits.cap_pause; 484152ccf843Smisaki } 484252ccf843Smisaki statsp->mac_stats.link_pause = link_pause; 484344961713Sgirish } 4844d81011f0Ssbehera } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 4845d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 4846d81011f0Ssbehera statsp->mac_stats.link_duplex = 2; 484744961713Sgirish } 4848a3c5bd6dSspeer *link_up = LINK_IS_UP; 4849a3c5bd6dSspeer } 4850a3c5bd6dSspeer 4851a3c5bd6dSspeer if (nxgep->link_notify) { 4852a3c5bd6dSspeer *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 485352ccf843Smisaki LINK_IS_DOWN); 4854a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 485544961713Sgirish } 485644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 485744961713Sgirish return (NXGE_OK); 485844961713Sgirish fail: 485944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 486052ccf843Smisaki "nxge_mii_check: Unable to check MII")); 486144961713Sgirish return (status); 486244961713Sgirish } 486344961713Sgirish 486400161856Syc /* 486500161856Syc * Check PCS to see if there is any link status change. 486600161856Syc * This function is called by PORT_1G_SERDES only. 486700161856Syc */ 486800161856Syc void 48692e59129aSraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 48702e59129aSraghus { 48712e59129aSraghus p_nxge_stats_t statsp; 48722e59129aSraghus boolean_t linkup; 48732e59129aSraghus 48742e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 48752e59129aSraghus 48762e59129aSraghus statsp = nxgep->statsp; 48772e59129aSraghus *link_up = LINK_NO_CHANGE; 48782e59129aSraghus 48792e59129aSraghus (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 48802e59129aSraghus if (linkup) { 48812e59129aSraghus if (nxgep->link_notify || 48822e59129aSraghus nxgep->statsp->mac_stats.link_up == 0) { 48832e59129aSraghus statsp->mac_stats.link_up = 1; 48842e59129aSraghus statsp->mac_stats.link_speed = 1000; 48852e59129aSraghus statsp->mac_stats.link_duplex = 2; 48862e59129aSraghus *link_up = LINK_IS_UP; 48872e59129aSraghus nxgep->link_notify = B_FALSE; 48882e59129aSraghus } 48892e59129aSraghus } else { 48902e59129aSraghus if (nxgep->link_notify || 48912e59129aSraghus nxgep->statsp->mac_stats.link_up == 1) { 48922e59129aSraghus statsp->mac_stats.link_up = 0; 48932e59129aSraghus statsp->mac_stats.link_speed = 0; 48942e59129aSraghus statsp->mac_stats.link_duplex = 0; 48952e59129aSraghus *link_up = LINK_IS_DOWN; 48962e59129aSraghus nxgep->link_notify = B_FALSE; 48972e59129aSraghus } 48982e59129aSraghus } 48992e59129aSraghus 49002e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 49012e59129aSraghus } 49022e59129aSraghus 490344961713Sgirish /* Add a multicast address entry into the HW hash table */ 490444961713Sgirish 490544961713Sgirish nxge_status_t 490644961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 490744961713Sgirish { 490844961713Sgirish uint32_t mchash; 490944961713Sgirish p_hash_filter_t hash_filter; 491044961713Sgirish uint16_t hash_bit; 491144961713Sgirish boolean_t rx_init = B_FALSE; 491244961713Sgirish uint_t j; 491344961713Sgirish nxge_status_t status = NXGE_OK; 491444961713Sgirish 491544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 491644961713Sgirish 491744961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 491844961713Sgirish mchash = crc32_mchash(addrp); 491944961713Sgirish if (nxgep->hash_filter == NULL) { 492044961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 492152ccf843Smisaki "Allocating hash filter storage.")); 492244961713Sgirish nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 492352ccf843Smisaki KM_SLEEP); 492444961713Sgirish } 492544961713Sgirish hash_filter = nxgep->hash_filter; 492644961713Sgirish j = mchash / HASH_REG_WIDTH; 492744961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 492844961713Sgirish hash_filter->hash_filter_regs[j] |= hash_bit; 492944961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]++; 493044961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 493144961713Sgirish hash_filter->hash_ref_cnt++; 493244961713Sgirish rx_init = B_TRUE; 493344961713Sgirish } 493444961713Sgirish if (rx_init) { 493544961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 493644961713Sgirish goto fail; 493744961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 493844961713Sgirish goto fail; 493944961713Sgirish } 494044961713Sgirish 494144961713Sgirish RW_EXIT(&nxgep->filter_lock); 494244961713Sgirish 494344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 494444961713Sgirish 494544961713Sgirish return (NXGE_OK); 494644961713Sgirish fail: 494744961713Sgirish RW_EXIT(&nxgep->filter_lock); 494844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 494952ccf843Smisaki "Unable to add multicast address")); 495044961713Sgirish return (status); 495144961713Sgirish } 495244961713Sgirish 495344961713Sgirish /* Remove a multicast address entry from the HW hash table */ 495444961713Sgirish 495544961713Sgirish nxge_status_t 495644961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 495744961713Sgirish { 495844961713Sgirish uint32_t mchash; 495944961713Sgirish p_hash_filter_t hash_filter; 496044961713Sgirish uint16_t hash_bit; 496144961713Sgirish boolean_t rx_init = B_FALSE; 496244961713Sgirish uint_t j; 496344961713Sgirish nxge_status_t status = NXGE_OK; 496444961713Sgirish 496544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 496644961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 496744961713Sgirish mchash = crc32_mchash(addrp); 496844961713Sgirish if (nxgep->hash_filter == NULL) { 496944961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 497052ccf843Smisaki "Hash filter already de_allocated.")); 497144961713Sgirish RW_EXIT(&nxgep->filter_lock); 497244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 497344961713Sgirish return (NXGE_OK); 497444961713Sgirish } 497544961713Sgirish hash_filter = nxgep->hash_filter; 497644961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]--; 497744961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 497844961713Sgirish j = mchash / HASH_REG_WIDTH; 497944961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 498044961713Sgirish hash_filter->hash_filter_regs[j] &= ~hash_bit; 498144961713Sgirish hash_filter->hash_ref_cnt--; 498244961713Sgirish rx_init = B_TRUE; 498344961713Sgirish } 498444961713Sgirish if (hash_filter->hash_ref_cnt == 0) { 498544961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 498652ccf843Smisaki "De-allocating hash filter storage.")); 498744961713Sgirish KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 498844961713Sgirish nxgep->hash_filter = NULL; 498944961713Sgirish } 499044961713Sgirish 499144961713Sgirish if (rx_init) { 499244961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 499344961713Sgirish goto fail; 499444961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 499544961713Sgirish goto fail; 499644961713Sgirish } 499744961713Sgirish RW_EXIT(&nxgep->filter_lock); 499844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 499944961713Sgirish 500044961713Sgirish return (NXGE_OK); 500144961713Sgirish fail: 500244961713Sgirish RW_EXIT(&nxgep->filter_lock); 500344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 500452ccf843Smisaki "Unable to remove multicast address")); 500544961713Sgirish 500644961713Sgirish return (status); 500744961713Sgirish } 500844961713Sgirish 500944961713Sgirish /* Set MAC address into MAC address HW registers */ 501044961713Sgirish 501144961713Sgirish nxge_status_t 501244961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 501344961713Sgirish { 501444961713Sgirish nxge_status_t status = NXGE_OK; 501544961713Sgirish 501644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 501744961713Sgirish 501844961713Sgirish MUTEX_ENTER(&nxgep->ouraddr_lock); 501944961713Sgirish /* 502044961713Sgirish * Exit if the address is same as ouraddr or multicast or broadcast 502144961713Sgirish */ 502244961713Sgirish if (((addrp->ether_addr_octet[0] & 01) == 1) || 502352ccf843Smisaki (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 502452ccf843Smisaki (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 502544961713Sgirish goto nxge_set_mac_addr_exit; 502644961713Sgirish } 502744961713Sgirish nxgep->ouraddr = *addrp; 502844961713Sgirish /* 502944961713Sgirish * Set new interface local address and re-init device. 503044961713Sgirish * This is destructive to any other streams attached 503144961713Sgirish * to this device. 503244961713Sgirish */ 503344961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 503444961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 503544961713Sgirish goto fail; 503644961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 503744961713Sgirish goto fail; 503844961713Sgirish 503944961713Sgirish RW_EXIT(&nxgep->filter_lock); 504044961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 504144961713Sgirish goto nxge_set_mac_addr_end; 504244961713Sgirish nxge_set_mac_addr_exit: 504344961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 504444961713Sgirish nxge_set_mac_addr_end: 504544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 504644961713Sgirish 504744961713Sgirish return (NXGE_OK); 504844961713Sgirish fail: 504944961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 505044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 505152ccf843Smisaki "Unable to set mac address")); 505244961713Sgirish return (status); 505344961713Sgirish } 505444961713Sgirish 505598ecde52Stm static 505698ecde52Stm check_link_state_t 505700161856Syc nxge_check_link_stop(nxge_t *nxge) 505898ecde52Stm { 505998ecde52Stm /* If the poll has been cancelled, return STOP. */ 506098ecde52Stm MUTEX_ENTER(&nxge->poll_lock); 506198ecde52Stm if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 506298ecde52Stm nxge->poll_state = LINK_MONITOR_STOP; 506398ecde52Stm nxge->nxge_link_poll_timerid = 0; 506498ecde52Stm cv_broadcast(&nxge->poll_cv); 506598ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 506698ecde52Stm 506798ecde52Stm NXGE_DEBUG_MSG((nxge, MAC_CTL, 506898ecde52Stm "nxge_check_%s_link(port<%d>) stopped.", 506998ecde52Stm nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 507098ecde52Stm nxge->mac.portnum)); 507198ecde52Stm return (CHECK_LINK_STOP); 507298ecde52Stm } 507398ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 507498ecde52Stm 507598ecde52Stm return (CHECK_LINK_RESCHEDULE); 507698ecde52Stm } 507798ecde52Stm 507800161856Syc /* 507900161856Syc * Check status of MII (MIF or PCS) link. 508000161856Syc * This function is called once per second, that is because this function 508100161856Syc * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to 508200161856Syc * call this function recursively. 508300161856Syc */ 508459ac0c16Sdavemq static nxge_status_t 508544961713Sgirish nxge_check_mii_link(p_nxge_t nxgep) 508644961713Sgirish { 508744961713Sgirish mii_bmsr_t bmsr_ints, bmsr_data; 508844961713Sgirish mii_anlpar_t anlpar; 508944961713Sgirish mii_gsr_t gsr; 509044961713Sgirish p_mii_regs_t mii_regs; 509144961713Sgirish nxge_status_t status = NXGE_OK; 509244961713Sgirish uint8_t portn; 5093a3c5bd6dSspeer nxge_link_state_t link_up; 509444961713Sgirish 509598ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 509698ecde52Stm return (NXGE_ERROR); 509798ecde52Stm 509898ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 509998ecde52Stm return (NXGE_OK); 510098ecde52Stm 510144961713Sgirish portn = nxgep->mac.portnum; 510244961713Sgirish 510344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 510498ecde52Stm portn)); 510544961713Sgirish 510644961713Sgirish mii_regs = NULL; 510744961713Sgirish 510844961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 510944961713Sgirish 511044961713Sgirish if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 511144961713Sgirish goto nxge_check_mii_link_exit; 511244961713Sgirish 51132e59129aSraghus switch (nxgep->mac.portmode) { 51142e59129aSraghus default: 5115d81011f0Ssbehera bmsr_data.value = 0; 511644961713Sgirish if ((status = nxge_mii_read(nxgep, 51172e59129aSraghus nxgep->statsp->mac_stats.xcvr_portn, 5118adfcba55Sjoycey #if defined(__i386) 5119adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 5120adfcba55Sjoycey #else 51212e59129aSraghus (uint8_t)(uint64_t)(&mii_regs->bmsr), 5122adfcba55Sjoycey #endif 51232e59129aSraghus &bmsr_data.value)) != NXGE_OK) { 512444961713Sgirish goto fail; 512544961713Sgirish } 512644961713Sgirish 5127d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5128d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> " 5129d81011f0Ssbehera "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 51302d17280bSsbehera portn, bmsr_data.value, nxgep->bmsr.value)); 5131d81011f0Ssbehera 51322e59129aSraghus if (nxgep->param_arr[param_autoneg].value) { 51332e59129aSraghus if ((status = nxge_mii_read(nxgep, 513452ccf843Smisaki nxgep->statsp->mac_stats.xcvr_portn, 5135adfcba55Sjoycey #if defined(__i386) 513652ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gsr), 5137adfcba55Sjoycey #else 513852ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gsr), 5139adfcba55Sjoycey #endif 514052ccf843Smisaki &gsr.value)) != NXGE_OK) 51412e59129aSraghus goto fail; 51422e59129aSraghus if ((status = nxge_mii_read(nxgep, 514352ccf843Smisaki nxgep->statsp->mac_stats.xcvr_portn, 5144adfcba55Sjoycey #if defined(__i386) 514552ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->anlpar), 5146adfcba55Sjoycey #else 514752ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->anlpar), 5148adfcba55Sjoycey #endif 514952ccf843Smisaki &anlpar.value)) != NXGE_OK) 51502e59129aSraghus goto fail; 5151d81011f0Ssbehera if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 5152d81011f0Ssbehera 5153d81011f0Ssbehera if (nxgep->statsp->mac_stats.link_up && 5154d81011f0Ssbehera ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 5155d81011f0Ssbehera gsr.bits.link_1000fdx) || 5156d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 5157d81011f0Ssbehera gsr.bits.link_1000hdx) || 5158d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 5159d81011f0Ssbehera anlpar.bits.cap_100T4) || 5160d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 5161d81011f0Ssbehera anlpar.bits.cap_100fdx) || 5162d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 5163d81011f0Ssbehera anlpar.bits.cap_100hdx) || 5164d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 5165d81011f0Ssbehera anlpar.bits.cap_10fdx) || 5166d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 5167d81011f0Ssbehera anlpar.bits.cap_10hdx))) { 5168d81011f0Ssbehera bmsr_data.bits.link_status = 0; 5169d81011f0Ssbehera } 51702e59129aSraghus } 51712e59129aSraghus } 517244961713Sgirish 51732e59129aSraghus /* Workaround for link down issue */ 51742e59129aSraghus if (bmsr_data.value == 0) { 51752e59129aSraghus cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 51762e59129aSraghus goto nxge_check_mii_link_exit; 51772e59129aSraghus } 51782e59129aSraghus 5179d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5180d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> :" 5181d81011f0Ssbehera "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 51822d17280bSsbehera portn, nxgep->bmsr.value, bmsr_data.value)); 5183d81011f0Ssbehera 51842e59129aSraghus bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 51852e59129aSraghus nxgep->bmsr.value = bmsr_data.value; 5186d81011f0Ssbehera 5187d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5188d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> CALLING " 5189d81011f0Ssbehera "bmsr_data 0x%x bmsr_ints.value 0x%x", 51902d17280bSsbehera portn, bmsr_data.value, bmsr_ints.value)); 5191d81011f0Ssbehera 51922e59129aSraghus if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 51932e59129aSraghus &link_up)) != NXGE_OK) { 51942e59129aSraghus goto fail; 51952e59129aSraghus } 51962e59129aSraghus break; 51972e59129aSraghus 51982e59129aSraghus case PORT_1G_SERDES: 519900161856Syc /* 520000161856Syc * Above default is for all cases except PORT_1G_SERDES. 520100161856Syc * The default case gets information from the PHY, but a 520200161856Syc * nxge whose portmode equals PORT_1G_SERDES does not 520300161856Syc * have a PHY. 520400161856Syc */ 52052e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 52062e59129aSraghus "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 520700161856Syc nxge_pcs_check(nxgep, portn, &link_up); 52082e59129aSraghus break; 52092e59129aSraghus } 521044961713Sgirish 521144961713Sgirish nxge_check_mii_link_exit: 521244961713Sgirish RW_EXIT(&nxgep->filter_lock); 5213a3c5bd6dSspeer if (link_up == LINK_IS_UP) { 5214a3c5bd6dSspeer nxge_link_is_up(nxgep); 5215a3c5bd6dSspeer } else if (link_up == LINK_IS_DOWN) { 5216a3c5bd6dSspeer nxge_link_is_down(nxgep); 5217a3c5bd6dSspeer } 521844961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 521944961713Sgirish 522044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 522152ccf843Smisaki portn)); 522244961713Sgirish return (NXGE_OK); 522344961713Sgirish 522444961713Sgirish fail: 522544961713Sgirish RW_EXIT(&nxgep->filter_lock); 522644961713Sgirish 522744961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 522844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 522952ccf843Smisaki "nxge_check_mii_link: Failed to check link port<%d>", portn)); 523044961713Sgirish return (status); 523144961713Sgirish } 523244961713Sgirish 523344961713Sgirish /*ARGSUSED*/ 523459ac0c16Sdavemq static nxge_status_t 523544961713Sgirish nxge_check_10g_link(p_nxge_t nxgep) 523644961713Sgirish { 523744961713Sgirish uint8_t portn; 523844961713Sgirish nxge_status_t status = NXGE_OK; 5239763fcc44Ssbehera boolean_t link_up; 52402e59129aSraghus uint32_t val; 52412e59129aSraghus npi_status_t rs; 524244961713Sgirish 524398ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 524498ecde52Stm return (NXGE_ERROR); 524598ecde52Stm 524698ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 524798ecde52Stm return (NXGE_OK); 524898ecde52Stm 524944961713Sgirish portn = nxgep->mac.portnum; 5250d81011f0Ssbehera val = 0; 5251d81011f0Ssbehera rs = NPI_SUCCESS; 525244961713Sgirish 525344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 525498ecde52Stm portn)); 525544961713Sgirish 52562e59129aSraghus switch (nxgep->mac.portmode) { 52572e59129aSraghus default: 52582d17280bSsbehera /* 52592d17280bSsbehera * Check if the phy is present in case of hot swappable phy 52602d17280bSsbehera */ 52612d17280bSsbehera if (nxgep->hot_swappable_phy) { 52622d17280bSsbehera boolean_t phy_present_now = B_FALSE; 52632d17280bSsbehera 52642d17280bSsbehera /* 52652d17280bSsbehera * If this is the 2nd Goa port, then check 2 addresses 52662d17280bSsbehera * to take care of the Goa NEM card requirements. 52672d17280bSsbehera */ 52682d17280bSsbehera if (portn == 1) { 52692d17280bSsbehera if (nxge_is_phy_present(nxgep, 527000161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR, 52712d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 52722d17280bSsbehera phy_present_now = B_TRUE; 52732d17280bSsbehera nxgep->xcvr_addr = 527400161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR; 52752d17280bSsbehera goto phy_check_done; 52762d17280bSsbehera } 52772d17280bSsbehera } 52782d17280bSsbehera if (nxge_is_phy_present(nxgep, 527900161856Syc (GOA_CLAUSE45_PORT_ADDR_BASE) + portn, 52802d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 52812d17280bSsbehera nxgep->xcvr_addr = 528200161856Syc (GOA_CLAUSE45_PORT_ADDR_BASE) + portn; 52832d17280bSsbehera phy_present_now = B_TRUE; 52842d17280bSsbehera } 52852d17280bSsbehera 52862d17280bSsbehera phy_check_done: 52871c7408c9Stc /* Check back-to-back XAUI connect to detect Opus NEM */ 52881c7408c9Stc rs = npi_xmac_xpcs_read(nxgep->npi_handle, 52891c7408c9Stc nxgep->mac.portnum, XPCS_REG_STATUS, &val); 52901c7408c9Stc if (rs != 0) 52911c7408c9Stc goto fail; 52921c7408c9Stc 52931c7408c9Stc link_up = B_FALSE; 52941c7408c9Stc if (val & XPCS_STATUS_LANE_ALIGN) { 52951c7408c9Stc link_up = B_TRUE; 52961c7408c9Stc } 52971c7408c9Stc 52982d17280bSsbehera if (nxgep->phy_absent) { 52992d17280bSsbehera if (phy_present_now) { 53002d17280bSsbehera /* 53012d17280bSsbehera * Detect, Initialize phy and do link up 53022d17280bSsbehera * set xcvr vals, link_init, nxge_init 53032d17280bSsbehera */ 53042d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 53052d17280bSsbehera "Hot swappable phy DETECTED!!")); 53062d17280bSsbehera nxgep->phy_absent = B_FALSE; 53072d17280bSsbehera (void) nxge_xcvr_find(nxgep); 53082d17280bSsbehera (void) nxge_link_init(nxgep); 53092d17280bSsbehera if (!(nxgep->drv_state & 53102d17280bSsbehera STATE_HW_INITIALIZED)) { 53112d17280bSsbehera status = nxge_init(nxgep); 53122d17280bSsbehera if (status != NXGE_OK) { 53132d17280bSsbehera NXGE_ERROR_MSG((nxgep, 53142d17280bSsbehera NXGE_ERR_CTL, 53152d17280bSsbehera "Hot swappable " 53162d17280bSsbehera "phy present, but" 53172d17280bSsbehera " driver init" 53182d17280bSsbehera " failed...")); 53192d17280bSsbehera goto fail; 53202d17280bSsbehera } 53212d17280bSsbehera } 53221c7408c9Stc } else if (link_up) { /* XAUI linkup, no PHY */ 532348056c53SMichael Speer /* 53241c7408c9Stc * This is the back-to-back XAUI 53251c7408c9Stc * connect case for Opus NEM. 53261c7408c9Stc */ 53271c7408c9Stc nxgep->statsp->mac_stats.xcvr_inuse = 53281c7408c9Stc XPCS_XCVR; 53291c7408c9Stc nxgep->mac.portmode = PORT_10G_SERDES; 53301c7408c9Stc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 53311c7408c9Stc "HSP 10G Serdes DETECTED!!")); 53321c7408c9Stc break; 53332d17280bSsbehera } 53342d17280bSsbehera 53352d17280bSsbehera goto start_link_check; 53362d17280bSsbehera 53372d17280bSsbehera } else if (!phy_present_now) { 53382d17280bSsbehera /* 53392d17280bSsbehera * Phy gone, bring link down reset xcvr vals 53402d17280bSsbehera */ 53412d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 53422d17280bSsbehera "Hot swappable phy REMOVED!!")); 53432d17280bSsbehera nxgep->phy_absent = B_TRUE; 53442d17280bSsbehera nxgep->statsp->mac_stats.link_up = 0; 53452d17280bSsbehera nxgep->statsp->mac_stats.link_speed = 0; 53462d17280bSsbehera nxgep->statsp->mac_stats.link_duplex = 0; 53472d17280bSsbehera nxge_link_is_down(nxgep); 53482d17280bSsbehera nxgep->link_notify = B_FALSE; 53492d17280bSsbehera 53502d17280bSsbehera (void) nxge_xcvr_find(nxgep); 53512d17280bSsbehera 53522d17280bSsbehera goto start_link_check; 53532d17280bSsbehera 53542d17280bSsbehera } 53552d17280bSsbehera } 535652cdd236Ssbehera if (nxgep->chip_id == MRVL88X201X_CHIP_ID) { 535700161856Syc status = nxge_check_mrvl88x2011_link(nxgep, &link_up); 535852cdd236Ssbehera } else { 535952cdd236Ssbehera status = nxge_check_bcm8704_link(nxgep, &link_up); 536052cdd236Ssbehera } 53612e59129aSraghus if (status != NXGE_OK) 53622e59129aSraghus goto fail; 53632e59129aSraghus break; 53642e59129aSraghus case PORT_10G_SERDES: 53652e59129aSraghus rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 5366763fcc44Ssbehera XPCS_REG_STATUS, &val); 53672e59129aSraghus if (rs != 0) 53682e59129aSraghus goto fail; 53692e59129aSraghus 53702e59129aSraghus link_up = B_FALSE; 5371763fcc44Ssbehera if (val & XPCS_STATUS_LANE_ALIGN) { 5372763fcc44Ssbehera link_up = B_TRUE; 53732e59129aSraghus } 53742e59129aSraghus 53752e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 53762e59129aSraghus "==> nxge_check_10g_link port<%d> " 5377763fcc44Ssbehera "XPCS_REG_STATUS2 0x%x link_up %d", 5378763fcc44Ssbehera portn, val, link_up)); 53792e59129aSraghus 53802e59129aSraghus break; 53812e59129aSraghus } 538244961713Sgirish 538344961713Sgirish if (link_up) { 5384a3c5bd6dSspeer if (nxgep->link_notify || 538552ccf843Smisaki nxgep->statsp->mac_stats.link_up == 0) { 538644961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 538744961713Sgirish goto fail; 538844961713Sgirish nxgep->statsp->mac_stats.link_up = 1; 538944961713Sgirish nxgep->statsp->mac_stats.link_speed = 10000; 539044961713Sgirish nxgep->statsp->mac_stats.link_duplex = 2; 539144961713Sgirish 539244961713Sgirish nxge_link_is_up(nxgep); 5393a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 539444961713Sgirish } 539544961713Sgirish } else { 5396a3c5bd6dSspeer if (nxgep->link_notify || 539752ccf843Smisaki nxgep->statsp->mac_stats.link_up == 1) { 539844961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 539944961713Sgirish goto fail; 540044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 540152ccf843Smisaki "Link down cable problem")); 540244961713Sgirish nxgep->statsp->mac_stats.link_up = 0; 540344961713Sgirish nxgep->statsp->mac_stats.link_speed = 0; 540444961713Sgirish nxgep->statsp->mac_stats.link_duplex = 0; 540544961713Sgirish 540644961713Sgirish nxge_link_is_down(nxgep); 5407a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 54081c7408c9Stc 54091c7408c9Stc if (nxgep->mac.portmode == PORT_10G_SERDES) { 54101c7408c9Stc /* 54111c7408c9Stc * NEM was unplugged, set up xcvr table 54121c7408c9Stc * to find another xcvr in the future. 54131c7408c9Stc */ 54141c7408c9Stc (void) nxge_xcvr_find(nxgep); 54151c7408c9Stc } 541644961713Sgirish } 541744961713Sgirish } 541844961713Sgirish 54192d17280bSsbehera start_link_check: 542044961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 542144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 542298ecde52Stm portn)); 542344961713Sgirish return (NXGE_OK); 542444961713Sgirish 542544961713Sgirish fail: 542698ecde52Stm (void) nxge_check_link_stop(nxgep); 542798ecde52Stm 542844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 542998ecde52Stm "nxge_check_10g_link: Failed to check link port<%d>", 543098ecde52Stm portn)); 543144961713Sgirish return (status); 543244961713Sgirish } 543344961713Sgirish 543444961713Sgirish 543544961713Sgirish /* Declare link down */ 543644961713Sgirish 543744961713Sgirish void 543844961713Sgirish nxge_link_is_down(p_nxge_t nxgep) 543944961713Sgirish { 544059ac0c16Sdavemq p_nxge_stats_t statsp; 544159ac0c16Sdavemq char link_stat_msg[64]; 544259ac0c16Sdavemq 544344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 544444961713Sgirish 544559ac0c16Sdavemq statsp = nxgep->statsp; 544659ac0c16Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 544759ac0c16Sdavemq statsp->mac_stats.xcvr_portn); 544859ac0c16Sdavemq 544959ac0c16Sdavemq if (nxge_no_msg == B_FALSE) { 545059ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 545159ac0c16Sdavemq } 545259ac0c16Sdavemq 545344961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_DOWN); 545444961713Sgirish 545544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 545644961713Sgirish } 545744961713Sgirish 545844961713Sgirish /* Declare link up */ 545944961713Sgirish 546044961713Sgirish void 546144961713Sgirish nxge_link_is_up(p_nxge_t nxgep) 546244961713Sgirish { 546359ac0c16Sdavemq p_nxge_stats_t statsp; 546459ac0c16Sdavemq char link_stat_msg[64]; 546544961713Sgirish uint32_t val; 546644961713Sgirish 546744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 546844961713Sgirish 546959ac0c16Sdavemq statsp = nxgep->statsp; 547059ac0c16Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 547159ac0c16Sdavemq statsp->mac_stats.xcvr_portn, 547259ac0c16Sdavemq statsp->mac_stats.link_speed); 547359ac0c16Sdavemq 547459ac0c16Sdavemq if (statsp->mac_stats.link_T4) 547559ac0c16Sdavemq (void) strcat(link_stat_msg, "T4"); 547659ac0c16Sdavemq else if (statsp->mac_stats.link_duplex == 2) 547759ac0c16Sdavemq (void) strcat(link_stat_msg, "full duplex"); 547859ac0c16Sdavemq else 547959ac0c16Sdavemq (void) strcat(link_stat_msg, "half duplex"); 548059ac0c16Sdavemq 548144961713Sgirish 548244961713Sgirish /* Clean up symbol errors incurred during link transition */ 54832e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 54842e59129aSraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 548544961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 548652ccf843Smisaki XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 548744961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 548852ccf843Smisaki XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 548944961713Sgirish } 549044961713Sgirish 549100161856Syc /* 549200161856Syc * If the driver was plumbed without a link (therefore auto-negotiation 549300161856Syc * could not complete), the driver will detect a link up when a cable 549400161856Syc * conneting to a link partner is plugged into the port. By the time 549500161856Syc * link-up is detected, auto-negotiation should have completed (The 549600161856Syc * TN1010 tries to contact a link partner every 8~24ms). Here we re- 549700161856Syc * configure the Neptune/NIU according to the newly negotiated speed. 549800161856Syc * This is necessary only for the TN1010 basad device because only the 549900161856Syc * TN1010 supports dual speeds. 550000161856Syc */ 550100161856Syc if (nxgep->mac.portmode == PORT_1G_TN1010 || 550200161856Syc nxgep->mac.portmode == PORT_10G_TN1010) { 550300161856Syc 550400161856Syc (void) nxge_set_tn1010_param(nxgep); 550500161856Syc 550600161856Syc /* 550700161856Syc * nxge_xcvr_find calls nxge_get_xcvr_type (which sets 550800161856Syc * nxgep->portmode) and nxge_setup_xcvr_table (which sets 550900161856Syc * the nxgep->xcvr to the proper nxge_xcvr_table_t struct). 551000161856Syc */ 551100161856Syc if (nxge_xcvr_find(nxgep) != NXGE_OK) { 551200161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 551300161856Syc "nxge_link_is_up: nxge_xcvr_find failed")); 551400161856Syc } 551500161856Syc 551600161856Syc /* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */ 551700161856Syc if (nxge_link_init(nxgep) != NXGE_OK) { 551800161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 551900161856Syc "nxge_link_is_up: nxge_link_init failed")); 552000161856Syc } 552100161856Syc 552200161856Syc /* 552300161856Syc * nxge_mac_init calls many subroutines including 552400161856Syc * nxge_xif_init which sets XGMII or GMII mode 552500161856Syc */ 552600161856Syc if (nxge_mac_init(nxgep) != NXGE_OK) { 552700161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 552800161856Syc "nxge_link_is_up: nxge_mac_init failed")); 552900161856Syc } 553000161856Syc } else { 553100161856Syc (void) nxge_xif_init(nxgep); 553200161856Syc } 553300161856Syc 553459ac0c16Sdavemq if (nxge_no_msg == B_FALSE) { 553559ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 553659ac0c16Sdavemq } 553759ac0c16Sdavemq 553844961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UP); 553944961713Sgirish 554044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 554144961713Sgirish } 554244961713Sgirish 554300161856Syc #ifdef NXGE_DEBUG 554400161856Syc /* Dump all TN1010 Status registers */ 554500161856Syc static void 554600161856Syc nxge_dump_tn1010_status_regs(p_nxge_t nxgep) 554700161856Syc { 554800161856Syc uint16_t val; 554900161856Syc 555000161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 555100161856Syc TN1010_PMA_PMD_DEV_ADDR, 1, &val); 555200161856Syc cmn_err(CE_NOTE, "PMA status1 = 0x%x", val); 555300161856Syc 555400161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 555500161856Syc TN1010_PMA_PMD_DEV_ADDR, 8, &val); 555600161856Syc cmn_err(CE_NOTE, "PMA status2 = 0x%x", val); 555700161856Syc 555800161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 555900161856Syc TN1010_PMA_PMD_DEV_ADDR, 129, &val); 556000161856Syc cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val); 556100161856Syc 556200161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 556300161856Syc TN1010_PCS_DEV_ADDR, 1, &val); 556400161856Syc cmn_err(CE_NOTE, "PCS status1 = 0x%x", val); 556500161856Syc 556600161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 556700161856Syc TN1010_PCS_DEV_ADDR, 8, &val); 556800161856Syc cmn_err(CE_NOTE, "PCS status2 = 0x%x", val); 556900161856Syc 557000161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 557100161856Syc TN1010_PCS_DEV_ADDR, 32, &val); 557200161856Syc cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val); 557300161856Syc 557400161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 557500161856Syc TN1010_PCS_DEV_ADDR, 33, &val); 557600161856Syc cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val); 557700161856Syc 557800161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 557900161856Syc TN1010_PHYXS_DEV_ADDR, 1, &val); 558000161856Syc cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val); 558100161856Syc 558200161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 558300161856Syc TN1010_PHYXS_DEV_ADDR, 8, &val); 558400161856Syc cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val); 558500161856Syc 558600161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 558700161856Syc TN1010_PHYXS_DEV_ADDR, 24, &val); 558800161856Syc cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val); 558900161856Syc 559000161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 559100161856Syc TN1010_AUTONEG_DEV_ADDR, 1, &val); 559200161856Syc cmn_err(CE_NOTE, "Autoneg status = 0x%x", val); 559300161856Syc 559400161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 559500161856Syc TN1010_AUTONEG_DEV_ADDR, 33, &val); 559600161856Syc cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val); 559700161856Syc 559800161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 559900161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val); 560000161856Syc cmn_err(CE_NOTE, "TN1010 status = 0x%x", val); 560100161856Syc 560200161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 560300161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val); 560400161856Syc cmn_err(CE_NOTE, "Device status = 0x%x", val); 560500161856Syc 560600161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 560700161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val); 560800161856Syc cmn_err(CE_NOTE, "DDR status = 0x%x", val); 560900161856Syc 561000161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 561100161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val); 561200161856Syc cmn_err(CE_NOTE, "DDR fault status = 0x%x", val); 561300161856Syc 561400161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 561500161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val); 561600161856Syc cmn_err(CE_NOTE, "Firmware Revision = 0x%x Major = 0x%x Minor = 0x%x", 561700161856Syc val, (val & 0xFF00) >> 8, val & 0x00FF); 561800161856Syc } 561900161856Syc #endif 562000161856Syc 562144961713Sgirish /* 562244961713Sgirish * Calculate the bit in the multicast address filter 562344961713Sgirish * that selects the given * address. 562444961713Sgirish * Note: For GEM, the last 8-bits are used. 562544961713Sgirish */ 562644961713Sgirish uint32_t 562744961713Sgirish crc32_mchash(p_ether_addr_t addr) 562844961713Sgirish { 562944961713Sgirish uint8_t *cp; 563044961713Sgirish uint32_t crc; 563144961713Sgirish uint32_t c; 563244961713Sgirish int byte; 563344961713Sgirish int bit; 563444961713Sgirish 563544961713Sgirish cp = (uint8_t *)addr; 563644961713Sgirish crc = (uint32_t)0xffffffff; 563744961713Sgirish for (byte = 0; byte < 6; byte++) { 563844961713Sgirish c = (uint32_t)cp[byte]; 563944961713Sgirish for (bit = 0; bit < 8; bit++) { 564044961713Sgirish if ((c & 0x1) ^ (crc & 0x1)) 564144961713Sgirish crc = (crc >> 1)^0xedb88320; 564244961713Sgirish else 564344961713Sgirish crc = (crc >> 1); 564444961713Sgirish c >>= 1; 564544961713Sgirish } 564644961713Sgirish } 564744961713Sgirish return ((~crc) >> (32 - HASH_BITS)); 564844961713Sgirish } 564944961713Sgirish 565044961713Sgirish /* Reset serdes */ 565144961713Sgirish 565244961713Sgirish nxge_status_t 565344961713Sgirish nxge_serdes_reset(p_nxge_t nxgep) 565444961713Sgirish { 565544961713Sgirish npi_handle_t handle; 565644961713Sgirish 565744961713Sgirish handle = nxgep->npi_handle; 565844961713Sgirish 565944961713Sgirish ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 566044961713Sgirish drv_usecwait(500); 566144961713Sgirish ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 566244961713Sgirish 566344961713Sgirish return (NXGE_OK); 566444961713Sgirish } 566544961713Sgirish 566600161856Syc /* 566700161856Syc * This function monitors link status using interrupt or polling. 566800161856Syc * It calls nxgep->xcvr.check_link, a member function of 566900161856Syc * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this 567000161856Syc * function back, that is why the check_link routine is 567100161856Syc * executed periodically. 567200161856Syc */ 567344961713Sgirish nxge_status_t 567444961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 567544961713Sgirish { 567644961713Sgirish nxge_status_t status = NXGE_OK; 567744961713Sgirish 5678678453a8Sspeer /* If we are a guest domain driver, don't bother. */ 5679678453a8Sspeer if (isLDOMguest(nxgep)) 5680678453a8Sspeer return (status); 5681678453a8Sspeer 568244961713Sgirish /* 568398ecde52Stm * Return immediately if this is an imaginary XMAC port. 568498ecde52Stm * (At least, we don't have 4-port XMAC cards yet.) 568544961713Sgirish */ 56862e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER || 56872e59129aSraghus nxgep->mac.portmode == PORT_10G_SERDES) && 56882e59129aSraghus (nxgep->mac.portnum > 1)) 568944961713Sgirish return (NXGE_OK); 569044961713Sgirish 569144961713Sgirish if (nxgep->statsp == NULL) { 569244961713Sgirish /* stats has not been allocated. */ 569344961713Sgirish return (NXGE_OK); 569444961713Sgirish } 5695321febdeSsbehera /* Don't check link if we're in internal loopback mode */ 5696321febdeSsbehera if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g) 569744961713Sgirish return (NXGE_OK); 569844961713Sgirish 569944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 570098ecde52Stm "==> nxge_link_monitor port<%d> enable=%d", 570198ecde52Stm nxgep->mac.portnum, enable)); 570244961713Sgirish if (enable == LINK_MONITOR_START) { 570344961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 570444961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 570598ecde52Stm != NXGE_OK) 570644961713Sgirish goto fail; 570744961713Sgirish } else { 570898ecde52Stm timeout_id_t timerid; 570900161856Syc /* 571000161856Syc * check_link_stop means "Stop the link check", so 571100161856Syc * we return without starting the timer. 571200161856Syc */ 571398ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 571498ecde52Stm return (NXGE_OK); 571598ecde52Stm 571600161856Syc /* 571700161856Syc * Otherwise fire the timer for the nxge to check 571800161856Syc * the link using the check_link function 571900161856Syc * of the nxge_xcvr_table and pass "nxgep" as the 572000161856Syc * argument to the check_link function. 572100161856Syc */ 572259ac0c16Sdavemq if (nxgep->xcvr.check_link) { 572359ac0c16Sdavemq timerid = timeout( 572459ac0c16Sdavemq (fptrv_t)(nxgep->xcvr.check_link), 572598ecde52Stm nxgep, 572698ecde52Stm drv_usectohz(LINK_MONITOR_PERIOD)); 572759ac0c16Sdavemq MUTEX_ENTER(&nxgep->poll_lock); 572859ac0c16Sdavemq nxgep->nxge_link_poll_timerid = timerid; 572959ac0c16Sdavemq MUTEX_EXIT(&nxgep->poll_lock); 573059ac0c16Sdavemq } else { 573198ecde52Stm return (NXGE_ERROR); 573244961713Sgirish } 573344961713Sgirish } 573444961713Sgirish } else { 573544961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 573644961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 573798ecde52Stm != NXGE_OK) 573844961713Sgirish goto fail; 573944961713Sgirish } else { 574098ecde52Stm clock_t rv; 574198ecde52Stm 574298ecde52Stm MUTEX_ENTER(&nxgep->poll_lock); 574398ecde52Stm 574498ecde52Stm /* If <timerid> == 0, the link monitor has */ 574598ecde52Stm /* never been started, or just now stopped. */ 574698ecde52Stm if (nxgep->nxge_link_poll_timerid == 0) { 574798ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 574898ecde52Stm return (NXGE_OK); 574998ecde52Stm } 575098ecde52Stm 575198ecde52Stm nxgep->poll_state = LINK_MONITOR_STOPPING; 5752d3d50737SRafael Vanoni rv = cv_reltimedwait(&nxgep->poll_cv, &nxgep->poll_lock, 575398ecde52Stm drv_usectohz(LM_WAIT_MULTIPLIER * 5754d3d50737SRafael Vanoni LINK_MONITOR_PERIOD), TR_CLOCK_TICK); 575598ecde52Stm if (rv == -1) { 575698ecde52Stm NXGE_DEBUG_MSG((nxgep, MAC_CTL, 575798ecde52Stm "==> stopping port %d: " 575898ecde52Stm "cv_timedwait(%d) timed out", 575998ecde52Stm nxgep->mac.portnum, nxgep->poll_state)); 576098ecde52Stm nxgep->poll_state = LINK_MONITOR_STOP; 576144961713Sgirish nxgep->nxge_link_poll_timerid = 0; 576244961713Sgirish } 576398ecde52Stm 576498ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 576544961713Sgirish } 576644961713Sgirish } 576744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 576898ecde52Stm "<== nxge_link_monitor port<%d> enable=%d", 576998ecde52Stm nxgep->mac.portnum, enable)); 5770678453a8Sspeer 577144961713Sgirish return (NXGE_OK); 577244961713Sgirish fail: 577344961713Sgirish return (status); 577400161856Syc 577500161856Syc } 577600161856Syc 577700161856Syc nxge_status_t 577800161856Syc nxge_check_tn1010_link(p_nxge_t nxgep) 577900161856Syc { 578000161856Syc nxge_status_t status = NXGE_OK; 578100161856Syc nxge_link_state_t link_up; 578200161856Syc 578300161856Syc if (nxgep->nxge_magic != NXGE_MAGIC) { 578400161856Syc /* magic is 0 if driver is not attached */ 578500161856Syc return (NXGE_ERROR); 578600161856Syc } 578700161856Syc 578800161856Syc /* Link has been stopped, no need to continue */ 578900161856Syc if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) { 579000161856Syc return (NXGE_OK); 579100161856Syc } 579200161856Syc 579300161856Syc if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 579400161856Syc goto nxge_check_tn1010_link_exit; 579500161856Syc 579600161856Syc if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK) 579700161856Syc goto fail; 579800161856Syc 579900161856Syc nxge_check_tn1010_link_exit: 580000161856Syc if (link_up == LINK_IS_UP) 580100161856Syc nxge_link_is_up(nxgep); 580200161856Syc else if (link_up == LINK_IS_DOWN) 580300161856Syc nxge_link_is_down(nxgep); 580400161856Syc 580500161856Syc /* 580600161856Syc * nxge_link_monitor will call (nxgep->xcvr.check_link) 580700161856Syc * which could be THIS function. 580800161856Syc */ 580900161856Syc (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 581000161856Syc 581100161856Syc return (NXGE_OK); 581200161856Syc 581300161856Syc fail: 581400161856Syc (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 581500161856Syc 581600161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 581700161856Syc "nxge_check_tn1010_link: Failed to check link")); 581800161856Syc return (status); 581900161856Syc } 582000161856Syc 582100161856Syc 582200161856Syc /* 582300161856Syc * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN. 582400161856Syc */ 582500161856Syc static nxge_status_t 582600161856Syc nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up) 582700161856Syc { 582800161856Syc nxge_status_t status = NXGE_OK; 582900161856Syc p_nxge_stats_t statsp; 583000161856Syc uint8_t phy_port_addr, portn; 583100161856Syc uint16_t val; 583200161856Syc 583300161856Syc *link_up = LINK_NO_CHANGE; 583400161856Syc 583500161856Syc portn = NXGE_GET_PORT_NUM(nxgep->function_num); 583600161856Syc phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 583700161856Syc statsp = nxgep->statsp; 583800161856Syc 583900161856Syc /* Check if link is up */ 584000161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 584100161856Syc TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val)) 584200161856Syc != NXGE_OK) { 584300161856Syc goto fail; 584400161856Syc } 584500161856Syc /* 584600161856Syc * nxge_link_is_up has called nxge_set_tn1010_param and set 584700161856Syc * portmode and link_speed 584800161856Syc */ 584900161856Syc if (val & TN1010_AN_LINK_STAT_BIT) { 585000161856Syc if (nxgep->link_notify || 585100161856Syc nxgep->statsp->mac_stats.link_up == 0) { 585200161856Syc statsp->mac_stats.link_up = 1; 585300161856Syc statsp->mac_stats.link_duplex = 2; 585400161856Syc *link_up = LINK_IS_UP; 585500161856Syc nxgep->link_notify = B_FALSE; 585600161856Syc } 585700161856Syc } else { 585800161856Syc if (nxgep->link_notify || 585900161856Syc nxgep->statsp->mac_stats.link_up == 1) { 586000161856Syc statsp->mac_stats.link_up = 0; 586100161856Syc statsp->mac_stats.link_speed = 0; 586200161856Syc statsp->mac_stats.link_duplex = 0; 586300161856Syc *link_up = LINK_IS_DOWN; 586400161856Syc nxgep->link_notify = B_FALSE; 586500161856Syc } 586600161856Syc } 586700161856Syc return (NXGE_OK); 586800161856Syc 586900161856Syc fail: 587000161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 587100161856Syc "nxge_tn1010_check: Unable to check TN1010")); 587200161856Syc return (status); 587344961713Sgirish } 587444961713Sgirish 587500161856Syc 587644961713Sgirish /* Set promiscous mode */ 587744961713Sgirish 587844961713Sgirish nxge_status_t 587944961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 588044961713Sgirish { 588144961713Sgirish nxge_status_t status = NXGE_OK; 588244961713Sgirish 588359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 588444961713Sgirish 588544961713Sgirish nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 588644961713Sgirish 588744961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 588844961713Sgirish 588944961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 589044961713Sgirish goto fail; 589144961713Sgirish } 589244961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 589344961713Sgirish goto fail; 589444961713Sgirish } 589544961713Sgirish 589644961713Sgirish RW_EXIT(&nxgep->filter_lock); 589744961713Sgirish 589844961713Sgirish if (on) 589944961713Sgirish nxgep->statsp->mac_stats.promisc = B_TRUE; 590044961713Sgirish else 590144961713Sgirish nxgep->statsp->mac_stats.promisc = B_FALSE; 590244961713Sgirish 590344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 590444961713Sgirish 590544961713Sgirish return (NXGE_OK); 590644961713Sgirish fail: 590744961713Sgirish RW_EXIT(&nxgep->filter_lock); 590844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 590959ac0c16Sdavemq "Unable to set promisc (%d)", on)); 591044961713Sgirish 591144961713Sgirish return (status); 591244961713Sgirish } 591344961713Sgirish 591444961713Sgirish /*ARGSUSED*/ 591544961713Sgirish uint_t 591644961713Sgirish nxge_mif_intr(void *arg1, void *arg2) 591744961713Sgirish { 591844961713Sgirish #ifdef NXGE_DEBUG 591944961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 592044961713Sgirish #endif 592144961713Sgirish #if NXGE_MIF 592244961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 592344961713Sgirish uint32_t status; 592444961713Sgirish npi_handle_t handle; 592544961713Sgirish uint8_t portn; 592644961713Sgirish p_nxge_stats_t statsp; 592744961713Sgirish #endif 592844961713Sgirish 592944961713Sgirish #ifdef NXGE_MIF 593044961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 593144961713Sgirish nxgep = ldvp->nxgep; 593244961713Sgirish } 593344961713Sgirish nxgep = ldvp->nxgep; 593444961713Sgirish #endif 593544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 593644961713Sgirish 593744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 593844961713Sgirish return (DDI_INTR_CLAIMED); 593944961713Sgirish 594044961713Sgirish mif_intr_fail: 594144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 594244961713Sgirish return (DDI_INTR_UNCLAIMED); 594344961713Sgirish } 594444961713Sgirish 594544961713Sgirish /*ARGSUSED*/ 594644961713Sgirish uint_t 594744961713Sgirish nxge_mac_intr(void *arg1, void *arg2) 594844961713Sgirish { 594944961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 595044961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 595144961713Sgirish p_nxge_ldg_t ldgp; 595244961713Sgirish uint32_t status; 595344961713Sgirish npi_handle_t handle; 595444961713Sgirish uint8_t portn; 595544961713Sgirish p_nxge_stats_t statsp; 595644961713Sgirish npi_status_t rs = NPI_SUCCESS; 595744961713Sgirish 595844961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 595944961713Sgirish nxgep = ldvp->nxgep; 596044961713Sgirish } 596144961713Sgirish 596244961713Sgirish ldgp = ldvp->ldgp; 596344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 596459ac0c16Sdavemq "group %d", ldgp->ldg)); 596544961713Sgirish 596644961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 596744961713Sgirish /* 596844961713Sgirish * This interrupt handler is for a specific 596944961713Sgirish * mac port. 597044961713Sgirish */ 597144961713Sgirish statsp = (p_nxge_stats_t)nxgep->statsp; 597244961713Sgirish portn = nxgep->mac.portnum; 597344961713Sgirish 597444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 597559ac0c16Sdavemq "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 597644961713Sgirish 597744961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 597844961713Sgirish rs = npi_xmac_tx_get_istatus(handle, portn, 597952ccf843Smisaki (xmac_tx_iconfig_t *)&status); 598044961713Sgirish if (rs != NPI_SUCCESS) 598144961713Sgirish goto npi_fail; 598244961713Sgirish if (status & ICFG_XMAC_TX_ALL) { 598344961713Sgirish if (status & ICFG_XMAC_TX_UNDERRUN) { 598444961713Sgirish statsp->xmac_stats.tx_underflow_err++; 598544961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 598652ccf843Smisaki NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 598744961713Sgirish } 598844961713Sgirish if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 598944961713Sgirish statsp->xmac_stats.tx_maxpktsize_err++; 5990f6485eecSyc /* 5991f6485eecSyc * Do not send FMA ereport because this 5992f6485eecSyc * error does not indicate HW failure. 5993f6485eecSyc */ 599444961713Sgirish } 599544961713Sgirish if (status & ICFG_XMAC_TX_OVERFLOW) { 599644961713Sgirish statsp->xmac_stats.tx_overflow_err++; 599744961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 599852ccf843Smisaki NXGE_FM_EREPORT_TXMAC_OVERFLOW); 599944961713Sgirish } 600044961713Sgirish if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 600144961713Sgirish statsp->xmac_stats.tx_fifo_xfr_err++; 600244961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 600352ccf843Smisaki NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 600444961713Sgirish } 600544961713Sgirish if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 600644961713Sgirish statsp->xmac_stats.tx_byte_cnt += 600752ccf843Smisaki XTXMAC_BYTE_CNT_MASK; 600844961713Sgirish } 600944961713Sgirish if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 601044961713Sgirish statsp->xmac_stats.tx_frame_cnt += 601152ccf843Smisaki XTXMAC_FRM_CNT_MASK; 601244961713Sgirish } 601344961713Sgirish } 601444961713Sgirish 601544961713Sgirish rs = npi_xmac_rx_get_istatus(handle, portn, 601652ccf843Smisaki (xmac_rx_iconfig_t *)&status); 601744961713Sgirish if (rs != NPI_SUCCESS) 601844961713Sgirish goto npi_fail; 601944961713Sgirish if (status & ICFG_XMAC_RX_ALL) { 602044961713Sgirish if (status & ICFG_XMAC_RX_OVERFLOW) 602144961713Sgirish statsp->xmac_stats.rx_overflow_err++; 602244961713Sgirish if (status & ICFG_XMAC_RX_UNDERFLOW) { 602344961713Sgirish statsp->xmac_stats.rx_underflow_err++; 602444961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 602552ccf843Smisaki NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 602644961713Sgirish } 6027f6485eecSyc /* 6028f6485eecSyc * Do not send FMA ereport for the following 3 errors 6029f6485eecSyc * because they do not indicate HW failures. 6030f6485eecSyc */ 603144961713Sgirish if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 603244961713Sgirish statsp->xmac_stats.rx_crc_err_cnt += 603352ccf843Smisaki XRXMAC_CRC_ER_CNT_MASK; 603444961713Sgirish } 603544961713Sgirish if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 603644961713Sgirish statsp->xmac_stats.rx_len_err_cnt += 603752ccf843Smisaki MAC_LEN_ER_CNT_MASK; 603844961713Sgirish } 603944961713Sgirish if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 604044961713Sgirish statsp->xmac_stats.rx_viol_err_cnt += 604152ccf843Smisaki XRXMAC_CD_VIO_CNT_MASK; 604244961713Sgirish } 604344961713Sgirish if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 604444961713Sgirish statsp->xmac_stats.rx_byte_cnt += 604552ccf843Smisaki XRXMAC_BT_CNT_MASK; 604644961713Sgirish } 604744961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 604844961713Sgirish statsp->xmac_stats.rx_hist1_cnt += 604952ccf843Smisaki XRXMAC_HIST_CNT1_MASK; 605044961713Sgirish } 605144961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 605244961713Sgirish statsp->xmac_stats.rx_hist2_cnt += 605352ccf843Smisaki XRXMAC_HIST_CNT2_MASK; 605444961713Sgirish } 605544961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 605644961713Sgirish statsp->xmac_stats.rx_hist3_cnt += 605752ccf843Smisaki XRXMAC_HIST_CNT3_MASK; 605844961713Sgirish } 605944961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 606044961713Sgirish statsp->xmac_stats.rx_hist4_cnt += 606152ccf843Smisaki XRXMAC_HIST_CNT4_MASK; 606244961713Sgirish } 606344961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 606444961713Sgirish statsp->xmac_stats.rx_hist5_cnt += 606552ccf843Smisaki XRXMAC_HIST_CNT5_MASK; 606644961713Sgirish } 606744961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 606844961713Sgirish statsp->xmac_stats.rx_hist6_cnt += 606952ccf843Smisaki XRXMAC_HIST_CNT6_MASK; 607044961713Sgirish } 607144961713Sgirish if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 607244961713Sgirish statsp->xmac_stats.rx_broadcast_cnt += 607352ccf843Smisaki XRXMAC_BC_FRM_CNT_MASK; 607444961713Sgirish } 607544961713Sgirish if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 607644961713Sgirish statsp->xmac_stats.rx_mult_cnt += 607752ccf843Smisaki XRXMAC_MC_FRM_CNT_MASK; 607844961713Sgirish } 6079f6485eecSyc /* 6080f6485eecSyc * Do not send FMA ereport for the following 3 errors 6081f6485eecSyc * because they do not indicate HW failures. 6082f6485eecSyc */ 608344961713Sgirish if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 608444961713Sgirish statsp->xmac_stats.rx_frag_cnt += 608552ccf843Smisaki XRXMAC_FRAG_CNT_MASK; 608644961713Sgirish } 608744961713Sgirish if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 608844961713Sgirish statsp->xmac_stats.rx_frame_align_err_cnt += 608952ccf843Smisaki XRXMAC_AL_ER_CNT_MASK; 609044961713Sgirish } 609144961713Sgirish if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 609244961713Sgirish statsp->xmac_stats.rx_linkfault_err_cnt += 609352ccf843Smisaki XMAC_LINK_FLT_CNT_MASK; 609444961713Sgirish } 609544961713Sgirish if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 609644961713Sgirish statsp->xmac_stats.rx_remotefault_err++; 609744961713Sgirish } 609844961713Sgirish if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 609944961713Sgirish statsp->xmac_stats.rx_localfault_err++; 610044961713Sgirish } 610144961713Sgirish } 610244961713Sgirish 610344961713Sgirish rs = npi_xmac_ctl_get_istatus(handle, portn, 610452ccf843Smisaki (xmac_ctl_iconfig_t *)&status); 610544961713Sgirish if (rs != NPI_SUCCESS) 610644961713Sgirish goto npi_fail; 610744961713Sgirish if (status & ICFG_XMAC_CTRL_ALL) { 610844961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 610944961713Sgirish statsp->xmac_stats.rx_pause_cnt++; 611044961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 611144961713Sgirish statsp->xmac_stats.tx_pause_state++; 611244961713Sgirish if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 611344961713Sgirish statsp->xmac_stats.tx_nopause_state++; 611444961713Sgirish } 611544961713Sgirish } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 611644961713Sgirish rs = npi_bmac_tx_get_istatus(handle, portn, 611752ccf843Smisaki (bmac_tx_iconfig_t *)&status); 611844961713Sgirish if (rs != NPI_SUCCESS) 611944961713Sgirish goto npi_fail; 612044961713Sgirish if (status & ICFG_BMAC_TX_ALL) { 612144961713Sgirish if (status & ICFG_BMAC_TX_UNDERFLOW) { 612244961713Sgirish statsp->bmac_stats.tx_underrun_err++; 612344961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 612452ccf843Smisaki NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 612544961713Sgirish } 612644961713Sgirish if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 612744961713Sgirish statsp->bmac_stats.tx_max_pkt_err++; 612844961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 612952ccf843Smisaki NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 613044961713Sgirish } 613144961713Sgirish if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 613244961713Sgirish statsp->bmac_stats.tx_byte_cnt += 613352ccf843Smisaki BTXMAC_BYTE_CNT_MASK; 613444961713Sgirish } 613544961713Sgirish if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 613644961713Sgirish statsp->bmac_stats.tx_frame_cnt += 613752ccf843Smisaki BTXMAC_FRM_CNT_MASK; 613844961713Sgirish } 613944961713Sgirish } 614044961713Sgirish 614144961713Sgirish rs = npi_bmac_rx_get_istatus(handle, portn, 614252ccf843Smisaki (bmac_rx_iconfig_t *)&status); 614344961713Sgirish if (rs != NPI_SUCCESS) 614444961713Sgirish goto npi_fail; 614544961713Sgirish if (status & ICFG_BMAC_RX_ALL) { 614644961713Sgirish if (status & ICFG_BMAC_RX_OVERFLOW) { 614744961713Sgirish statsp->bmac_stats.rx_overflow_err++; 614844961713Sgirish } 614944961713Sgirish if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 615044961713Sgirish statsp->bmac_stats.rx_frame_cnt += 615152ccf843Smisaki RXMAC_FRM_CNT_MASK; 615244961713Sgirish } 615344961713Sgirish if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 615444961713Sgirish statsp->bmac_stats.rx_crc_err_cnt += 615552ccf843Smisaki BMAC_CRC_ER_CNT_MASK; 615644961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 615752ccf843Smisaki NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 615844961713Sgirish } 615944961713Sgirish if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 616044961713Sgirish statsp->bmac_stats.rx_len_err_cnt += 616152ccf843Smisaki MAC_LEN_ER_CNT_MASK; 616244961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 616352ccf843Smisaki NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 616444961713Sgirish } 616544961713Sgirish if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 616644961713Sgirish statsp->bmac_stats.rx_viol_err_cnt += 616752ccf843Smisaki BMAC_CD_VIO_CNT_MASK; 616844961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 616952ccf843Smisaki NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 617044961713Sgirish } 617144961713Sgirish if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 617244961713Sgirish statsp->bmac_stats.rx_byte_cnt += 617352ccf843Smisaki BRXMAC_BYTE_CNT_MASK; 617444961713Sgirish } 617544961713Sgirish if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 617644961713Sgirish statsp->bmac_stats.rx_align_err_cnt += 617752ccf843Smisaki BMAC_AL_ER_CNT_MASK; 617844961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 617952ccf843Smisaki NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 618044961713Sgirish } 618144961713Sgirish 618244961713Sgirish rs = npi_bmac_ctl_get_istatus(handle, portn, 618352ccf843Smisaki (bmac_ctl_iconfig_t *)&status); 618444961713Sgirish if (rs != NPI_SUCCESS) 618544961713Sgirish goto npi_fail; 618644961713Sgirish 618744961713Sgirish if (status & ICFG_BMAC_CTL_ALL) { 618844961713Sgirish if (status & ICFG_BMAC_CTL_RCVPAUSE) 618944961713Sgirish statsp->bmac_stats.rx_pause_cnt++; 619044961713Sgirish if (status & ICFG_BMAC_CTL_INPAUSE_ST) 619144961713Sgirish statsp->bmac_stats.tx_pause_state++; 619244961713Sgirish if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 619344961713Sgirish statsp->bmac_stats.tx_nopause_state++; 619444961713Sgirish } 619544961713Sgirish } 619644961713Sgirish 619744961713Sgirish if (ldgp->nldvs == 1) { 619844961713Sgirish (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 619952ccf843Smisaki B_TRUE, ldgp->ldg_timer); 620044961713Sgirish } 620144961713Sgirish 620244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 620344961713Sgirish return (DDI_INTR_CLAIMED); 620444961713Sgirish 620544961713Sgirish npi_fail: 620644961713Sgirish NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 620744961713Sgirish return (DDI_INTR_UNCLAIMED); 620844961713Sgirish } 620944961713Sgirish 621044961713Sgirish nxge_status_t 621144961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 621244961713Sgirish { 621344961713Sgirish uint8_t phy_port_addr; 621444961713Sgirish nxge_status_t status = NXGE_OK; 621544961713Sgirish boolean_t rx_sig_ok; 621644961713Sgirish boolean_t pcs_blk_lock; 621744961713Sgirish boolean_t link_align; 621844961713Sgirish uint16_t val1, val2, val3; 621944961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 622044961713Sgirish uint16_t val_debug; 6221*4df55fdeSJanie Lu uint32_t val; 622244961713Sgirish #endif 622344961713Sgirish 622444961713Sgirish phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 622544961713Sgirish 622644961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 622744961713Sgirish /* Check Device 3 Register Device 3 0xC809 */ 622844961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 622944961713Sgirish if ((val_debug & ~0x200) != 0) { 623044961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 623152ccf843Smisaki nxgep->mac.portnum, val_debug); 623244961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 623352ccf843Smisaki &val_debug); 623444961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 623552ccf843Smisaki nxgep->mac.portnum, val_debug); 623644961713Sgirish } 623744961713Sgirish 623844961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 623952ccf843Smisaki XPCS_REG_DESCWERR_COUNTER, &val); 624044961713Sgirish if (val != 0) 624144961713Sgirish cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 624244961713Sgirish 624344961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 624452ccf843Smisaki XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 624544961713Sgirish if (val != 0) 624644961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 624744961713Sgirish 624844961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 624952ccf843Smisaki XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 625044961713Sgirish if (val != 0) 625144961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 625244961713Sgirish #endif 625344961713Sgirish 625444961713Sgirish /* Check from BCM8704 if 10G link is up or down */ 625544961713Sgirish 625644961713Sgirish /* Check Device 1 Register 0xA bit0 */ 625752ccf843Smisaki status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR, 625852ccf843Smisaki BCM8704_PMD_RECEIVE_SIG_DETECT, &val1); 625944961713Sgirish if (status != NXGE_OK) 626044961713Sgirish goto fail; 626144961713Sgirish rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 626244961713Sgirish 626344961713Sgirish /* Check Device 3 Register 0x20 bit0 */ 626452ccf843Smisaki if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR, 626552ccf843Smisaki BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS) 626644961713Sgirish goto fail; 626744961713Sgirish pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 626844961713Sgirish 626944961713Sgirish /* Check Device 4 Register 0x18 bit12 */ 627052ccf843Smisaki status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 627152ccf843Smisaki BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3); 627244961713Sgirish if (status != NXGE_OK) 627344961713Sgirish goto fail; 62742d17280bSsbehera 62752d17280bSsbehera switch (nxgep->chip_id) { 62762d17280bSsbehera case BCM8704_CHIP_ID: 62772d17280bSsbehera link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | 62782d17280bSsbehera XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 62792d17280bSsbehera XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 62802d17280bSsbehera break; 62812d17280bSsbehera case BCM8706_CHIP_ID: 62822d17280bSsbehera link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) && 62832d17280bSsbehera (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) && 62842d17280bSsbehera (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ? 62852d17280bSsbehera B_TRUE : B_FALSE; 62862d17280bSsbehera break; 62872d17280bSsbehera default: 62882d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:" 62892d17280bSsbehera "Unknown chip ID [0x%x]", nxgep->chip_id)); 62902d17280bSsbehera goto fail; 62912d17280bSsbehera } 62922d17280bSsbehera 629344961713Sgirish #ifdef NXGE_DEBUG_ALIGN_ERR 629444961713Sgirish /* Temp workaround for link down issue */ 629544961713Sgirish if (pcs_blk_lock == B_FALSE) { 629644961713Sgirish if (val2 != 0x4) { 629744961713Sgirish pcs_blk_lock = B_TRUE; 629852ccf843Smisaki cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 " 629952ccf843Smisaki "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2); 630044961713Sgirish } 630144961713Sgirish } 630244961713Sgirish 630344961713Sgirish if (link_align == B_FALSE) { 630444961713Sgirish if (val3 != 0x140f) { 630544961713Sgirish link_align = B_TRUE; 630652ccf843Smisaki cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 " 630752ccf843Smisaki "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3); 630844961713Sgirish } 630944961713Sgirish } 631044961713Sgirish 631144961713Sgirish if (rx_sig_ok == B_FALSE) { 631244961713Sgirish if ((val2 == 0) || (val3 == 0)) { 631344961713Sgirish rx_sig_ok = B_TRUE; 631444961713Sgirish cmn_err(CE_NOTE, 631552ccf843Smisaki "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 631652ccf843Smisaki nxgep->mac.portnum); 631744961713Sgirish } 631844961713Sgirish } 631944961713Sgirish #endif 632044961713Sgirish 632144961713Sgirish *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 632252ccf843Smisaki (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 632344961713Sgirish 632444961713Sgirish return (NXGE_OK); 632544961713Sgirish fail: 632644961713Sgirish return (status); 632744961713Sgirish } 632844961713Sgirish 632952cdd236Ssbehera static nxge_status_t 633000161856Syc nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up) 633152cdd236Ssbehera { 633252cdd236Ssbehera uint8_t phy; 633352cdd236Ssbehera nxge_status_t status = NXGE_OK; 633452cdd236Ssbehera boolean_t pma_status; 633552cdd236Ssbehera boolean_t pcs_status; 633652cdd236Ssbehera boolean_t xgxs_status; 633752cdd236Ssbehera uint16_t val; 633852cdd236Ssbehera 633952cdd236Ssbehera phy = nxgep->statsp->mac_stats.xcvr_portn; 634052cdd236Ssbehera 634152cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 634252cdd236Ssbehera MRVL_88X2011_10G_PMD_STAT_2, &val); 634352cdd236Ssbehera 634452cdd236Ssbehera *link_up = B_FALSE; 634552cdd236Ssbehera 634652cdd236Ssbehera /* Check from Marvell 88X2011 if 10G link is up or down */ 634752cdd236Ssbehera 634852cdd236Ssbehera /* Check PMA/PMD Register: 1.0001.2 == 1 */ 634952cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 635052cdd236Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 635152cdd236Ssbehera 635252cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 635352cdd236Ssbehera "nxge_check_mrvl88x2011_link: pmd=0x%x", val)); 635452cdd236Ssbehera 635552cdd236Ssbehera pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 635652cdd236Ssbehera 635752cdd236Ssbehera /* Check PMC Register : 3.0001.2 == 1: read twice */ 635852cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 635952cdd236Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 636052cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 636152cdd236Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 636252cdd236Ssbehera 636352cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 636452cdd236Ssbehera "nxge_check_mrvl88x2011_link: pcs=0x%x", val)); 636552cdd236Ssbehera 636652cdd236Ssbehera pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 636752cdd236Ssbehera 636852cdd236Ssbehera /* Check XGXS Register : 4.0018.[0-3,12] */ 636952cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR, 637052cdd236Ssbehera MRVL_88X2011_10G_XGXS_LANE_STAT, &val); 637152cdd236Ssbehera 637252cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 637352cdd236Ssbehera "nxge_check_mrvl88x2011_link: xgxs=0x%x", val)); 637452cdd236Ssbehera 637552cdd236Ssbehera xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 637652cdd236Ssbehera XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 637752cdd236Ssbehera XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY | 637852cdd236Ssbehera XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE; 637952cdd236Ssbehera 638052cdd236Ssbehera *link_up = (pma_status && pcs_status && xgxs_status) ? 638152cdd236Ssbehera B_TRUE : B_FALSE; 638252cdd236Ssbehera 638352cdd236Ssbehera fail: 638452cdd236Ssbehera 638552cdd236Ssbehera if (*link_up == B_FALSE) { 638652cdd236Ssbehera /* PCS OFF */ 638752cdd236Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF); 638852cdd236Ssbehera } else { 638952cdd236Ssbehera /* PCS Activity */ 639052cdd236Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT); 639152cdd236Ssbehera } 639252cdd236Ssbehera 639352cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 639452cdd236Ssbehera " <== nxge_check_mrvl88x2011_link: up=%d", *link_up)); 639552cdd236Ssbehera 639652cdd236Ssbehera return (status); 639752cdd236Ssbehera } 639852cdd236Ssbehera 639959ac0c16Sdavemq nxge_status_t 640059ac0c16Sdavemq nxge_10g_link_led_on(p_nxge_t nxgep) 640159ac0c16Sdavemq { 640259ac0c16Sdavemq if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 640359ac0c16Sdavemq != NPI_SUCCESS) 640459ac0c16Sdavemq return (NXGE_ERROR); 640559ac0c16Sdavemq else 640659ac0c16Sdavemq return (NXGE_OK); 640759ac0c16Sdavemq } 640844961713Sgirish 640944961713Sgirish nxge_status_t 641059ac0c16Sdavemq nxge_10g_link_led_off(p_nxge_t nxgep) 641144961713Sgirish { 641259ac0c16Sdavemq if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 641359ac0c16Sdavemq != NPI_SUCCESS) 641459ac0c16Sdavemq return (NXGE_ERROR); 641559ac0c16Sdavemq else 641659ac0c16Sdavemq return (NXGE_OK); 641759ac0c16Sdavemq } 641844961713Sgirish 64192d17280bSsbehera static boolean_t 64202d17280bSsbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask) 64212d17280bSsbehera { 64222d17280bSsbehera uint32_t pma_pmd_id = 0; 64232d17280bSsbehera uint32_t pcs_id = 0; 64242d17280bSsbehera uint32_t phy_id = 0; 64252d17280bSsbehera 64262d17280bSsbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr); 64272d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 64282d17280bSsbehera "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id)); 64292d17280bSsbehera if ((pma_pmd_id & mask) == (id & mask)) 64302d17280bSsbehera goto found_phy; 64312d17280bSsbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, addr); 64322d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 64332d17280bSsbehera "nxge_is_phy_present: pcs_id[0x%x]", pcs_id)); 64342d17280bSsbehera if ((pcs_id & mask) == (id & mask)) 64352d17280bSsbehera goto found_phy; 64362d17280bSsbehera phy_id = nxge_get_cl22_phy_id(nxgep, addr); 64372d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 64382d17280bSsbehera "nxge_is_phy_present: phy_id[0x%x]", phy_id)); 64392d17280bSsbehera if ((phy_id & mask) == (id & mask)) 64402d17280bSsbehera goto found_phy; 64412d17280bSsbehera 64422d17280bSsbehera return (B_FALSE); 64432d17280bSsbehera 64442d17280bSsbehera found_phy: 64452d17280bSsbehera return (B_TRUE); 64462d17280bSsbehera } 64472d17280bSsbehera 644859ac0c16Sdavemq /* Check if the given id read using the given MDIO Clause is supported */ 644959ac0c16Sdavemq 645059ac0c16Sdavemq static boolean_t 645159ac0c16Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type) 645259ac0c16Sdavemq { 645359ac0c16Sdavemq int i; 645459ac0c16Sdavemq boolean_t found = B_FALSE; 645559ac0c16Sdavemq 645659ac0c16Sdavemq switch (type) { 645759ac0c16Sdavemq case CLAUSE_45_TYPE: 645800161856Syc for (i = 0; i < NUM_CLAUSE_45_IDS; i++) { 645900161856Syc if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 646000161856Syc (id & BCM_PHY_ID_MASK)) || 646100161856Syc (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK))) { 646259ac0c16Sdavemq found = B_TRUE; 646359ac0c16Sdavemq break; 646459ac0c16Sdavemq } 646559ac0c16Sdavemq } 646659ac0c16Sdavemq break; 646759ac0c16Sdavemq case CLAUSE_22_TYPE: 646800161856Syc for (i = 0; i < NUM_CLAUSE_22_IDS; i++) { 646930505775Ssbehera if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 647030505775Ssbehera (id & BCM_PHY_ID_MASK)) { 647159ac0c16Sdavemq found = B_TRUE; 647259ac0c16Sdavemq break; 647356d930aeSspeer } 647444961713Sgirish } 647559ac0c16Sdavemq break; 647659ac0c16Sdavemq default: 647759ac0c16Sdavemq break; 647856d930aeSspeer } 647956d930aeSspeer 648059ac0c16Sdavemq return (found); 648159ac0c16Sdavemq } 648259ac0c16Sdavemq 64832e59129aSraghus static uint32_t 64842e59129aSraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 64852e59129aSraghus { 64862e59129aSraghus uint16_t val1 = 0; 64872e59129aSraghus uint16_t val2 = 0; 64882e59129aSraghus uint32_t pma_pmd_dev_id = 0; 64892e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 64902e59129aSraghus 649153560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 64922e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 64932e59129aSraghus NXGE_DEV_ID_REG_1, &val1); 64942e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 64952e59129aSraghus NXGE_DEV_ID_REG_2, &val2); 649653560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 64972e59129aSraghus 649800161856Syc /* Concatenate the Device ID stored in two registers. */ 64992e59129aSraghus pma_pmd_dev_id = val1; 65002e59129aSraghus pma_pmd_dev_id = (pma_pmd_dev_id << 16); 65012e59129aSraghus pma_pmd_dev_id |= val2; 65022e59129aSraghus 65032e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 65042e59129aSraghus "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 65052e59129aSraghus 65062e59129aSraghus return (pma_pmd_dev_id); 65072e59129aSraghus } 65082e59129aSraghus 65092e59129aSraghus static uint32_t 65102e59129aSraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 65112e59129aSraghus { 65122e59129aSraghus uint16_t val1 = 0; 65132e59129aSraghus uint16_t val2 = 0; 65142e59129aSraghus uint32_t pcs_dev_id = 0; 65152e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 65162e59129aSraghus 651753560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 65182e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 65192e59129aSraghus NXGE_DEV_ID_REG_1, &val1); 65202e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 65212e59129aSraghus NXGE_DEV_ID_REG_2, &val2); 652253560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 65232e59129aSraghus 65242e59129aSraghus pcs_dev_id = val1; 65252e59129aSraghus pcs_dev_id = (pcs_dev_id << 16); 65262e59129aSraghus pcs_dev_id |= val2; 65272e59129aSraghus 65282e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 65292e59129aSraghus "devid[0x%llx]", phy_port, pcs_dev_id)); 65302e59129aSraghus 65312e59129aSraghus return (pcs_dev_id); 65322e59129aSraghus } 65332e59129aSraghus 65342e59129aSraghus static uint32_t 65352e59129aSraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 65362e59129aSraghus { 65372e59129aSraghus uint16_t val1 = 0; 65382e59129aSraghus uint16_t val2 = 0; 65392e59129aSraghus uint32_t phy_id = 0; 65402e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 65412e59129aSraghus npi_status_t npi_status = NPI_SUCCESS; 65422e59129aSraghus 6543321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 65442e59129aSraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 65452e59129aSraghus &val1); 65462e59129aSraghus if (npi_status != NPI_SUCCESS) { 65472e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 65482e59129aSraghus "clause 22 read to reg 2 failed!!!")); 65492e59129aSraghus goto exit; 65502e59129aSraghus } 65512e59129aSraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 65522e59129aSraghus &val2); 65532e59129aSraghus if (npi_status != 0) { 65542e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 65552e59129aSraghus "clause 22 read to reg 3 failed!!!")); 65562e59129aSraghus goto exit; 65572e59129aSraghus } 65582e59129aSraghus phy_id = val1; 65592e59129aSraghus phy_id = (phy_id << 16); 65602e59129aSraghus phy_id |= val2; 65612e59129aSraghus 65622e59129aSraghus exit: 6563321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 65642e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 65652e59129aSraghus phy_port, phy_id)); 65662e59129aSraghus 65672e59129aSraghus return (phy_id); 65682e59129aSraghus } 65692e59129aSraghus 657059ac0c16Sdavemq /* 657159ac0c16Sdavemq * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 657259ac0c16Sdavemq * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 657359ac0c16Sdavemq * read. Then use the values obtained to determine the phy type of each port 657459ac0c16Sdavemq * and the Neptune type. 657500161856Syc * 657600161856Syc * This function sets hw_p->xcvr_addr[i] for future MDIO access and set 657700161856Syc * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode 657800161856Syc * in case the portmode information is not available via OBP, nxge.conf, 657900161856Syc * VPD or SEEPROM. 658059ac0c16Sdavemq */ 658159ac0c16Sdavemq nxge_status_t 658259ac0c16Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 658359ac0c16Sdavemq { 658459a835ddSjoycey int i, j, l; 658559ac0c16Sdavemq uint32_t pma_pmd_dev_id = 0; 658659ac0c16Sdavemq uint32_t pcs_dev_id = 0; 658759ac0c16Sdavemq uint32_t phy_id = 0; 658830505775Ssbehera uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 658930505775Ssbehera uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 659030505775Ssbehera uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 659159ac0c16Sdavemq uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 659259ac0c16Sdavemq uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 65932d17280bSsbehera uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS]; 65942d17280bSsbehera uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS]; 659559ac0c16Sdavemq uint8_t total_port_fd, total_phy_fd; 659600161856Syc uint8_t num_xaui; 659759ac0c16Sdavemq nxge_status_t status = NXGE_OK; 659856d930aeSspeer 659959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 660056d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 660159ac0c16Sdavemq "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 660259ac0c16Sdavemq nxgep->niu_type)); 660359ac0c16Sdavemq 6604678453a8Sspeer if (isLDOMguest(nxgep)) { 6605678453a8Sspeer hw_p->niu_type = NIU_TYPE_NONE; 6606678453a8Sspeer hw_p->platform_type = P_NEPTUNE_NONE; 6607678453a8Sspeer return (NXGE_OK); 6608678453a8Sspeer } 6609678453a8Sspeer 661059a835ddSjoycey j = l = 0; 661159ac0c16Sdavemq total_port_fd = total_phy_fd = 0; 661256d930aeSspeer /* 661323b952a3SSantwona Behera * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved 661423b952a3SSantwona Behera * for on chip serdes usages. "i" in the following for loop starts at 6. 661556d930aeSspeer */ 661659ac0c16Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 66172e59129aSraghus 66182e59129aSraghus pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 661959ac0c16Sdavemq 662059ac0c16Sdavemq if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 662159ac0c16Sdavemq pma_pmd_dev_fd[i] = 1; 662259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 662352cdd236Ssbehera "PMA/PMD dev %x found", i, pma_pmd_dev_id)); 662430505775Ssbehera if (j < NXGE_PORTS_NEPTUNE) { 662500161856Syc if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK) 662600161856Syc == TN1010_DEV_ID) { 662700161856Syc port_pma_pmd_dev_id[j] = TN1010_DEV_ID; 662800161856Syc } else { 662900161856Syc port_pma_pmd_dev_id[j] = 663052ccf843Smisaki pma_pmd_dev_id & BCM_PHY_ID_MASK; 663100161856Syc } 66322d17280bSsbehera port_fd_arr[j] = (uint8_t)i; 663359ac0c16Sdavemq j++; 663459ac0c16Sdavemq } 663559ac0c16Sdavemq } else { 663659ac0c16Sdavemq pma_pmd_dev_fd[i] = 0; 663759ac0c16Sdavemq } 663859ac0c16Sdavemq 66392e59129aSraghus pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 664059ac0c16Sdavemq 664159ac0c16Sdavemq if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 664259ac0c16Sdavemq pcs_dev_fd[i] = 1; 664359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 664452cdd236Ssbehera "dev %x found", i, pcs_dev_id)); 664559a835ddSjoycey if (pma_pmd_dev_fd[i] == 1) { 664600161856Syc if ((pcs_dev_id & TN1010_DEV_ID_MASK) 664700161856Syc == TN1010_DEV_ID) { 664800161856Syc port_pcs_dev_id[j - 1] = 664900161856Syc TN1010_DEV_ID; 665000161856Syc } else { 665100161856Syc port_pcs_dev_id[j - 1] = 665200161856Syc pcs_dev_id & 665300161856Syc BCM_PHY_ID_MASK; 665400161856Syc } 665559a835ddSjoycey } else { 665659a835ddSjoycey if (j < NXGE_PORTS_NEPTUNE) { 665700161856Syc if ((pcs_dev_id & TN1010_DEV_ID_MASK) 665852ccf843Smisaki == TN1010_DEV_ID) { 665900161856Syc port_pcs_dev_id[j] = 666000161856Syc TN1010_DEV_ID; 666100161856Syc } else { 666200161856Syc port_pcs_dev_id[j] = 666300161856Syc pcs_dev_id & 666400161856Syc BCM_PHY_ID_MASK; 666500161856Syc } 666659a835ddSjoycey port_fd_arr[j] = (uint8_t)i; 666759a835ddSjoycey j++; 666859a835ddSjoycey } 666959ac0c16Sdavemq } 667059ac0c16Sdavemq } else { 667159ac0c16Sdavemq pcs_dev_fd[i] = 0; 667259ac0c16Sdavemq } 667359ac0c16Sdavemq 66742d17280bSsbehera if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) { 66752d17280bSsbehera total_port_fd ++; 66762d17280bSsbehera } 667759ac0c16Sdavemq 66782e59129aSraghus phy_id = nxge_get_cl22_phy_id(nxgep, i); 667959ac0c16Sdavemq if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 66802d17280bSsbehera total_phy_fd ++; 668159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 668252cdd236Ssbehera "%x found", i, phy_id)); 668330505775Ssbehera if (l < NXGE_PORTS_NEPTUNE) { 668400161856Syc if ((phy_id & TN1010_DEV_ID_MASK) 668500161856Syc == TN1010_DEV_ID) { 668600161856Syc port_phy_id[l] = TN1010_DEV_ID; 668700161856Syc } else { 668800161856Syc port_phy_id[l] 668900161856Syc = phy_id & BCM_PHY_ID_MASK; 669000161856Syc } 66912d17280bSsbehera phy_fd_arr[l] = (uint8_t)i; 669259ac0c16Sdavemq l++; 669359ac0c16Sdavemq } 669459ac0c16Sdavemq } 669559ac0c16Sdavemq } 669659ac0c16Sdavemq 669759ac0c16Sdavemq switch (total_port_fd) { 669859ac0c16Sdavemq case 2: 669959ac0c16Sdavemq switch (total_phy_fd) { 670059ac0c16Sdavemq case 2: 670123b952a3SSantwona Behera /* 2 10G, 2 1G RGMII Fiber / copper */ 670259a835ddSjoycey if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 670359a835ddSjoycey (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 670459a835ddSjoycey ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 670559a835ddSjoycey (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 670659a835ddSjoycey ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 670759a835ddSjoycey (port_phy_id[1] == PHY_BCM5482_FAMILY))) { 670859a835ddSjoycey 670923b952a3SSantwona Behera switch (hw_p->platform_type) { 671023b952a3SSantwona Behera case P_NEPTUNE_ROCK: 671123b952a3SSantwona Behera hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 671223b952a3SSantwona Behera /* 671323b952a3SSantwona Behera * ROCK platform has assigned a lower 671423b952a3SSantwona Behera * addr to port 1. (port 0 = 0x9 and 671523b952a3SSantwona Behera * port 1 = 0x8). 671623b952a3SSantwona Behera */ 671723b952a3SSantwona Behera hw_p->xcvr_addr[1] = port_fd_arr[0]; 671823b952a3SSantwona Behera hw_p->xcvr_addr[0] = port_fd_arr[1]; 671923b952a3SSantwona Behera 672023b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 672123b952a3SSantwona Behera "Rock with 2 10G, 2 1GC")); 672223b952a3SSantwona Behera break; 672323b952a3SSantwona Behera 672423b952a3SSantwona Behera case P_NEPTUNE_NONE: 672523b952a3SSantwona Behera default: 672623b952a3SSantwona Behera hw_p->platform_type = 672723b952a3SSantwona Behera P_NEPTUNE_GENERIC; 672823b952a3SSantwona Behera hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF; 672959a835ddSjoycey 673023b952a3SSantwona Behera hw_p->xcvr_addr[0] = port_fd_arr[0]; 673123b952a3SSantwona Behera hw_p->xcvr_addr[1] = port_fd_arr[1]; 673223b952a3SSantwona Behera 673323b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 673423b952a3SSantwona Behera "ARTM card with 2 10G, 2 1GF")); 673523b952a3SSantwona Behera break; 673623b952a3SSantwona Behera } 673759a835ddSjoycey 673859a835ddSjoycey hw_p->xcvr_addr[2] = phy_fd_arr[0]; 673959a835ddSjoycey hw_p->xcvr_addr[3] = phy_fd_arr[1]; 674059a835ddSjoycey 674159a835ddSjoycey } else { 674259a835ddSjoycey NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 674359a835ddSjoycey "Unsupported neptune type 1")); 674459a835ddSjoycey goto error_exit; 674559a835ddSjoycey } 674659a835ddSjoycey break; 674759a835ddSjoycey 674859ac0c16Sdavemq case 1: 674959ac0c16Sdavemq /* TODO - 2 10G, 1 1G */ 675059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 675159ac0c16Sdavemq "Unsupported neptune type 2 10G, 1 1G")); 675259ac0c16Sdavemq goto error_exit; 675359ac0c16Sdavemq case 0: 675400161856Syc /* 675500161856Syc * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI 675600161856Syc * cards, etc. 675700161856Syc */ 675830505775Ssbehera if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 675930505775Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 676030505775Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 676152cdd236Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) || 676252cdd236Ssbehera ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) && 676352cdd236Ssbehera (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) || 676452cdd236Ssbehera ((port_pma_pmd_dev_id[0] == 676552cdd236Ssbehera MARVELL_88X201X_PHY_ID) && 676652cdd236Ssbehera (port_pma_pmd_dev_id[1] == 676752cdd236Ssbehera MARVELL_88X201X_PHY_ID))) { 67682e59129aSraghus 67692e59129aSraghus /* 67702e59129aSraghus * Check the first phy port address against 67712e59129aSraghus * the known phy start addresses to determine 67722e59129aSraghus * the platform type. 67732e59129aSraghus */ 67742d17280bSsbehera 67752d17280bSsbehera switch (port_fd_arr[0]) { 677600161856Syc case NEPTUNE_CLAUSE45_PORT_ADDR_BASE: 677752cdd236Ssbehera /* 677852cdd236Ssbehera * The Marvell case also falls into 677952cdd236Ssbehera * this case as 678052cdd236Ssbehera * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE 678100161856Syc * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE. 678252cdd236Ssbehera * This is OK for the 2 10G case. 678352cdd236Ssbehera */ 67842e59129aSraghus hw_p->niu_type = NEPTUNE_2_10GF; 67852e59129aSraghus hw_p->platform_type = 67862e59129aSraghus P_NEPTUNE_ATLAS_2PORT; 67872d17280bSsbehera break; 678800161856Syc case GOA_CLAUSE45_PORT_ADDR_BASE: 67892d17280bSsbehera if (hw_p->platform_type != 67902d17280bSsbehera P_NEPTUNE_NIU) { 67912d17280bSsbehera hw_p->platform_type = 67922d17280bSsbehera P_NEPTUNE_GENERIC; 67932d17280bSsbehera hw_p->niu_type = 67942d17280bSsbehera NEPTUNE_2_10GF; 67952d17280bSsbehera } 67962d17280bSsbehera break; 67972d17280bSsbehera default: 67982d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 67992e59129aSraghus "Unsupported neptune type 2 - 1")); 68002e59129aSraghus goto error_exit; 68012e59129aSraghus } 68022d17280bSsbehera 68032d17280bSsbehera for (i = 0; i < 2; i++) { 68042d17280bSsbehera hw_p->xcvr_addr[i] = port_fd_arr[i]; 68052d17280bSsbehera } 680600161856Syc 680700161856Syc /* Both XAUI slots have copper XAUI cards */ 680800161856Syc } else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 680900161856Syc == TN1010_DEV_ID) && 681000161856Syc ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 681100161856Syc == TN1010_DEV_ID)) || 681200161856Syc (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 681300161856Syc == TN1010_DEV_ID) && 681400161856Syc ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 681500161856Syc == TN1010_DEV_ID))) { 681600161856Syc hw_p->niu_type = NEPTUNE_2_TN1010; 681700161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 681800161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 681900161856Syc 682000161856Syc /* Slot0 has fiber XAUI, slot1 has copper XAUI */ 682100161856Syc } else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 682200161856Syc (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 682300161856Syc == TN1010_DEV_ID) || 682400161856Syc (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 682500161856Syc (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) == 682600161856Syc TN1010_DEV_ID)) { 682700161856Syc hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010; 682800161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 682900161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 683000161856Syc 683100161856Syc /* Slot0 has copper XAUI, slot1 has fiber XAUI */ 683200161856Syc } else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY && 683300161856Syc (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 683400161856Syc == TN1010_DEV_ID) || 683500161856Syc (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 683600161856Syc (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 683700161856Syc == TN1010_DEV_ID)) { 683800161856Syc hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF; 683900161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 684000161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 684100161856Syc 684259ac0c16Sdavemq } else { 684359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 684459ac0c16Sdavemq "Unsupported neptune type 2")); 684559ac0c16Sdavemq goto error_exit; 684659ac0c16Sdavemq } 684759ac0c16Sdavemq break; 684800161856Syc 684959ac0c16Sdavemq case 4: 685000161856Syc if (nxge_get_num_of_xaui( 685100161856Syc port_pma_pmd_dev_id, port_pcs_dev_id, 685200161856Syc port_phy_id, &num_xaui) == NXGE_ERROR) { 685300161856Syc goto error_exit; 685400161856Syc } 685500161856Syc if (num_xaui != 2) 685600161856Syc goto error_exit; 685759ac0c16Sdavemq 685800161856Syc /* 685900161856Syc * Maramba with 2 XAUIs (either fiber or copper) 686000161856Syc * 686100161856Syc * Check the first phy port address against 686200161856Syc * the known phy start addresses to determine 686300161856Syc * the platform type. 686400161856Syc */ 686500161856Syc switch (phy_fd_arr[0]) { 686600161856Syc case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 686700161856Syc hw_p->platform_type = 686800161856Syc P_NEPTUNE_MARAMBA_P0; 686900161856Syc break; 687000161856Syc case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 687100161856Syc hw_p->platform_type = 687200161856Syc P_NEPTUNE_MARAMBA_P1; 687300161856Syc break; 687400161856Syc default: 687500161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 687600161856Syc "Unknown port %d...Cannot " 687700161856Syc "determine platform type", i)); 687800161856Syc goto error_exit; 687900161856Syc } 68802d17280bSsbehera 688100161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 688200161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 688300161856Syc hw_p->xcvr_addr[2] = phy_fd_arr[2]; 688400161856Syc hw_p->xcvr_addr[3] = phy_fd_arr[3]; 688500161856Syc 688600161856Syc /* slot0 has fiber XAUI, slot1 has Cu XAUI */ 688700161856Syc if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 688800161856Syc (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 688900161856Syc == TN1010_DEV_ID) { 689000161856Syc hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC; 689100161856Syc 689200161856Syc /* slot0 has Cu XAUI, slot1 has fiber XAUI */ 689300161856Syc } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 689400161856Syc == TN1010_DEV_ID) && 689500161856Syc port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 689600161856Syc hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC; 689700161856Syc 689800161856Syc /* Both slots have fiber XAUI */ 689900161856Syc } else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 690000161856Syc port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 69012e59129aSraghus hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 69022e59129aSraghus 690300161856Syc /* Both slots have copper XAUI */ 690400161856Syc } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 690500161856Syc == TN1010_DEV_ID) && 690600161856Syc (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 690700161856Syc == TN1010_DEV_ID) { 690800161856Syc hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC; 69092d17280bSsbehera 691059ac0c16Sdavemq } else { 691159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 691259ac0c16Sdavemq "Unsupported neptune type 3")); 691359ac0c16Sdavemq goto error_exit; 691459ac0c16Sdavemq } 691559ac0c16Sdavemq break; 691659ac0c16Sdavemq default: 691759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 691859ac0c16Sdavemq "Unsupported neptune type 5")); 691959ac0c16Sdavemq goto error_exit; 692059ac0c16Sdavemq } 692130505775Ssbehera break; 692200161856Syc case 1: /* Only one clause45 port */ 692300161856Syc switch (total_phy_fd) { /* Number of clause22 ports */ 692459ac0c16Sdavemq case 3: 69252e59129aSraghus /* 69262e59129aSraghus * TODO 3 1G, 1 10G mode. 69272e59129aSraghus * Differentiate between 1_1G_1_10G_2_1G and 69282e59129aSraghus * 1_10G_3_1G 69292e59129aSraghus */ 69302e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 69312e59129aSraghus "Unsupported neptune type 7")); 69322e59129aSraghus goto error_exit; 693359ac0c16Sdavemq case 2: 693459ac0c16Sdavemq /* 693559ac0c16Sdavemq * TODO 2 1G, 1 10G mode. 693659ac0c16Sdavemq * Differentiate between 1_1G_1_10G_1_1G and 693759ac0c16Sdavemq * 1_10G_2_1G 693859ac0c16Sdavemq */ 693959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 694059ac0c16Sdavemq "Unsupported neptune type 8")); 694159ac0c16Sdavemq goto error_exit; 694259ac0c16Sdavemq case 1: 694359ac0c16Sdavemq /* 694459ac0c16Sdavemq * TODO 1 1G, 1 10G mode. 694559ac0c16Sdavemq * Differentiate between 1_1G_1_10G and 694659ac0c16Sdavemq * 1_10G_1_1G 694759ac0c16Sdavemq */ 694859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 694959ac0c16Sdavemq "Unsupported neptune type 9")); 695059ac0c16Sdavemq goto error_exit; 695100161856Syc case 0: /* N2 with 1 XAUI (fiber or copper) */ 695200161856Syc /* Fiber XAUI */ 69532d17280bSsbehera if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 69542d17280bSsbehera port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) { 69552d17280bSsbehera 69562d17280bSsbehera /* 69572d17280bSsbehera * Check the first phy port address against 69582d17280bSsbehera * the known phy start addresses to determine 69592d17280bSsbehera * the platform type. 69602d17280bSsbehera */ 69612d17280bSsbehera 69622d17280bSsbehera switch (port_fd_arr[0]) { 696300161856Syc case N2_CLAUSE45_PORT_ADDR_BASE: 696400161856Syc case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 696500161856Syc case ALT_GOA_CLAUSE45_PORT1_ADDR: 696600161856Syc /* 696700161856Syc * If hw_p->platform_type == 696800161856Syc * P_NEPTUNE_NIU, then portmode 696900161856Syc * is already known, so there is 697000161856Syc * no need to figure out hw_p-> 697100161856Syc * platform_type because 697200161856Syc * platform_type is only for 697300161856Syc * figuring out portmode. 697400161856Syc */ 69752d17280bSsbehera if (hw_p->platform_type != 69762d17280bSsbehera P_NEPTUNE_NIU) { 69772d17280bSsbehera hw_p->platform_type = 69782d17280bSsbehera P_NEPTUNE_GENERIC; 69792d17280bSsbehera hw_p->niu_type = 69802d17280bSsbehera NEPTUNE_2_10GF; 69812d17280bSsbehera } 69822d17280bSsbehera break; 69832d17280bSsbehera default: 69842d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 69852d17280bSsbehera "Unsupported neptune type 10")); 69862d17280bSsbehera goto error_exit; 69872d17280bSsbehera } 6988321febdeSsbehera /* 6989321febdeSsbehera * For GOA, which is a hot swappable PHY, the 6990321febdeSsbehera * phy address to function number mapping 6991321febdeSsbehera * should be preserved, i.e., addr 16 is 6992321febdeSsbehera * assigned to function 0 and 20 to function 1 6993321febdeSsbehera * But for Huron XAUI, the assignment should 6994321febdeSsbehera * be by function number, i.e., whichever 6995321febdeSsbehera * function number attaches should be 6996321febdeSsbehera * assigned the available PHY (this is required 6997321febdeSsbehera * primarily to support pre-production Huron 6998321febdeSsbehera * boards where function 0 is mapped to addr 17 6999321febdeSsbehera */ 7000321febdeSsbehera if (port_fd_arr[0] == 700100161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR) { 7002321febdeSsbehera hw_p->xcvr_addr[1] = port_fd_arr[0]; 7003321febdeSsbehera } else { 7004321febdeSsbehera hw_p->xcvr_addr[nxgep->function_num] = 7005321febdeSsbehera port_fd_arr[0]; 7006321febdeSsbehera } 700700161856Syc 700800161856Syc /* A 10G copper XAUI in either slot0 or slot1 */ 700900161856Syc } else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 701000161856Syc == TN1010_DEV_ID || 701100161856Syc (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 701200161856Syc == TN1010_DEV_ID) { 701300161856Syc switch (port_fd_arr[0]) { 701400161856Syc /* The XAUI is in slot0 */ 701500161856Syc case N2_CLAUSE45_PORT_ADDR_BASE: 701600161856Syc hw_p->niu_type = NEPTUNE_1_TN1010; 701700161856Syc break; 701800161856Syc 701900161856Syc /* The XAUI is in slot1 */ 702000161856Syc case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 702100161856Syc hw_p->niu_type 702200161856Syc = NEPTUNE_1_NONE_1_TN1010; 702300161856Syc break; 702400161856Syc default: 702500161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 702600161856Syc "Unsupported XAUI port address")); 702700161856Syc goto error_exit; 702800161856Syc } 702900161856Syc hw_p->xcvr_addr[nxgep->function_num] 703000161856Syc = port_fd_arr[0]; 703100161856Syc 70322d17280bSsbehera } else { 70332d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 703400161856Syc "Unsupported PHY type")); 70352d17280bSsbehera goto error_exit; 70362d17280bSsbehera } 70372d17280bSsbehera break; 703800161856Syc case 4: /* Maramba always have 4 clause 45 ports */ 703959ac0c16Sdavemq 704000161856Syc /* Maramba with 1 XAUI */ 704152ccf843Smisaki if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) && 704252ccf843Smisaki (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) && 704300161856Syc ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 704452ccf843Smisaki != TN1010_DEV_ID) && 704500161856Syc ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 704652ccf843Smisaki != TN1010_DEV_ID)) { 704752ccf843Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, 704852ccf843Smisaki "Unsupported neptune type 12")); 704952ccf843Smisaki goto error_exit; 705052ccf843Smisaki } 70512e59129aSraghus 705252ccf843Smisaki /* 705352ccf843Smisaki * Check the first phy port address against 705452ccf843Smisaki * the known phy start addresses to determine 705552ccf843Smisaki * the platform type. 705652ccf843Smisaki */ 705752ccf843Smisaki switch (phy_fd_arr[0]) { 705852ccf843Smisaki case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 705952ccf843Smisaki hw_p->platform_type = 706052ccf843Smisaki P_NEPTUNE_MARAMBA_P0; 706152ccf843Smisaki break; 706252ccf843Smisaki case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 706352ccf843Smisaki hw_p->platform_type = 706452ccf843Smisaki P_NEPTUNE_MARAMBA_P1; 706552ccf843Smisaki break; 706652ccf843Smisaki default: 706752ccf843Smisaki NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 706852ccf843Smisaki "Unknown port %d...Cannot " 706952ccf843Smisaki "determine platform type 10 - 2", 707052ccf843Smisaki i)); 707152ccf843Smisaki goto error_exit; 707252ccf843Smisaki } 707352ccf843Smisaki 707452ccf843Smisaki /* 707552ccf843Smisaki * Check the clause45 address to determine 707652ccf843Smisaki * if XAUI is in port 0 or port 1. 707752ccf843Smisaki */ 707852ccf843Smisaki switch (port_fd_arr[0]) { 707952ccf843Smisaki case MARAMBA_CLAUSE45_PORT_ADDR_BASE: 708052ccf843Smisaki if (port_pcs_dev_id[0] 708152ccf843Smisaki == PHY_BCM8704_FAMILY || 708252ccf843Smisaki port_pma_pmd_dev_id[0] 708352ccf843Smisaki == PHY_BCM8704_FAMILY) { 708452ccf843Smisaki hw_p->niu_type 708552ccf843Smisaki = NEPTUNE_1_10GF_3_1GC; 708652ccf843Smisaki } else { 708752ccf843Smisaki hw_p->niu_type 708852ccf843Smisaki = NEPTUNE_1_TN1010_3_1GC; 708959ac0c16Sdavemq } 709052ccf843Smisaki hw_p->xcvr_addr[0] = port_fd_arr[0]; 709152ccf843Smisaki for (i = 1; i < NXGE_MAX_PORTS; i++) { 709252ccf843Smisaki hw_p->xcvr_addr[i] = 709352ccf843Smisaki phy_fd_arr[i]; 709452ccf843Smisaki } 709552ccf843Smisaki break; 709652ccf843Smisaki case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1): 709752ccf843Smisaki if (port_pcs_dev_id[0] 709852ccf843Smisaki == PHY_BCM8704_FAMILY || 709952ccf843Smisaki port_pma_pmd_dev_id[0] 710052ccf843Smisaki == PHY_BCM8704_FAMILY) { 710152ccf843Smisaki hw_p->niu_type = 710252ccf843Smisaki NEPTUNE_1_1GC_1_10GF_2_1GC; 710352ccf843Smisaki } else { 710452ccf843Smisaki hw_p->niu_type = 710552ccf843Smisaki NEPTUNE_1_1GC_1_TN1010_2_1GC; 710652ccf843Smisaki } 710752ccf843Smisaki hw_p->xcvr_addr[0] = phy_fd_arr[0]; 710852ccf843Smisaki hw_p->xcvr_addr[1] = port_fd_arr[0]; 710952ccf843Smisaki hw_p->xcvr_addr[2] = phy_fd_arr[2]; 711052ccf843Smisaki hw_p->xcvr_addr[3] = phy_fd_arr[3]; 711152ccf843Smisaki break; 711252ccf843Smisaki default: 711359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 711452ccf843Smisaki "Unsupported neptune type 11")); 711559ac0c16Sdavemq goto error_exit; 711659ac0c16Sdavemq } 711752ccf843Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, 711852ccf843Smisaki "Maramba with 1 XAUI (fiber or copper)")); 711959ac0c16Sdavemq break; 712059ac0c16Sdavemq default: 712159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 712259ac0c16Sdavemq "Unsupported neptune type 13")); 712359ac0c16Sdavemq goto error_exit; 712459ac0c16Sdavemq } 712559ac0c16Sdavemq break; 712600161856Syc case 0: /* 4 ports Neptune based NIC */ 712759ac0c16Sdavemq switch (total_phy_fd) { 712859ac0c16Sdavemq case 4: 712930505775Ssbehera if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 713030505775Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 713130505775Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 713230505775Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 713359ac0c16Sdavemq 713459ac0c16Sdavemq /* 713559ac0c16Sdavemq * Check the first phy port address against 713659ac0c16Sdavemq * the known phy start addresses to determine 713759ac0c16Sdavemq * the platform type. 713859ac0c16Sdavemq */ 71392d17280bSsbehera switch (phy_fd_arr[0]) { 714000161856Syc case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 714159ac0c16Sdavemq hw_p->platform_type = 714259ac0c16Sdavemq P_NEPTUNE_MARAMBA_P1; 71432d17280bSsbehera break; 714400161856Syc case NEPTUNE_CLAUSE22_PORT_ADDR_BASE: 71452e59129aSraghus hw_p->platform_type = 71462e59129aSraghus P_NEPTUNE_ATLAS_4PORT; 71472d17280bSsbehera break; 71482d17280bSsbehera default: 71492e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 71502e59129aSraghus "Unknown port %d...Cannot " 71512e59129aSraghus "determine platform type", i)); 71522e59129aSraghus goto error_exit; 715359ac0c16Sdavemq } 71542e59129aSraghus hw_p->niu_type = NEPTUNE_4_1GC; 71552d17280bSsbehera for (i = 0; i < NXGE_MAX_PORTS; i++) { 71562d17280bSsbehera hw_p->xcvr_addr[i] = phy_fd_arr[i]; 71572d17280bSsbehera } 715859ac0c16Sdavemq } else { 715959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 716059ac0c16Sdavemq "Unsupported neptune type 14")); 716159ac0c16Sdavemq goto error_exit; 716259ac0c16Sdavemq } 716359ac0c16Sdavemq break; 716459ac0c16Sdavemq case 3: 716559ac0c16Sdavemq /* TODO 3 1G mode */ 716659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 716759ac0c16Sdavemq "Unsupported neptune type 15")); 716859ac0c16Sdavemq goto error_exit; 716959ac0c16Sdavemq case 2: 717059ac0c16Sdavemq /* TODO 2 1G mode */ 717159a835ddSjoycey if ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 717259a835ddSjoycey (port_phy_id[1] == PHY_BCM5482_FAMILY)) { 717359a835ddSjoycey hw_p->platform_type = P_NEPTUNE_GENERIC; 717459a835ddSjoycey hw_p->niu_type = NEPTUNE_2_1GRF; 717559a835ddSjoycey hw_p->xcvr_addr[2] = phy_fd_arr[0]; 717659a835ddSjoycey hw_p->xcvr_addr[3] = phy_fd_arr[1]; 717759a835ddSjoycey } else { 717859a835ddSjoycey NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 717959a835ddSjoycey "Unsupported neptune type 16")); 718059a835ddSjoycey goto error_exit; 718159a835ddSjoycey } 718259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 718359a835ddSjoycey "2 RGMII Fiber ports - RTM")); 718459a835ddSjoycey break; 718559a835ddSjoycey 718659ac0c16Sdavemq case 1: 718759ac0c16Sdavemq /* TODO 1 1G mode */ 718859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 718959ac0c16Sdavemq "Unsupported neptune type 17")); 719059ac0c16Sdavemq goto error_exit; 719159ac0c16Sdavemq default: 719259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 719359ac0c16Sdavemq "Unsupported neptune type 18, total phy fd %d", 719459ac0c16Sdavemq total_phy_fd)); 719559ac0c16Sdavemq goto error_exit; 719659ac0c16Sdavemq } 719759ac0c16Sdavemq break; 719859ac0c16Sdavemq default: 719956d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 720059ac0c16Sdavemq "Unsupported neptune type 19")); 720159ac0c16Sdavemq goto error_exit; 720244961713Sgirish } 720344961713Sgirish 720459ac0c16Sdavemq scan_exit: 720544961713Sgirish 720659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 720759ac0c16Sdavemq "niu type [0x%x]\n", hw_p->niu_type)); 720859ac0c16Sdavemq return (status); 720944961713Sgirish 721059ac0c16Sdavemq error_exit: 721159ac0c16Sdavemq return (NXGE_ERROR); 721244961713Sgirish } 721356d930aeSspeer 721456d930aeSspeer boolean_t 721556d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr) 721656d930aeSspeer { 721756d930aeSspeer if ((mac_addr.ether_addr_octet[0] & 0x01) || 721856d930aeSspeer (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 721956d930aeSspeer (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 722056d930aeSspeer return (B_FALSE); 722156d930aeSspeer else 722256d930aeSspeer return (B_TRUE); 722356d930aeSspeer } 722459ac0c16Sdavemq 722559ac0c16Sdavemq static void 722659ac0c16Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 722759ac0c16Sdavemq 722859ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 722959ac0c16Sdavemq uint8_t xcvr_portn; 723059ac0c16Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 723159ac0c16Sdavemq 723259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 723359ac0c16Sdavemq 723459ac0c16Sdavemq if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 723500161856Syc xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE; 723659ac0c16Sdavemq } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 723700161856Syc xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE; 723859ac0c16Sdavemq } 723959ac0c16Sdavemq /* 724059ac0c16Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 724159ac0c16Sdavemq * swapped with ethernet port number. This is 724259ac0c16Sdavemq * designed for better signal integrity in routing. 724359ac0c16Sdavemq */ 724459ac0c16Sdavemq switch (portn) { 724559ac0c16Sdavemq case 0: 724659ac0c16Sdavemq xcvr_portn += 3; 724759ac0c16Sdavemq break; 724859ac0c16Sdavemq case 1: 724959ac0c16Sdavemq xcvr_portn += 2; 725059ac0c16Sdavemq break; 725159ac0c16Sdavemq case 2: 725259ac0c16Sdavemq xcvr_portn += 1; 725359ac0c16Sdavemq break; 725459ac0c16Sdavemq case 3: 725559ac0c16Sdavemq default: 725659ac0c16Sdavemq break; 725759ac0c16Sdavemq } 725859ac0c16Sdavemq 7259321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 726059ac0c16Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 726159ac0c16Sdavemq xcvr_portn, BCM5464R_MISC, 0xb4ee); 726259ac0c16Sdavemq if (rs != NPI_SUCCESS) { 726359ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 726459ac0c16Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 726559ac0c16Sdavemq "returned error 0x[%x]", rs)); 7266321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 726759ac0c16Sdavemq return; 726859ac0c16Sdavemq } 726959ac0c16Sdavemq 727059ac0c16Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 727159ac0c16Sdavemq xcvr_portn, BCM5464R_MISC, 0xb8ee); 727259ac0c16Sdavemq if (rs != NPI_SUCCESS) { 727359ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 727459ac0c16Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 727559ac0c16Sdavemq "returned error 0x[%x]", rs)); 727659ac0c16Sdavemq } 727759ac0c16Sdavemq 7278321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 727959ac0c16Sdavemq } 7280d81011f0Ssbehera 7281d81011f0Ssbehera static nxge_status_t 7282d81011f0Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep) 7283d81011f0Ssbehera { 7284d81011f0Ssbehera p_nxge_stats_t statsp; 7285d81011f0Ssbehera uint8_t xcvr_portn; 7286d81011f0Ssbehera p_mii_regs_t mii_regs; 7287d81011f0Ssbehera mii_mode_control_stat_t mode; 7288d81011f0Ssbehera int status = NXGE_OK; 7289d81011f0Ssbehera 7290d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 7291d81011f0Ssbehera 7292d81011f0Ssbehera statsp = nxgep->statsp; 7293d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 7294d81011f0Ssbehera mii_regs = NULL; 7295d81011f0Ssbehera mode.value = 0; 72966b438925Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 7297d81011f0Ssbehera #if defined(__i386) 7298d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 7299d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 7300d81011f0Ssbehera mode.value)) != NXGE_OK) { 7301d81011f0Ssbehera goto fail; 7302d81011f0Ssbehera #else 7303d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 7304d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 7305d81011f0Ssbehera mode.value)) != NXGE_OK) { 7306d81011f0Ssbehera goto fail; 7307d81011f0Ssbehera #endif 7308d81011f0Ssbehera } 7309d81011f0Ssbehera #if defined(__i386) 7310d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 7311d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 7312d81011f0Ssbehera &mode.value)) != NXGE_OK) { 7313d81011f0Ssbehera goto fail; 7314d81011f0Ssbehera } 7315d81011f0Ssbehera #else 7316d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 7317d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 7318d81011f0Ssbehera &mode.value)) != NXGE_OK) { 7319d81011f0Ssbehera goto fail; 7320d81011f0Ssbehera } 7321d81011f0Ssbehera #endif 7322d81011f0Ssbehera 7323d81011f0Ssbehera if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 7324d81011f0Ssbehera nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 7325d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7326d81011f0Ssbehera "nxge_mii_get_link_mode: fiber mode")); 7327d81011f0Ssbehera } 7328d81011f0Ssbehera 7329d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7330d81011f0Ssbehera "nxge_mii_get_link_mode: " 7331d81011f0Ssbehera "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 73326b438925Ssbehera NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 7333d81011f0Ssbehera mode.value, nxgep->mac.portmode)); 7334d81011f0Ssbehera 7335d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7336d81011f0Ssbehera "<== nxge_mii_get_link_mode")); 7337d81011f0Ssbehera return (status); 7338d81011f0Ssbehera fail: 7339d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7340d81011f0Ssbehera "<== nxge_mii_get_link_mode (failed)")); 7341d81011f0Ssbehera return (NXGE_ERROR); 7342d81011f0Ssbehera } 7343d81011f0Ssbehera 73441bd6825cSml nxge_status_t 73451bd6825cSml nxge_mac_set_framesize(p_nxge_t nxgep) 73461bd6825cSml { 73471bd6825cSml npi_attr_t ap; 73481bd6825cSml uint8_t portn; 73491bd6825cSml npi_handle_t handle; 73501bd6825cSml npi_status_t rs = NPI_SUCCESS; 73511bd6825cSml 73521bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize")); 73531bd6825cSml 73541bd6825cSml portn = NXGE_GET_PORT_NUM(nxgep->function_num); 73551bd6825cSml handle = nxgep->npi_handle; 73561bd6825cSml 73571bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 73581bd6825cSml "==> nxge_mac_sec_framesize: port<%d> " 73591bd6825cSml "min framesize %d max framesize %d ", 73601bd6825cSml portn, 73611bd6825cSml nxgep->mac.minframesize, 73621bd6825cSml nxgep->mac.maxframesize)); 73631bd6825cSml 73641bd6825cSml SET_MAC_ATTR2(handle, ap, portn, 73651bd6825cSml MAC_PORT_FRAME_SIZE, 73661bd6825cSml nxgep->mac.minframesize, 73671bd6825cSml nxgep->mac.maxframesize, 73681bd6825cSml rs); 73691bd6825cSml if (rs != NPI_SUCCESS) { 73701bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 73711bd6825cSml "<== nxge_mac_set_framesize: failed to configure " 73721bd6825cSml "max/min frame size port %d", portn)); 73731bd6825cSml 73741bd6825cSml return (NXGE_ERROR | rs); 73751bd6825cSml } 73761bd6825cSml 73771bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 73781bd6825cSml "<== nxge_mac_set_framesize: port<%d>", portn)); 73791bd6825cSml 73801bd6825cSml return (NXGE_OK); 73811bd6825cSml } 73821bd6825cSml 738300161856Syc static nxge_status_t 738400161856Syc nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id, 738500161856Syc uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui) 738600161856Syc { 738700161856Syc uint8_t i; 738800161856Syc 738900161856Syc for (i = 0; i < 4; i++) { 739000161856Syc if (port_phy_id[i] != PHY_BCM5464R_FAMILY) 739100161856Syc return (NXGE_ERROR); 739200161856Syc } 739300161856Syc 739400161856Syc *num_xaui = 0; 739500161856Syc if ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 739600161856Syc port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 739700161856Syc (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 739800161856Syc == TN1010_DEV_ID) && 739900161856Syc ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 740000161856Syc == TN1010_DEV_ID))) { 740100161856Syc (*num_xaui) ++; 740200161856Syc } 740300161856Syc if ((port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 740400161856Syc port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) || 740500161856Syc (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 740600161856Syc == TN1010_DEV_ID) && 740700161856Syc ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 740800161856Syc == TN1010_DEV_ID))) { 740900161856Syc (*num_xaui) ++; 741000161856Syc } 741100161856Syc return (NXGE_OK); 741200161856Syc } 741300161856Syc 741400161856Syc /* 741500161856Syc * Instruction from Teranetics: Once you detect link is up, go 741600161856Syc * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You 741700161856Syc * may want to qualify it by first checking Register 30.1.7:6 and 741800161856Syc * making sure it reads "01" (Auto-Neg Complete). 741900161856Syc * 742000161856Syc * If this function is called when the link is down or before auto- 742100161856Syc * negotiation has completed, then the speed of the PHY is not certain. 742200161856Syc * In such cases, this function returns 1G as the default speed with 742300161856Syc * NXGE_OK status instead of NXGE_ERROR. It is OK to initialize the 742400161856Syc * driver based on a default speed because this function will be called 742500161856Syc * again when the link comes up. Returning NXGE_ERROR, which may 742600161856Syc * cause brutal chain reaction in caller functions, is not necessary. 742700161856Syc */ 742800161856Syc static nxge_status_t 742900161856Syc nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed) 743000161856Syc { 743100161856Syc uint8_t phy_port_addr, autoneg_stat, link_up; 743200161856Syc nxge_status_t status = NXGE_OK; 743300161856Syc uint16_t val; 743400161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 743500161856Syc 743600161856Syc /* Set default speed to 10G */ 743700161856Syc *speed = TN1010_SPEED_10G; 743800161856Syc 743900161856Syc /* Set Clause 45 */ 744000161856Syc npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 744100161856Syc 744200161856Syc phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 744300161856Syc 744400161856Syc /* Check Device 1 Register 0xA bit0 for link up status */ 744500161856Syc status = nxge_mdio_read(nxgep, phy_port_addr, 744600161856Syc TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val); 744700161856Syc if (status != NXGE_OK) 744800161856Syc goto fail; 744900161856Syc 745000161856Syc link_up = ((val & TN1010_AN_LINK_STAT_BIT) 745100161856Syc ? B_TRUE : B_FALSE); 745200161856Syc if (link_up == B_FALSE) { 745300161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 745400161856Syc "nxge_get_tn1010_speed: link is down")); 745500161856Syc goto nxge_get_tn1010_speed_exit; 745600161856Syc } 745700161856Syc 745800161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 745900161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG, 746000161856Syc &val)) != NXGE_OK) { 746100161856Syc goto fail; 746200161856Syc } 746300161856Syc autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >> 746400161856Syc TN1010_VENDOR_MMD1_AN_STAT_SHIFT; 746500161856Syc 746600161856Syc /* 746700161856Syc * Return NXGE_OK even when we can not get a settled speed. In 746800161856Syc * such case, the speed reported should not be trusted but that 746900161856Syc * is OK, we will call this function periodically and will get 747000161856Syc * the correct speed after the link is up. 747100161856Syc */ 747200161856Syc switch (autoneg_stat) { 747300161856Syc case TN1010_AN_IN_PROG: 747400161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 747500161856Syc "nxge_get_tn1010_speed: Auto-negotiation in progress")); 747600161856Syc break; 747700161856Syc case TN1010_AN_COMPLETE: 747800161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 747900161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 748000161856Syc TN1010_VENDOR_MMD1_STATUS_REG, 748100161856Syc &val)) != NXGE_OK) { 748200161856Syc goto fail; 748300161856Syc } 748400161856Syc *speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >> 748500161856Syc TN1010_VENDOR_MMD1_AN_SPEED_SHIFT; 748600161856Syc break; 748700161856Syc case TN1010_AN_RSVD: 748800161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 748900161856Syc "nxge_get_tn1010_speed: Autoneg status undefined")); 749000161856Syc break; 749100161856Syc case TN1010_AN_FAILED: 749200161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 749300161856Syc "nxge_get_tn1010_speed: Auto-negotiation failed")); 749400161856Syc break; 749500161856Syc default: 749600161856Syc break; 749700161856Syc } 749800161856Syc nxge_get_tn1010_speed_exit: 749900161856Syc return (NXGE_OK); 750000161856Syc fail: 750100161856Syc return (status); 750200161856Syc } 750300161856Syc 750400161856Syc 750500161856Syc /* 750600161856Syc * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function 750700161856Syc * figures out the speed of the PHY determined by the autonegotiation 750800161856Syc * process and sets the following 3 parameters, 750900161856Syc * nxgep->mac.portmode 751000161856Syc * nxgep->statsp->mac_stats.link_speed 751100161856Syc * nxgep->statsp->mac_stats.xcvr_inuse 751200161856Syc */ 751300161856Syc static nxge_status_t 751400161856Syc nxge_set_tn1010_param(p_nxge_t nxgep) 751500161856Syc { 751600161856Syc uint16_t speed; 751700161856Syc 751800161856Syc if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 751900161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 752000161856Syc "nxge_set_tn1010_param: " 752100161856Syc "Failed to get TN1010 speed")); 752200161856Syc return (NXGE_ERROR); 752300161856Syc } 752400161856Syc if (speed == TN1010_SPEED_1G) { 752500161856Syc nxgep->mac.portmode = PORT_1G_TN1010; 752600161856Syc nxgep->statsp->mac_stats.link_speed = 1000; 752700161856Syc nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 752800161856Syc } else { 752900161856Syc nxgep->mac.portmode = PORT_10G_TN1010; 753000161856Syc nxgep->statsp->mac_stats.link_speed = 10000; 753100161856Syc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 753200161856Syc } 753300161856Syc return (NXGE_OK); 753400161856Syc } 753500161856Syc 7536d81011f0Ssbehera #ifdef NXGE_DEBUG 7537d81011f0Ssbehera static void 7538d81011f0Ssbehera nxge_mii_dump(p_nxge_t nxgep) 7539d81011f0Ssbehera { 7540d81011f0Ssbehera p_nxge_stats_t statsp; 7541d81011f0Ssbehera uint8_t xcvr_portn; 7542d81011f0Ssbehera p_mii_regs_t mii_regs; 7543d81011f0Ssbehera mii_bmcr_t bmcr; 7544d81011f0Ssbehera mii_bmsr_t bmsr; 7545d81011f0Ssbehera mii_idr1_t idr1; 7546d81011f0Ssbehera mii_idr2_t idr2; 7547d81011f0Ssbehera mii_mode_control_stat_t mode; 7548678453a8Sspeer p_nxge_param_t param_arr; 7549d81011f0Ssbehera 7550d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 7551d81011f0Ssbehera 7552d81011f0Ssbehera statsp = nxgep->statsp; 7553d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 7554d81011f0Ssbehera 7555d81011f0Ssbehera mii_regs = NULL; 7556d81011f0Ssbehera 7557d81011f0Ssbehera #if defined(__i386) 7558d81011f0Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 7559d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value); 7560d81011f0Ssbehera #else 7561d81011f0Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 7562d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 7563d81011f0Ssbehera #endif 7564d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7565d81011f0Ssbehera "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 7566d81011f0Ssbehera xcvr_portn, bmcr.value)); 7567d81011f0Ssbehera 7568d81011f0Ssbehera #if defined(__i386) 7569d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7570d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7571d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value); 7572d81011f0Ssbehera #else 7573d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7574d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7575d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 7576d81011f0Ssbehera #endif 7577d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7578d81011f0Ssbehera "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 7579d81011f0Ssbehera xcvr_portn, bmsr.value)); 7580d81011f0Ssbehera 7581d81011f0Ssbehera #if defined(__i386) 7582d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7583d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7584d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value); 7585d81011f0Ssbehera #else 7586d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7587d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7588d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 7589d81011f0Ssbehera #endif 7590d81011f0Ssbehera 7591d81011f0Ssbehera 7592d81011f0Ssbehera #if defined(__i386) 7593d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7594d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7595d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value); 7596d81011f0Ssbehera #else 7597d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7598d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7599d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 7600d81011f0Ssbehera #endif 7601d81011f0Ssbehera 7602d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7603d81011f0Ssbehera "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 7604d81011f0Ssbehera xcvr_portn, idr1.value)); 7605d81011f0Ssbehera 7606d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7607d81011f0Ssbehera "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 7608d81011f0Ssbehera xcvr_portn, idr2.value)); 7609d81011f0Ssbehera 7610d81011f0Ssbehera mode.value = 0; 76116b438925Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 7612d81011f0Ssbehera 7613d81011f0Ssbehera #if defined(__i386) 7614d81011f0Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 7615d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value); 7616d81011f0Ssbehera 7617d81011f0Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 7618d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value); 7619d81011f0Ssbehera #else 7620d81011f0Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 7621d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 7622d81011f0Ssbehera 7623d81011f0Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 7624d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 7625d81011f0Ssbehera #endif 7626d81011f0Ssbehera 7627d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7628d81011f0Ssbehera "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 7629d81011f0Ssbehera xcvr_portn, mode.value)); 7630d81011f0Ssbehera } 7631d81011f0Ssbehera #endif 7632