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 /* 22*89282175SSantwona Behera * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 2344961713Sgirish */ 2444961713Sgirish 2544961713Sgirish #include <sys/nxge/nxge_impl.h> 2644961713Sgirish #include <sys/nxge/nxge_mac.h> 27678453a8Sspeer #include <sys/nxge/nxge_hio.h> 2844961713Sgirish 2998ecde52Stm #define LINK_MONITOR_PERIOD (1000 * 1000) 3098ecde52Stm #define LM_WAIT_MULTIPLIER 8 3198ecde52Stm 32321febdeSsbehera #define SERDES_RDY_WT_INTERVAL 50 33321febdeSsbehera #define MAX_SERDES_RDY_RETRIES 10 34321febdeSsbehera 3500161856Syc #define TN1010_SPEED_1G 1 3600161856Syc #define TN1010_SPEED_10G 0 3700161856Syc #define TN1010_AN_IN_PROG 0 /* Auto negotiation in progress */ 3800161856Syc #define TN1010_AN_COMPLETE 1 3900161856Syc #define TN1010_AN_RSVD 2 4000161856Syc #define TN1010_AN_FAILED 3 4100161856Syc 4244961713Sgirish extern uint32_t nxge_no_link_notify; 4359ac0c16Sdavemq extern boolean_t nxge_no_msg; 4444961713Sgirish extern uint32_t nxge_lb_dbg; 454202ea4bSsbehera extern uint32_t nxge_jumbo_mtu; 4644961713Sgirish 4798ecde52Stm typedef enum { 4898ecde52Stm CHECK_LINK_RESCHEDULE, 4998ecde52Stm CHECK_LINK_STOP 5098ecde52Stm } check_link_state_t; 5198ecde52Stm 5298ecde52Stm static check_link_state_t nxge_check_link_stop(nxge_t *); 5398ecde52Stm 5444961713Sgirish /* 5544961713Sgirish * Ethernet broadcast address definition. 5644961713Sgirish */ 5744961713Sgirish static ether_addr_st etherbroadcastaddr = 5844961713Sgirish {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 5959ac0c16Sdavemq /* 6059ac0c16Sdavemq * Ethernet zero address definition. 6159ac0c16Sdavemq */ 6256d930aeSspeer static ether_addr_st etherzeroaddr = 6356d930aeSspeer {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 6459ac0c16Sdavemq /* 6559ac0c16Sdavemq * Supported chip types 6659ac0c16Sdavemq */ 6752cdd236Ssbehera static uint32_t nxge_supported_cl45_ids[] = { 6852cdd236Ssbehera BCM8704_DEV_ID, 6952cdd236Ssbehera MARVELL_88X_201X_DEV_ID, 7000161856Syc BCM8706_DEV_ID, 7100161856Syc TN1010_DEV_ID 7252cdd236Ssbehera }; 7352cdd236Ssbehera 74b1000363Sml static uint32_t nxge_supported_cl22_ids[] = { 75b1000363Sml BCM5464R_PHY_ID, 76b1000363Sml BCM5482_PHY_ID 77b1000363Sml }; 7859ac0c16Sdavemq 7959ac0c16Sdavemq #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 8059ac0c16Sdavemq sizeof (uint32_t)) 8159ac0c16Sdavemq #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 8259ac0c16Sdavemq sizeof (uint32_t)) 8359ac0c16Sdavemq /* 8459ac0c16Sdavemq * static functions 8559ac0c16Sdavemq */ 862e59129aSraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int); 872e59129aSraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int); 882e59129aSraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int); 8959ac0c16Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t); 90*89282175SSantwona Behera static boolean_t nxge_hswap_phy_present(p_nxge_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); 934df55fdeSJanie 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); 111*89282175SSantwona Behera static nxge_status_t nxge_check_nlp2020_link(p_nxge_t, boolean_t *); 112*89282175SSantwona Behera static nxge_status_t nxge_nlp2020_xcvr_init(p_nxge_t); 113*89282175SSantwona Behera static int nxge_nlp2020_i2c_read(p_nxge_t, uint8_t, uint16_t, uint16_t, 114*89282175SSantwona Behera uint8_t *); 115*89282175SSantwona Behera static boolean_t nxge_is_nlp2020_phy(p_nxge_t); 116*89282175SSantwona Behera static uint8_t nxge_get_nlp2020_connector_type(p_nxge_t); 117*89282175SSantwona Behera static nxge_status_t nxge_set_nlp2020_param(p_nxge_t); 11800161856Syc static nxge_status_t nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id, 11900161856Syc uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui); 12000161856Syc static nxge_status_t nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed); 12100161856Syc static nxge_status_t nxge_set_tn1010_param(p_nxge_t nxgep); 12200161856Syc static nxge_status_t nxge_tn1010_check(p_nxge_t nxgep, 12300161856Syc nxge_link_state_t *link_up); 12400161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep); 12500161856Syc static nxge_status_t nxge_tn1010_xcvr_init(p_nxge_t nxgep); 12600161856Syc 12700161856Syc nxge_status_t nxge_mac_init(p_nxge_t); 12800161856Syc static nxge_status_t nxge_mii_get_link_mode(p_nxge_t); 12900161856Syc 13000161856Syc #ifdef NXGE_DEBUG 13100161856Syc static void nxge_mii_dump(p_nxge_t); 13200161856Syc static nxge_status_t nxge_tn1010_reset(p_nxge_t nxgep); 13300161856Syc static void nxge_dump_tn1010_status_regs(p_nxge_t nxgep); 13400161856Syc #endif 13559ac0c16Sdavemq 13659ac0c16Sdavemq /* 13759ac0c16Sdavemq * xcvr tables for supported transceivers 13859ac0c16Sdavemq */ 13959ac0c16Sdavemq 14000161856Syc /* 14100161856Syc * nxge_n2_10G_table is for 10G fiber or serdes on N2-NIU systems. 14200161856Syc * The Teranetics TN1010 based copper XAUI card can also be used 14300161856Syc * on N2-NIU systems in 10G mode, but it uses its own table 14400161856Syc * nxge_n2_10G_tn1010_table below. 14500161856Syc */ 1462e59129aSraghus static nxge_xcvr_table_t nxge_n2_10G_table = { 14759ac0c16Sdavemq nxge_n2_serdes_init, 14859ac0c16Sdavemq nxge_10G_xcvr_init, 14959ac0c16Sdavemq nxge_10G_link_intr_stop, 15059ac0c16Sdavemq nxge_10G_link_intr_start, 15159ac0c16Sdavemq nxge_check_10g_link, 1522d17280bSsbehera PCS_XCVR 15359ac0c16Sdavemq }; 15459ac0c16Sdavemq 15500161856Syc /* 15600161856Syc * For the Teranetics TN1010 based copper XAUI card 15700161856Syc */ 15800161856Syc static nxge_xcvr_table_t nxge_n2_10G_tn1010_table = { 15900161856Syc nxge_n2_serdes_init, /* Handle both 1G and 10G */ 16000161856Syc nxge_tn1010_xcvr_init, /* Handle both 1G and 10G */ 16100161856Syc nxge_10G_link_intr_stop, 16200161856Syc nxge_10G_link_intr_start, 16300161856Syc nxge_check_tn1010_link, /* Will figure out speed */ 16400161856Syc XPCS_XCVR 16500161856Syc }; 16600161856Syc 1672e59129aSraghus static nxge_xcvr_table_t nxge_n2_1G_table = { 1682e59129aSraghus nxge_n2_serdes_init, 1692e59129aSraghus nxge_1G_xcvr_init, 1702e59129aSraghus nxge_1G_fiber_link_intr_stop, 1712e59129aSraghus nxge_1G_fiber_link_intr_start, 1722e59129aSraghus nxge_check_mii_link, 1732d17280bSsbehera PCS_XCVR 1742e59129aSraghus }; 1752e59129aSraghus 17600161856Syc static nxge_xcvr_table_t nxge_n2_1G_tn1010_table = { 17700161856Syc nxge_n2_serdes_init, 17800161856Syc nxge_tn1010_xcvr_init, 17900161856Syc nxge_1G_fiber_link_intr_stop, /* TN1010 is a Cu PHY, but it uses */ 18000161856Syc nxge_1G_fiber_link_intr_start, /* PCS for 1G, so call fiber func */ 18100161856Syc nxge_check_tn1010_link, 18200161856Syc PCS_XCVR 18300161856Syc }; 18400161856Syc 18500161856Syc static nxge_xcvr_table_t nxge_10G_tn1010_table = { 18600161856Syc nxge_neptune_10G_serdes_init, 18700161856Syc nxge_tn1010_xcvr_init, 18800161856Syc nxge_10G_link_intr_stop, 18900161856Syc nxge_10G_link_intr_start, 19000161856Syc nxge_check_tn1010_link, 19100161856Syc XPCS_XCVR 19200161856Syc }; 19300161856Syc 19400161856Syc static nxge_xcvr_table_t nxge_1G_tn1010_table = { 19500161856Syc nxge_1G_serdes_init, 19600161856Syc nxge_tn1010_xcvr_init, 19700161856Syc nxge_1G_fiber_link_intr_stop, 19800161856Syc nxge_1G_fiber_link_intr_start, 19900161856Syc nxge_check_tn1010_link, 20000161856Syc PCS_XCVR 20100161856Syc }; 20200161856Syc 20359ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = { 20459ac0c16Sdavemq nxge_neptune_10G_serdes_init, 20559ac0c16Sdavemq nxge_10G_xcvr_init, 20659ac0c16Sdavemq nxge_10G_link_intr_stop, 20759ac0c16Sdavemq nxge_10G_link_intr_start, 20859ac0c16Sdavemq nxge_check_10g_link, 2092d17280bSsbehera PCS_XCVR 21059ac0c16Sdavemq }; 21159ac0c16Sdavemq 21259ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = { 21359ac0c16Sdavemq NULL, 21459ac0c16Sdavemq nxge_1G_xcvr_init, 21559ac0c16Sdavemq nxge_1G_copper_link_intr_stop, 21659ac0c16Sdavemq nxge_1G_copper_link_intr_start, 21759ac0c16Sdavemq nxge_check_mii_link, 2182d17280bSsbehera INT_MII_XCVR 21959ac0c16Sdavemq }; 22059ac0c16Sdavemq 22100161856Syc /* This table is for Neptune portmode == PORT_1G_SERDES cases */ 22259ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = { 22359ac0c16Sdavemq nxge_1G_serdes_init, 22459ac0c16Sdavemq nxge_1G_xcvr_init, 22559ac0c16Sdavemq nxge_1G_fiber_link_intr_stop, 22659ac0c16Sdavemq nxge_1G_fiber_link_intr_start, 22759ac0c16Sdavemq nxge_check_mii_link, 2282d17280bSsbehera PCS_XCVR 22959ac0c16Sdavemq }; 23059ac0c16Sdavemq 23159ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = { 23259ac0c16Sdavemq nxge_neptune_10G_serdes_init, 23359ac0c16Sdavemq NULL, 23459ac0c16Sdavemq NULL, 23559ac0c16Sdavemq NULL, 2362e59129aSraghus NULL, 2372d17280bSsbehera PCS_XCVR 23859ac0c16Sdavemq }; 23944961713Sgirish 24000161856Syc /* 24100161856Syc * NXGE_PORT_TN1010 is defined as, 24200161856Syc * NXGE_PORT_SPD_NONE | (NXGE_PHY_TN1010 << NXGE_PHY_SHIFT) 24300161856Syc * = 0 | 5 << 16 = 0x50000 24400161856Syc * 24500161856Syc * So NEPTUNE_2_TN1010 = 24600161856Syc * (NXGE_PORT_TN1010 | 24700161856Syc * (NXGE_PORT_TN1010 << 4) | 24800161856Syc * (NXGE_PORT_NONE << 8) | 24900161856Syc * (NXGE_PORT_NONE << 12)), 25000161856Syc * = 0x50000 | (0x50000 << 4) 25100161856Syc * = 0x550000 25200161856Syc * 25300161856Syc * This function partitions nxgep->nxge_hw_p->niu_type (which may have 25400161856Syc * value NEPTUNE_2_TN1010) and checks if a port has type = NXGE_PORT_TN1010 25500161856Syc * = 0x50000 25600161856Syc */ 25700161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep) 25800161856Syc { 25900161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 26000161856Syc 26100161856Syc if (((nxgep->nxge_hw_p->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn)) 26200161856Syc & NXGE_PHY_MASK) == NXGE_PORT_TN1010) { 26300161856Syc return (B_TRUE); 26400161856Syc } else { 26500161856Syc return (B_FALSE); 26600161856Syc } 26700161856Syc } 26844961713Sgirish 269d81011f0Ssbehera 27000161856Syc /* 27100161856Syc * Figure out nxgep->mac.portmode from nxge.conf, OBP's device properties, 27200161856Syc * serial EEPROM or VPD if possible. Note that not all systems could get 27300161856Syc * the portmode information by calling this function. For example, the 27400161856Syc * Maramba system figures out the portmode information by calling function 27500161856Syc * nxge_setup_xcvr_table. 27600161856Syc */ 2772e59129aSraghus nxge_status_t 2782e59129aSraghus nxge_get_xcvr_type(p_nxge_t nxgep) 2792e59129aSraghus { 2802e59129aSraghus nxge_status_t status = NXGE_OK; 2812e59129aSraghus char *phy_type; 2822e59129aSraghus char *prop_val; 28300161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 2841c7408c9Stc uint32_t val; 2851c7408c9Stc npi_status_t rs; 2861c7408c9Stc 2871c7408c9Stc /* For Opus NEM, skip xcvr checking if 10G Serdes link is up */ 2881c7408c9Stc if (nxgep->mac.portmode == PORT_10G_SERDES && 2891c7408c9Stc nxgep->statsp->mac_stats.link_up) { 2901c7408c9Stc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2911c7408c9Stc return (status); 2921c7408c9Stc } 2932e59129aSraghus 2942e59129aSraghus nxgep->mac.portmode = 0; 2952d17280bSsbehera nxgep->xcvr_addr = 0; 2962e59129aSraghus 2972d17280bSsbehera /* 2982d17280bSsbehera * First check for hot swappable phy property. 2992d17280bSsbehera */ 3002d17280bSsbehera if (nxgep->hot_swappable_phy == B_TRUE) { 3012d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 3022d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 3032d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable")); 3042d17280bSsbehera } else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 3052d17280bSsbehera DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 3062d17280bSsbehera "hot-swappable-phy") == 1) { 3072d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 3082d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 3092d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable")); 3102d17280bSsbehera } else if (nxgep->niu_type == N2_NIU && 3112d17280bSsbehera ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0, 3122d17280bSsbehera "hot-swappable-phy") == 1) { 3132d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 3142d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 3152d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable")); 3162d17280bSsbehera } 3172d17280bSsbehera 3182d17280bSsbehera /* 3192d17280bSsbehera * MDIO polling support for Monza RTM card, Goa NEM card 3202d17280bSsbehera */ 3212d17280bSsbehera if (nxgep->mac.portmode == PORT_HSP_MODE) { 3222d17280bSsbehera nxgep->hot_swappable_phy = B_TRUE; 323ef523517SMichael Speer if (portn > 1) { 324ef523517SMichael Speer return (NXGE_ERROR); 325ef523517SMichael Speer } 326ef523517SMichael Speer 327*89282175SSantwona Behera if (nxge_hswap_phy_present(nxgep, portn)) 3282d17280bSsbehera goto found_phy; 3292d17280bSsbehera 3302d17280bSsbehera nxgep->phy_absent = B_TRUE; 3311c7408c9Stc 3321c7408c9Stc /* Check Serdes link to detect Opus NEM */ 3331c7408c9Stc rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 3341c7408c9Stc XPCS_REG_STATUS, &val); 3351c7408c9Stc 3361c7408c9Stc if (rs == 0 && val & XPCS_STATUS_LANE_ALIGN) { 3371c7408c9Stc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3381c7408c9Stc nxgep->mac.portmode = PORT_10G_SERDES; 3391c7408c9Stc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3401c7408c9Stc "HSP 10G Serdes FOUND!!")); 3411c7408c9Stc } 3422d17280bSsbehera goto check_phy_done; 3432d17280bSsbehera found_phy: 3442d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3452d17280bSsbehera nxgep->mac.portmode = PORT_10G_FIBER; 3462d17280bSsbehera nxgep->phy_absent = B_FALSE; 3472d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr " 3482d17280bSsbehera "found for hot swappable phy")); 3492d17280bSsbehera check_phy_done: 3502d17280bSsbehera return (status); 3512d17280bSsbehera } 3522d17280bSsbehera 35300161856Syc /* Get phy-type property (May have been set by nxge.conf) */ 3542e59129aSraghus if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 3552e59129aSraghus DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 3562e59129aSraghus "phy-type", &prop_val)) == DDI_PROP_SUCCESS) { 3572e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3582e59129aSraghus "found conf file: phy-type %s", prop_val)); 3592e59129aSraghus if (strcmp("xgsd", prop_val) == 0) { 3602e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3612e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 3622e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3632e59129aSraghus "found: 10G Serdes")); 3642e59129aSraghus } else if (strcmp("gsd", prop_val) == 0) { 3652e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3662e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 3672e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes")); 3682e59129aSraghus } else if (strcmp("mif", prop_val) == 0) { 3692e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 3702e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 3712e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr")); 3722e59129aSraghus } else if (strcmp("pcs", prop_val) == 0) { 3732e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3742e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 3752e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr")); 376321febdeSsbehera } else if (strcmp("xgf", prop_val) == 0) { 37700161856Syc /* 37800161856Syc * Before OBP supports new phy-type property 37900161856Syc * value "xgc", the 10G copper XAUI may carry 38000161856Syc * "xgf" instead of "xgc". If the OBP is 38100161856Syc * upgraded to a newer version which supports 38200161856Syc * "xgc", then the TN1010 related code in this 38300161856Syc * "xgf" case will not be used anymore. 38400161856Syc */ 38500161856Syc if (nxge_is_tn1010_phy(nxgep)) { 38600161856Syc if ((status = nxge_set_tn1010_param(nxgep)) 38700161856Syc != NXGE_OK) { 38800161856Syc return (status); 38900161856Syc } 39000161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 39100161856Syc } else { /* For Fiber XAUI */ 39200161856Syc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 39300161856Syc nxgep->mac.portmode = PORT_10G_FIBER; 39400161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39500161856Syc "10G Fiber Xcvr")); 39600161856Syc } 39700161856Syc } else if (strcmp("xgc", prop_val) == 0) { 39800161856Syc if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK) 39900161856Syc return (status); 40000161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 4012e59129aSraghus } 4022e59129aSraghus 4032e59129aSraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 4042e59129aSraghus "phy-type", prop_val); 4052e59129aSraghus ddi_prop_free(prop_val); 4062e59129aSraghus 4072e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 4082e59129aSraghus "Got phy type [0x%x] from conf file", 4092e59129aSraghus nxgep->mac.portmode)); 4102e59129aSraghus 4112e59129aSraghus return (NXGE_OK); 4122e59129aSraghus } 4132d17280bSsbehera 4142d17280bSsbehera /* Get phy-type property from OBP */ 4152e59129aSraghus if (nxgep->niu_type == N2_NIU) { 4162e59129aSraghus if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 4172e59129aSraghus "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 4182e59129aSraghus if (strcmp("xgf", prop_val) == 0) { 41900161856Syc /* 42000161856Syc * Before OBP supports new phy-type property 42100161856Syc * value "xgc", the 10G copper XAUI may carry 42200161856Syc * "xgf" instead of "xgc". If the OBP is 42300161856Syc * upgraded to a newer version which supports 42400161856Syc * "xgc", then the TN1010 related code in this 42500161856Syc * "xgf" case will not be used anymore. 42600161856Syc */ 42700161856Syc if (nxge_is_tn1010_phy(nxgep)) { 42800161856Syc if ((status = 42900161856Syc nxge_set_tn1010_param(nxgep)) 43000161856Syc != NXGE_OK) { 43100161856Syc return (status); 43200161856Syc } 43300161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43400161856Syc "TN1010 Xcvr")); 435*89282175SSantwona Behera } else if (nxge_is_nlp2020_phy(nxgep)) { 436*89282175SSantwona Behera if ((status = 437*89282175SSantwona Behera nxge_set_nlp2020_param(nxgep)) 438*89282175SSantwona Behera != NXGE_OK) { 439*89282175SSantwona Behera return (status); 440*89282175SSantwona Behera } 441*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 442*89282175SSantwona Behera "NLP2020 Xcvr")); 443*89282175SSantwona Behera } else { /* For Fiber XAUI */ 44400161856Syc nxgep->statsp->mac_stats.xcvr_inuse 44500161856Syc = XPCS_XCVR; 44600161856Syc nxgep->mac.portmode = PORT_10G_FIBER; 44700161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44800161856Syc "10G Fiber Xcvr")); 44900161856Syc } 4502e59129aSraghus } else if (strcmp("mif", prop_val) == 0) { 4512e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = 4522e59129aSraghus INT_MII_XCVR; 4532e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 4542e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4552e59129aSraghus "1G Copper Xcvr")); 4562e59129aSraghus } else if (strcmp("pcs", prop_val) == 0) { 4572e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 4582e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 4592e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4602e59129aSraghus "1G Fiber Xcvr")); 4612e59129aSraghus } else if (strcmp("xgc", prop_val) == 0) { 46200161856Syc status = nxge_set_tn1010_param(nxgep); 46300161856Syc if (status != NXGE_OK) 46400161856Syc return (status); 46500161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 4662e59129aSraghus } else if (strcmp("xgsd", prop_val) == 0) { 4672e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 4682e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 4692e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4702e59129aSraghus "OBP: 10G Serdes")); 4712e59129aSraghus } else if (strcmp("gsd", prop_val) == 0) { 4722e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 4732e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 4742e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4752e59129aSraghus "OBP: 1G Serdes")); 4762e59129aSraghus } else { 4772e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4782e59129aSraghus "Unknown phy-type: %s", prop_val)); 4792e59129aSraghus ddi_prop_free(prop_val); 4802e59129aSraghus return (NXGE_ERROR); 4812e59129aSraghus } 4822e59129aSraghus status = NXGE_OK; 4832e59129aSraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, 4842e59129aSraghus nxgep->dip, "phy-type", prop_val); 4852e59129aSraghus ddi_prop_free(prop_val); 4862e59129aSraghus 4872e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 4882e59129aSraghus "Got phy type [0x%x] from OBP", 4892e59129aSraghus nxgep->mac.portmode)); 4902e59129aSraghus 4912e59129aSraghus return (status); 4922e59129aSraghus } else { 4932e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4942e59129aSraghus "Exiting...phy-type property not found")); 4952e59129aSraghus return (NXGE_ERROR); 4962e59129aSraghus } 4972e59129aSraghus } 4982e59129aSraghus 4992e59129aSraghus 5002e59129aSraghus if (!nxgep->vpd_info.present) { 5012e59129aSraghus return (NXGE_OK); 5022e59129aSraghus } 5032e59129aSraghus 5042e59129aSraghus if (!nxgep->vpd_info.ver_valid) { 5052e59129aSraghus goto read_seeprom; 5062e59129aSraghus } 5072e59129aSraghus 5082e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5092e59129aSraghus "Reading phy type from expansion ROM")); 5102e59129aSraghus /* 5112e59129aSraghus * Try to read the phy type from the vpd data read off the 5122e59129aSraghus * expansion ROM. 5132e59129aSraghus */ 5142e59129aSraghus phy_type = nxgep->vpd_info.phy_type; 5152e59129aSraghus 516d81011f0Ssbehera if (strncmp(phy_type, "mif", 3) == 0) { 5172e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 5182e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 519d81011f0Ssbehera } else if (strncmp(phy_type, "xgf", 3) == 0) { 5202e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 5212e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 522d81011f0Ssbehera } else if (strncmp(phy_type, "pcs", 3) == 0) { 5232e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 5242e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 525d81011f0Ssbehera } else if (strncmp(phy_type, "xgc", 3) == 0) { 52600161856Syc status = nxge_set_tn1010_param(nxgep); 52700161856Syc if (status != NXGE_OK) { 52800161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 52900161856Syc "nxge_get_xcvr_type: Failed to set TN1010 param")); 53000161856Syc goto read_seeprom; 53100161856Syc } 532d81011f0Ssbehera } else if (strncmp(phy_type, "xgsd", 4) == 0) { 533d81011f0Ssbehera nxgep->mac.portmode = PORT_10G_SERDES; 534d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 535d81011f0Ssbehera } else if (strncmp(phy_type, "gsd", 3) == 0) { 536d81011f0Ssbehera nxgep->mac.portmode = PORT_1G_SERDES; 537d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 5382e59129aSraghus } else { 539d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5402e59129aSraghus "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 5412e59129aSraghus phy_type[0], phy_type[1], phy_type[2])); 5422e59129aSraghus goto read_seeprom; 5432e59129aSraghus } 5442e59129aSraghus 5452e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 5462e59129aSraghus "Got phy type [0x%x] from VPD", nxgep->mac.portmode)); 5472e59129aSraghus 5482e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 5492e59129aSraghus return (status); 5502e59129aSraghus 5512e59129aSraghus read_seeprom: 5522e59129aSraghus /* 5532e59129aSraghus * read the phy type from the SEEPROM - NCR registers 5542e59129aSraghus */ 5552e59129aSraghus status = nxge_espc_phy_type_get(nxgep); 5562e59129aSraghus if (status != NXGE_OK) { 5572e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5582e59129aSraghus "Failed to get phy type")); 5592e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 5602e59129aSraghus "[%s] invalid...please update", nxgep->vpd_info.ver)); 5612e59129aSraghus } 5622e59129aSraghus 5632e59129aSraghus return (status); 5642e59129aSraghus 5652e59129aSraghus } 5662e59129aSraghus 56759ac0c16Sdavemq /* Set up the PHY specific values. */ 56859ac0c16Sdavemq 56959ac0c16Sdavemq nxge_status_t 57059ac0c16Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep) 57159ac0c16Sdavemq { 57259ac0c16Sdavemq nxge_status_t status = NXGE_OK; 57359ac0c16Sdavemq uint32_t port_type; 57459ac0c16Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 5752e59129aSraghus uint32_t pcs_id = 0; 5762e59129aSraghus uint32_t pma_pmd_id = 0; 5772e59129aSraghus uint32_t phy_id = 0; 5782d17280bSsbehera uint16_t chip_id = 0; 57959ac0c16Sdavemq 58059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>", 58159ac0c16Sdavemq portn)); 58259ac0c16Sdavemq 5832e59129aSraghus switch (nxgep->niu_type) { 5842e59129aSraghus case N2_NIU: 5852e59129aSraghus switch (nxgep->mac.portmode) { 5862e59129aSraghus case PORT_1G_FIBER: 5872e59129aSraghus case PORT_1G_SERDES: 5882e59129aSraghus nxgep->xcvr = nxge_n2_1G_table; 5892d17280bSsbehera nxgep->xcvr_addr = portn; 5902e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr", 5912e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" : 5922e59129aSraghus "Serdes")); 5932e59129aSraghus break; 5942e59129aSraghus case PORT_10G_FIBER: 595*89282175SSantwona Behera case PORT_10G_COPPER: 5962e59129aSraghus case PORT_10G_SERDES: 5972e59129aSraghus nxgep->xcvr = nxge_n2_10G_table; 5982d17280bSsbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 5992d17280bSsbehera nxgep->xcvr_addr = 6002d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 6012d17280bSsbehera } 6022e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr", 6032e59129aSraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" : 604*89282175SSantwona Behera ((nxgep->mac.portmode == PORT_10G_COPPER) ? 605*89282175SSantwona Behera "Copper" : "Serdes"))); 6062e59129aSraghus break; 60700161856Syc case PORT_1G_TN1010: 60800161856Syc nxgep->xcvr = nxge_n2_1G_tn1010_table; 60900161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 61000161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61100161856Syc "TN1010 Copper Xcvr in 1G")); 61200161856Syc break; 61300161856Syc case PORT_10G_TN1010: 61400161856Syc nxgep->xcvr = nxge_n2_10G_tn1010_table; 61500161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 61600161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61700161856Syc "TN1010 Copper Xcvr in 10G")); 61800161856Syc break; 6192d17280bSsbehera case PORT_HSP_MODE: 6202d17280bSsbehera nxgep->xcvr = nxge_n2_10G_table; 6212d17280bSsbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 6222d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot " 6232d17280bSsbehera "Swappable Xcvr (not present)")); 6242d17280bSsbehera break; 6252e59129aSraghus default: 6262e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6272e59129aSraghus "<== nxge_setup_xcvr_table: " 6282e59129aSraghus "Unable to determine NIU portmode")); 6292e59129aSraghus return (NXGE_ERROR); 6302e59129aSraghus } 6312e59129aSraghus break; 6322e59129aSraghus default: 6332e59129aSraghus if (nxgep->mac.portmode == 0) { 6342e59129aSraghus /* 6352e59129aSraghus * Would be the case for platforms like Maramba 6362e59129aSraghus * in which the phy type could not be got from conf 6372e59129aSraghus * file, OBP, VPD or Serial PROM. 6382e59129aSraghus */ 6392e59129aSraghus if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 6402e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6412e59129aSraghus "<== nxge_setup_xcvr_table:" 6422e59129aSraghus " Invalid Neptune type [0x%x]", 6432e59129aSraghus nxgep->niu_type)); 6442e59129aSraghus return (NXGE_ERROR); 6452e59129aSraghus } 6462e59129aSraghus 6472e59129aSraghus port_type = nxgep->niu_type >> 6482e59129aSraghus (NXGE_PORT_TYPE_SHIFT * portn); 6492e59129aSraghus port_type = port_type & (NXGE_PORT_TYPE_MASK); 6502e59129aSraghus 6512e59129aSraghus switch (port_type) { 6522e59129aSraghus 6532e59129aSraghus case NXGE_PORT_1G_COPPER: 6542e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 6552e59129aSraghus break; 6562e59129aSraghus case NXGE_PORT_10G_COPPER: 6572e59129aSraghus nxgep->mac.portmode = PORT_10G_COPPER; 6582e59129aSraghus break; 6592e59129aSraghus case NXGE_PORT_1G_FIBRE: 6602e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 6612e59129aSraghus break; 6622e59129aSraghus case NXGE_PORT_10G_FIBRE: 6632e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 6642e59129aSraghus break; 6652e59129aSraghus case NXGE_PORT_1G_SERDES: 6662e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 6672e59129aSraghus break; 6682e59129aSraghus case NXGE_PORT_10G_SERDES: 6692e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 6702e59129aSraghus break; 67100161856Syc /* Ports 2 and 3 of Alonso or ARTM */ 6722e59129aSraghus case NXGE_PORT_1G_RGMII_FIBER: 6732e59129aSraghus nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 6742e59129aSraghus break; 67500161856Syc case NXGE_PORT_TN1010: 67600161856Syc /* 67700161856Syc * If this port uses the TN1010 copper 67800161856Syc * PHY, then its speed is not known yet 67900161856Syc * because nxge_scan_ports_phy could only 68000161856Syc * figure out the vendor of the PHY but 68100161856Syc * not its speed. nxge_set_tn1010_param 68200161856Syc * will read the PHY speed and set 68300161856Syc * portmode accordingly. 68400161856Syc */ 68500161856Syc if ((status = nxge_set_tn1010_param(nxgep)) 68600161856Syc != NXGE_OK) { 68700161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 68800161856Syc "nxge_set_tn1010_param failed")); 68900161856Syc return (status); 69000161856Syc } 69100161856Syc break; 6922e59129aSraghus default: 6932e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6942e59129aSraghus "<== nxge_setup_xcvr_table: " 6952e59129aSraghus "Unknown port-type: 0x%x", port_type)); 6962e59129aSraghus return (NXGE_ERROR); 6972e59129aSraghus } 6982e59129aSraghus } 6992e59129aSraghus 70000161856Syc /* 70100161856Syc * Above switch has figured out nxge->mac.portmode, now set 70200161856Syc * nxgep->xcvr (the table) and nxgep->xcvr_addr according 70300161856Syc * to portmode. 70400161856Syc */ 7052e59129aSraghus switch (nxgep->mac.portmode) { 7062e59129aSraghus case PORT_1G_COPPER: 7072e59129aSraghus case PORT_1G_RGMII_FIBER: 70859ac0c16Sdavemq nxgep->xcvr = nxge_1G_copper_table; 7092d17280bSsbehera nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 71059ac0c16Sdavemq /* 71159ac0c16Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 71259ac0c16Sdavemq * swapped with ethernet port number. This is 7132e59129aSraghus * designed for better signal integrity in 7142e59129aSraghus * routing. This is also the case for the 7152e59129aSraghus * on-board Neptune copper ports on the Maramba 7162e59129aSraghus * platform. 71759ac0c16Sdavemq */ 7182e59129aSraghus switch (nxgep->platform_type) { 7192e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 7202e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 7212e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 7222e59129aSraghus switch (portn) { 7232e59129aSraghus case 0: 7242d17280bSsbehera nxgep->xcvr_addr += 3; 7252e59129aSraghus break; 7262e59129aSraghus case 1: 7272d17280bSsbehera nxgep->xcvr_addr += 1; 7282e59129aSraghus break; 7292e59129aSraghus case 2: 7302d17280bSsbehera nxgep->xcvr_addr -= 1; 7312e59129aSraghus break; 7322e59129aSraghus case 3: 7332d17280bSsbehera nxgep->xcvr_addr -= 3; 7342e59129aSraghus break; 7352e59129aSraghus default: 7362e59129aSraghus return (NXGE_ERROR); 7372e59129aSraghus } 73859ac0c16Sdavemq break; 73959ac0c16Sdavemq default: 7402e59129aSraghus break; 74159ac0c16Sdavemq } 742d81011f0Ssbehera 7432e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 7442e59129aSraghus (nxgep->mac.portmode == PORT_1G_COPPER) ? 7452e59129aSraghus "Copper" : "RGMII Fiber")); 74659ac0c16Sdavemq break; 74700161856Syc 7482e59129aSraghus case PORT_10G_COPPER: 74959ac0c16Sdavemq nxgep->xcvr = nxge_10G_copper_table; 75059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr")); 75159ac0c16Sdavemq break; 75200161856Syc 75300161856Syc case PORT_1G_TN1010: 75400161856Syc nxgep->xcvr = nxge_1G_tn1010_table; 75500161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 75600161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 75700161856Syc "1G TN1010 copper Xcvr")); 75800161856Syc break; 75900161856Syc 76000161856Syc case PORT_10G_TN1010: 76100161856Syc nxgep->xcvr = nxge_10G_tn1010_table; 76200161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 76300161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 76400161856Syc "10G TN1010 copper Xcvr")); 76500161856Syc break; 76600161856Syc 7672e59129aSraghus case PORT_1G_FIBER: 7682e59129aSraghus case PORT_1G_SERDES: 76959ac0c16Sdavemq nxgep->xcvr = nxge_1G_fiber_table; 7702d17280bSsbehera nxgep->xcvr_addr = portn; 7712e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 7722e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? 7732e59129aSraghus "Fiber" : "Serdes")); 77459ac0c16Sdavemq break; 7752e59129aSraghus case PORT_10G_FIBER: 7762e59129aSraghus case PORT_10G_SERDES: 77759ac0c16Sdavemq nxgep->xcvr = nxge_10G_fiber_table; 7782d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr " 7792d17280bSsbehera "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] " 7802d17280bSsbehera "nxgep->xcvr_addr = [%d]", 7812d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn], 7822d17280bSsbehera nxgep->xcvr_addr)); 7832d17280bSsbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 7842d17280bSsbehera nxgep->xcvr_addr = 7852d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 7862d17280bSsbehera } 7872e59129aSraghus switch (nxgep->platform_type) { 7882e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 7892e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 79059ac0c16Sdavemq /* 79159ac0c16Sdavemq * Switch off LED for corresponding copper 79259ac0c16Sdavemq * port 79359ac0c16Sdavemq */ 79459ac0c16Sdavemq nxge_bcm5464_link_led_off(nxgep); 7952e59129aSraghus break; 7962e59129aSraghus default: 7972e59129aSraghus break; 79859ac0c16Sdavemq } 7992e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr", 8002e59129aSraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? 8012e59129aSraghus "Fiber" : "Serdes")); 80259ac0c16Sdavemq break; 8032d17280bSsbehera 8042d17280bSsbehera case PORT_HSP_MODE: 8052d17280bSsbehera nxgep->xcvr = nxge_10G_fiber_table; 8062d17280bSsbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 8072d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot " 8082d17280bSsbehera "Swappable Xcvr (not present)")); 8092d17280bSsbehera break; 81059ac0c16Sdavemq default: 81159ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 81259ac0c16Sdavemq "Unknown port-type: 0x%x", port_type)); 81359ac0c16Sdavemq return (NXGE_ERROR); 81459ac0c16Sdavemq } 81559ac0c16Sdavemq } 81659ac0c16Sdavemq 817*89282175SSantwona Behera if (nxgep->mac.portmode == PORT_10G_FIBER || 818*89282175SSantwona Behera nxgep->mac.portmode == PORT_10G_COPPER) { 81952cdd236Ssbehera uint32_t pma_pmd_id; 82052cdd236Ssbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, 82152cdd236Ssbehera nxgep->xcvr_addr); 82252cdd236Ssbehera if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) { 82352cdd236Ssbehera chip_id = MRVL88X201X_CHIP_ID; 82452cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 82552cdd236Ssbehera "nxge_setup_xcvr_table: " 82652cdd236Ssbehera "Chip ID MARVELL [0x%x] for 10G xcvr", chip_id)); 827*89282175SSantwona Behera } else if ((pma_pmd_id & NLP2020_DEV_ID_MASK) == 828*89282175SSantwona Behera NLP2020_DEV_ID) { 829*89282175SSantwona Behera chip_id = NLP2020_CHIP_ID; 830*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 831*89282175SSantwona Behera "nxge_setup_xcvr_table: " 832*89282175SSantwona Behera "Chip ID AEL2020 [0x%x] for 10G xcvr", chip_id)); 83352cdd236Ssbehera } else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr, 8342d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG, 8352d17280bSsbehera &chip_id)) == NXGE_OK) { 8362d17280bSsbehera 8372d17280bSsbehera switch (chip_id) { 8382d17280bSsbehera case BCM8704_CHIP_ID: 8392d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8402d17280bSsbehera "nxge_setup_xcvr_table: " 8412d17280bSsbehera "Chip ID 8704 [0x%x] for 10G xcvr", 8422d17280bSsbehera chip_id)); 8432d17280bSsbehera break; 8442d17280bSsbehera case BCM8706_CHIP_ID: 8452d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8462d17280bSsbehera "nxge_setup_xcvr_table: " 8472d17280bSsbehera "Chip ID 8706 [0x%x] for 10G xcvr", 8482d17280bSsbehera chip_id)); 8492d17280bSsbehera break; 8502d17280bSsbehera default: 8512d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8522d17280bSsbehera "nxge_setup_xcvr_table: " 8532d17280bSsbehera "Unknown Chip ID [0x%x] for 10G xcvr", 8542d17280bSsbehera chip_id)); 8552d17280bSsbehera break; 8562d17280bSsbehera } 8572d17280bSsbehera } 8582d17280bSsbehera } 8592d17280bSsbehera 86059ac0c16Sdavemq nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse; 8612d17280bSsbehera nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr; 8622d17280bSsbehera nxgep->chip_id = chip_id; 8632e59129aSraghus 8642e59129aSraghus /* 8652e59129aSraghus * Get the actual device ID value returned by MDIO read. 8662e59129aSraghus */ 8672e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = 0; 8682e59129aSraghus 8692d17280bSsbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr); 8702e59129aSraghus if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) { 8712e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id; 8722e59129aSraghus } else { 8732d17280bSsbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr); 8742e59129aSraghus if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) { 8752e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = pcs_id; 8762e59129aSraghus } else { 8772e59129aSraghus phy_id = nxge_get_cl22_phy_id(nxgep, 8782d17280bSsbehera nxgep->xcvr_addr); 8792e59129aSraghus if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 8802e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = phy_id; 8812e59129aSraghus } 8822e59129aSraghus } 8832e59129aSraghus } 8842e59129aSraghus 88559ac0c16Sdavemq nxgep->mac.linkchkmode = LINKCHK_TIMER; 88659ac0c16Sdavemq 8872e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type" 88823b952a3SSantwona Behera "[0x%x] platform type[0x%x] xcvr_addr[%d]", nxgep->niu_type, 8892d17280bSsbehera nxgep->platform_type, nxgep->xcvr_addr)); 8902e59129aSraghus 89159ac0c16Sdavemq return (status); 89259ac0c16Sdavemq } 89359ac0c16Sdavemq 89444961713Sgirish /* Initialize the entire MAC and physical layer */ 89544961713Sgirish 89644961713Sgirish nxge_status_t 89744961713Sgirish nxge_mac_init(p_nxge_t nxgep) 89844961713Sgirish { 89944961713Sgirish uint8_t portn; 90044961713Sgirish nxge_status_t status = NXGE_OK; 90144961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 90244961713Sgirish 90344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 90444961713Sgirish 90544961713Sgirish nxgep->mac.portnum = portn; 90644961713Sgirish nxgep->mac.porttype = PORT_TYPE_XMAC; 90744961713Sgirish 90844961713Sgirish if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 90944961713Sgirish nxgep->mac.porttype = PORT_TYPE_BMAC; 91044961713Sgirish 91100161856Syc 91244961713Sgirish /* Initialize XIF to configure a network mode */ 91344961713Sgirish if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 91444961713Sgirish goto fail; 91544961713Sgirish } 91644961713Sgirish 91744961713Sgirish if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 91844961713Sgirish goto fail; 91944961713Sgirish } 92044961713Sgirish 92144961713Sgirish /* Initialize TX and RX MACs */ 92244961713Sgirish /* 92344961713Sgirish * Always perform XIF init first, before TX and RX MAC init 92444961713Sgirish */ 92544961713Sgirish if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 92644961713Sgirish goto fail; 92744961713Sgirish 92844961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 92944961713Sgirish goto fail; 93044961713Sgirish 93144961713Sgirish if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 93244961713Sgirish goto fail; 93344961713Sgirish 93444961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 93544961713Sgirish goto fail; 93644961713Sgirish 93744961713Sgirish if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 93844961713Sgirish goto fail; 93944961713Sgirish 940e759c33aSMichael Speer if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 941e759c33aSMichael Speer if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 942e759c33aSMichael Speer goto fail; 943e759c33aSMichael Speer } 94444961713Sgirish 945cb9d3ae6Smisaki /* Initialize MAC control configuration */ 946cb9d3ae6Smisaki if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) { 947cb9d3ae6Smisaki goto fail; 948cb9d3ae6Smisaki } 949cb9d3ae6Smisaki 95044961713Sgirish nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 95144961713Sgirish 952d81011f0Ssbehera /* The Neptune Serdes needs to be reinitialized again */ 953d81011f0Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 954d81011f0Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 95500161856Syc (nxgep->mac.portmode == PORT_1G_TN1010) || 956d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 957d81011f0Ssbehera ((portn == 0) || (portn == 1))) { 958d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 959d81011f0Ssbehera "nxge_mac_init: reinit Neptune 1G Serdes ")); 960d81011f0Ssbehera if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) { 961d81011f0Ssbehera goto fail; 962d81011f0Ssbehera } 963d81011f0Ssbehera } 964d81011f0Ssbehera 9652e59129aSraghus 96644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 96744961713Sgirish 96844961713Sgirish return (NXGE_OK); 96944961713Sgirish fail: 97044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 97152ccf843Smisaki "nxge_mac_init: failed to initialize MAC port<%d>", portn)); 97244961713Sgirish return (status); 97344961713Sgirish } 97444961713Sgirish 97544961713Sgirish /* Initialize the Ethernet Link */ 97644961713Sgirish 97744961713Sgirish nxge_status_t 97844961713Sgirish nxge_link_init(p_nxge_t nxgep) 97944961713Sgirish { 98044961713Sgirish nxge_status_t status = NXGE_OK; 9812e59129aSraghus nxge_port_mode_t portmode; 98244961713Sgirish #ifdef NXGE_DEBUG 98344961713Sgirish uint8_t portn; 98444961713Sgirish 98544961713Sgirish portn = nxgep->mac.portnum; 98644961713Sgirish 98744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 98844961713Sgirish #endif 9891c7408c9Stc /* For Opus NEM, Serdes always needs to be initialized */ 99044961713Sgirish 9912e59129aSraghus portmode = nxgep->mac.portmode; 9922d17280bSsbehera 99300161856Syc /* 99400161856Syc * Workaround to get link up in both NIU ports. Some portmodes require 99500161856Syc * that the xcvr be initialized twice, the first time before calling 99600161856Syc * nxge_serdes_init. 99700161856Syc */ 9982e59129aSraghus if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) && 99900161856Syc (portmode != PORT_10G_TN1010) && 100000161856Syc (portmode != PORT_1G_TN1010) && 10012e59129aSraghus (portmode != PORT_1G_SERDES)) { 10022e59129aSraghus if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) { 100344961713Sgirish goto fail; 10042e59129aSraghus } 100544961713Sgirish } 100600161856Syc 100744961713Sgirish NXGE_DELAY(200000); 100844961713Sgirish /* Initialize internal serdes */ 100944961713Sgirish if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 101044961713Sgirish goto fail; 101144961713Sgirish NXGE_DELAY(200000); 101244961713Sgirish if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 101344961713Sgirish goto fail; 101444961713Sgirish 101544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 101644961713Sgirish 101744961713Sgirish return (NXGE_OK); 101844961713Sgirish 101944961713Sgirish fail: 102052ccf843Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_link_init: ", 102152ccf843Smisaki "failed to initialize Ethernet link on port<%d>", portn)); 102244961713Sgirish 102344961713Sgirish return (status); 102444961713Sgirish } 102544961713Sgirish 102644961713Sgirish 102744961713Sgirish /* Initialize the XIF sub-block within the MAC */ 102844961713Sgirish 102944961713Sgirish nxge_status_t 103044961713Sgirish nxge_xif_init(p_nxge_t nxgep) 103144961713Sgirish { 103244961713Sgirish uint32_t xif_cfg = 0; 103344961713Sgirish npi_attr_t ap; 103444961713Sgirish uint8_t portn; 103544961713Sgirish nxge_port_t portt; 103644961713Sgirish nxge_port_mode_t portmode; 103744961713Sgirish p_nxge_stats_t statsp; 103844961713Sgirish npi_status_t rs = NPI_SUCCESS; 103944961713Sgirish npi_handle_t handle; 104044961713Sgirish 104144961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 104244961713Sgirish 104344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 104444961713Sgirish 104544961713Sgirish handle = nxgep->npi_handle; 104644961713Sgirish portmode = nxgep->mac.portmode; 104744961713Sgirish portt = nxgep->mac.porttype; 104844961713Sgirish statsp = nxgep->statsp; 104944961713Sgirish 1050d81011f0Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 1051d81011f0Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 105200161856Syc (nxgep->mac.portmode == PORT_1G_TN1010) || 1053d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 1054d81011f0Ssbehera ((portn == 0) || (portn == 1))) { 1055d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1056d81011f0Ssbehera "nxge_xcvr_init: set ATCA mode")); 1057d81011f0Ssbehera npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE); 1058d81011f0Ssbehera } 1059d81011f0Ssbehera 106044961713Sgirish if (portt == PORT_TYPE_XMAC) { 106144961713Sgirish 106244961713Sgirish /* Setup XIF Configuration for XMAC */ 106344961713Sgirish 106444961713Sgirish if ((portmode == PORT_10G_FIBER) || 10652e59129aSraghus (portmode == PORT_10G_COPPER) || 106600161856Syc (portmode == PORT_10G_TN1010) || 10671c7408c9Stc (portmode == PORT_HSP_MODE) || 10682e59129aSraghus (portmode == PORT_10G_SERDES)) 106944961713Sgirish xif_cfg |= CFG_XMAC_XIF_LFS; 107044961713Sgirish 107100161856Syc /* Bypass PCS so that RGMII will be used */ 107244961713Sgirish if (portmode == PORT_1G_COPPER) { 107344961713Sgirish xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 107444961713Sgirish } 107544961713Sgirish 107644961713Sgirish /* Set MAC Internal Loopback if necessary */ 107744961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 107844961713Sgirish xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 107944961713Sgirish 108044961713Sgirish if (statsp->mac_stats.link_speed == 100) 108144961713Sgirish xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 108244961713Sgirish 108344961713Sgirish xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 108444961713Sgirish 10852e59129aSraghus if ((portmode == PORT_10G_FIBER) || 1086*89282175SSantwona Behera (portmode == PORT_10G_COPPER) || 108700161856Syc (portmode == PORT_10G_TN1010) || 108800161856Syc (portmode == PORT_1G_TN1010) || 10891c7408c9Stc (portmode == PORT_HSP_MODE) || 10902e59129aSraghus (portmode == PORT_10G_SERDES)) { 109100161856Syc /* Assume LED same for 1G and 10G */ 109244961713Sgirish if (statsp->mac_stats.link_up) { 109344961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 109444961713Sgirish } else { 109544961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 109644961713Sgirish } 109744961713Sgirish } 109844961713Sgirish 109944961713Sgirish rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 110044961713Sgirish if (rs != NPI_SUCCESS) 110144961713Sgirish goto fail; 110244961713Sgirish 110344961713Sgirish nxgep->mac.xif_config = xif_cfg; 110444961713Sgirish 110544961713Sgirish /* Set Port Mode */ 110644961713Sgirish if ((portmode == PORT_10G_FIBER) || 11072e59129aSraghus (portmode == PORT_10G_COPPER) || 110800161856Syc (portmode == PORT_10G_TN1010) || 11091c7408c9Stc (portmode == PORT_HSP_MODE) || 11102e59129aSraghus (portmode == PORT_10G_SERDES)) { 111144961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 111252ccf843Smisaki MAC_XGMII_MODE, rs); 111344961713Sgirish if (rs != NPI_SUCCESS) 111444961713Sgirish goto fail; 111544961713Sgirish if (statsp->mac_stats.link_up) { 111644961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 111744961713Sgirish goto fail; 111844961713Sgirish } else { 111944961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 112044961713Sgirish goto fail; 112144961713Sgirish } 112244961713Sgirish } else if ((portmode == PORT_1G_FIBER) || 11232e59129aSraghus (portmode == PORT_1G_COPPER) || 1124d81011f0Ssbehera (portmode == PORT_1G_SERDES) || 112500161856Syc (portmode == PORT_1G_TN1010) || 1126d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 1127d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1128d81011f0Ssbehera "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]", 1129d81011f0Ssbehera portn, portmode, statsp->mac_stats.link_speed)); 113044961713Sgirish if (statsp->mac_stats.link_speed == 1000) { 113144961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 113252ccf843Smisaki MAC_GMII_MODE, rs); 113344961713Sgirish } else { 113444961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 113552ccf843Smisaki MAC_MII_MODE, rs); 113644961713Sgirish } 113744961713Sgirish if (rs != NPI_SUCCESS) 113844961713Sgirish goto fail; 113944961713Sgirish } else { 114044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 114152ccf843Smisaki "nxge_xif_init: Unknown port mode (%d)" 114252ccf843Smisaki " for port<%d>", portmode, portn)); 114344961713Sgirish goto fail; 114444961713Sgirish } 114544961713Sgirish 1146d81011f0Ssbehera /* Enable ATCA mode */ 1147d81011f0Ssbehera 114844961713Sgirish } else if (portt == PORT_TYPE_BMAC) { 114944961713Sgirish 115044961713Sgirish /* Setup XIF Configuration for BMAC */ 115144961713Sgirish 1152d81011f0Ssbehera if ((portmode == PORT_1G_COPPER) || 1153d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 115444961713Sgirish if (statsp->mac_stats.link_speed == 100) 115544961713Sgirish xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 115644961713Sgirish } 115744961713Sgirish 115844961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 115944961713Sgirish xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 116044961713Sgirish 116144961713Sgirish if (statsp->mac_stats.link_speed == 1000) 116244961713Sgirish xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 116344961713Sgirish 116444961713Sgirish xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 116544961713Sgirish 116644961713Sgirish rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 116744961713Sgirish if (rs != NPI_SUCCESS) 116844961713Sgirish goto fail; 116944961713Sgirish nxgep->mac.xif_config = xif_cfg; 117044961713Sgirish } 117144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 117244961713Sgirish return (NXGE_OK); 117344961713Sgirish fail: 117444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 117552ccf843Smisaki "nxge_xif_init: Failed to initialize XIF port<%d>", portn)); 117644961713Sgirish return (NXGE_ERROR | rs); 117744961713Sgirish } 117844961713Sgirish 117944961713Sgirish 118000161856Syc /* 118100161856Syc * Initialize the PCS sub-block in the MAC. Note that PCS does not 118200161856Syc * support loopback like XPCS. 118300161856Syc */ 118444961713Sgirish nxge_status_t 118544961713Sgirish nxge_pcs_init(p_nxge_t nxgep) 118644961713Sgirish { 118744961713Sgirish pcs_cfg_t pcs_cfg; 118844961713Sgirish uint32_t val; 118944961713Sgirish uint8_t portn; 119044961713Sgirish nxge_port_mode_t portmode; 119144961713Sgirish npi_handle_t handle; 119244961713Sgirish p_nxge_stats_t statsp; 119300161856Syc pcs_ctrl_t pcs_ctrl; 119444961713Sgirish npi_status_t rs = NPI_SUCCESS; 119500161856Syc uint8_t i; 119644961713Sgirish 119744961713Sgirish handle = nxgep->npi_handle; 119844961713Sgirish portmode = nxgep->mac.portmode; 119944961713Sgirish portn = nxgep->mac.portnum; 120044961713Sgirish statsp = nxgep->statsp; 120144961713Sgirish 120244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 120344961713Sgirish 120400161856Syc if (portmode == PORT_1G_FIBER || 120500161856Syc portmode == PORT_1G_TN1010 || 120600161856Syc portmode == PORT_1G_SERDES) { 120700161856Syc if (portmode == PORT_1G_TN1010) { 120800161856Syc /* Reset PCS multiple time in PORT_1G_TN1010 mode */ 120900161856Syc for (i = 0; i < 6; i ++) { 121000161856Syc if ((rs = npi_mac_pcs_reset(handle, portn)) 121100161856Syc != NPI_SUCCESS) { 121200161856Syc goto fail; 121300161856Syc } 121400161856Syc } 121500161856Syc } else { 121600161856Syc if ((rs = npi_mac_pcs_reset(handle, portn)) 121700161856Syc != NPI_SUCCESS) 121800161856Syc goto fail; 12192e59129aSraghus } 12202e59129aSraghus 122144961713Sgirish /* Initialize port's PCS */ 122244961713Sgirish pcs_cfg.value = 0; 122344961713Sgirish pcs_cfg.bits.w0.enable = 1; 122444961713Sgirish pcs_cfg.bits.w0.mask = 1; 122544961713Sgirish PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 122644961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 122744961713Sgirish 12282e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12292e59129aSraghus "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx", 12302e59129aSraghus portn, pcs_cfg.value)); 123100161856Syc 123200161856Syc if (portmode == PORT_1G_TN1010) { 123300161856Syc /* 123400161856Syc * Must disable PCS auto-negotiation when the the driver 123500161856Syc * is driving the TN1010 based XAUI card Otherwise the 123600161856Syc * autonegotiation between the PCS and the TN1010 PCS 123700161856Syc * will never complete and the Neptune/NIU will not work 123800161856Syc */ 123900161856Syc pcs_ctrl.value = 0; 124000161856Syc PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG, 124100161856Syc pcs_ctrl.value); 124200161856Syc } 124300161856Syc } else if (portmode == PORT_10G_FIBER || 124400161856Syc portmode == PORT_10G_COPPER || 124500161856Syc portmode == PORT_10G_TN1010 || 12461c7408c9Stc portmode == PORT_HSP_MODE || 124700161856Syc portmode == PORT_10G_SERDES) { 124844961713Sgirish /* Use internal XPCS, bypass 1G PCS */ 124944961713Sgirish XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 125044961713Sgirish val &= ~XMAC_XIF_XPCS_BYPASS; 125144961713Sgirish XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 125244961713Sgirish 125344961713Sgirish if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 125444961713Sgirish goto fail; 125544961713Sgirish 125644961713Sgirish /* Set XPCS Internal Loopback if necessary */ 125744961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 125852ccf843Smisaki XPCS_REG_CONTROL1, &val)) != NPI_SUCCESS) 125944961713Sgirish goto fail; 126000161856Syc 126144961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 126252ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 126344961713Sgirish val |= XPCS_CTRL1_LOOPBK; 126444961713Sgirish else 126544961713Sgirish val &= ~XPCS_CTRL1_LOOPBK; 126644961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 126752ccf843Smisaki XPCS_REG_CONTROL1, val)) != NPI_SUCCESS) 126844961713Sgirish goto fail; 126944961713Sgirish 127044961713Sgirish /* Clear descw errors */ 127144961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 127252ccf843Smisaki XPCS_REG_DESCWERR_COUNTER, 0)) != NPI_SUCCESS) 127344961713Sgirish goto fail; 127444961713Sgirish /* Clear symbol errors */ 127544961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 127652ccf843Smisaki XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) != NPI_SUCCESS) 127744961713Sgirish goto fail; 127844961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 127952ccf843Smisaki XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) != NPI_SUCCESS) 128044961713Sgirish goto fail; 128144961713Sgirish 1282d81011f0Ssbehera } else if ((portmode == PORT_1G_COPPER) || 1283d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 1284d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1285d81011f0Ssbehera "==> nxge_pcs_init: (1G) copper port<%d>", portn)); 128644961713Sgirish if (portn < 4) { 128744961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 128852ccf843Smisaki PCS_DATAPATH_MODE_MII); 128944961713Sgirish } 129044961713Sgirish if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 129144961713Sgirish goto fail; 129244961713Sgirish 129344961713Sgirish } else { 129444961713Sgirish goto fail; 129544961713Sgirish } 129644961713Sgirish pass: 129744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 129844961713Sgirish return (NXGE_OK); 129944961713Sgirish fail: 130044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 130152ccf843Smisaki "nxge_pcs_init: Failed to initialize PCS port<%d>", portn)); 130244961713Sgirish return (NXGE_ERROR | rs); 130344961713Sgirish } 130444961713Sgirish 1305cb9d3ae6Smisaki /* 1306cb9d3ae6Smisaki * Initialize the MAC CTRL sub-block within the MAC 1307cb9d3ae6Smisaki * Only the receive-pause-cap is supported. 1308cb9d3ae6Smisaki */ 1309cb9d3ae6Smisaki nxge_status_t 1310cb9d3ae6Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep) 1311cb9d3ae6Smisaki { 1312cb9d3ae6Smisaki uint8_t portn; 1313cb9d3ae6Smisaki nxge_port_t portt; 1314cb9d3ae6Smisaki p_nxge_stats_t statsp; 1315cb9d3ae6Smisaki npi_handle_t handle; 1316cb9d3ae6Smisaki uint32_t val; 1317cb9d3ae6Smisaki 1318cb9d3ae6Smisaki portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1319cb9d3ae6Smisaki 1320cb9d3ae6Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>", 1321cb9d3ae6Smisaki portn)); 1322cb9d3ae6Smisaki 1323cb9d3ae6Smisaki handle = nxgep->npi_handle; 1324cb9d3ae6Smisaki portt = nxgep->mac.porttype; 1325cb9d3ae6Smisaki statsp = nxgep->statsp; 1326cb9d3ae6Smisaki 1327cb9d3ae6Smisaki if (portt == PORT_TYPE_XMAC) { 132800161856Syc /* Reading the current XMAC Config Register for XMAC */ 1329cb9d3ae6Smisaki XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 1330cb9d3ae6Smisaki 1331cb9d3ae6Smisaki /* 1332cb9d3ae6Smisaki * Setup XMAC Configuration for XMAC 1333cb9d3ae6Smisaki * XMAC only supports receive-pause 1334cb9d3ae6Smisaki */ 1335cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 1336cb9d3ae6Smisaki if (!statsp->mac_stats.adv_cap_pause) { 1337cb9d3ae6Smisaki /* 1338cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1339cb9d3ae6Smisaki * is 0, enable receive pause. 1340cb9d3ae6Smisaki */ 1341cb9d3ae6Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 1342cb9d3ae6Smisaki } else { 1343cb9d3ae6Smisaki /* 1344cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1345cb9d3ae6Smisaki * is 1, disable receive pause. Send pause is 1346cb9d3ae6Smisaki * not supported. 1347cb9d3ae6Smisaki */ 1348cb9d3ae6Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1349cb9d3ae6Smisaki } 1350cb9d3ae6Smisaki } else { 13511bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13521bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: pause", 13531bd6825cSml portn)); 1354cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 13551bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13561bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: " 13571bd6825cSml "enable pause", portn)); 1358cb9d3ae6Smisaki /* 1359cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1360cb9d3ae6Smisaki * is 1, enable receive pause. 1361cb9d3ae6Smisaki */ 1362cb9d3ae6Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 1363cb9d3ae6Smisaki } else { 1364cb9d3ae6Smisaki /* 1365cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1366cb9d3ae6Smisaki * is 0, disable receive pause. Send pause is 1367cb9d3ae6Smisaki * not supported 1368cb9d3ae6Smisaki */ 13691bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13701bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: " 13711bd6825cSml "disable pause", portn)); 1372cb9d3ae6Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1373cb9d3ae6Smisaki } 1374cb9d3ae6Smisaki } 1375cb9d3ae6Smisaki XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 1376cb9d3ae6Smisaki } else if (portt == PORT_TYPE_BMAC) { 137700161856Syc /* Reading the current MAC CTRL Config Register for BMAC */ 1378cb9d3ae6Smisaki BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val); 1379cb9d3ae6Smisaki 1380cb9d3ae6Smisaki /* Setup MAC CTRL Configuration for BMAC */ 1381cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 1382cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 1383cb9d3ae6Smisaki /* 1384cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1385cb9d3ae6Smisaki * is 1, disable receive pause. Send pause 1386cb9d3ae6Smisaki * is not supported 1387cb9d3ae6Smisaki */ 1388cb9d3ae6Smisaki val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN; 1389cb9d3ae6Smisaki } else { 1390cb9d3ae6Smisaki /* 1391cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1392cb9d3ae6Smisaki * is 0, enable receive pause and disable 1393cb9d3ae6Smisaki * send pause. 1394cb9d3ae6Smisaki */ 1395cb9d3ae6Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1396cb9d3ae6Smisaki val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN; 1397cb9d3ae6Smisaki } 1398cb9d3ae6Smisaki } else { 1399cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 1400cb9d3ae6Smisaki /* 1401cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1402cb9d3ae6Smisaki * is 1, enable receive pause. Send pause is 1403cb9d3ae6Smisaki * not supported. 1404cb9d3ae6Smisaki */ 1405cb9d3ae6Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1406cb9d3ae6Smisaki } else { 1407cb9d3ae6Smisaki /* 1408cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1409cb9d3ae6Smisaki * is 0, pause capability is not available in 1410cb9d3ae6Smisaki * either direction. 1411cb9d3ae6Smisaki */ 1412cb9d3ae6Smisaki val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN & 141352ccf843Smisaki ~MAC_CTRL_CFG_RECV_PAUSE_EN); 1414cb9d3ae6Smisaki } 1415cb9d3ae6Smisaki } 1416cb9d3ae6Smisaki BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val); 1417cb9d3ae6Smisaki } 1418cb9d3ae6Smisaki 1419cb9d3ae6Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>", 1420cb9d3ae6Smisaki portn)); 1421cb9d3ae6Smisaki 1422cb9d3ae6Smisaki return (NXGE_OK); 1423cb9d3ae6Smisaki } 1424cb9d3ae6Smisaki 142544961713Sgirish /* Initialize the Internal Serdes */ 142644961713Sgirish 142744961713Sgirish nxge_status_t 142844961713Sgirish nxge_serdes_init(p_nxge_t nxgep) 142944961713Sgirish { 143044961713Sgirish p_nxge_stats_t statsp; 143144961713Sgirish #ifdef NXGE_DEBUG 143244961713Sgirish uint8_t portn; 143344961713Sgirish #endif 143444961713Sgirish nxge_status_t status = NXGE_OK; 143544961713Sgirish 143644961713Sgirish #ifdef NXGE_DEBUG 143744961713Sgirish portn = nxgep->mac.portnum; 143844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 143959ac0c16Sdavemq "==> nxge_serdes_init port<%d>", portn)); 144044961713Sgirish #endif 144144961713Sgirish 144259ac0c16Sdavemq if (nxgep->xcvr.serdes_init) { 144359ac0c16Sdavemq statsp = nxgep->statsp; 144459ac0c16Sdavemq status = nxgep->xcvr.serdes_init(nxgep); 144559ac0c16Sdavemq if (status != NXGE_OK) 144644961713Sgirish goto fail; 144759ac0c16Sdavemq statsp->mac_stats.serdes_inits++; 144844961713Sgirish } 144944961713Sgirish 145044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 145159ac0c16Sdavemq portn)); 145244961713Sgirish 145344961713Sgirish return (NXGE_OK); 145444961713Sgirish 145544961713Sgirish fail: 145644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 145759ac0c16Sdavemq "nxge_serdes_init: Failed to initialize serdes for port<%d>", 145859ac0c16Sdavemq portn)); 145944961713Sgirish 146044961713Sgirish return (status); 146144961713Sgirish } 146244961713Sgirish 146344961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 146444961713Sgirish 146559ac0c16Sdavemq static nxge_status_t 146644961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep) 146744961713Sgirish { 146844961713Sgirish uint8_t portn; 146944961713Sgirish int chan; 147044961713Sgirish esr_ti_cfgpll_l_t pll_cfg_l; 14712e59129aSraghus esr_ti_cfgpll_l_t pll_sts_l; 147244961713Sgirish esr_ti_cfgrx_l_t rx_cfg_l; 147344961713Sgirish esr_ti_cfgrx_h_t rx_cfg_h; 147444961713Sgirish esr_ti_cfgtx_l_t tx_cfg_l; 147544961713Sgirish esr_ti_cfgtx_h_t tx_cfg_h; 14762e59129aSraghus #ifdef NXGE_DEBUG 14772e59129aSraghus esr_ti_testcfg_t cfg; 14782e59129aSraghus #endif 147944961713Sgirish esr_ti_testcfg_t test_cfg; 148044961713Sgirish nxge_status_t status = NXGE_OK; 148144961713Sgirish 148244961713Sgirish portn = nxgep->mac.portnum; 148344961713Sgirish 148444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 148552ccf843Smisaki portn)); 14864df55fdeSJanie Lu if (nxgep->niu_hw_type == NIU_HW_TYPE_RF) { 14874df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 14884df55fdeSJanie Lu "==> nxge_n2_serdes_init port<%d>: KT-NIU", portn)); 14894df55fdeSJanie Lu return (nxge_n2_kt_serdes_init(nxgep)); 14904df55fdeSJanie Lu } 149144961713Sgirish 149244961713Sgirish tx_cfg_l.value = 0; 149344961713Sgirish tx_cfg_h.value = 0; 149444961713Sgirish rx_cfg_l.value = 0; 149544961713Sgirish rx_cfg_h.value = 0; 149644961713Sgirish pll_cfg_l.value = 0; 14972e59129aSraghus pll_sts_l.value = 0; 149844961713Sgirish test_cfg.value = 0; 149944961713Sgirish 150000161856Syc /* 150100161856Syc * If the nxge driver has been plumbed without a link, then it will 150200161856Syc * detect a link up when a cable connecting to an anto-negotiation 150300161856Syc * partner is plugged into the port. Because the TN1010 PHY supports 150400161856Syc * both 1G and 10G speeds, the driver must re-configure the 150500161856Syc * Neptune/NIU according to the negotiated speed. nxge_n2_serdes_init 150600161856Syc * is called at the post-link-up reconfiguration time. Here it calls 150700161856Syc * nxge_set_tn1010_param to set portmode before re-initializing 150800161856Syc * the serdes. 150900161856Syc */ 151000161856Syc if (nxgep->mac.portmode == PORT_1G_TN1010 || 151100161856Syc nxgep->mac.portmode == PORT_10G_TN1010) { 151200161856Syc if (nxge_set_tn1010_param(nxgep) != NXGE_OK) { 151300161856Syc goto fail; 151400161856Syc } 151500161856Syc } 151600161856Syc 151700161856Syc if (nxgep->mac.portmode == PORT_10G_FIBER || 1518*89282175SSantwona Behera nxgep->mac.portmode == PORT_10G_COPPER || 151900161856Syc nxgep->mac.portmode == PORT_10G_TN1010 || 15201c7408c9Stc nxgep->mac.portmode == PORT_HSP_MODE || 152100161856Syc nxgep->mac.portmode == PORT_10G_SERDES) { 152244961713Sgirish /* 0x0E01 */ 152344961713Sgirish tx_cfg_l.bits.entx = 1; 152444961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 152544961713Sgirish 152644961713Sgirish /* 0x9101 */ 152744961713Sgirish rx_cfg_l.bits.enrx = 1; 152844961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 152944961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 153044961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 153144961713Sgirish 153244961713Sgirish /* 0x0008 */ 153344961713Sgirish rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 153444961713Sgirish 153544961713Sgirish /* Set loopback mode if necessary */ 153644961713Sgirish if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 153744961713Sgirish tx_cfg_l.bits.entest = 1; 153844961713Sgirish rx_cfg_l.bits.entest = 1; 153944961713Sgirish test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 154044961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 154152ccf843Smisaki ESR_N2_DEV_ADDR, 154252ccf843Smisaki ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) 154344961713Sgirish goto fail; 154444961713Sgirish } 154544961713Sgirish 154600161856Syc /* Initialize PLL for 10G */ 154700161856Syc pll_cfg_l.bits.mpy = CFGPLL_MPY_10X; 154800161856Syc pll_cfg_l.bits.enpll = 1; 154900161856Syc pll_sts_l.bits.enpll = 1; 155000161856Syc if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 155100161856Syc ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK) 155200161856Syc goto fail; 155300161856Syc 155400161856Syc if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 155500161856Syc ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 155600161856Syc goto fail; 155744961713Sgirish 155800161856Syc #ifdef NXGE_DEBUG 155900161856Syc nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 156000161856Syc ESR_N2_PLL_CFG_L_REG, &cfg.value); 156100161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 156200161856Syc "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 156300161856Syc portn, pll_cfg_l.value, cfg.value)); 156444961713Sgirish 156500161856Syc nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 156600161856Syc ESR_N2_PLL_STS_L_REG, &cfg.value); 156700161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 156800161856Syc "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 156900161856Syc portn, pll_sts_l.value, cfg.value)); 157000161856Syc #endif 157100161856Syc } else if (nxgep->mac.portmode == PORT_1G_FIBER || 157200161856Syc nxgep->mac.portmode == PORT_1G_TN1010 || 157300161856Syc nxgep->mac.portmode == PORT_1G_SERDES) { 157444961713Sgirish /* 0x0E21 */ 157544961713Sgirish tx_cfg_l.bits.entx = 1; 157644961713Sgirish tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 157744961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 157844961713Sgirish 157944961713Sgirish /* 0x9121 */ 158044961713Sgirish rx_cfg_l.bits.enrx = 1; 158144961713Sgirish rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 158244961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 158344961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 158444961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 158544961713Sgirish 15862e59129aSraghus if (portn == 0) { 15872e59129aSraghus /* 0x8 */ 15882e59129aSraghus rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 15892e59129aSraghus } 159044961713Sgirish 159100161856Syc /* Initialize PLL for 1G */ 159244961713Sgirish pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 159344961713Sgirish pll_cfg_l.bits.enpll = 1; 15942e59129aSraghus pll_sts_l.bits.enpll = 1; 159544961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 159652ccf843Smisaki ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK) 159744961713Sgirish goto fail; 15982e59129aSraghus 15992e59129aSraghus if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 16002e59129aSraghus ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 16012e59129aSraghus goto fail; 16022e59129aSraghus 16032e59129aSraghus #ifdef NXGE_DEBUG 16042e59129aSraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 16052e59129aSraghus ESR_N2_PLL_CFG_L_REG, &cfg.value); 16062e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16072e59129aSraghus "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 16082e59129aSraghus portn, pll_cfg_l.value, cfg.value)); 16092e59129aSraghus 16102e59129aSraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 16112e59129aSraghus ESR_N2_PLL_STS_L_REG, &cfg.value); 16122e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16132e59129aSraghus "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 16142e59129aSraghus portn, pll_sts_l.value, cfg.value)); 16152e59129aSraghus #endif 16162e59129aSraghus 16172e59129aSraghus /* Set loopback mode if necessary */ 16182e59129aSraghus if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 16192e59129aSraghus tx_cfg_l.bits.entest = 1; 16202e59129aSraghus rx_cfg_l.bits.entest = 1; 16212e59129aSraghus test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 16222e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16232e59129aSraghus "==> nxge_n2_serdes_init port<%d>: loopback 0x%x", 16242e59129aSraghus portn, test_cfg.value)); 16252e59129aSraghus if ((status = nxge_mdio_write(nxgep, portn, 16262e59129aSraghus ESR_N2_DEV_ADDR, 16272e59129aSraghus ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 16282e59129aSraghus goto fail; 16292e59129aSraghus } 16302e59129aSraghus } 163144961713Sgirish } else { 163244961713Sgirish goto fail; 163344961713Sgirish } 163444961713Sgirish 163544961713Sgirish /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 163644961713Sgirish 163744961713Sgirish NXGE_DELAY(20); 163844961713Sgirish 163944961713Sgirish /* init TX channels */ 164044961713Sgirish for (chan = 0; chan < 4; chan++) { 164144961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 164252ccf843Smisaki ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK) 164344961713Sgirish goto fail; 164444961713Sgirish 164544961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 164652ccf843Smisaki ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK) 164744961713Sgirish goto fail; 16482e59129aSraghus 16492e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16502e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x", 16512e59129aSraghus portn, chan, tx_cfg_l.value)); 16522e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16532e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x", 16542e59129aSraghus portn, chan, tx_cfg_h.value)); 165544961713Sgirish } 165644961713Sgirish 165744961713Sgirish /* init RX channels */ 165844961713Sgirish for (chan = 0; chan < 4; chan++) { 165944961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 166052ccf843Smisaki ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) != NXGE_OK) 166144961713Sgirish goto fail; 166244961713Sgirish 166344961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 166452ccf843Smisaki ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) != NXGE_OK) 166544961713Sgirish goto fail; 16662e59129aSraghus 16672e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16682e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x", 16692e59129aSraghus portn, chan, rx_cfg_l.value)); 167000161856Syc 16712e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16722e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x", 16732e59129aSraghus portn, chan, rx_cfg_h.value)); 167444961713Sgirish } 167544961713Sgirish 167644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 167752ccf843Smisaki portn)); 167844961713Sgirish 167944961713Sgirish return (NXGE_OK); 168044961713Sgirish fail: 16812d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16822d17280bSsbehera "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 16832d17280bSsbehera portn)); 168444961713Sgirish 168544961713Sgirish return (status); 16864df55fdeSJanie Lu 16874df55fdeSJanie Lu } 16884df55fdeSJanie Lu 16894df55fdeSJanie Lu /* Initialize the TI Hedwig Internal Serdes (N2-KT-NIU only) */ 16904df55fdeSJanie Lu 16914df55fdeSJanie Lu static nxge_status_t 16924df55fdeSJanie Lu nxge_n2_kt_serdes_init(p_nxge_t nxgep) 16934df55fdeSJanie Lu { 16944df55fdeSJanie Lu uint8_t portn; 1695*89282175SSantwona Behera int chan, i; 16964df55fdeSJanie Lu k_esr_ti_cfgpll_l_t pll_cfg_l; 16974df55fdeSJanie Lu k_esr_ti_cfgrx_l_t rx_cfg_l; 16984df55fdeSJanie Lu k_esr_ti_cfgrx_h_t rx_cfg_h; 16994df55fdeSJanie Lu k_esr_ti_cfgtx_l_t tx_cfg_l; 17004df55fdeSJanie Lu k_esr_ti_cfgtx_h_t tx_cfg_h; 17014df55fdeSJanie Lu #ifdef NXGE_DEBUG 17024df55fdeSJanie Lu k_esr_ti_testcfg_t cfg; 17034df55fdeSJanie Lu #endif 17044df55fdeSJanie Lu k_esr_ti_testcfg_t test_cfg; 17054df55fdeSJanie Lu nxge_status_t status = NXGE_OK; 17064df55fdeSJanie Lu boolean_t mode_1g = B_FALSE; 1707*89282175SSantwona Behera uint64_t val; 1708*89282175SSantwona Behera npi_handle_t handle; 17094df55fdeSJanie Lu 17104df55fdeSJanie Lu portn = nxgep->mac.portnum; 17114df55fdeSJanie Lu 17124df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 17134df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>", portn)); 1714*89282175SSantwona Behera handle = nxgep->npi_handle; 17154df55fdeSJanie Lu 17164df55fdeSJanie Lu tx_cfg_l.value = 0; 17174df55fdeSJanie Lu tx_cfg_h.value = 0; 17184df55fdeSJanie Lu rx_cfg_l.value = 0; 17194df55fdeSJanie Lu rx_cfg_h.value = 0; 17204df55fdeSJanie Lu pll_cfg_l.value = 0; 17214df55fdeSJanie Lu test_cfg.value = 0; 17224df55fdeSJanie Lu 17234df55fdeSJanie Lu /* 17244df55fdeSJanie Lu * The following setting assumes the reference clock frquency 17254df55fdeSJanie Lu * is 156.25 MHz. 17264df55fdeSJanie Lu */ 17274df55fdeSJanie Lu /* 17284df55fdeSJanie Lu * If the nxge driver has been plumbed without a link, then it will 17294df55fdeSJanie Lu * detect a link up when a cable connecting to an anto-negotiation 17304df55fdeSJanie Lu * partner is plugged into the port. Because the TN1010 PHY supports 17314df55fdeSJanie Lu * both 1G and 10G speeds, the driver must re-configure the 17324df55fdeSJanie Lu * Neptune/NIU according to the negotiated speed. nxge_n2_serdes_init 17334df55fdeSJanie Lu * is called at the post-link-up reconfiguration time. Here it calls 17344df55fdeSJanie Lu * nxge_set_tn1010_param to set portmode before re-initializing 17354df55fdeSJanie Lu * the serdes. 17364df55fdeSJanie Lu */ 17374df55fdeSJanie Lu if (nxgep->mac.portmode == PORT_1G_TN1010 || 17384df55fdeSJanie Lu nxgep->mac.portmode == PORT_10G_TN1010) { 17394df55fdeSJanie Lu if (nxge_set_tn1010_param(nxgep) != NXGE_OK) { 17404df55fdeSJanie Lu goto fail; 17414df55fdeSJanie Lu } 17424df55fdeSJanie Lu } 17434df55fdeSJanie Lu if (nxgep->mac.portmode == PORT_10G_FIBER || 1744*89282175SSantwona Behera nxgep->mac.portmode == PORT_10G_COPPER || 17454df55fdeSJanie Lu nxgep->mac.portmode == PORT_10G_TN1010 || 17464df55fdeSJanie Lu nxgep->mac.portmode == PORT_10G_SERDES) { 17474df55fdeSJanie Lu tx_cfg_l.bits.entx = K_CFGTX_ENABLE_TX; 17484df55fdeSJanie Lu /* 0x1e21 */ 17494df55fdeSJanie Lu tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV; 17504df55fdeSJanie Lu tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF; 17514df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 17524df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x", 17534df55fdeSJanie Lu portn, tx_cfg_l.value)); 17544df55fdeSJanie Lu 17554df55fdeSJanie Lu /* channel 0: enable syn. master */ 17564df55fdeSJanie Lu /* 0x40 */ 17574df55fdeSJanie Lu tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC; 17584df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 17594df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x", 17604df55fdeSJanie Lu portn, tx_cfg_h.value)); 17614df55fdeSJanie Lu /* 0x4821 */ 17624df55fdeSJanie Lu rx_cfg_l.bits.enrx = K_CFGRX_ENABLE_RX; 17634df55fdeSJanie Lu rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF; 17644df55fdeSJanie Lu rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN; 17654df55fdeSJanie Lu rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE; 17664df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 17674df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x", 17684df55fdeSJanie Lu portn, rx_cfg_l.value)); 17694df55fdeSJanie Lu 17704df55fdeSJanie Lu /* 0x0008 */ 17714df55fdeSJanie Lu rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE; 17724df55fdeSJanie Lu 17734df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 17744df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_h 0x%x", 17754df55fdeSJanie Lu portn, rx_cfg_h.value)); 17764df55fdeSJanie Lu 17774df55fdeSJanie Lu /* Set loopback mode if necessary */ 17784df55fdeSJanie Lu if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 17794df55fdeSJanie Lu tx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK; 17804df55fdeSJanie Lu rx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK; 17814df55fdeSJanie Lu rx_cfg_l.bits.los = 0; 17824df55fdeSJanie Lu 17834df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 17844df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 17854df55fdeSJanie Lu "loopback 0x%x", portn, tx_cfg_h.value)); 17864df55fdeSJanie Lu } 17874df55fdeSJanie Lu /* 0xa1: Initialize PLL for 10G */ 17884df55fdeSJanie Lu pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X; 17894df55fdeSJanie Lu pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL; 17904df55fdeSJanie Lu 17914df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 17924df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x", 17934df55fdeSJanie Lu portn, pll_cfg_l.value)); 17944df55fdeSJanie Lu 17954df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 17964df55fdeSJanie Lu ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK) 17974df55fdeSJanie Lu goto fail; 17984df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 17994df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x", 18004df55fdeSJanie Lu portn, pll_cfg_l.value)); 18014df55fdeSJanie Lu #ifdef NXGE_DEBUG 18024df55fdeSJanie Lu nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 18034df55fdeSJanie Lu ESR_N2_PLL_CFG_L_REG, &cfg.value); 18044df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 18054df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 18064df55fdeSJanie Lu "PLL cfg.l 0x%x (0x%x)", 18074df55fdeSJanie Lu portn, pll_cfg_l.value, cfg.value)); 18084df55fdeSJanie Lu 18094df55fdeSJanie Lu nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 18104df55fdeSJanie Lu ESR_N2_PLL_STS_L_REG, &cfg.value); 18114df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 18124df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)", 18134df55fdeSJanie Lu portn, cfg.value)); 18144df55fdeSJanie Lu #endif 18154df55fdeSJanie Lu } else if (nxgep->mac.portmode == PORT_1G_FIBER || 18164df55fdeSJanie Lu nxgep->mac.portmode == PORT_1G_TN1010 || 18174df55fdeSJanie Lu nxgep->mac.portmode == PORT_1G_SERDES) { 18184df55fdeSJanie Lu mode_1g = B_TRUE; 18194df55fdeSJanie Lu /* 0x1e41 */ 18204df55fdeSJanie Lu tx_cfg_l.bits.entx = 1; 18214df55fdeSJanie Lu tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF; 18224df55fdeSJanie Lu tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV; 18234df55fdeSJanie Lu 18244df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 18254df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x", 18264df55fdeSJanie Lu portn, tx_cfg_l.value)); 18274df55fdeSJanie Lu 18284df55fdeSJanie Lu 18294df55fdeSJanie Lu /* channel 0: enable syn. master */ 18304df55fdeSJanie Lu tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC; 18314df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 18324df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x", 18334df55fdeSJanie Lu portn, tx_cfg_h.value)); 18344df55fdeSJanie Lu 18354df55fdeSJanie Lu 18364df55fdeSJanie Lu /* 0x4841 */ 18374df55fdeSJanie Lu rx_cfg_l.bits.enrx = 1; 18384df55fdeSJanie Lu rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF; 18394df55fdeSJanie Lu rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN; 18404df55fdeSJanie Lu rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE; 18414df55fdeSJanie Lu 18424df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 18434df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x", 18444df55fdeSJanie Lu portn, rx_cfg_l.value)); 18454df55fdeSJanie Lu 18464df55fdeSJanie Lu /* 0x0008 */ 18474df55fdeSJanie Lu rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE_LF_365MHZ_ZF; 18484df55fdeSJanie Lu 18494df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 18504df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x", 18514df55fdeSJanie Lu portn, rx_cfg_h.value)); 18524df55fdeSJanie Lu 18534df55fdeSJanie Lu /* 0xa1: Initialize PLL for 1G */ 18544df55fdeSJanie Lu pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X; 18554df55fdeSJanie Lu pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL; 18564df55fdeSJanie Lu 18574df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 18584df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x", 18594df55fdeSJanie Lu portn, pll_cfg_l.value)); 18604df55fdeSJanie Lu 18614df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 18624df55fdeSJanie Lu ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 18634df55fdeSJanie Lu != NXGE_OK) 18644df55fdeSJanie Lu goto fail; 18654df55fdeSJanie Lu 18664df55fdeSJanie Lu 18674df55fdeSJanie Lu #ifdef NXGE_DEBUG 18684df55fdeSJanie Lu nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 18694df55fdeSJanie Lu ESR_N2_PLL_CFG_L_REG, &cfg.value); 18704df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 18714df55fdeSJanie Lu "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 18724df55fdeSJanie Lu portn, pll_cfg_l.value, cfg.value)); 18734df55fdeSJanie Lu 18744df55fdeSJanie Lu nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 18754df55fdeSJanie Lu ESR_N2_PLL_STS_L_REG, &cfg.value); 18764df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 18774df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)", 18784df55fdeSJanie Lu portn, cfg.value)); 18794df55fdeSJanie Lu #endif 18804df55fdeSJanie Lu 18814df55fdeSJanie Lu /* Set loopback mode if necessary */ 18824df55fdeSJanie Lu if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 18834df55fdeSJanie Lu tx_cfg_h.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 18844df55fdeSJanie Lu 18854df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 18864df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 18874df55fdeSJanie Lu "loopback 0x%x", portn, test_cfg.value)); 18884df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, 18894df55fdeSJanie Lu ESR_N2_DEV_ADDR, 18904df55fdeSJanie Lu ESR_N2_TX_CFG_L_REG_ADDR(0), 18914df55fdeSJanie Lu tx_cfg_h.value)) != NXGE_OK) { 18924df55fdeSJanie Lu goto fail; 18934df55fdeSJanie Lu } 18944df55fdeSJanie Lu } 18954df55fdeSJanie Lu } else { 18964df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 18974df55fdeSJanie Lu "nxge_n2_kt_serdes_init:port<%d> - " 18984df55fdeSJanie Lu "unsupported port mode %d", 18994df55fdeSJanie Lu portn, nxgep->mac.portmode)); 19004df55fdeSJanie Lu goto fail; 19014df55fdeSJanie Lu } 19024df55fdeSJanie Lu 19034df55fdeSJanie Lu NXGE_DELAY(20); 19044df55fdeSJanie Lu /* Clear the test register (offset 0x8004) */ 19054df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 19064df55fdeSJanie Lu ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 19074df55fdeSJanie Lu goto fail; 19084df55fdeSJanie Lu } 19094df55fdeSJanie Lu NXGE_DELAY(20); 19104df55fdeSJanie Lu 19114df55fdeSJanie Lu /* init TX channels */ 19124df55fdeSJanie Lu for (chan = 0; chan < 4; chan++) { 19134df55fdeSJanie Lu if (mode_1g) 19144df55fdeSJanie Lu tx_cfg_l.value = 0; 19154df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 19164df55fdeSJanie Lu ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK) 19174df55fdeSJanie Lu goto fail; 19184df55fdeSJanie Lu 19194df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 19204df55fdeSJanie Lu ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK) 19214df55fdeSJanie Lu goto fail; 19224df55fdeSJanie Lu 19234df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 19244df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 19254df55fdeSJanie Lu "chan %d tx_cfg_l 0x%x", portn, chan, tx_cfg_l.value)); 19264df55fdeSJanie Lu 19274df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 19284df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 19294df55fdeSJanie Lu "chan %d tx_cfg_h 0x%x", portn, chan, tx_cfg_h.value)); 19304df55fdeSJanie Lu } 19314df55fdeSJanie Lu 19324df55fdeSJanie Lu /* init RX channels */ 19334df55fdeSJanie Lu /* 1G mode only write to the first channel */ 19344df55fdeSJanie Lu for (chan = 0; chan < 4; chan++) { 19354df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 19364df55fdeSJanie Lu ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 19374df55fdeSJanie Lu != NXGE_OK) 19384df55fdeSJanie Lu goto fail; 19394df55fdeSJanie Lu 19404df55fdeSJanie Lu if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 19414df55fdeSJanie Lu ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 19424df55fdeSJanie Lu != NXGE_OK) 19434df55fdeSJanie Lu goto fail; 19444df55fdeSJanie Lu 19454df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 19464df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 19474df55fdeSJanie Lu "chan %d rx_cfg_l 0x%x", portn, chan, rx_cfg_l.value)); 19484df55fdeSJanie Lu 19494df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 19504df55fdeSJanie Lu "==> nxge_n2_kt_serdes_init port<%d>: " 19514df55fdeSJanie Lu "chan %d rx_cfg_h 0x%x", portn, chan, rx_cfg_h.value)); 19524df55fdeSJanie Lu } 19534df55fdeSJanie Lu 1954*89282175SSantwona Behera if (portn == 0) { 1955*89282175SSantwona Behera /* Wait for serdes to be ready */ 1956*89282175SSantwona Behera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 1957*89282175SSantwona Behera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1958*89282175SSantwona Behera if ((val & ESR_SIG_P0_BITS_MASK) != 1959*89282175SSantwona Behera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 1960*89282175SSantwona Behera ESR_SIG_XSERDES_RDY_P0 | 1961*89282175SSantwona Behera ESR_SIG_XDETECT_P0_CH3 | 1962*89282175SSantwona Behera ESR_SIG_XDETECT_P0_CH2 | 1963*89282175SSantwona Behera ESR_SIG_XDETECT_P0_CH1 | 1964*89282175SSantwona Behera ESR_SIG_XDETECT_P0_CH0)) 1965*89282175SSantwona Behera 1966*89282175SSantwona Behera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 1967*89282175SSantwona Behera else 1968*89282175SSantwona Behera break; 1969*89282175SSantwona Behera } 1970*89282175SSantwona Behera 1971*89282175SSantwona Behera if (i == MAX_SERDES_RDY_RETRIES) { 1972*89282175SSantwona Behera /* 1973*89282175SSantwona Behera * RDY signal stays low may due to the absent of the 1974*89282175SSantwona Behera * external PHY, it is not an error condition. 1975*89282175SSantwona Behera * But still print the message for the debugging 1976*89282175SSantwona Behera * purpose when link stays down 1977*89282175SSantwona Behera */ 1978*89282175SSantwona Behera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1979*89282175SSantwona Behera "nxge_n2_kt_serdes_init: " 1980*89282175SSantwona Behera "Serdes/signal for port<%d> not ready", portn)); 1981*89282175SSantwona Behera goto done; 1982*89282175SSantwona Behera } 1983*89282175SSantwona Behera } else if (portn == 1) { 1984*89282175SSantwona Behera /* Wait for serdes to be ready */ 1985*89282175SSantwona Behera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 1986*89282175SSantwona Behera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1987*89282175SSantwona Behera if ((val & ESR_SIG_P1_BITS_MASK) != 1988*89282175SSantwona Behera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 1989*89282175SSantwona Behera ESR_SIG_XSERDES_RDY_P1 | 1990*89282175SSantwona Behera ESR_SIG_XDETECT_P1_CH3 | 1991*89282175SSantwona Behera ESR_SIG_XDETECT_P1_CH2 | 1992*89282175SSantwona Behera ESR_SIG_XDETECT_P1_CH1 | 1993*89282175SSantwona Behera ESR_SIG_XDETECT_P1_CH0)) 1994*89282175SSantwona Behera 1995*89282175SSantwona Behera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 1996*89282175SSantwona Behera else 1997*89282175SSantwona Behera break; 1998*89282175SSantwona Behera } 1999*89282175SSantwona Behera 2000*89282175SSantwona Behera if (i == MAX_SERDES_RDY_RETRIES) { 2001*89282175SSantwona Behera /* 2002*89282175SSantwona Behera * RDY signal stays low may due to the absent of the 2003*89282175SSantwona Behera * external PHY, it is not an error condition. 2004*89282175SSantwona Behera * But still print the message for the debugging 2005*89282175SSantwona Behera * purpose when link stays down 2006*89282175SSantwona Behera */ 2007*89282175SSantwona Behera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2008*89282175SSantwona Behera "nxge_n2_kt_serdes_init: " 2009*89282175SSantwona Behera "Serdes/signal for port<%d> not ready", portn)); 2010*89282175SSantwona Behera goto done; 2011*89282175SSantwona Behera } 2012*89282175SSantwona Behera } 2013*89282175SSantwona Behera done: 2014*89282175SSantwona Behera 20154df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, MAC_CTL, 20164df55fdeSJanie Lu "<== nxge_n2_kt_serdes_init port<%d>", portn)); 20174df55fdeSJanie Lu 20184df55fdeSJanie Lu return (NXGE_OK); 20194df55fdeSJanie Lu fail: 20204df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20214df55fdeSJanie Lu "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 20224df55fdeSJanie Lu portn)); 20234df55fdeSJanie Lu 20244df55fdeSJanie Lu return (status); 202544961713Sgirish } 202644961713Sgirish 202759ac0c16Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */ 202844961713Sgirish 202959ac0c16Sdavemq static nxge_status_t 203059ac0c16Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep) 203144961713Sgirish { 203244961713Sgirish npi_handle_t handle; 203344961713Sgirish uint8_t portn; 2034321febdeSsbehera int chan, i; 203544961713Sgirish sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 203644961713Sgirish sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 203744961713Sgirish sr_glue_ctrl0_l_t glue_ctrl0_l; 203844961713Sgirish sr_glue_ctrl0_h_t glue_ctrl0_h; 203944961713Sgirish uint64_t val; 204044961713Sgirish uint16_t val16l; 204144961713Sgirish uint16_t val16h; 204244961713Sgirish nxge_status_t status = NXGE_OK; 204344961713Sgirish 204444961713Sgirish portn = nxgep->mac.portnum; 204544961713Sgirish 204644961713Sgirish if ((portn != 0) && (portn != 1)) 204744961713Sgirish return (NXGE_OK); 204844961713Sgirish 204959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 205059ac0c16Sdavemq "==> nxge_neptune_10G_serdes_init port<%d>", portn)); 205144961713Sgirish handle = nxgep->npi_handle; 205259ac0c16Sdavemq switch (portn) { 205359ac0c16Sdavemq case 0: 20544202ea4bSsbehera /* Reset Serdes */ 20554202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0); 20564202ea4bSsbehera NXGE_DELAY(20); 20574202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 20584202ea4bSsbehera NXGE_DELAY(2000); 20594202ea4bSsbehera 20604202ea4bSsbehera /* Configure Serdes to 10G mode */ 20614202ea4bSsbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 20624202ea4bSsbehera ESR_PLL_CFG_10G_SERDES); 20634202ea4bSsbehera 206459ac0c16Sdavemq ESR_REG_WR(handle, ESR_0_CONTROL_REG, 206559ac0c16Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 206659ac0c16Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 206759ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 206859ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 206959ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 207059ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 207159ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 207259ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 207359ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 207459ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 207559ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 207659ac0c16Sdavemq 207759ac0c16Sdavemq /* Set Serdes0 Internal Loopback if necessary */ 207859ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 207959ac0c16Sdavemq ESR_REG_WR(handle, 208059ac0c16Sdavemq ESR_0_TEST_CONFIG_REG, 208159ac0c16Sdavemq ESR_PAD_LOOPBACK_CH3 | 208259ac0c16Sdavemq ESR_PAD_LOOPBACK_CH2 | 208359ac0c16Sdavemq ESR_PAD_LOOPBACK_CH1 | 208459ac0c16Sdavemq ESR_PAD_LOOPBACK_CH0); 208559ac0c16Sdavemq } else { 208659ac0c16Sdavemq ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 208744961713Sgirish } 208859ac0c16Sdavemq break; 208959ac0c16Sdavemq case 1: 20904202ea4bSsbehera /* Reset Serdes */ 20914202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1); 20924202ea4bSsbehera NXGE_DELAY(20); 20934202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 20944202ea4bSsbehera NXGE_DELAY(2000); 20954202ea4bSsbehera 20964202ea4bSsbehera /* Configure Serdes to 10G mode */ 20974202ea4bSsbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 20984202ea4bSsbehera ESR_PLL_CFG_10G_SERDES); 20994202ea4bSsbehera 210059ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_CONTROL_REG, 210159ac0c16Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 210259ac0c16Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 210359ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 210459ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 210559ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 210659ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 210759ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 210859ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 210959ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 211059ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 211159ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 211259ac0c16Sdavemq 211359ac0c16Sdavemq /* Set Serdes1 Internal Loopback if necessary */ 211459ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 211559ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 211659ac0c16Sdavemq ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 | 211759ac0c16Sdavemq ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0); 211859ac0c16Sdavemq } else { 211959ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 212044961713Sgirish } 212159ac0c16Sdavemq break; 212259ac0c16Sdavemq default: 212359ac0c16Sdavemq /* Nothing to do here */ 212459ac0c16Sdavemq goto done; 212559ac0c16Sdavemq } 212644961713Sgirish 212759ac0c16Sdavemq /* init TX RX channels */ 212859ac0c16Sdavemq for (chan = 0; chan < 4; chan++) { 212959ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 213059ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 213159ac0c16Sdavemq &rx_tx_ctrl_l.value)) != NXGE_OK) 213244961713Sgirish goto fail; 213359ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 213459ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 213559ac0c16Sdavemq &rx_tx_ctrl_h.value)) != NXGE_OK) 213644961713Sgirish goto fail; 213759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 213859ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 213959ac0c16Sdavemq &glue_ctrl0_l.value)) != NXGE_OK) 214059ac0c16Sdavemq goto fail; 214159ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 214259ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 214359ac0c16Sdavemq &glue_ctrl0_h.value)) != NXGE_OK) 214459ac0c16Sdavemq goto fail; 214559ac0c16Sdavemq rx_tx_ctrl_l.bits.enstretch = 1; 214659ac0c16Sdavemq rx_tx_ctrl_h.bits.vmuxlo = 2; 214759ac0c16Sdavemq rx_tx_ctrl_h.bits.vpulselo = 2; 214859ac0c16Sdavemq glue_ctrl0_l.bits.rxlosenable = 1; 214959ac0c16Sdavemq glue_ctrl0_l.bits.samplerate = 0xF; 215059ac0c16Sdavemq glue_ctrl0_l.bits.thresholdcount = 0xFF; 215159ac0c16Sdavemq glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 215244961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 215359ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 215459ac0c16Sdavemq rx_tx_ctrl_l.value)) != NXGE_OK) 215544961713Sgirish goto fail; 215644961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 215759ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 215859ac0c16Sdavemq rx_tx_ctrl_h.value)) != NXGE_OK) 215944961713Sgirish goto fail; 216059ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 216159ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 216259ac0c16Sdavemq glue_ctrl0_l.value)) != NXGE_OK) 216344961713Sgirish goto fail; 216459ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 216559ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 216659ac0c16Sdavemq glue_ctrl0_h.value)) != NXGE_OK) 216744961713Sgirish goto fail; 216844961713Sgirish } 216944961713Sgirish 217059ac0c16Sdavemq /* Apply Tx core reset */ 217159ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 217259ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 217359ac0c16Sdavemq (uint16_t)0)) != NXGE_OK) 217459ac0c16Sdavemq goto fail; 217559ac0c16Sdavemq 217659ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 217759ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 217859ac0c16Sdavemq NXGE_OK) 217959ac0c16Sdavemq goto fail; 218059ac0c16Sdavemq 218159ac0c16Sdavemq NXGE_DELAY(200); 218259ac0c16Sdavemq 218359ac0c16Sdavemq /* Apply Rx core reset */ 218459ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 218559ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 218659ac0c16Sdavemq NXGE_OK) 218759ac0c16Sdavemq goto fail; 218859ac0c16Sdavemq 218959ac0c16Sdavemq NXGE_DELAY(200); 219059ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 219159ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) 219259ac0c16Sdavemq goto fail; 219359ac0c16Sdavemq 219459ac0c16Sdavemq NXGE_DELAY(200); 219559ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 219659ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 219759ac0c16Sdavemq &val16l)) != NXGE_OK) 219859ac0c16Sdavemq goto fail; 219959ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 220059ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) 220159ac0c16Sdavemq goto fail; 220259ac0c16Sdavemq if ((val16l != 0) || (val16h != 0)) { 220359ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2204d81011f0Ssbehera "Failed to reset port<%d> XAUI Serdes " 2205d81011f0Ssbehera "(val16l 0x%x val16h 0x%x)", 2206d81011f0Ssbehera portn, val16l, val16h)); 220759ac0c16Sdavemq } 220859ac0c16Sdavemq 220959ac0c16Sdavemq if (portn == 0) { 2210321febdeSsbehera /* Wait for serdes to be ready */ 2211321febdeSsbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 2212321febdeSsbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2213321febdeSsbehera if ((val & ESR_SIG_P0_BITS_MASK) != 2214321febdeSsbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 2215321febdeSsbehera ESR_SIG_XSERDES_RDY_P0 | 2216321febdeSsbehera ESR_SIG_XDETECT_P0_CH3 | 2217321febdeSsbehera ESR_SIG_XDETECT_P0_CH2 | 2218321febdeSsbehera ESR_SIG_XDETECT_P0_CH1 | 2219321febdeSsbehera ESR_SIG_XDETECT_P0_CH0)) 2220321febdeSsbehera 2221321febdeSsbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 2222321febdeSsbehera else 2223321febdeSsbehera break; 2224321febdeSsbehera } 2225321febdeSsbehera 2226321febdeSsbehera if (i == MAX_SERDES_RDY_RETRIES) { 2227ab6abb7aSjoycey /* 2228ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 2229ab6abb7aSjoycey * external PHY, it is not an error condition. But still 2230ab6abb7aSjoycey * print the message for the debugging purpose when link 2231ab6abb7aSjoycey * stays down 2232ab6abb7aSjoycey */ 2233774da109Stc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2234321febdeSsbehera "nxge_neptune_10G_serdes_init: " 2235321febdeSsbehera "Serdes/signal for port<%d> not ready", portn)); 223600161856Syc goto done; 223759ac0c16Sdavemq } 223859ac0c16Sdavemq } else if (portn == 1) { 2239321febdeSsbehera /* Wait for serdes to be ready */ 2240321febdeSsbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 2241321febdeSsbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2242321febdeSsbehera if ((val & ESR_SIG_P1_BITS_MASK) != 2243321febdeSsbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 2244321febdeSsbehera ESR_SIG_XSERDES_RDY_P1 | 2245321febdeSsbehera ESR_SIG_XDETECT_P1_CH3 | 2246321febdeSsbehera ESR_SIG_XDETECT_P1_CH2 | 2247321febdeSsbehera ESR_SIG_XDETECT_P1_CH1 | 2248321febdeSsbehera ESR_SIG_XDETECT_P1_CH0)) 2249321febdeSsbehera 2250321febdeSsbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 2251321febdeSsbehera else 2252321febdeSsbehera break; 2253321febdeSsbehera } 2254321febdeSsbehera 2255321febdeSsbehera if (i == MAX_SERDES_RDY_RETRIES) { 2256ab6abb7aSjoycey /* 2257ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 2258ab6abb7aSjoycey * external PHY, it is not an error condition. But still 2259ab6abb7aSjoycey * print the message for the debugging purpose when link 2260ab6abb7aSjoycey * stays down 2261ab6abb7aSjoycey */ 2262774da109Stc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2263321febdeSsbehera "nxge_neptune_10G_serdes_init: " 2264321febdeSsbehera "Serdes/signal for port<%d> not ready", portn)); 226500161856Syc goto done; 226644961713Sgirish } 226744961713Sgirish } 226844961713Sgirish 226944961713Sgirish done: 227059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 227159ac0c16Sdavemq "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 227259ac0c16Sdavemq 227344961713Sgirish return (NXGE_OK); 227444961713Sgirish fail: 22752d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 227659ac0c16Sdavemq "nxge_neptune_10G_serdes_init: " 227759ac0c16Sdavemq "Failed to initialize Neptune serdes for port<%d>", portn)); 227844961713Sgirish 227944961713Sgirish return (status); 228044961713Sgirish } 228144961713Sgirish 228259ac0c16Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 228344961713Sgirish 228459ac0c16Sdavemq static nxge_status_t 228559ac0c16Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep) 228644961713Sgirish { 228759ac0c16Sdavemq npi_handle_t handle; 228859ac0c16Sdavemq uint8_t portn; 2289d81011f0Ssbehera int chan; 2290d81011f0Ssbehera sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 2291d81011f0Ssbehera sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 2292d81011f0Ssbehera sr_glue_ctrl0_l_t glue_ctrl0_l; 2293d81011f0Ssbehera sr_glue_ctrl0_h_t glue_ctrl0_h; 229459ac0c16Sdavemq uint64_t val; 2295d81011f0Ssbehera uint16_t val16l; 2296d81011f0Ssbehera uint16_t val16h; 2297d81011f0Ssbehera nxge_status_t status = NXGE_OK; 229844961713Sgirish 229944961713Sgirish portn = nxgep->mac.portnum; 230044961713Sgirish 230159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 230259ac0c16Sdavemq "==> nxge_1G_serdes_init port<%d>", portn)); 230344961713Sgirish 230459ac0c16Sdavemq handle = nxgep->npi_handle; 230544961713Sgirish 230659ac0c16Sdavemq switch (portn) { 230759ac0c16Sdavemq case 0: 2308d81011f0Ssbehera /* Assert the reset register */ 2309d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 2310d81011f0Ssbehera val |= ESR_RESET_0; 2311d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 2312d81011f0Ssbehera 2313d81011f0Ssbehera /* Set the PLL register to 0x79 */ 2314d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 2315d81011f0Ssbehera ESR_PLL_CFG_1G_SERDES); 2316d81011f0Ssbehera 2317d81011f0Ssbehera /* Set the control register to 0x249249f */ 2318d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES); 2319d81011f0Ssbehera 2320d81011f0Ssbehera /* Set Serdes0 Internal Loopback if necessary */ 2321d81011f0Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 2322d81011f0Ssbehera /* Set pad loopback modes 0xaa */ 2323d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 2324d81011f0Ssbehera ESR_TSTCFG_LBTEST_PAD); 2325d81011f0Ssbehera } else { 2326d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 2327d81011f0Ssbehera } 2328d81011f0Ssbehera 2329d81011f0Ssbehera /* Deassert the reset register */ 2330d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 2331d81011f0Ssbehera val &= ~ESR_RESET_0; 2332d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 233359ac0c16Sdavemq break; 2334d81011f0Ssbehera 233559ac0c16Sdavemq case 1: 2336d81011f0Ssbehera /* Assert the reset register */ 2337d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 2338d81011f0Ssbehera val |= ESR_RESET_1; 2339d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 2340d81011f0Ssbehera 2341d81011f0Ssbehera /* Set PLL register to 0x79 */ 2342d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 2343d81011f0Ssbehera ESR_PLL_CFG_1G_SERDES); 2344d81011f0Ssbehera 2345d81011f0Ssbehera /* Set the control register to 0x249249f */ 2346d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES); 2347d81011f0Ssbehera 2348d81011f0Ssbehera /* Set Serdes1 Internal Loopback if necessary */ 2349d81011f0Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 2350d81011f0Ssbehera /* Set pad loopback mode 0xaa */ 2351d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 2352d81011f0Ssbehera ESR_TSTCFG_LBTEST_PAD); 2353d81011f0Ssbehera } else { 2354d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 2355d81011f0Ssbehera } 2356d81011f0Ssbehera 2357d81011f0Ssbehera /* Deassert the reset register */ 2358d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 2359d81011f0Ssbehera val &= ~ESR_RESET_1; 2360d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 236159ac0c16Sdavemq break; 2362d81011f0Ssbehera 236359ac0c16Sdavemq default: 2364d81011f0Ssbehera /* Nothing to do here */ 2365d81011f0Ssbehera goto done; 2366d81011f0Ssbehera } 2367d81011f0Ssbehera 2368d81011f0Ssbehera /* init TX RX channels */ 2369d81011f0Ssbehera for (chan = 0; chan < 4; chan++) { 2370d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2371d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2372d81011f0Ssbehera &rx_tx_ctrl_l.value)) != NXGE_OK) { 2373d81011f0Ssbehera goto fail; 2374d81011f0Ssbehera } 2375d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2376d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2377d81011f0Ssbehera &rx_tx_ctrl_h.value)) != NXGE_OK) { 2378d81011f0Ssbehera goto fail; 2379d81011f0Ssbehera } 2380d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2381d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2382d81011f0Ssbehera &glue_ctrl0_l.value)) != NXGE_OK) { 2383d81011f0Ssbehera goto fail; 2384d81011f0Ssbehera } 2385d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2386d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2387d81011f0Ssbehera &glue_ctrl0_h.value)) != NXGE_OK) { 2388d81011f0Ssbehera goto fail; 2389d81011f0Ssbehera } 2390d81011f0Ssbehera 2391d81011f0Ssbehera rx_tx_ctrl_l.bits.enstretch = 1; 2392d81011f0Ssbehera rx_tx_ctrl_h.bits.vmuxlo = 2; 2393d81011f0Ssbehera rx_tx_ctrl_h.bits.vpulselo = 2; 2394d81011f0Ssbehera glue_ctrl0_l.bits.rxlosenable = 1; 2395d81011f0Ssbehera glue_ctrl0_l.bits.samplerate = 0xF; 2396d81011f0Ssbehera glue_ctrl0_l.bits.thresholdcount = 0xFF; 2397d81011f0Ssbehera glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 2398d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2399d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2400d81011f0Ssbehera rx_tx_ctrl_l.value)) != NXGE_OK) { 2401d81011f0Ssbehera goto fail; 2402d81011f0Ssbehera } 2403d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2404d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2405d81011f0Ssbehera rx_tx_ctrl_h.value)) != NXGE_OK) { 2406d81011f0Ssbehera goto fail; 2407d81011f0Ssbehera } 2408d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2409d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2410d81011f0Ssbehera glue_ctrl0_l.value)) != NXGE_OK) { 2411d81011f0Ssbehera goto fail; 2412d81011f0Ssbehera } 2413d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2414d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2415d81011f0Ssbehera glue_ctrl0_h.value)) != NXGE_OK) { 2416d81011f0Ssbehera goto fail; 2417d81011f0Ssbehera } 2418d81011f0Ssbehera } 2419d81011f0Ssbehera 2420d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2421d81011f0Ssbehera ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) { 2422d81011f0Ssbehera goto fail; 2423d81011f0Ssbehera } 2424d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2425d81011f0Ssbehera ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 2426d81011f0Ssbehera goto fail; 2427d81011f0Ssbehera } 2428d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2429d81011f0Ssbehera ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) { 2430d81011f0Ssbehera goto fail; 2431d81011f0Ssbehera } 2432d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2433d81011f0Ssbehera ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 243459ac0c16Sdavemq goto fail; 243544961713Sgirish } 243644961713Sgirish 2437d81011f0Ssbehera /* Apply Tx core reset */ 2438d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2439d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) { 2440d81011f0Ssbehera goto fail; 2441d81011f0Ssbehera } 2442d81011f0Ssbehera 2443d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2444d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 2445d81011f0Ssbehera NXGE_OK) { 2446d81011f0Ssbehera goto fail; 2447d81011f0Ssbehera } 2448d81011f0Ssbehera 2449d81011f0Ssbehera NXGE_DELAY(200); 2450d81011f0Ssbehera 2451d81011f0Ssbehera /* Apply Rx core reset */ 2452d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2453d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 2454d81011f0Ssbehera NXGE_OK) { 2455d81011f0Ssbehera goto fail; 2456d81011f0Ssbehera } 2457d81011f0Ssbehera 2458d81011f0Ssbehera NXGE_DELAY(200); 2459d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2460d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) { 2461d81011f0Ssbehera goto fail; 2462d81011f0Ssbehera } 2463d81011f0Ssbehera 2464d81011f0Ssbehera NXGE_DELAY(200); 2465d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2466d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) { 2467d81011f0Ssbehera goto fail; 2468d81011f0Ssbehera } 2469d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2470d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) { 2471d81011f0Ssbehera goto fail; 2472d81011f0Ssbehera } 2473d81011f0Ssbehera if ((val16l != 0) || (val16h != 0)) { 2474d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2475d81011f0Ssbehera "Failed to reset port<%d> XAUI Serdes " 2476d81011f0Ssbehera "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h)); 2477d81011f0Ssbehera status = NXGE_ERROR; 2478d81011f0Ssbehera goto fail; 2479d81011f0Ssbehera } 2480d81011f0Ssbehera 2481d81011f0Ssbehera NXGE_DELAY(200); 2482d81011f0Ssbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2483d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2484d81011f0Ssbehera "nxge_neptune_serdes_init: read internal signal reg port<%d> " 2485d81011f0Ssbehera "val 0x%x", portn, val)); 2486d81011f0Ssbehera if (portn == 0) { 2487d81011f0Ssbehera if ((val & ESR_SIG_P0_BITS_MASK_1G) != 2488d81011f0Ssbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) { 2489ab6abb7aSjoycey /* 2490ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 2491ab6abb7aSjoycey * external PHY, it is not an error condition. But still 2492ab6abb7aSjoycey * print the message for the debugging purpose when link 2493ab6abb7aSjoycey * stays down 2494ab6abb7aSjoycey */ 2495d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2496ab6abb7aSjoycey "nxge_neptune_1G_serdes_init: " 2497ab6abb7aSjoycey "Serdes/signal for port<%d> not ready", portn)); 249800161856Syc goto done; 2499d81011f0Ssbehera } 2500d81011f0Ssbehera } else if (portn == 1) { 2501d81011f0Ssbehera if ((val & ESR_SIG_P1_BITS_MASK_1G) != 2502d81011f0Ssbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) { 2503ab6abb7aSjoycey /* 2504ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 2505ab6abb7aSjoycey * external PHY, it is not an error condition. But still 2506ab6abb7aSjoycey * print the message for the debugging purpose when link 2507ab6abb7aSjoycey * stays down 2508ab6abb7aSjoycey */ 2509d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2510ab6abb7aSjoycey "nxge_neptune_1G_serdes_init: " 2511ab6abb7aSjoycey "Serdes/signal for port<%d> not ready", portn)); 251200161856Syc goto done; 251300161856Syc 2514d81011f0Ssbehera } 2515d81011f0Ssbehera } 2516d81011f0Ssbehera done: 251759ac0c16Sdavemq 251859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 251959ac0c16Sdavemq "<== nxge_1G_serdes_init port<%d>", portn)); 252044961713Sgirish return (NXGE_OK); 252159ac0c16Sdavemq fail: 2522d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 252359ac0c16Sdavemq "nxge_1G_serdes_init: " 252459ac0c16Sdavemq "Failed to initialize Neptune serdes for port<%d>", 252559ac0c16Sdavemq portn)); 252659ac0c16Sdavemq 2527d81011f0Ssbehera return (status); 252844961713Sgirish } 252944961713Sgirish 25302d17280bSsbehera /* Initialize the BCM 8704 xcvr */ 253144961713Sgirish 253259ac0c16Sdavemq static nxge_status_t 25332d17280bSsbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep) 253444961713Sgirish { 253544961713Sgirish uint16_t val; 253644961713Sgirish #ifdef NXGE_DEBUG 253714ea4bb7Ssd uint8_t portn; 253844961713Sgirish uint16_t val1; 253944961713Sgirish #endif 254044961713Sgirish uint8_t phy_port_addr; 254144961713Sgirish pmd_tx_control_t tx_ctl; 254244961713Sgirish control_t ctl; 254344961713Sgirish phyxs_control_t phyxs_ctl; 254444961713Sgirish pcs_control_t pcs_ctl; 254544961713Sgirish uint32_t delay = 0; 254644961713Sgirish optics_dcntr_t op_ctr; 254744961713Sgirish nxge_status_t status = NXGE_OK; 254814ea4bb7Ssd #ifdef NXGE_DEBUG 254944961713Sgirish portn = nxgep->mac.portnum; 255014ea4bb7Ssd #endif 25512d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 255259ac0c16Sdavemq portn)); 255344961713Sgirish 255459ac0c16Sdavemq phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 255559ac0c16Sdavemq 255659ac0c16Sdavemq /* Reset the transceiver */ 255759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 255859ac0c16Sdavemq BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 255959ac0c16Sdavemq goto fail; 256059ac0c16Sdavemq 256159ac0c16Sdavemq phyxs_ctl.bits.reset = 1; 256259ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 256359ac0c16Sdavemq BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 256459ac0c16Sdavemq goto fail; 256559ac0c16Sdavemq 256659ac0c16Sdavemq do { 256759ac0c16Sdavemq drv_usecwait(500); 256859ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 256959ac0c16Sdavemq BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 257059ac0c16Sdavemq &phyxs_ctl.value)) != NXGE_OK) 257159ac0c16Sdavemq goto fail; 257259ac0c16Sdavemq delay++; 257359ac0c16Sdavemq } while ((phyxs_ctl.bits.reset) && (delay < 100)); 257459ac0c16Sdavemq if (delay == 100) { 257559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 257659ac0c16Sdavemq "failed to reset Transceiver on port<%d>", portn)); 257759ac0c16Sdavemq status = NXGE_ERROR; 257859ac0c16Sdavemq goto fail; 257959ac0c16Sdavemq } 258044961713Sgirish 258159ac0c16Sdavemq /* Set to 0x7FBF */ 258259ac0c16Sdavemq ctl.value = 0; 258359ac0c16Sdavemq ctl.bits.res1 = 0x3F; 258459ac0c16Sdavemq ctl.bits.optxon_lvl = 1; 258559ac0c16Sdavemq ctl.bits.oprxflt_lvl = 1; 258659ac0c16Sdavemq ctl.bits.optrxlos_lvl = 1; 258759ac0c16Sdavemq ctl.bits.optxflt_lvl = 1; 258859ac0c16Sdavemq ctl.bits.opprflt_lvl = 1; 258959ac0c16Sdavemq ctl.bits.obtmpflt_lvl = 1; 259059ac0c16Sdavemq ctl.bits.opbiasflt_lvl = 1; 259159ac0c16Sdavemq ctl.bits.optxrst_lvl = 1; 259259ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 259359ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 259459ac0c16Sdavemq != NXGE_OK) 259559ac0c16Sdavemq goto fail; 259659ac0c16Sdavemq 259759ac0c16Sdavemq /* Set to 0x164 */ 259859ac0c16Sdavemq tx_ctl.value = 0; 259959ac0c16Sdavemq tx_ctl.bits.tsck_lpwren = 1; 260059ac0c16Sdavemq tx_ctl.bits.tx_dac_txck = 0x2; 260159ac0c16Sdavemq tx_ctl.bits.tx_dac_txd = 0x1; 260259ac0c16Sdavemq tx_ctl.bits.xfp_clken = 1; 260359ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 260459ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 260559ac0c16Sdavemq tx_ctl.value)) != NXGE_OK) 260659ac0c16Sdavemq goto fail; 260744961713Sgirish /* 260859ac0c16Sdavemq * According to Broadcom's instruction, SW needs to read 260959ac0c16Sdavemq * back these registers twice after written. 261044961713Sgirish */ 261159ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 261259ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 261359ac0c16Sdavemq != NXGE_OK) 261459ac0c16Sdavemq goto fail; 261544961713Sgirish 261659ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 261759ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 261859ac0c16Sdavemq != NXGE_OK) 261959ac0c16Sdavemq goto fail; 262044961713Sgirish 262159ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 262259ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 262359ac0c16Sdavemq != NXGE_OK) 262459ac0c16Sdavemq goto fail; 262544961713Sgirish 262659ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 262759ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 262859ac0c16Sdavemq != NXGE_OK) 262959ac0c16Sdavemq goto fail; 263044961713Sgirish 263159ac0c16Sdavemq /* Enable Tx and Rx LEDs to be driven by traffic */ 263259ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 263359ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 263459ac0c16Sdavemq &op_ctr.value)) != NXGE_OK) 263559ac0c16Sdavemq goto fail; 2636cb9d3ae6Smisaki if (NXGE_IS_XAUI_PLATFORM(nxgep)) { 2637cb9d3ae6Smisaki op_ctr.bits.gpio_sel = 0x1; 2638cb9d3ae6Smisaki } else { 2639cb9d3ae6Smisaki op_ctr.bits.gpio_sel = 0x3; 2640cb9d3ae6Smisaki } 264159ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 264259ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 264359ac0c16Sdavemq op_ctr.value)) != NXGE_OK) 264459ac0c16Sdavemq goto fail; 264544961713Sgirish 264659ac0c16Sdavemq NXGE_DELAY(1000000); 264744961713Sgirish 264859ac0c16Sdavemq /* Set BCM8704 Internal Loopback mode if necessary */ 264959ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 265059ac0c16Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 265159ac0c16Sdavemq != NXGE_OK) 265259ac0c16Sdavemq goto fail; 265359ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 265459ac0c16Sdavemq pcs_ctl.bits.loopback = 1; 265559ac0c16Sdavemq else 265659ac0c16Sdavemq pcs_ctl.bits.loopback = 0; 265759ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 265859ac0c16Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 265959ac0c16Sdavemq != NXGE_OK) 266059ac0c16Sdavemq goto fail; 266144961713Sgirish 266259ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 266359ac0c16Sdavemq if (status != NXGE_OK) 266459ac0c16Sdavemq goto fail; 266559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 266659ac0c16Sdavemq "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 266759ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 266859ac0c16Sdavemq if (status != NXGE_OK) 266959ac0c16Sdavemq goto fail; 267059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 267159ac0c16Sdavemq "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 267259ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 267359ac0c16Sdavemq if (status != NXGE_OK) 267459ac0c16Sdavemq goto fail; 267559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 267659ac0c16Sdavemq "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 267744961713Sgirish 267859ac0c16Sdavemq #ifdef NXGE_DEBUG 267959ac0c16Sdavemq /* Diagnose link issue if link is not up */ 268059ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 268159ac0c16Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 268259ac0c16Sdavemq &val); 268359ac0c16Sdavemq if (status != NXGE_OK) 268459ac0c16Sdavemq goto fail; 268544961713Sgirish 268659ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 268752ccf843Smisaki BCM8704_USER_DEV3_ADDR, BCM8704_USER_ANALOG_STATUS0_REG, &val); 268859ac0c16Sdavemq if (status != NXGE_OK) 268959ac0c16Sdavemq goto fail; 269044961713Sgirish 269159ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 269252ccf843Smisaki BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1); 269359ac0c16Sdavemq if (status != NXGE_OK) 269459ac0c16Sdavemq goto fail; 269544961713Sgirish 269659ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 269752ccf843Smisaki BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1); 269859ac0c16Sdavemq if (status != NXGE_OK) 269959ac0c16Sdavemq goto fail; 270044961713Sgirish 270159ac0c16Sdavemq if (val != 0x3FC) { 270259ac0c16Sdavemq if ((val == 0x43BC) && (val1 != 0)) { 270359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 270459ac0c16Sdavemq "Cable not connected to peer or bad" 270559ac0c16Sdavemq " cable on port<%d>\n", portn)); 270659ac0c16Sdavemq } else if (val == 0x639C) { 270759ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 270859ac0c16Sdavemq "Optical module (XFP) is bad or absent" 270959ac0c16Sdavemq " on port<%d>\n", portn)); 271059ac0c16Sdavemq } 271159ac0c16Sdavemq } 271259ac0c16Sdavemq #endif 271344961713Sgirish 27142d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 27152d17280bSsbehera portn)); 27162d17280bSsbehera return (NXGE_OK); 27172d17280bSsbehera 27182d17280bSsbehera fail: 27192d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27202d17280bSsbehera "nxge_BCM8704_xcvr_init: failed to initialize transceiver for " 27212d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 27222d17280bSsbehera return (NXGE_ERROR); 27232d17280bSsbehera } 27242d17280bSsbehera 27252d17280bSsbehera /* Initialize the BCM 8706 Transceiver */ 27262d17280bSsbehera 27272d17280bSsbehera static nxge_status_t 27282d17280bSsbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep) 27292d17280bSsbehera { 27302d17280bSsbehera uint8_t phy_port_addr; 27312d17280bSsbehera phyxs_control_t phyxs_ctl; 27322d17280bSsbehera pcs_control_t pcs_ctl; 27332d17280bSsbehera uint32_t delay = 0; 27342d17280bSsbehera optics_dcntr_t op_ctr; 27352d17280bSsbehera nxge_status_t status = NXGE_OK; 27362d17280bSsbehera #ifdef NXGE_DEBUG 27372d17280bSsbehera uint8_t portn = nxgep->mac.portnum; 27382d17280bSsbehera #endif 27392d17280bSsbehera 27402d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 27412d17280bSsbehera portn)); 27422d17280bSsbehera 27432d17280bSsbehera phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 27442d17280bSsbehera 27452d17280bSsbehera /* Reset the transceiver */ 27462d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 27472d17280bSsbehera BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 27482d17280bSsbehera goto fail; 27492d17280bSsbehera 27502d17280bSsbehera phyxs_ctl.bits.reset = 1; 27512d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 27522d17280bSsbehera BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 27532d17280bSsbehera goto fail; 27542d17280bSsbehera do { 27552d17280bSsbehera drv_usecwait(500); 27562d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 27572d17280bSsbehera BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 27582d17280bSsbehera &phyxs_ctl.value)) != NXGE_OK) 27592d17280bSsbehera goto fail; 27602d17280bSsbehera delay++; 27612d17280bSsbehera } while ((phyxs_ctl.bits.reset) && (delay < 100)); 27622d17280bSsbehera 27632d17280bSsbehera if (delay == 100) { 27642d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 27652d17280bSsbehera "failed to reset Transceiver on port<%d>", portn)); 27662d17280bSsbehera status = NXGE_ERROR; 27672d17280bSsbehera goto fail; 27682d17280bSsbehera } 27692d17280bSsbehera 27702d17280bSsbehera NXGE_DELAY(1000000); 27712d17280bSsbehera 27722d17280bSsbehera /* Set BCM8706 Internal Loopback mode if necessary */ 27732d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 27742d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 27752d17280bSsbehera != NXGE_OK) 27762d17280bSsbehera goto fail; 27772d17280bSsbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 27782d17280bSsbehera pcs_ctl.bits.loopback = 1; 27792d17280bSsbehera else 27802d17280bSsbehera pcs_ctl.bits.loopback = 0; 27812d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 27822d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 27832d17280bSsbehera != NXGE_OK) 27842d17280bSsbehera goto fail; 27852d17280bSsbehera 27862d17280bSsbehera /* Enable Tx and Rx LEDs to be driven by traffic */ 27872d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 27882d17280bSsbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 27892d17280bSsbehera &op_ctr.value)) != NXGE_OK) 27902d17280bSsbehera goto fail; 27912d17280bSsbehera op_ctr.bits.gpio_sel = 0x3; 27922d17280bSsbehera op_ctr.bits.res2 = 0x1; 27932d17280bSsbehera 27942d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 27952d17280bSsbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 27962d17280bSsbehera op_ctr.value)) != NXGE_OK) 27972d17280bSsbehera goto fail; 27982d17280bSsbehera 27992d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 28002d17280bSsbehera portn)); 28012d17280bSsbehera return (NXGE_OK); 28022d17280bSsbehera 28032d17280bSsbehera fail: 28042d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 28052d17280bSsbehera "nxge_BCM8706_xcvr_init: failed to initialize transceiver for " 28062d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 28072d17280bSsbehera return (status); 28082d17280bSsbehera } 28092d17280bSsbehera 2810*89282175SSantwona Behera static int 2811*89282175SSantwona Behera nxge_nlp2020_i2c_read(p_nxge_t nxgep, uint8_t ctrl_port, uint16_t address, 2812*89282175SSantwona Behera uint16_t reg, uint8_t *data) 2813*89282175SSantwona Behera { 2814*89282175SSantwona Behera int phy_dev, phy_reg; 2815*89282175SSantwona Behera uint16_t phy_data = 0; 2816*89282175SSantwona Behera uint16_t stat; 2817*89282175SSantwona Behera uint8_t count = 100; 2818*89282175SSantwona Behera 2819*89282175SSantwona Behera /* 2820*89282175SSantwona Behera * NLP2020_I2C_SNOOP_ADDR_REG [15:9][1] - Address 2821*89282175SSantwona Behera * NLP2020_I2C_SNOOP_ADDR_REG[7:0] - register in the xcvr's i2c 2822*89282175SSantwona Behera */ 2823*89282175SSantwona Behera phy_dev = NLP2020_I2C_SNOOP_DEV_ADDR; 2824*89282175SSantwona Behera phy_reg = NLP2020_I2C_SNOOP_ADDR_REG; 2825*89282175SSantwona Behera phy_data = ((address + 1) << NLP2020_XCVR_I2C_ADDR_SH) | reg; 2826*89282175SSantwona Behera if (nxge_mdio_write(nxgep, ctrl_port, 2827*89282175SSantwona Behera phy_dev, phy_reg, phy_data) != NXGE_OK) 2828*89282175SSantwona Behera goto fail; 2829*89282175SSantwona Behera 2830*89282175SSantwona Behera phy_reg = NLP2020_I2C_SNOOP_STAT_REG; 2831*89282175SSantwona Behera (void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg, &stat); 2832*89282175SSantwona Behera while ((stat != 0x01) && (count-- > 0)) { 2833*89282175SSantwona Behera (void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg, 2834*89282175SSantwona Behera &stat); 2835*89282175SSantwona Behera } 2836*89282175SSantwona Behera if (count) { 2837*89282175SSantwona Behera phy_reg = NLP2020_I2C_SNOOP_DATA_REG; 2838*89282175SSantwona Behera (void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg, 2839*89282175SSantwona Behera &phy_data); 2840*89282175SSantwona Behera *data = (phy_data >> 8); 2841*89282175SSantwona Behera return (0); 2842*89282175SSantwona Behera } 2843*89282175SSantwona Behera fail: 2844*89282175SSantwona Behera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2845*89282175SSantwona Behera "nxge_nlp2020_i2c_read: FAILED")); 2846*89282175SSantwona Behera return (1); 2847*89282175SSantwona Behera 2848*89282175SSantwona Behera } 2849*89282175SSantwona Behera 2850*89282175SSantwona Behera /* Initialize the Netlogic AEL2020 Transceiver */ 2851*89282175SSantwona Behera 2852*89282175SSantwona Behera #define NLP_INI_WAIT 1 2853*89282175SSantwona Behera #define NLP_INI_STOP 0 2854*89282175SSantwona Behera 2855*89282175SSantwona Behera static nxge_nlp_initseq_t nlp2020_revC_fiber_init[] = { 2856*89282175SSantwona Behera {0x1C003, 0x3101}, 2857*89282175SSantwona Behera {0x1CC01, 0x488a}, 2858*89282175SSantwona Behera {0x1CB1B, 0x0200}, 2859*89282175SSantwona Behera {0x1CB1C, 0x00f0}, 2860*89282175SSantwona Behera {0x1CC06, 0x00e0}, 2861*89282175SSantwona Behera {NLP_INI_STOP, 0}, 2862*89282175SSantwona Behera }; 2863*89282175SSantwona Behera 2864*89282175SSantwona Behera static nxge_nlp_initseq_t nlp2020_revC_copper_init[] = { 2865*89282175SSantwona Behera 2866*89282175SSantwona Behera {0x1C003, 0x3101}, 2867*89282175SSantwona Behera {0x1CD40, 0x0001}, 2868*89282175SSantwona Behera 2869*89282175SSantwona Behera {0x1CA12, 0x0100}, 2870*89282175SSantwona Behera {0x1CA22, 0x0100}, 2871*89282175SSantwona Behera {0x1CA42, 0x0100}, 2872*89282175SSantwona Behera {0x1C20D, 0x0002}, 2873*89282175SSantwona Behera {NLP_INI_WAIT, 100}, 2874*89282175SSantwona Behera 2875*89282175SSantwona Behera {0x1ff28, 0x4001}, 2876*89282175SSantwona Behera {0x1ff2A, 0x004A}, 2877*89282175SSantwona Behera {NLP_INI_WAIT, 500}, 2878*89282175SSantwona Behera 2879*89282175SSantwona Behera {0x1d000, 0x5200}, 2880*89282175SSantwona Behera {NLP_INI_WAIT, 500}, 2881*89282175SSantwona Behera 2882*89282175SSantwona Behera {0x1d800, 0x4009}, 2883*89282175SSantwona Behera {0x1d801, 0x2fff}, 2884*89282175SSantwona Behera {0x1d802, 0x300f}, 2885*89282175SSantwona Behera {0x1d803, 0x40aa}, 2886*89282175SSantwona Behera {0x1d804, 0x401c}, 2887*89282175SSantwona Behera {0x1d805, 0x401e}, 2888*89282175SSantwona Behera {0x1d806, 0x20c5}, 2889*89282175SSantwona Behera {0x1d807, 0x3c05}, 2890*89282175SSantwona Behera {0x1d808, 0x6536}, 2891*89282175SSantwona Behera {0x1d809, 0x2fe4}, 2892*89282175SSantwona Behera {0x1d80a, 0x3dc4}, 2893*89282175SSantwona Behera {0x1d80b, 0x6624}, 2894*89282175SSantwona Behera {0x1d80c, 0x2ff4}, 2895*89282175SSantwona Behera {0x1d80d, 0x3dc4}, 2896*89282175SSantwona Behera {0x1d80e, 0x2035}, 2897*89282175SSantwona Behera {0x1d80f, 0x30a5}, 2898*89282175SSantwona Behera {0x1d810, 0x6524}, 2899*89282175SSantwona Behera {0x1d811, 0x2ca2}, 2900*89282175SSantwona Behera {0x1d812, 0x3012}, 2901*89282175SSantwona Behera {0x1d813, 0x1002}, 2902*89282175SSantwona Behera {0x1d814, 0x2882}, 2903*89282175SSantwona Behera {0x1d815, 0x3022}, 2904*89282175SSantwona Behera {0x1d816, 0x1002}, 2905*89282175SSantwona Behera {0x1d817, 0x2972}, 2906*89282175SSantwona Behera {0x1d818, 0x3022}, 2907*89282175SSantwona Behera {0x1d819, 0x1002}, 2908*89282175SSantwona Behera {0x1d81a, 0x2892}, 2909*89282175SSantwona Behera {0x1d81b, 0x3012}, 2910*89282175SSantwona Behera {0x1d81c, 0x1002}, 2911*89282175SSantwona Behera {0x1d81d, 0x24e2}, 2912*89282175SSantwona Behera {0x1d81e, 0x3022}, 2913*89282175SSantwona Behera {0x1d81f, 0x1002}, 2914*89282175SSantwona Behera {0x1d820, 0x27e2}, 2915*89282175SSantwona Behera {0x1d821, 0x3012}, 2916*89282175SSantwona Behera {0x1d822, 0x1002}, 2917*89282175SSantwona Behera {0x1d823, 0x2422}, 2918*89282175SSantwona Behera {0x1d824, 0x3022}, 2919*89282175SSantwona Behera {0x1d825, 0x1002}, 2920*89282175SSantwona Behera {0x1d826, 0x22cd}, 2921*89282175SSantwona Behera {0x1d827, 0x301d}, 2922*89282175SSantwona Behera {0x1d828, 0x2992}, 2923*89282175SSantwona Behera {0x1d829, 0x3022}, 2924*89282175SSantwona Behera {0x1d82a, 0x1002}, 2925*89282175SSantwona Behera {0x1d82b, 0x5553}, 2926*89282175SSantwona Behera {0x1d82c, 0x0307}, 2927*89282175SSantwona Behera {0x1d82d, 0x2572}, 2928*89282175SSantwona Behera {0x1d82e, 0x3022}, 2929*89282175SSantwona Behera {0x1d82f, 0x1002}, 2930*89282175SSantwona Behera {0x1d830, 0x21a2}, 2931*89282175SSantwona Behera {0x1d831, 0x3012}, 2932*89282175SSantwona Behera {0x1d832, 0x1002}, 2933*89282175SSantwona Behera {0x1d833, 0x4016}, 2934*89282175SSantwona Behera {0x1d834, 0x5e63}, 2935*89282175SSantwona Behera {0x1d835, 0x0344}, 2936*89282175SSantwona Behera {0x1d836, 0x21a2}, 2937*89282175SSantwona Behera {0x1d837, 0x3012}, 2938*89282175SSantwona Behera {0x1d838, 0x1002}, 2939*89282175SSantwona Behera {0x1d839, 0x400e}, 2940*89282175SSantwona Behera {0x1d83a, 0x2572}, 2941*89282175SSantwona Behera {0x1d83b, 0x3022}, 2942*89282175SSantwona Behera {0x1d83c, 0x1002}, 2943*89282175SSantwona Behera {0x1d83d, 0x2b22}, 2944*89282175SSantwona Behera {0x1d83e, 0x3012}, 2945*89282175SSantwona Behera {0x1d83f, 0x1002}, 2946*89282175SSantwona Behera {0x1d840, 0x28e2}, 2947*89282175SSantwona Behera {0x1d841, 0x3022}, 2948*89282175SSantwona Behera {0x1d842, 0x1002}, 2949*89282175SSantwona Behera {0x1d843, 0x2782}, 2950*89282175SSantwona Behera {0x1d844, 0x3022}, 2951*89282175SSantwona Behera {0x1d845, 0x1002}, 2952*89282175SSantwona Behera {0x1d846, 0x2fa4}, 2953*89282175SSantwona Behera {0x1d847, 0x3dc4}, 2954*89282175SSantwona Behera {0x1d848, 0x6624}, 2955*89282175SSantwona Behera {0x1d849, 0x2e8b}, 2956*89282175SSantwona Behera {0x1d84a, 0x303b}, 2957*89282175SSantwona Behera {0x1d84b, 0x56b3}, 2958*89282175SSantwona Behera {0x1d84c, 0x03c6}, 2959*89282175SSantwona Behera {0x1d84d, 0x866b}, 2960*89282175SSantwona Behera {0x1d84e, 0x400c}, 2961*89282175SSantwona Behera {0x1d84f, 0x2782}, 2962*89282175SSantwona Behera {0x1d850, 0x3012}, 2963*89282175SSantwona Behera {0x1d851, 0x1002}, 2964*89282175SSantwona Behera {0x1d852, 0x2c4b}, 2965*89282175SSantwona Behera {0x1d853, 0x309b}, 2966*89282175SSantwona Behera {0x1d854, 0x56b3}, 2967*89282175SSantwona Behera {0x1d855, 0x03c3}, 2968*89282175SSantwona Behera {0x1d856, 0x866b}, 2969*89282175SSantwona Behera {0x1d857, 0x400c}, 2970*89282175SSantwona Behera {0x1d858, 0x22a2}, 2971*89282175SSantwona Behera {0x1d859, 0x3022}, 2972*89282175SSantwona Behera {0x1d85a, 0x1002}, 2973*89282175SSantwona Behera {0x1d85b, 0x28e2}, 2974*89282175SSantwona Behera {0x1d85c, 0x3022}, 2975*89282175SSantwona Behera {0x1d85d, 0x1002}, 2976*89282175SSantwona Behera {0x1d85e, 0x2782}, 2977*89282175SSantwona Behera {0x1d85f, 0x3022}, 2978*89282175SSantwona Behera {0x1d860, 0x1002}, 2979*89282175SSantwona Behera {0x1d861, 0x2fb4}, 2980*89282175SSantwona Behera {0x1d862, 0x3dc4}, 2981*89282175SSantwona Behera {0x1d863, 0x6624}, 2982*89282175SSantwona Behera {0x1d864, 0x56b3}, 2983*89282175SSantwona Behera {0x1d865, 0x03c3}, 2984*89282175SSantwona Behera {0x1d866, 0x866b}, 2985*89282175SSantwona Behera {0x1d867, 0x401c}, 2986*89282175SSantwona Behera {0x1d868, 0x2c45}, 2987*89282175SSantwona Behera {0x1d869, 0x3095}, 2988*89282175SSantwona Behera {0x1d86a, 0x5b53}, 2989*89282175SSantwona Behera {0x1d86b, 0x23d2}, 2990*89282175SSantwona Behera {0x1d86c, 0x3012}, 2991*89282175SSantwona Behera {0x1d86d, 0x13c2}, 2992*89282175SSantwona Behera {0x1d86e, 0x5cc3}, 2993*89282175SSantwona Behera {0x1d86f, 0x2782}, 2994*89282175SSantwona Behera {0x1d870, 0x3012}, 2995*89282175SSantwona Behera {0x1d871, 0x1312}, 2996*89282175SSantwona Behera {0x1d872, 0x2b22}, 2997*89282175SSantwona Behera {0x1d873, 0x3012}, 2998*89282175SSantwona Behera {0x1d874, 0x1002}, 2999*89282175SSantwona Behera {0x1d875, 0x28e2}, 3000*89282175SSantwona Behera {0x1d876, 0x3022}, 3001*89282175SSantwona Behera {0x1d877, 0x1002}, 3002*89282175SSantwona Behera {0x1d878, 0x2672}, 3003*89282175SSantwona Behera {0x1d879, 0x3022}, 3004*89282175SSantwona Behera {0x1d87a, 0x1002}, 3005*89282175SSantwona Behera {0x1d87b, 0x21a2}, 3006*89282175SSantwona Behera {0x1d87c, 0x3012}, 3007*89282175SSantwona Behera {0x1d87d, 0x1002}, 3008*89282175SSantwona Behera {0x1d87e, 0x628f}, 3009*89282175SSantwona Behera {0x1d87f, 0x2985}, 3010*89282175SSantwona Behera {0x1d880, 0x33a5}, 3011*89282175SSantwona Behera {0x1d881, 0x2782}, 3012*89282175SSantwona Behera {0x1d882, 0x3022}, 3013*89282175SSantwona Behera {0x1d883, 0x1002}, 3014*89282175SSantwona Behera {0x1d884, 0x5653}, 3015*89282175SSantwona Behera {0x1d885, 0x03d2}, 3016*89282175SSantwona Behera {0x1d886, 0x401e}, 3017*89282175SSantwona Behera {0x1d887, 0x6f72}, 3018*89282175SSantwona Behera {0x1d888, 0x1002}, 3019*89282175SSantwona Behera {0x1d889, 0x628f}, 3020*89282175SSantwona Behera {0x1d88a, 0x2304}, 3021*89282175SSantwona Behera {0x1d88b, 0x3c84}, 3022*89282175SSantwona Behera {0x1d88c, 0x6436}, 3023*89282175SSantwona Behera {0x1d88d, 0xdff4}, 3024*89282175SSantwona Behera {0x1d88e, 0x6436}, 3025*89282175SSantwona Behera {0x1d88f, 0x2ff5}, 3026*89282175SSantwona Behera {0x1d890, 0x3005}, 3027*89282175SSantwona Behera {0x1d891, 0x8656}, 3028*89282175SSantwona Behera {0x1d892, 0xdfba}, 3029*89282175SSantwona Behera {0x1d893, 0x56a3}, 3030*89282175SSantwona Behera {0x1d894, 0xd05a}, 3031*89282175SSantwona Behera {0x1d895, 0x29e2}, 3032*89282175SSantwona Behera {0x1d896, 0x3012}, 3033*89282175SSantwona Behera {0x1d897, 0x1392}, 3034*89282175SSantwona Behera {0x1d898, 0xd05a}, 3035*89282175SSantwona Behera {0x1d899, 0x56a3}, 3036*89282175SSantwona Behera {0x1d89a, 0xdfba}, 3037*89282175SSantwona Behera {0x1d89b, 0x0383}, 3038*89282175SSantwona Behera {0x1d89c, 0x6f72}, 3039*89282175SSantwona Behera {0x1d89d, 0x1002}, 3040*89282175SSantwona Behera {0x1d89e, 0x2a64}, 3041*89282175SSantwona Behera {0x1d89f, 0x3014}, 3042*89282175SSantwona Behera {0x1d8a0, 0x2005}, 3043*89282175SSantwona Behera {0x1d8a1, 0x3d75}, 3044*89282175SSantwona Behera {0x1d8a2, 0xc451}, 3045*89282175SSantwona Behera {0x1d8a3, 0x2a42}, 3046*89282175SSantwona Behera {0x1d8a4, 0x3022}, 3047*89282175SSantwona Behera {0x1d8a5, 0x1002}, 3048*89282175SSantwona Behera {0x1d8a6, 0x178c}, 3049*89282175SSantwona Behera {0x1d8a7, 0x1898}, 3050*89282175SSantwona Behera {0x1d8a8, 0x19a4}, 3051*89282175SSantwona Behera {0x1d8a9, 0x1ab0}, 3052*89282175SSantwona Behera {0x1d8aa, 0x1bbc}, 3053*89282175SSantwona Behera {0x1d8ab, 0x1cc8}, 3054*89282175SSantwona Behera {0x1d8ac, 0x1dd3}, 3055*89282175SSantwona Behera {0x1d8ad, 0x1ede}, 3056*89282175SSantwona Behera {0x1d8ae, 0x1fe9}, 3057*89282175SSantwona Behera {0x1d8af, 0x20f4}, 3058*89282175SSantwona Behera {0x1d8b0, 0x21ff}, 3059*89282175SSantwona Behera {0x1d8b1, 0x0000}, 3060*89282175SSantwona Behera {0x1d8b2, 0x27e1}, 3061*89282175SSantwona Behera {0x1d8b3, 0x3021}, 3062*89282175SSantwona Behera {0x1d8b4, 0x1001}, 3063*89282175SSantwona Behera {0x1d8b5, 0xc620}, 3064*89282175SSantwona Behera {0x1d8b6, 0x0000}, 3065*89282175SSantwona Behera {0x1d8b7, 0xc621}, 3066*89282175SSantwona Behera {0x1d8b8, 0x0000}, 3067*89282175SSantwona Behera {0x1d8b9, 0xc622}, 3068*89282175SSantwona Behera {0x1d8ba, 0x00e2}, 3069*89282175SSantwona Behera {0x1d8bb, 0xc623}, 3070*89282175SSantwona Behera {0x1d8bc, 0x007f}, 3071*89282175SSantwona Behera {0x1d8bd, 0xc624}, 3072*89282175SSantwona Behera {0x1d8be, 0x00ce}, 3073*89282175SSantwona Behera {0x1d8bf, 0xc625}, 3074*89282175SSantwona Behera {0x1d8c0, 0x0000}, 3075*89282175SSantwona Behera {0x1d8c1, 0xc627}, 3076*89282175SSantwona Behera {0x1d8c2, 0x0000}, 3077*89282175SSantwona Behera {0x1d8c3, 0xc628}, 3078*89282175SSantwona Behera {0x1d8c4, 0x0000}, 3079*89282175SSantwona Behera {0x1d8c5, 0xc90a}, 3080*89282175SSantwona Behera {0x1d8c6, 0x3a7c}, 3081*89282175SSantwona Behera {0x1d8c7, 0xc62c}, 3082*89282175SSantwona Behera {0x1d8c8, 0x0000}, 3083*89282175SSantwona Behera {0x1d8c9, 0x0000}, 3084*89282175SSantwona Behera {0x1d8ca, 0x27e1}, 3085*89282175SSantwona Behera {0x1d8cb, 0x3021}, 3086*89282175SSantwona Behera {0x1d8cc, 0x1001}, 3087*89282175SSantwona Behera {0x1d8cd, 0xc502}, 3088*89282175SSantwona Behera {0x1d8ce, 0x53ac}, 3089*89282175SSantwona Behera {0x1d8cf, 0xc503}, 3090*89282175SSantwona Behera {0x1d8d0, 0x2cd3}, 3091*89282175SSantwona Behera {0x1d8d1, 0xc600}, 3092*89282175SSantwona Behera {0x1d8d2, 0x2a6e}, 3093*89282175SSantwona Behera {0x1d8d3, 0xc601}, 3094*89282175SSantwona Behera {0x1d8d4, 0x2a2c}, 3095*89282175SSantwona Behera {0x1d8d5, 0xc605}, 3096*89282175SSantwona Behera {0x1d8d6, 0x5557}, 3097*89282175SSantwona Behera {0x1d8d7, 0xc60c}, 3098*89282175SSantwona Behera {0x1d8d8, 0x5400}, 3099*89282175SSantwona Behera {0x1d8d9, 0xc710}, 3100*89282175SSantwona Behera {0x1d8da, 0x0700}, 3101*89282175SSantwona Behera {0x1d8db, 0xc711}, 3102*89282175SSantwona Behera {0x1d8dc, 0x0f06}, 3103*89282175SSantwona Behera {0x1d8dd, 0xc718}, 3104*89282175SSantwona Behera {0x1d8de, 0x0700}, 3105*89282175SSantwona Behera {0x1d8df, 0xc719}, 3106*89282175SSantwona Behera {0x1d8e0, 0x0f06}, 3107*89282175SSantwona Behera {0x1d8e1, 0xc720}, 3108*89282175SSantwona Behera {0x1d8e2, 0x4700}, 3109*89282175SSantwona Behera {0x1d8e3, 0xc721}, 3110*89282175SSantwona Behera {0x1d8e4, 0x0f06}, 3111*89282175SSantwona Behera {0x1d8e5, 0xc728}, 3112*89282175SSantwona Behera {0x1d8e6, 0x0700}, 3113*89282175SSantwona Behera {0x1d8e7, 0xc729}, 3114*89282175SSantwona Behera {0x1d8e8, 0x1207}, 3115*89282175SSantwona Behera {0x1d8e9, 0xc801}, 3116*89282175SSantwona Behera {0x1d8ea, 0x7f50}, 3117*89282175SSantwona Behera {0x1d8eb, 0xc802}, 3118*89282175SSantwona Behera {0x1d8ec, 0x7760}, 3119*89282175SSantwona Behera {0x1d8ed, 0xc803}, 3120*89282175SSantwona Behera {0x1d8ee, 0x7fce}, 3121*89282175SSantwona Behera {0x1d8ef, 0xc804}, 3122*89282175SSantwona Behera {0x1d8f0, 0x520e}, 3123*89282175SSantwona Behera {0x1d8f1, 0xc805}, 3124*89282175SSantwona Behera {0x1d8f2, 0x5c11}, 3125*89282175SSantwona Behera {0x1d8f3, 0xc806}, 3126*89282175SSantwona Behera {0x1d8f4, 0x3c51}, 3127*89282175SSantwona Behera {0x1d8f5, 0xc807}, 3128*89282175SSantwona Behera {0x1d8f6, 0x4061}, 3129*89282175SSantwona Behera {0x1d8f7, 0xc808}, 3130*89282175SSantwona Behera {0x1d8f8, 0x49c1}, 3131*89282175SSantwona Behera {0x1d8f9, 0xc809}, 3132*89282175SSantwona Behera {0x1d8fa, 0x3840}, 3133*89282175SSantwona Behera {0x1d8fb, 0xc80a}, 3134*89282175SSantwona Behera {0x1d8fc, 0x0000}, 3135*89282175SSantwona Behera {0x1d8fd, 0xc821}, 3136*89282175SSantwona Behera {0x1d8fe, 0x0002}, 3137*89282175SSantwona Behera {0x1d8ff, 0xc822}, 3138*89282175SSantwona Behera {0x1d900, 0x0046}, 3139*89282175SSantwona Behera {0x1d901, 0xc844}, 3140*89282175SSantwona Behera {0x1d902, 0x182f}, 3141*89282175SSantwona Behera {0x1d903, 0xc849}, 3142*89282175SSantwona Behera {0x1d904, 0x0400}, 3143*89282175SSantwona Behera {0x1d905, 0xc84a}, 3144*89282175SSantwona Behera {0x1d906, 0x0002}, 3145*89282175SSantwona Behera {0x1d907, 0xc013}, 3146*89282175SSantwona Behera {0x1d908, 0xf341}, 3147*89282175SSantwona Behera {0x1d909, 0xc084}, 3148*89282175SSantwona Behera {0x1d90a, 0x0030}, 3149*89282175SSantwona Behera {0x1d90b, 0xc904}, 3150*89282175SSantwona Behera {0x1d90c, 0x1401}, 3151*89282175SSantwona Behera {0x1d90d, 0xcb0c}, 3152*89282175SSantwona Behera {0x1d90e, 0x0004}, 3153*89282175SSantwona Behera {0x1d90f, 0xcb0e}, 3154*89282175SSantwona Behera {0x1d910, 0xa00a}, 3155*89282175SSantwona Behera {0x1d911, 0xcb0f}, 3156*89282175SSantwona Behera {0x1d912, 0xc0c0}, 3157*89282175SSantwona Behera {0x1d913, 0xcb10}, 3158*89282175SSantwona Behera {0x1d914, 0xc0c0}, 3159*89282175SSantwona Behera {0x1d915, 0xcb11}, 3160*89282175SSantwona Behera {0x1d916, 0x00a0}, 3161*89282175SSantwona Behera {0x1d917, 0xcb12}, 3162*89282175SSantwona Behera {0x1d918, 0x0007}, 3163*89282175SSantwona Behera {0x1d919, 0xc241}, 3164*89282175SSantwona Behera {0x1d91a, 0xa000}, 3165*89282175SSantwona Behera {0x1d91b, 0xc243}, 3166*89282175SSantwona Behera {0x1d91c, 0x7fe0}, 3167*89282175SSantwona Behera {0x1d91d, 0xc604}, 3168*89282175SSantwona Behera {0x1d91e, 0x000e}, 3169*89282175SSantwona Behera {0x1d91f, 0xc609}, 3170*89282175SSantwona Behera {0x1d920, 0x00f5}, 3171*89282175SSantwona Behera {0x1d921, 0x0c61}, 3172*89282175SSantwona Behera {0x1d922, 0x000e}, 3173*89282175SSantwona Behera {0x1d923, 0xc660}, 3174*89282175SSantwona Behera {0x1d924, 0x9600}, 3175*89282175SSantwona Behera {0x1d925, 0xc687}, 3176*89282175SSantwona Behera {0x1d926, 0x0004}, 3177*89282175SSantwona Behera {0x1d927, 0xc60a}, 3178*89282175SSantwona Behera {0x1d928, 0x04f5}, 3179*89282175SSantwona Behera {0x1d929, 0x0000}, 3180*89282175SSantwona Behera {0x1d92a, 0x27e1}, 3181*89282175SSantwona Behera {0x1d92b, 0x3021}, 3182*89282175SSantwona Behera {0x1d92c, 0x1001}, 3183*89282175SSantwona Behera {0x1d92d, 0xc620}, 3184*89282175SSantwona Behera {0x1d92e, 0x14e5}, 3185*89282175SSantwona Behera {0x1d92f, 0xc621}, 3186*89282175SSantwona Behera {0x1d930, 0xc53d}, 3187*89282175SSantwona Behera {0x1d931, 0xc622}, 3188*89282175SSantwona Behera {0x1d932, 0x3cbe}, 3189*89282175SSantwona Behera {0x1d933, 0xc623}, 3190*89282175SSantwona Behera {0x1d934, 0x4452}, 3191*89282175SSantwona Behera {0x1d935, 0xc624}, 3192*89282175SSantwona Behera {0x1d936, 0xc5c5}, 3193*89282175SSantwona Behera {0x1d937, 0xc625}, 3194*89282175SSantwona Behera {0x1d938, 0xe01e}, 3195*89282175SSantwona Behera {0x1d939, 0xc627}, 3196*89282175SSantwona Behera {0x1d93a, 0x0000}, 3197*89282175SSantwona Behera {0x1d93b, 0xc628}, 3198*89282175SSantwona Behera {0x1d93c, 0x0000}, 3199*89282175SSantwona Behera {0x1d93d, 0xc62c}, 3200*89282175SSantwona Behera {0x1d93e, 0x0000}, 3201*89282175SSantwona Behera {0x1d93f, 0xc90a}, 3202*89282175SSantwona Behera {0x1d940, 0x3a7c}, 3203*89282175SSantwona Behera {0x1d941, 0x0000}, 3204*89282175SSantwona Behera {0x1d942, 0x2b84}, 3205*89282175SSantwona Behera {0x1d943, 0x3c74}, 3206*89282175SSantwona Behera {0x1d944, 0x6435}, 3207*89282175SSantwona Behera {0x1d945, 0xdff4}, 3208*89282175SSantwona Behera {0x1d946, 0x6435}, 3209*89282175SSantwona Behera {0x1d947, 0x2806}, 3210*89282175SSantwona Behera {0x1d948, 0x3006}, 3211*89282175SSantwona Behera {0x1d949, 0x8565}, 3212*89282175SSantwona Behera {0x1d94a, 0x2b24}, 3213*89282175SSantwona Behera {0x1d94b, 0x3c24}, 3214*89282175SSantwona Behera {0x1d94c, 0x6436}, 3215*89282175SSantwona Behera {0x1d94d, 0x1002}, 3216*89282175SSantwona Behera {0x1d94e, 0x2b24}, 3217*89282175SSantwona Behera {0x1d94f, 0x3c24}, 3218*89282175SSantwona Behera {0x1d950, 0x6436}, 3219*89282175SSantwona Behera {0x1d951, 0x4045}, 3220*89282175SSantwona Behera {0x1d952, 0x8656}, 3221*89282175SSantwona Behera {0x1d953, 0x5663}, 3222*89282175SSantwona Behera {0x1d954, 0x0302}, 3223*89282175SSantwona Behera {0x1d955, 0x401e}, 3224*89282175SSantwona Behera {0x1d956, 0x1002}, 3225*89282175SSantwona Behera {0x1d957, 0x2017}, 3226*89282175SSantwona Behera {0x1d958, 0x3b17}, 3227*89282175SSantwona Behera {0x1d959, 0x2084}, 3228*89282175SSantwona Behera {0x1d95a, 0x3c14}, 3229*89282175SSantwona Behera {0x1d95b, 0x6724}, 3230*89282175SSantwona Behera {0x1d95c, 0x2807}, 3231*89282175SSantwona Behera {0x1d95d, 0x31a7}, 3232*89282175SSantwona Behera {0x1d95e, 0x20c4}, 3233*89282175SSantwona Behera {0x1d95f, 0x3c24}, 3234*89282175SSantwona Behera {0x1d960, 0x6724}, 3235*89282175SSantwona Behera {0x1d961, 0x2ff7}, 3236*89282175SSantwona Behera {0x1d962, 0x30f7}, 3237*89282175SSantwona Behera {0x1d963, 0x20c4}, 3238*89282175SSantwona Behera {0x1d964, 0x3c04}, 3239*89282175SSantwona Behera {0x1d965, 0x6724}, 3240*89282175SSantwona Behera {0x1d966, 0x1002}, 3241*89282175SSantwona Behera {0x1d967, 0x2807}, 3242*89282175SSantwona Behera {0x1d968, 0x3187}, 3243*89282175SSantwona Behera {0x1d969, 0x20c4}, 3244*89282175SSantwona Behera {0x1d96a, 0x3c24}, 3245*89282175SSantwona Behera {0x1d96b, 0x6724}, 3246*89282175SSantwona Behera {0x1d96c, 0x2fe4}, 3247*89282175SSantwona Behera {0x1d96d, 0x3dc4}, 3248*89282175SSantwona Behera {0x1d96e, 0x6437}, 3249*89282175SSantwona Behera {0x1d96f, 0x20c4}, 3250*89282175SSantwona Behera {0x1d970, 0x3c04}, 3251*89282175SSantwona Behera {0x1d971, 0x6724}, 3252*89282175SSantwona Behera {0x1d972, 0x2017}, 3253*89282175SSantwona Behera {0x1d973, 0x3d17}, 3254*89282175SSantwona Behera {0x1d974, 0x2084}, 3255*89282175SSantwona Behera {0x1d975, 0x3c14}, 3256*89282175SSantwona Behera {0x1d976, 0x6724}, 3257*89282175SSantwona Behera {0x1d977, 0x1002}, 3258*89282175SSantwona Behera {0x1d978, 0x24f4}, 3259*89282175SSantwona Behera {0x1d979, 0x3c64}, 3260*89282175SSantwona Behera {0x1d97a, 0x6436}, 3261*89282175SSantwona Behera {0x1d97b, 0xdff4}, 3262*89282175SSantwona Behera {0x1d97c, 0x6436}, 3263*89282175SSantwona Behera {0x1d97d, 0x1002}, 3264*89282175SSantwona Behera {0x1d97e, 0x2006}, 3265*89282175SSantwona Behera {0x1d97f, 0x3d76}, 3266*89282175SSantwona Behera {0x1d980, 0xc161}, 3267*89282175SSantwona Behera {0x1d981, 0x6134}, 3268*89282175SSantwona Behera {0x1d982, 0x6135}, 3269*89282175SSantwona Behera {0x1d983, 0x5443}, 3270*89282175SSantwona Behera {0x1d984, 0x0303}, 3271*89282175SSantwona Behera {0x1d985, 0x6524}, 3272*89282175SSantwona Behera {0x1d986, 0x00fb}, 3273*89282175SSantwona Behera {0x1d987, 0x1002}, 3274*89282175SSantwona Behera {0x1d988, 0x20d4}, 3275*89282175SSantwona Behera {0x1d989, 0x3c24}, 3276*89282175SSantwona Behera {0x1d98a, 0x2025}, 3277*89282175SSantwona Behera {0x1d98b, 0x3005}, 3278*89282175SSantwona Behera {0x1d98c, 0x6524}, 3279*89282175SSantwona Behera {0x1d98d, 0x1002}, 3280*89282175SSantwona Behera {0x1d98e, 0xd019}, 3281*89282175SSantwona Behera {0x1d98f, 0x2104}, 3282*89282175SSantwona Behera {0x1d990, 0x3c24}, 3283*89282175SSantwona Behera {0x1d991, 0x2105}, 3284*89282175SSantwona Behera {0x1d992, 0x3805}, 3285*89282175SSantwona Behera {0x1d993, 0x6524}, 3286*89282175SSantwona Behera {0x1d994, 0xdff4}, 3287*89282175SSantwona Behera {0x1d995, 0x4005}, 3288*89282175SSantwona Behera {0x1d996, 0x6524}, 3289*89282175SSantwona Behera {0x1d997, 0x2e8d}, 3290*89282175SSantwona Behera {0x1d998, 0x303d}, 3291*89282175SSantwona Behera {0x1d999, 0x2408}, 3292*89282175SSantwona Behera {0x1d99a, 0x35d8}, 3293*89282175SSantwona Behera {0x1d99b, 0x5dd3}, 3294*89282175SSantwona Behera {0x1d99c, 0x0307}, 3295*89282175SSantwona Behera {0x1d99d, 0x8887}, 3296*89282175SSantwona Behera {0x1d99e, 0x63a7}, 3297*89282175SSantwona Behera {0x1d99f, 0x8887}, 3298*89282175SSantwona Behera {0x1d9a0, 0x63a7}, 3299*89282175SSantwona Behera {0x1d9a1, 0xdffd}, 3300*89282175SSantwona Behera {0x1d9a2, 0x00f9}, 3301*89282175SSantwona Behera {0x1d9a3, 0x1002}, 3302*89282175SSantwona Behera {0x1d9a4, 0x866a}, 3303*89282175SSantwona Behera {0x1d9a5, 0x6138}, 3304*89282175SSantwona Behera {0x1d9a6, 0x5883}, 3305*89282175SSantwona Behera {0x1d9a7, 0x2b42}, 3306*89282175SSantwona Behera {0x1d9a8, 0x3022}, 3307*89282175SSantwona Behera {0x1d9a9, 0x1302}, 3308*89282175SSantwona Behera {0x1d9aa, 0x2ff7}, 3309*89282175SSantwona Behera {0x1d9ab, 0x3007}, 3310*89282175SSantwona Behera {0x1d9ac, 0x8785}, 3311*89282175SSantwona Behera {0x1d9ad, 0xb887}, 3312*89282175SSantwona Behera {0x1d9ae, 0x8786}, 3313*89282175SSantwona Behera {0x1d9af, 0xb8c6}, 3314*89282175SSantwona Behera {0x1d9b0, 0x5a53}, 3315*89282175SSantwona Behera {0x1d9b1, 0x2a52}, 3316*89282175SSantwona Behera {0x1d9b2, 0x3022}, 3317*89282175SSantwona Behera {0x1d9b3, 0x13c2}, 3318*89282175SSantwona Behera {0x1d9b4, 0x2474}, 3319*89282175SSantwona Behera {0x1d9b5, 0x3c84}, 3320*89282175SSantwona Behera {0x1d9b6, 0x64d7}, 3321*89282175SSantwona Behera {0x1d9b7, 0x64d7}, 3322*89282175SSantwona Behera {0x1d9b8, 0x2ff5}, 3323*89282175SSantwona Behera {0x1d9b9, 0x3c05}, 3324*89282175SSantwona Behera {0x1d9ba, 0x8757}, 3325*89282175SSantwona Behera {0x1d9bb, 0xb886}, 3326*89282175SSantwona Behera {0x1d9bc, 0x9767}, 3327*89282175SSantwona Behera {0x1d9bd, 0x67c4}, 3328*89282175SSantwona Behera {0x1d9be, 0x6f72}, 3329*89282175SSantwona Behera {0x1d9bf, 0x1002}, 3330*89282175SSantwona Behera {0x1d9c0, 0x0000}, 3331*89282175SSantwona Behera {0x1d080, 0x0100}, 3332*89282175SSantwona Behera {0x1d092, 0x0000}, 3333*89282175SSantwona Behera {NLP_INI_STOP, 0}, 3334*89282175SSantwona Behera }; 3335*89282175SSantwona Behera 3336*89282175SSantwona Behera static nxge_status_t 3337*89282175SSantwona Behera nxge_nlp2020_xcvr_init(p_nxge_t nxgep) 3338*89282175SSantwona Behera { 3339*89282175SSantwona Behera uint8_t phy_port_addr; 3340*89282175SSantwona Behera nxge_status_t status = NXGE_OK; 3341*89282175SSantwona Behera uint16_t ctrl_reg, rst_val, pmd_ctl, rx_los; 3342*89282175SSantwona Behera int i = 0, count = 1000; 3343*89282175SSantwona Behera 3344*89282175SSantwona Behera uint8_t connector = 0, len, lpm; 3345*89282175SSantwona Behera p_nxge_nlp_initseq_t initseq; 3346*89282175SSantwona Behera uint16_t dev, reg, val; 3347*89282175SSantwona Behera 3348*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_nlp2020_xcvr_init: " 3349*89282175SSantwona Behera "port<%d>, phyaddr[0x%x]", nxgep->mac.portnum, 3350*89282175SSantwona Behera nxgep->statsp->mac_stats.xcvr_portn)); 3351*89282175SSantwona Behera 3352*89282175SSantwona Behera phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 3353*89282175SSantwona Behera 3354*89282175SSantwona Behera /* Reset the transceiver */ 3355*89282175SSantwona Behera rst_val = ctrl_reg = NLP2020_PMA_PMD_PHY_RST; 3356*89282175SSantwona Behera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 3357*89282175SSantwona Behera NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, rst_val)) 3358*89282175SSantwona Behera != NXGE_OK) 3359*89282175SSantwona Behera goto fail; 3360*89282175SSantwona Behera while ((count--) && (ctrl_reg & rst_val)) { 3361*89282175SSantwona Behera drv_usecwait(1000); 3362*89282175SSantwona Behera (void) nxge_mdio_read(nxgep, phy_port_addr, 3363*89282175SSantwona Behera NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, &ctrl_reg); 3364*89282175SSantwona Behera } 3365*89282175SSantwona Behera if (count == 0) { 3366*89282175SSantwona Behera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_nlp2020_xcvr_init: " 3367*89282175SSantwona Behera "PMA_PMD reset failed")); 3368*89282175SSantwona Behera goto fail; 3369*89282175SSantwona Behera } 3370*89282175SSantwona Behera 3371*89282175SSantwona Behera /* Set loopback mode if required */ 3372*89282175SSantwona Behera /* Set PMA PMD system loopback */ 3373*89282175SSantwona Behera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 3374*89282175SSantwona Behera NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, &pmd_ctl)) 3375*89282175SSantwona Behera != NXGE_OK) 3376*89282175SSantwona Behera goto fail; 3377*89282175SSantwona Behera 3378*89282175SSantwona Behera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 3379*89282175SSantwona Behera pmd_ctl |= 0x0001; 3380*89282175SSantwona Behera else 3381*89282175SSantwona Behera pmd_ctl &= 0xfffe; 3382*89282175SSantwona Behera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 3383*89282175SSantwona Behera NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, pmd_ctl)) 3384*89282175SSantwona Behera != NXGE_OK) 3385*89282175SSantwona Behera goto fail; 3386*89282175SSantwona Behera 3387*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_nlp2020_xcvr_init: " 3388*89282175SSantwona Behera "setting LB, wrote NLP2020_PMA_PMD_CTL_REG[0x%x]", pmd_ctl)); 3389*89282175SSantwona Behera 3390*89282175SSantwona Behera /* Check connector details using I2c */ 3391*89282175SSantwona Behera if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR, 3392*89282175SSantwona Behera QSFP_MSA_CONN_REG, &connector) == 1) { 3393*89282175SSantwona Behera goto fail; 3394*89282175SSantwona Behera } 3395*89282175SSantwona Behera 3396*89282175SSantwona Behera switch (connector) { 3397*89282175SSantwona Behera case SFPP_FIBER: 3398*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3399*89282175SSantwona Behera "nxge_nlp2020_xcvr_init: SFPP_FIBER detected")); 3400*89282175SSantwona Behera initseq = nlp2020_revC_fiber_init; 3401*89282175SSantwona Behera nxgep->nlp_conn = NXGE_NLP_CONN_FIBER; 3402*89282175SSantwona Behera break; 3403*89282175SSantwona Behera case QSFP_FIBER: 3404*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3405*89282175SSantwona Behera "nxge_nlp2020_xcvr_init: QSFP_FIBER detected")); 3406*89282175SSantwona Behera initseq = nlp2020_revC_fiber_init; 3407*89282175SSantwona Behera nxgep->nlp_conn = NXGE_NLP_CONN_FIBER; 3408*89282175SSantwona Behera break; 3409*89282175SSantwona Behera case QSFP_COPPER_TWINAX: 3410*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3411*89282175SSantwona Behera "nxge_nlp2020_xcvr_init: QSFP_COPPER_TWINAX/" 3412*89282175SSantwona Behera "SFPP_COPPER_TWINAX detected")); 3413*89282175SSantwona Behera 3414*89282175SSantwona Behera initseq = nlp2020_revC_copper_init; 3415*89282175SSantwona Behera nxgep->nlp_conn = NXGE_NLP_CONN_COPPER_LT_7M; 3416*89282175SSantwona Behera break; 3417*89282175SSantwona Behera default: 3418*89282175SSantwona Behera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3419*89282175SSantwona Behera "nxge_nlp2020_xcvr_init: Unknown type [0x%x] detected", 3420*89282175SSantwona Behera "...setting to QSFP_FIBER", 3421*89282175SSantwona Behera connector)); 3422*89282175SSantwona Behera initseq = nlp2020_revC_fiber_init; 3423*89282175SSantwona Behera nxgep->nlp_conn = NXGE_NLP_CONN_FIBER; 3424*89282175SSantwona Behera break; 3425*89282175SSantwona Behera } 3426*89282175SSantwona Behera 3427*89282175SSantwona Behera /* Run appropriate init sequence */ 3428*89282175SSantwona Behera for (i = 0; initseq[i].dev_reg != NLP_INI_STOP; i++) { 3429*89282175SSantwona Behera dev = initseq[i].dev_reg >> 16; 3430*89282175SSantwona Behera reg = initseq[i].dev_reg & 0xffff; 3431*89282175SSantwona Behera val = initseq[i].val; 3432*89282175SSantwona Behera 3433*89282175SSantwona Behera if (reg == NLP_INI_WAIT) { 3434*89282175SSantwona Behera drv_usecwait(1000 * val); 3435*89282175SSantwona Behera } else { 3436*89282175SSantwona Behera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 3437*89282175SSantwona Behera dev, reg, val)) != NXGE_OK) 3438*89282175SSantwona Behera goto fail; 3439*89282175SSantwona Behera } 3440*89282175SSantwona Behera } 3441*89282175SSantwona Behera 3442*89282175SSantwona Behera /* rx_los inversion */ 3443*89282175SSantwona Behera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 3444*89282175SSantwona Behera NLP2020_PMA_PMD_ADDR, NLP2020_OPT_SET_REG, &rx_los)) != NXGE_OK) 3445*89282175SSantwona Behera goto fail; 3446*89282175SSantwona Behera 3447*89282175SSantwona Behera rx_los &= ~(NLP2020_RXLOS_ACT_H); 3448*89282175SSantwona Behera 3449*89282175SSantwona Behera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 3450*89282175SSantwona Behera NLP2020_PMA_PMD_ADDR, NLP2020_OPT_SET_REG, rx_los)) != NXGE_OK) 3451*89282175SSantwona Behera goto fail; 3452*89282175SSantwona Behera 3453*89282175SSantwona Behera if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR, 3454*89282175SSantwona Behera QSFP_MSA_LEN_REG, &len) == 1) { 3455*89282175SSantwona Behera goto fail; 3456*89282175SSantwona Behera } 3457*89282175SSantwona Behera 3458*89282175SSantwona Behera if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR, 3459*89282175SSantwona Behera QSFP_MSA_LPM_REG, &lpm) == 1) { 3460*89282175SSantwona Behera goto fail; 3461*89282175SSantwona Behera } 3462*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3463*89282175SSantwona Behera "nxge_nlp2020_xcvr_init: len[0x%x] lpm[0x%x]", len, lpm)); 3464*89282175SSantwona Behera 3465*89282175SSantwona Behera if (connector == QSFP_COPPER_TWINAX) { 3466*89282175SSantwona Behera if (len >= 7) { 3467*89282175SSantwona Behera nxgep->nlp_conn = NXGE_NLP_CONN_COPPER_7M_ABOVE; 3468*89282175SSantwona Behera /* enable pre-emphasis */ 3469*89282175SSantwona Behera (void) nxge_mdio_write(nxgep, phy_port_addr, 3470*89282175SSantwona Behera NLP2020_PMA_PMD_ADDR, NLP2020_TX_DRV_CTL1_REG, 3471*89282175SSantwona Behera NLP2020_TX_DRV_CTL1_PREEMP_EN); 3472*89282175SSantwona Behera /* write emphasis value */ 3473*89282175SSantwona Behera (void) nxge_mdio_write(nxgep, phy_port_addr, 3474*89282175SSantwona Behera NLP2020_PMA_PMD_ADDR, NLP2020_TX_DRV_CTL2_REG, 3475*89282175SSantwona Behera NLP2020_TX_DRV_CTL2_EMP_VAL); 3476*89282175SSantwona Behera /* stop microcontroller */ 3477*89282175SSantwona Behera (void) nxge_mdio_write(nxgep, phy_port_addr, 3478*89282175SSantwona Behera NLP2020_PMA_PMD_ADDR, NLP2020_UC_CTL_REG, 3479*89282175SSantwona Behera NLP2020_UC_CTL_STOP); 3480*89282175SSantwona Behera /* reset program counter */ 3481*89282175SSantwona Behera (void) nxge_mdio_write(nxgep, phy_port_addr, 3482*89282175SSantwona Behera NLP2020_PMA_PMD_ADDR, NLP2020_UC_PC_START_REG, 3483*89282175SSantwona Behera NLP2020_UC_PC_START_VAL); 3484*89282175SSantwona Behera /* start microcontroller */ 3485*89282175SSantwona Behera (void) nxge_mdio_write(nxgep, phy_port_addr, 3486*89282175SSantwona Behera NLP2020_PMA_PMD_ADDR, NLP2020_UC_CTL_REG, 3487*89282175SSantwona Behera NLP2020_UC_CTL_START); 3488*89282175SSantwona Behera } 3489*89282175SSantwona Behera } 3490*89282175SSantwona Behera if (lpm & QSFP_MSA_LPM_HIGH) { 3491*89282175SSantwona Behera /* enable high power mode */ 3492*89282175SSantwona Behera (void) nxge_mdio_write(nxgep, phy_port_addr, 3493*89282175SSantwona Behera NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 3494*89282175SSantwona Behera NLP2020_GPIO_ACT); 3495*89282175SSantwona Behera } else { 3496*89282175SSantwona Behera /* revert to low power mode */ 3497*89282175SSantwona Behera (void) nxge_mdio_write(nxgep, phy_port_addr, 3498*89282175SSantwona Behera NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 3499*89282175SSantwona Behera NLP2020_GPIO_INACT); 3500*89282175SSantwona Behera } 3501*89282175SSantwona Behera /* It takes ~2s for EDC to settle */ 3502*89282175SSantwona Behera drv_usecwait(2000000); 3503*89282175SSantwona Behera 3504*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_nlp2020_xcvr_init: " 3505*89282175SSantwona Behera "port<%d> phyaddr[0x%x]", nxgep->mac.portnum, phy_port_addr)); 3506*89282175SSantwona Behera 3507*89282175SSantwona Behera return (NXGE_OK); 3508*89282175SSantwona Behera 3509*89282175SSantwona Behera fail: 3510*89282175SSantwona Behera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3511*89282175SSantwona Behera "nxge_nlp2020_xcvr_init: failed to initialize transceiver for " 3512*89282175SSantwona Behera "port<%d>", nxgep->mac.portnum)); 3513*89282175SSantwona Behera return (status); 3514*89282175SSantwona Behera } 3515*89282175SSantwona Behera 3516*89282175SSantwona Behera static boolean_t nxge_is_nlp2020_phy(p_nxge_t nxgep) 3517*89282175SSantwona Behera { 3518*89282175SSantwona Behera uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 3519*89282175SSantwona Behera uint32_t pcs_id = 0; 3520*89282175SSantwona Behera uint32_t pma_pmd_id = 0; 3521*89282175SSantwona Behera uint8_t xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 3522*89282175SSantwona Behera 3523*89282175SSantwona Behera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, xcvr_addr); 3524*89282175SSantwona Behera pcs_id = nxge_get_cl45_pcs_id(nxgep, xcvr_addr); 3525*89282175SSantwona Behera 3526*89282175SSantwona Behera if (((pma_pmd_id & NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID) || 3527*89282175SSantwona Behera ((pcs_id & NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID)) { 3528*89282175SSantwona Behera return (B_TRUE); 3529*89282175SSantwona Behera } else { 3530*89282175SSantwona Behera return (B_FALSE); 3531*89282175SSantwona Behera } 3532*89282175SSantwona Behera } 3533*89282175SSantwona Behera 3534*89282175SSantwona Behera static uint8_t nxge_get_nlp2020_connector_type(p_nxge_t nxgep) 3535*89282175SSantwona Behera { 3536*89282175SSantwona Behera uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 3537*89282175SSantwona Behera uint8_t xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 3538*89282175SSantwona Behera uint8_t connector = 0; 3539*89282175SSantwona Behera 3540*89282175SSantwona Behera (void) nxge_nlp2020_i2c_read(nxgep, xcvr_addr, NLP2020_XCVR_I2C_ADDR, 3541*89282175SSantwona Behera QSFP_MSA_CONN_REG, &connector); 3542*89282175SSantwona Behera 3543*89282175SSantwona Behera return (connector); 3544*89282175SSantwona Behera } 3545*89282175SSantwona Behera 3546*89282175SSantwona Behera static nxge_status_t nxge_set_nlp2020_param(p_nxge_t nxgep) 3547*89282175SSantwona Behera { 3548*89282175SSantwona Behera uint8_t connector = 0; 3549*89282175SSantwona Behera 3550*89282175SSantwona Behera connector = nxge_get_nlp2020_connector_type(nxgep); 3551*89282175SSantwona Behera 3552*89282175SSantwona Behera switch (connector) { 3553*89282175SSantwona Behera case SFPP_FIBER: 3554*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3555*89282175SSantwona Behera "nxge_set_nlp2020_param: SFPP_FIBER detected")); 3556*89282175SSantwona Behera nxgep->mac.portmode = PORT_10G_FIBER; 3557*89282175SSantwona Behera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3558*89282175SSantwona Behera break; 3559*89282175SSantwona Behera case QSFP_FIBER: 3560*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3561*89282175SSantwona Behera "nxge_set_nlp2020_param: QSFP_FIBER detected")); 3562*89282175SSantwona Behera nxgep->mac.portmode = PORT_10G_FIBER; 3563*89282175SSantwona Behera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3564*89282175SSantwona Behera break; 3565*89282175SSantwona Behera case QSFP_COPPER_TWINAX: 3566*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3567*89282175SSantwona Behera "nxge_set_nlp2020_param: QSFP_COPPER_TWINAX/" 3568*89282175SSantwona Behera "SFPP_COPPER_TWINAX detected")); 3569*89282175SSantwona Behera nxgep->mac.portmode = PORT_10G_COPPER; 3570*89282175SSantwona Behera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3571*89282175SSantwona Behera break; 3572*89282175SSantwona Behera default: 3573*89282175SSantwona Behera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3574*89282175SSantwona Behera "nxge_set_nlp2020_param: Unknown type [0x%x] detected" 3575*89282175SSantwona Behera "...setting to QSFP_FIBER", 3576*89282175SSantwona Behera connector)); 3577*89282175SSantwona Behera nxgep->mac.portmode = PORT_10G_FIBER; 3578*89282175SSantwona Behera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3579*89282175SSantwona Behera break; 3580*89282175SSantwona Behera } 3581*89282175SSantwona Behera 3582*89282175SSantwona Behera return (NXGE_OK); 3583*89282175SSantwona Behera } 3584*89282175SSantwona Behera 358552cdd236Ssbehera #define CHK_STAT(x) status = (x); if (status != NXGE_OK) goto fail 358652cdd236Ssbehera 358752cdd236Ssbehera #define MRVL88X2011_RD(nxgep, port, d, r, p) \ 358852cdd236Ssbehera CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p)) 358952cdd236Ssbehera 359052cdd236Ssbehera #define MRVL88X2011_WR(nxgep, port, d, r, p) \ 359152cdd236Ssbehera CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p)) 359252cdd236Ssbehera 359352cdd236Ssbehera 359452cdd236Ssbehera static void 359552cdd236Ssbehera nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate) 359652cdd236Ssbehera { 359752cdd236Ssbehera uint16_t value; 359852cdd236Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 359952cdd236Ssbehera 360052cdd236Ssbehera if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 360152cdd236Ssbehera MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) { 360252cdd236Ssbehera value &= ~MRVL_88X2011_LED_BLK_MASK; 360352cdd236Ssbehera value |= (rate << MRVL_88X2011_LED_BLK_SHIFT); 360452cdd236Ssbehera (void) nxge_mdio_write(nxgep, phy, 360552cdd236Ssbehera MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL, 360652cdd236Ssbehera value); 360752cdd236Ssbehera } 360852cdd236Ssbehera } 360952cdd236Ssbehera 361052cdd236Ssbehera static nxge_status_t 361152cdd236Ssbehera nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep) 361252cdd236Ssbehera { 361352cdd236Ssbehera nxge_status_t status; 361452cdd236Ssbehera pcs_control_t pcs_ctl; 361552cdd236Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 361652cdd236Ssbehera 361752cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 361852cdd236Ssbehera MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value); 361952cdd236Ssbehera 362052cdd236Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 362152cdd236Ssbehera pcs_ctl.bits.loopback = 1; 362252cdd236Ssbehera else 362352cdd236Ssbehera pcs_ctl.bits.loopback = 0; 362452cdd236Ssbehera 362552cdd236Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 362652cdd236Ssbehera MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value); 362752cdd236Ssbehera 362852cdd236Ssbehera fail: 362952cdd236Ssbehera return (status); 363052cdd236Ssbehera } 363152cdd236Ssbehera 363252cdd236Ssbehera 363352cdd236Ssbehera static void 363452cdd236Ssbehera nxge_mrvl88x2011_led(p_nxge_t nxgep, uint16_t val) 363552cdd236Ssbehera { 363652cdd236Ssbehera uint16_t val2; 363752cdd236Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 363852cdd236Ssbehera 363952cdd236Ssbehera val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 364052cdd236Ssbehera val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, 364152cdd236Ssbehera MRVL_88X2011_LED_CTL_MASK); 364252cdd236Ssbehera val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 364352cdd236Ssbehera 364452cdd236Ssbehera if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 364552cdd236Ssbehera MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) { 364652cdd236Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 364752cdd236Ssbehera "nxge_mrvl88x2011_led: nxge_mdio_write failed!!")); 364852cdd236Ssbehera } 364952cdd236Ssbehera } 365052cdd236Ssbehera 365152cdd236Ssbehera 365252cdd236Ssbehera static nxge_status_t 365352cdd236Ssbehera nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep) 365452cdd236Ssbehera { 365552cdd236Ssbehera uint8_t phy; 365652cdd236Ssbehera nxge_status_t status; 365752cdd236Ssbehera uint16_t clk; 365852cdd236Ssbehera 365952cdd236Ssbehera phy = nxgep->statsp->mac_stats.xcvr_portn; 366052cdd236Ssbehera 366152cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 366252cdd236Ssbehera "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>", 366352cdd236Ssbehera nxgep->mac.portnum, phy)); 366452cdd236Ssbehera 366552cdd236Ssbehera /* Set LED functions */ 366652cdd236Ssbehera nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS); 366752cdd236Ssbehera /* PCS activity */ 366852cdd236Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT); 366952cdd236Ssbehera 367052cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 367152cdd236Ssbehera MRVL_88X2011_GEN_CTL, &clk); 367252cdd236Ssbehera clk |= MRVL_88X2011_ENA_XFPREFCLK; 367352cdd236Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 367452cdd236Ssbehera MRVL_88X2011_GEN_CTL, clk); 367552cdd236Ssbehera 367652cdd236Ssbehera /* Set internal loopback mode if necessary */ 367752cdd236Ssbehera 367852cdd236Ssbehera CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep)); 367952cdd236Ssbehera 368052cdd236Ssbehera /* Enable PMD */ 368152cdd236Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 368252cdd236Ssbehera MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX); 368352cdd236Ssbehera 368452cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK")); 368552cdd236Ssbehera 368652cdd236Ssbehera fail: 368752cdd236Ssbehera return (status); 368852cdd236Ssbehera } 368952cdd236Ssbehera 369052cdd236Ssbehera 369152cdd236Ssbehera 36922d17280bSsbehera /* Initialize the 10G Transceiver */ 36932d17280bSsbehera 36942d17280bSsbehera static nxge_status_t 36952d17280bSsbehera nxge_10G_xcvr_init(p_nxge_t nxgep) 36962d17280bSsbehera { 36972d17280bSsbehera p_nxge_stats_t statsp; 36981bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 36992d17280bSsbehera nxge_status_t status = NXGE_OK; 37002d17280bSsbehera #ifdef NXGE_DEBUG 37012d17280bSsbehera uint8_t portn = nxgep->mac.portnum; 37022d17280bSsbehera #endif 37032d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 37042d17280bSsbehera portn)); 37052d17280bSsbehera 37062d17280bSsbehera statsp = nxgep->statsp; 37072d17280bSsbehera 37081c7408c9Stc /* Disable Link LEDs, with or without PHY */ 37091c7408c9Stc if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 37102d17280bSsbehera goto done; 37112d17280bSsbehera 37121c7408c9Stc /* Skip MDIO, if PHY absent */ 37131c7408c9Stc if (nxgep->mac.portmode == PORT_10G_SERDES || nxgep->phy_absent) { 37141c7408c9Stc goto done; 37151c7408c9Stc } 37162d17280bSsbehera 37172d17280bSsbehera /* Set Clause 45 */ 37182d17280bSsbehera npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 37192d17280bSsbehera 37202d17280bSsbehera switch (nxgep->chip_id) { 37212d17280bSsbehera case BCM8704_CHIP_ID: 372200161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 37232d17280bSsbehera "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id)); 37242d17280bSsbehera status = nxge_BCM8704_xcvr_init(nxgep); 37252d17280bSsbehera break; 37262d17280bSsbehera case BCM8706_CHIP_ID: 372700161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 37282d17280bSsbehera "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 37292d17280bSsbehera status = nxge_BCM8706_xcvr_init(nxgep); 37302d17280bSsbehera break; 373152cdd236Ssbehera case MRVL88X201X_CHIP_ID: 373200161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 3733*89282175SSantwona Behera "Chip ID MRVL [0x%x] for 10G xcvr", nxgep->chip_id)); 373452cdd236Ssbehera status = nxge_mrvl88x2011_xcvr_init(nxgep); 373552cdd236Ssbehera break; 3736*89282175SSantwona Behera case NLP2020_CHIP_ID: 3737*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 3738*89282175SSantwona Behera "Chip ID NL2020 [0x%x] for 10G xcvr", nxgep->chip_id)); 3739*89282175SSantwona Behera status = nxge_nlp2020_xcvr_init(nxgep); 3740*89282175SSantwona Behera break; 37412d17280bSsbehera default: 37422d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: " 37432d17280bSsbehera "Unknown chip ID 0x%x for 10G xcvr addr[%d]", 37442d17280bSsbehera nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn)); 37452d17280bSsbehera goto fail; 37462d17280bSsbehera } 37472d17280bSsbehera 37482d17280bSsbehera if (status != NXGE_OK) { 37492d17280bSsbehera goto fail; 37502d17280bSsbehera } 37512e59129aSraghus done: 375259ac0c16Sdavemq statsp->mac_stats.cap_10gfdx = 1; 375359ac0c16Sdavemq statsp->mac_stats.lp_cap_10gfdx = 1; 37541bd6825cSml statsp->mac_stats.adv_cap_asmpause = 37551bd6825cSml param_arr[param_anar_asmpause].value; 37561bd6825cSml statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 375744961713Sgirish 375859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 375959ac0c16Sdavemq portn)); 376059ac0c16Sdavemq return (NXGE_OK); 376144961713Sgirish 376259ac0c16Sdavemq fail: 37632d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 376459ac0c16Sdavemq "nxge_10G_xcvr_init: failed to initialize transceiver for " 37652d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 37662d17280bSsbehera return (NXGE_ERROR); 376759ac0c16Sdavemq } 376844961713Sgirish 376959ac0c16Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */ 377044961713Sgirish 377159ac0c16Sdavemq static nxge_status_t 377259ac0c16Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep) 377359ac0c16Sdavemq { 377459ac0c16Sdavemq p_nxge_param_t param_arr = nxgep->param_arr; 377559ac0c16Sdavemq p_nxge_stats_t statsp = nxgep->statsp; 377659ac0c16Sdavemq nxge_status_t status = NXGE_OK; 377744961713Sgirish 37782e59129aSraghus if (nxgep->mac.portmode == PORT_1G_SERDES) { 37792e59129aSraghus statsp->mac_stats.cap_1000fdx = 37802e59129aSraghus param_arr[param_anar_1000fdx].value; 37812e59129aSraghus goto done; 37822e59129aSraghus } 37832e59129aSraghus 378459ac0c16Sdavemq /* Set Clause 22 */ 378559ac0c16Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 378644961713Sgirish 378759ac0c16Sdavemq /* Set capability flags */ 378859ac0c16Sdavemq statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 37892e59129aSraghus if ((nxgep->mac.portmode == PORT_1G_COPPER) || 37902e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER)) { 37912e59129aSraghus statsp->mac_stats.cap_100fdx = 37922e59129aSraghus param_arr[param_anar_100fdx].value; 37932e59129aSraghus statsp->mac_stats.cap_10fdx = 37942e59129aSraghus param_arr[param_anar_10fdx].value; 37952e59129aSraghus } 379644961713Sgirish 379759ac0c16Sdavemq status = nxge_mii_xcvr_init(nxgep); 37982e59129aSraghus done: 379959ac0c16Sdavemq return (status); 380059ac0c16Sdavemq } 380159ac0c16Sdavemq 380200161856Syc /* 380300161856Syc * Although the Teranetics copper transceiver (TN1010) does not need 380400161856Syc * to be initialized by the driver for passing packets, this funtion 380500161856Syc * initializes the members of nxgep->statsp->mac_stats struct for 380600161856Syc * kstat based on the value of nxgep->statsp->ports_stats.lb_mode. 380700161856Syc * It also configures the TN1010 for PHY loopback to support SunVTS. 380800161856Syc * 380900161856Syc * TN1010 only has the option to disable advertisement for the 10G 381000161856Syc * mode. So we can set it to either Dual Mode or 1G Only mode but 381100161856Syc * can't set it to 10G Only mode. 381200161856Syc * 381300161856Syc * ndd -set command can set the following 6 speed/duplex related parameters. 381400161856Syc * 381500161856Syc * ---------------------------------------------------------------- 381600161856Syc * ndd -set /dev/nxgeX param n kstat nxge:X | grep param 381700161856Syc * ---------------------------------------------------------------- 381800161856Syc * adv_autoneg_cap kstat nxge:1 | grep adv_cap_autoneg 381900161856Syc * adv_10gfdx_cap 382000161856Syc * adv_1000fdx_cap kstat nxge:1 | grep adv_cap_1000fdx 382100161856Syc * adv_100fdx_cap kstat nxge:1 | grep adv_cap_100fdx 382200161856Syc * adv_10fdx_cap kstat nxge:1 | grep adv_cap_10fdx 382300161856Syc * adv_pause_cap kstat nxge:1 | grep adv_cap_pause 382400161856Syc * ---------------------------------------------------------------- 382500161856Syc */ 382600161856Syc static nxge_status_t 382700161856Syc nxge_tn1010_xcvr_init(p_nxge_t nxgep) 382800161856Syc { 382900161856Syc p_nxge_param_t param_arr; 383000161856Syc p_nxge_stats_t statsp; 383100161856Syc tn1010_pcs_ctrl_t tn1010_pcs_ctrl; 383200161856Syc uint16_t speed; 383300161856Syc uint8_t phy_port_addr; 383400161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 383500161856Syc int status = NXGE_OK; 383600161856Syc 383700161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init")); 383800161856Syc 383900161856Syc param_arr = nxgep->param_arr; 384000161856Syc statsp = nxgep->statsp; 384100161856Syc 384200161856Syc /* 384300161856Syc * Initialize the xcvr statistics which are NOT controlled by ndd 384400161856Syc */ 384500161856Syc statsp->mac_stats.cap_autoneg = 1; /* TN1010 autoneg is always on */ 384600161856Syc statsp->mac_stats.cap_100T4 = 0; 384700161856Syc 384800161856Syc /* 384900161856Syc * Read the TN1010 link speed and initialize capabilities kstat. Note 385000161856Syc * that function nxge_check_tn1010_link repeatedly invoked by the 385100161856Syc * timer will update link_speed real time. 385200161856Syc */ 385300161856Syc if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 385400161856Syc goto fail; 385500161856Syc } 385600161856Syc if (speed == TN1010_SPEED_1G) { 385700161856Syc statsp->mac_stats.cap_10gfdx = 0; 385800161856Syc } else { 385900161856Syc statsp->mac_stats.cap_10gfdx = 1; 386000161856Syc } 386100161856Syc 386200161856Syc /* Whether we are in 1G or 10G mode, we always have the 1G capability */ 386300161856Syc statsp->mac_stats.cap_1000fdx = 1; 386400161856Syc 386500161856Syc /* TN1010 is not able to operate in the following states */ 386600161856Syc statsp->mac_stats.cap_1000hdx = 0; 386700161856Syc statsp->mac_stats.cap_100fdx = 0; 386800161856Syc statsp->mac_stats.cap_100hdx = 0; 386900161856Syc statsp->mac_stats.cap_10fdx = 0; 387000161856Syc statsp->mac_stats.cap_10hdx = 0; 387100161856Syc 387200161856Syc /* param_anar_pause can be modified by ndd -set */ 387300161856Syc statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 387400161856Syc 387500161856Syc /* 387600161856Syc * The following 4 lines actually overwrites what ever the ndd command 387700161856Syc * has set. For example, by command 387800161856Syc * ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1) 387900161856Syc * we could set param_arr[param_autoneg].value to n. However, because 388000161856Syc * here we assign constants to these parameters, whatever we set with 388100161856Syc * the "ndd -set" command will be replaced. So command 388200161856Syc * kstat nxge:X | grep param 388300161856Syc * will always show those constant values. In other words, the 388400161856Syc * "ndd -set" command can NOT change the values of these 4 parameters 388500161856Syc * even though the command appears to be successful. 388600161856Syc * 388700161856Syc * Note: TN1010 auto negotiation is always enabled. 388800161856Syc */ 388900161856Syc statsp->mac_stats.adv_cap_autoneg 389000161856Syc = param_arr[param_autoneg].value = 1; 389100161856Syc statsp->mac_stats.adv_cap_1000fdx 389200161856Syc = param_arr[param_anar_1000fdx].value = 1; 389300161856Syc statsp->mac_stats.adv_cap_100fdx 389400161856Syc = param_arr[param_anar_100fdx].value = 0; 389500161856Syc statsp->mac_stats.adv_cap_10fdx 389600161856Syc = param_arr[param_anar_10fdx].value = 0; 389700161856Syc 389800161856Syc /* 389900161856Syc * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as 390000161856Syc * defined in nxge_param_arr[], therefore they are not seen by the 390100161856Syc * "ndd -get" command and can not be changed by ndd. We just set 390200161856Syc * them (both ndd param and kstat values) to constant 0 because TN1010 390300161856Syc * does not support those speeds. 390400161856Syc */ 390500161856Syc statsp->mac_stats.adv_cap_100T4 390600161856Syc = param_arr[param_anar_100T4].value = 0; 390700161856Syc statsp->mac_stats.adv_cap_1000hdx 390800161856Syc = param_arr[param_anar_1000hdx].value = 0; 390900161856Syc statsp->mac_stats.adv_cap_100hdx 391000161856Syc = param_arr[param_anar_100hdx].value = 0; 391100161856Syc statsp->mac_stats.adv_cap_10hdx 391200161856Syc = param_arr[param_anar_10hdx].value = 0; 391300161856Syc 391400161856Syc /* 391500161856Syc * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified 391600161856Syc * by ndd 391700161856Syc */ 391800161856Syc statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 391900161856Syc 392000161856Syc /* 392100161856Syc * nxge_param_arr[] defines the adv_cap_asmpause with type 392200161856Syc * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the 392300161856Syc * "ndd -get" command and can not be changed by ndd. Here we do not 392400161856Syc * assign a constant to it so the default value defined in 392500161856Syc * nxge_param_arr[] will be used to set the parameter and 392600161856Syc * will be shown by the kstat. 392700161856Syc */ 392800161856Syc statsp->mac_stats.adv_cap_asmpause 392900161856Syc = param_arr[param_anar_asmpause].value; 393000161856Syc 393100161856Syc /* 393200161856Syc * Initialize the link statistics. 393300161856Syc */ 393400161856Syc statsp->mac_stats.link_T4 = 0; 393500161856Syc statsp->mac_stats.link_asmpause = 0; 393600161856Syc statsp->mac_stats.link_pause = 0; 393700161856Syc if (speed == TN1010_SPEED_1G) { 393800161856Syc statsp->mac_stats.link_speed = 1000; 393900161856Syc statsp->mac_stats.link_duplex = 2; /* Full duplex */ 394000161856Syc statsp->mac_stats.link_up = 1; 394100161856Syc } else { 394200161856Syc statsp->mac_stats.link_speed = 10000; 394300161856Syc statsp->mac_stats.link_duplex = 2; 394400161856Syc statsp->mac_stats.link_up = 1; 394500161856Syc } 394600161856Syc 394700161856Syc /* 394800161856Syc * Because TN1010 does not have a link partner register, to 394900161856Syc * figure out the link partner's capabilities is tricky. Here we 395000161856Syc * just set the kstat based on our knowledge about the partner 395100161856Syc * (The partner must support auto-neg because auto-negotiation 395200161856Syc * has completed, it must support 1G or 10G because that is the 395300161856Syc * negotiated speed we are using.) 395400161856Syc * 395500161856Syc * Note: Current kstat does not show lp_cap_10gfdx and 395600161856Syc * lp_cap_10ghdx. 395700161856Syc */ 395800161856Syc if (speed == TN1010_SPEED_1G) { 395900161856Syc statsp->mac_stats.lp_cap_1000fdx = 1; 396000161856Syc statsp->mac_stats.lp_cap_10gfdx = 0; 396100161856Syc } else { 396200161856Syc statsp->mac_stats.lp_cap_1000fdx = 0; 396300161856Syc statsp->mac_stats.lp_cap_10gfdx = 1; 396400161856Syc } 396500161856Syc statsp->mac_stats.lp_cap_10ghdx = 0; 396600161856Syc statsp->mac_stats.lp_cap_1000hdx = 0; 396700161856Syc statsp->mac_stats.lp_cap_100fdx = 0; 396800161856Syc statsp->mac_stats.lp_cap_100hdx = 0; 396900161856Syc statsp->mac_stats.lp_cap_10fdx = 0; 397000161856Syc statsp->mac_stats.lp_cap_10hdx = 0; 397100161856Syc statsp->mac_stats.lp_cap_10gfdx = 0; 397200161856Syc statsp->mac_stats.lp_cap_10ghdx = 0; 397300161856Syc statsp->mac_stats.lp_cap_100T4 = 0; 397400161856Syc statsp->mac_stats.lp_cap_autoneg = 1; 397500161856Syc statsp->mac_stats.lp_cap_asmpause = 0; 397600161856Syc statsp->mac_stats.lp_cap_pause = 0; 397700161856Syc 397800161856Syc /* Handle PHY loopback for SunVTS loopback test */ 397900161856Syc npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 398000161856Syc phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 398100161856Syc 398200161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 398300161856Syc TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG, 398400161856Syc &tn1010_pcs_ctrl.value)) != NXGE_OK) { 398500161856Syc goto fail; 398600161856Syc } 398700161856Syc if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) || 398800161856Syc (statsp->port_stats.lb_mode == nxge_lb_phy10g)) { 398900161856Syc tn1010_pcs_ctrl.bits.loopback = 1; 399000161856Syc } else { 399100161856Syc tn1010_pcs_ctrl.bits.loopback = 0; 399200161856Syc } 399300161856Syc if ((status = nxge_mdio_write(nxgep, phy_port_addr, 399400161856Syc TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG, 399500161856Syc tn1010_pcs_ctrl.value)) != NXGE_OK) { 399600161856Syc goto fail; 399700161856Syc } 399800161856Syc 399900161856Syc statsp->mac_stats.xcvr_inits++; 400000161856Syc 400100161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 400200161856Syc "<== nxge_1G_tn1010_xcvr_init status 0x%x", status)); 400300161856Syc return (status); 400400161856Syc fail: 400500161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 400600161856Syc "<== nxge_1G_tn1010_xcvr_init status 0x%x", status)); 400700161856Syc return (status); 400800161856Syc } 400900161856Syc 401059ac0c16Sdavemq /* Initialize transceiver */ 401159ac0c16Sdavemq 401259ac0c16Sdavemq nxge_status_t 401359ac0c16Sdavemq nxge_xcvr_init(p_nxge_t nxgep) 401459ac0c16Sdavemq { 401559ac0c16Sdavemq p_nxge_stats_t statsp; 401659ac0c16Sdavemq #ifdef NXGE_DEBUG 401759ac0c16Sdavemq uint8_t portn; 401844961713Sgirish #endif 401944961713Sgirish 402059ac0c16Sdavemq nxge_status_t status = NXGE_OK; 402159ac0c16Sdavemq #ifdef NXGE_DEBUG 402259ac0c16Sdavemq portn = nxgep->mac.portnum; 402359ac0c16Sdavemq #endif 402459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 402559ac0c16Sdavemq statsp = nxgep->statsp; 402644961713Sgirish 402759ac0c16Sdavemq /* 402800161856Syc * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will 402900161856Syc * modify mac_stats. 403059ac0c16Sdavemq */ 403159ac0c16Sdavemq statsp->mac_stats.cap_autoneg = 0; 403259ac0c16Sdavemq statsp->mac_stats.cap_100T4 = 0; 403359ac0c16Sdavemq statsp->mac_stats.cap_100fdx = 0; 403459ac0c16Sdavemq statsp->mac_stats.cap_100hdx = 0; 403559ac0c16Sdavemq statsp->mac_stats.cap_10fdx = 0; 403659ac0c16Sdavemq statsp->mac_stats.cap_10hdx = 0; 403759ac0c16Sdavemq statsp->mac_stats.cap_asmpause = 0; 403859ac0c16Sdavemq statsp->mac_stats.cap_pause = 0; 403959ac0c16Sdavemq statsp->mac_stats.cap_1000fdx = 0; 404059ac0c16Sdavemq statsp->mac_stats.cap_1000hdx = 0; 404159ac0c16Sdavemq statsp->mac_stats.cap_10gfdx = 0; 404259ac0c16Sdavemq statsp->mac_stats.cap_10ghdx = 0; 404359ac0c16Sdavemq 404459ac0c16Sdavemq /* 404559ac0c16Sdavemq * Initialize the link statistics. 404659ac0c16Sdavemq */ 404759ac0c16Sdavemq statsp->mac_stats.link_T4 = 0; 404859ac0c16Sdavemq statsp->mac_stats.link_asmpause = 0; 404959ac0c16Sdavemq statsp->mac_stats.link_pause = 0; 405044961713Sgirish 405159ac0c16Sdavemq if (nxgep->xcvr.xcvr_init) { 405259ac0c16Sdavemq status = nxgep->xcvr.xcvr_init(nxgep); 405359ac0c16Sdavemq if (status != NXGE_OK) 405444961713Sgirish goto fail; 405559ac0c16Sdavemq statsp->mac_stats.xcvr_inits++; 405644961713Sgirish } 405744961713Sgirish 405859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 405959ac0c16Sdavemq portn)); 406044961713Sgirish return (NXGE_OK); 406144961713Sgirish 406244961713Sgirish fail: 406344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 406459ac0c16Sdavemq "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 406559ac0c16Sdavemq portn)); 406644961713Sgirish return (status); 406744961713Sgirish } 406844961713Sgirish 40692e59129aSraghus /* Look for transceiver type */ 40702e59129aSraghus 40712e59129aSraghus nxge_status_t 40722e59129aSraghus nxge_xcvr_find(p_nxge_t nxgep) 40732e59129aSraghus { 4074d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", 4075d81011f0Ssbehera nxgep->mac.portnum)); 40762e59129aSraghus 40772e59129aSraghus if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 40782e59129aSraghus return (NXGE_ERROR); 40792e59129aSraghus 40802e59129aSraghus if (nxge_setup_xcvr_table(nxgep) != NXGE_OK) 40812e59129aSraghus return (NXGE_ERROR); 40822e59129aSraghus 40832e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 40842e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse)); 40852e59129aSraghus return (NXGE_OK); 40862e59129aSraghus } 408744961713Sgirish 408844961713Sgirish /* Initialize the TxMAC sub-block */ 408944961713Sgirish 409044961713Sgirish nxge_status_t 409144961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep) 409244961713Sgirish { 409344961713Sgirish npi_attr_t ap; 409444961713Sgirish uint8_t portn; 409544961713Sgirish nxge_port_mode_t portmode; 409644961713Sgirish nxge_port_t portt; 409744961713Sgirish npi_handle_t handle; 409844961713Sgirish npi_status_t rs = NPI_SUCCESS; 409944961713Sgirish 410044961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 410144961713Sgirish portt = nxgep->mac.porttype; 410244961713Sgirish handle = nxgep->npi_handle; 410344961713Sgirish portmode = nxgep->mac.portmode; 410444961713Sgirish 410544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 410652ccf843Smisaki portn)); 410744961713Sgirish /* Set Max and Min Frame Size */ 41081bd6825cSml /* 41091bd6825cSml * Use maxframesize to configure the hardware maxframe size 411000161856Syc * and minframesize to configure the hardware minframe size. 41111bd6825cSml */ 41121bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 41131bd6825cSml "==> nxge_tx_mac_init: port<%d> " 41141bd6825cSml "min framesize %d max framesize %d ", 41151bd6825cSml nxgep->mac.minframesize, 41161bd6825cSml nxgep->mac.maxframesize, 41171bd6825cSml portn)); 411844961713Sgirish 41191bd6825cSml SET_MAC_ATTR2(handle, ap, portn, 41201bd6825cSml MAC_PORT_FRAME_SIZE, 41211bd6825cSml nxgep->mac.minframesize, 41221bd6825cSml nxgep->mac.maxframesize, 41231bd6825cSml rs); 412444961713Sgirish if (rs != NPI_SUCCESS) 412544961713Sgirish goto fail; 412644961713Sgirish 412744961713Sgirish if (portt == PORT_TYPE_XMAC) { 412844961713Sgirish if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 412952ccf843Smisaki 0)) != NPI_SUCCESS) 413044961713Sgirish goto fail; 413144961713Sgirish nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 413244961713Sgirish if ((portmode == PORT_10G_FIBER) || 41332e59129aSraghus (portmode == PORT_10G_COPPER) || 413400161856Syc (portmode == PORT_10G_TN1010) || 41351c7408c9Stc (portmode == PORT_HSP_MODE) || 41362e59129aSraghus (portmode == PORT_10G_SERDES)) { 413744961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 413852ccf843Smisaki XGMII_IPG_12_15, rs); 413944961713Sgirish if (rs != NPI_SUCCESS) 414044961713Sgirish goto fail; 414144961713Sgirish nxgep->mac.ipg[0] = XGMII_IPG_12_15; 414244961713Sgirish } else { 414344961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 414452ccf843Smisaki MII_GMII_IPG_12, rs); 414544961713Sgirish if (rs != NPI_SUCCESS) 414644961713Sgirish goto fail; 414744961713Sgirish nxgep->mac.ipg[0] = MII_GMII_IPG_12; 414844961713Sgirish } 414944961713Sgirish if ((rs = npi_xmac_tx_config(handle, INIT, portn, 415052ccf843Smisaki CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 415144961713Sgirish goto fail; 415244961713Sgirish nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 415344961713Sgirish nxgep->mac.maxburstsize = 0; /* not programmable */ 415444961713Sgirish nxgep->mac.ctrltype = 0; /* not programmable */ 415544961713Sgirish nxgep->mac.pa_size = 0; /* not programmable */ 415644961713Sgirish 415744961713Sgirish if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 415852ccf843Smisaki != NPI_SUCCESS) 415944961713Sgirish goto fail; 416044961713Sgirish 416144961713Sgirish } else { 416244961713Sgirish if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 416352ccf843Smisaki 0)) != NPI_SUCCESS) 416444961713Sgirish goto fail; 416544961713Sgirish nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 416644961713Sgirish 416744961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 416852ccf843Smisaki rs); 416944961713Sgirish if (rs != NPI_SUCCESS) 417044961713Sgirish goto fail; 417144961713Sgirish nxgep->mac.ctrltype = 0x8808; 417244961713Sgirish 417344961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 417444961713Sgirish if (rs != NPI_SUCCESS) 417544961713Sgirish goto fail; 417644961713Sgirish nxgep->mac.pa_size = 0x7; 417744961713Sgirish 417844961713Sgirish if ((rs = npi_bmac_tx_config(handle, INIT, portn, 417952ccf843Smisaki CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 418044961713Sgirish goto fail; 418144961713Sgirish nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 418244961713Sgirish } 418344961713Sgirish 418444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 418552ccf843Smisaki portn)); 418644961713Sgirish 418744961713Sgirish return (NXGE_OK); 418844961713Sgirish fail: 418944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 419052ccf843Smisaki "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn)); 419144961713Sgirish 419244961713Sgirish return (NXGE_ERROR | rs); 419344961713Sgirish } 419444961713Sgirish 41950dc2366fSVenugopal Iyer static npi_status_t 41960dc2366fSVenugopal Iyer nxge_rx_mac_mcast_hash_table(p_nxge_t nxgep) 41970dc2366fSVenugopal Iyer { 41980dc2366fSVenugopal Iyer uint32_t i; 41990dc2366fSVenugopal Iyer uint16_t hashtab_e; 42000dc2366fSVenugopal Iyer p_hash_filter_t hash_filter; 42010dc2366fSVenugopal Iyer uint8_t portn; 42020dc2366fSVenugopal Iyer npi_handle_t handle; 42030dc2366fSVenugopal Iyer npi_status_t rs = NPI_SUCCESS; 42040dc2366fSVenugopal Iyer 42050dc2366fSVenugopal Iyer portn = NXGE_GET_PORT_NUM(nxgep->function_num); 42060dc2366fSVenugopal Iyer handle = nxgep->npi_handle; 42070dc2366fSVenugopal Iyer 42080dc2366fSVenugopal Iyer /* 42090dc2366fSVenugopal Iyer * Load the multicast hash filter bits. 42100dc2366fSVenugopal Iyer */ 42110dc2366fSVenugopal Iyer hash_filter = nxgep->hash_filter; 42120dc2366fSVenugopal Iyer for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 42130dc2366fSVenugopal Iyer if (hash_filter != NULL) { 42140dc2366fSVenugopal Iyer hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 42150dc2366fSVenugopal Iyer (NMCFILTER_REGS - 1) - i]; 42160dc2366fSVenugopal Iyer } else { 42170dc2366fSVenugopal Iyer hashtab_e = 0; 42180dc2366fSVenugopal Iyer } 42190dc2366fSVenugopal Iyer 42200dc2366fSVenugopal Iyer if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 42210dc2366fSVenugopal Iyer (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 42220dc2366fSVenugopal Iyer return (rs); 42230dc2366fSVenugopal Iyer } 4224678453a8Sspeer 42250dc2366fSVenugopal Iyer return (NPI_SUCCESS); 42260dc2366fSVenugopal Iyer } 422744961713Sgirish 42280dc2366fSVenugopal Iyer /* 42290dc2366fSVenugopal Iyer * Initialize the RxMAC sub-block 42300dc2366fSVenugopal Iyer */ 423144961713Sgirish nxge_status_t 423244961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep) 423344961713Sgirish { 423444961713Sgirish npi_attr_t ap; 423544961713Sgirish nxge_port_t portt; 423644961713Sgirish uint8_t portn; 423744961713Sgirish npi_handle_t handle; 423844961713Sgirish npi_status_t rs = NPI_SUCCESS; 423944961713Sgirish uint16_t *addr16p; 424044961713Sgirish uint16_t addr0, addr1, addr2; 424144961713Sgirish xmac_rx_config_t xconfig; 424244961713Sgirish bmac_rx_config_t bconfig; 424344961713Sgirish 424444961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 424544961713Sgirish 424644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 424752ccf843Smisaki portn)); 424844961713Sgirish handle = nxgep->npi_handle; 424944961713Sgirish portt = nxgep->mac.porttype; 425044961713Sgirish 425144961713Sgirish addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 425244961713Sgirish addr0 = ntohs(addr16p[2]); 425344961713Sgirish addr1 = ntohs(addr16p[1]); 425444961713Sgirish addr2 = ntohs(addr16p[0]); 42550dc2366fSVenugopal Iyer SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, 42560dc2366fSVenugopal Iyer addr0, addr1, addr2, rs); 425744961713Sgirish if (rs != NPI_SUCCESS) 425844961713Sgirish goto fail; 425944961713Sgirish SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 426044961713Sgirish if (rs != NPI_SUCCESS) 426144961713Sgirish goto fail; 426244961713Sgirish SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 426344961713Sgirish if (rs != NPI_SUCCESS) 426444961713Sgirish goto fail; 426544961713Sgirish 42660dc2366fSVenugopal Iyer rs = nxge_rx_mac_mcast_hash_table(nxgep); 42670dc2366fSVenugopal Iyer if (rs != NPI_SUCCESS) 42680dc2366fSVenugopal Iyer goto fail; 426944961713Sgirish 427044961713Sgirish if (portt == PORT_TYPE_XMAC) { 427144961713Sgirish if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 427252ccf843Smisaki 0)) != NPI_SUCCESS) 427344961713Sgirish goto fail; 427444961713Sgirish nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 427544961713Sgirish 427644961713Sgirish (void) nxge_fflp_init_hostinfo(nxgep); 427744961713Sgirish 427844961713Sgirish xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 427952ccf843Smisaki CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 428052ccf843Smisaki ~CFG_XMAC_RX_STRIP_CRC; 428144961713Sgirish 428244961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 428344961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUS; 428444961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 428544961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 428644961713Sgirish 428744961713Sgirish xconfig |= CFG_XMAC_RX_HASH_FILTER; 428844961713Sgirish 42890dc2366fSVenugopal Iyer if ((rs = npi_xmac_rx_config(handle, INIT, 42900dc2366fSVenugopal Iyer portn, xconfig)) != NPI_SUCCESS) 429144961713Sgirish goto fail; 429244961713Sgirish nxgep->mac.rx_config = xconfig; 429344961713Sgirish 42940dc2366fSVenugopal Iyer /* 42950dc2366fSVenugopal Iyer * Comparison of mac unique address is always 42960dc2366fSVenugopal Iyer * enabled on XMAC 42970dc2366fSVenugopal Iyer */ 429844961713Sgirish if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 429952ccf843Smisaki != NPI_SUCCESS) 430044961713Sgirish goto fail; 430144961713Sgirish } else { 430244961713Sgirish if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 430352ccf843Smisaki 0) != NPI_SUCCESS) 430444961713Sgirish goto fail; 43050dc2366fSVenugopal Iyer 430644961713Sgirish nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 430744961713Sgirish 43080dc2366fSVenugopal Iyer (void) nxge_fflp_init_hostinfo(nxgep); 43090dc2366fSVenugopal Iyer 4310a3c5bd6dSspeer bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 431152ccf843Smisaki ~CFG_BMAC_RX_STRIP_CRC; 431244961713Sgirish 431344961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 431444961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUS; 431544961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 431644961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 431744961713Sgirish 431844961713Sgirish bconfig |= CFG_BMAC_RX_HASH_FILTER; 43190dc2366fSVenugopal Iyer if ((rs = npi_bmac_rx_config(handle, INIT, 43200dc2366fSVenugopal Iyer portn, bconfig)) != NPI_SUCCESS) 432144961713Sgirish goto fail; 432244961713Sgirish nxgep->mac.rx_config = bconfig; 432344961713Sgirish 43240dc2366fSVenugopal Iyer /* 43250dc2366fSVenugopal Iyer * Always enable comparison of mac unique address 43260dc2366fSVenugopal Iyer */ 43270dc2366fSVenugopal Iyer if ((rs = npi_mac_altaddr_enable(handle, 43280dc2366fSVenugopal Iyer portn, 0)) != NPI_SUCCESS) 432944961713Sgirish goto fail; 433044961713Sgirish } 433144961713Sgirish 433244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 433352ccf843Smisaki portn)); 433444961713Sgirish 433544961713Sgirish return (NXGE_OK); 433644961713Sgirish 433744961713Sgirish fail: 433844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 433952ccf843Smisaki "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn)); 434044961713Sgirish 434144961713Sgirish return (NXGE_ERROR | rs); 434244961713Sgirish } 434344961713Sgirish 434444961713Sgirish /* Enable TXMAC */ 434544961713Sgirish 434644961713Sgirish nxge_status_t 434744961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep) 434844961713Sgirish { 434944961713Sgirish npi_handle_t handle; 435044961713Sgirish npi_status_t rs = NPI_SUCCESS; 435144961713Sgirish nxge_status_t status = NXGE_OK; 435244961713Sgirish 435344961713Sgirish handle = nxgep->npi_handle; 435444961713Sgirish 435544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 435652ccf843Smisaki nxgep->mac.portnum)); 435744961713Sgirish 435844961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 435944961713Sgirish goto fail; 436044961713Sgirish 436144961713Sgirish /* based on speed */ 436244961713Sgirish nxgep->msg_min = ETHERMIN; 436344961713Sgirish 436444961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 436544961713Sgirish if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 436652ccf843Smisaki CFG_XMAC_TX)) != NPI_SUCCESS) 436744961713Sgirish goto fail; 436844961713Sgirish } else { 436944961713Sgirish if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 437052ccf843Smisaki CFG_BMAC_TX)) != NPI_SUCCESS) 437144961713Sgirish goto fail; 437244961713Sgirish } 437344961713Sgirish 437444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 437552ccf843Smisaki nxgep->mac.portnum)); 437644961713Sgirish 437744961713Sgirish return (NXGE_OK); 437844961713Sgirish fail: 437944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 438052ccf843Smisaki "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 438152ccf843Smisaki nxgep->mac.portnum)); 438244961713Sgirish if (rs != NPI_SUCCESS) 438344961713Sgirish return (NXGE_ERROR | rs); 438444961713Sgirish else 438544961713Sgirish return (status); 438644961713Sgirish } 438744961713Sgirish 438844961713Sgirish /* Disable TXMAC */ 438944961713Sgirish 439044961713Sgirish nxge_status_t 439144961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep) 439244961713Sgirish { 439344961713Sgirish npi_handle_t handle; 439444961713Sgirish npi_status_t rs = NPI_SUCCESS; 439544961713Sgirish 4396678453a8Sspeer if (isLDOMguest(nxgep)) 4397678453a8Sspeer return (NXGE_OK); 4398678453a8Sspeer 439944961713Sgirish handle = nxgep->npi_handle; 440044961713Sgirish 440144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 440252ccf843Smisaki nxgep->mac.portnum)); 440344961713Sgirish 440444961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 440544961713Sgirish if ((rs = npi_xmac_tx_config(handle, DISABLE, 440652ccf843Smisaki nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 440744961713Sgirish goto fail; 440844961713Sgirish } else { 440944961713Sgirish if ((rs = npi_bmac_tx_config(handle, DISABLE, 441052ccf843Smisaki nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 441144961713Sgirish goto fail; 441244961713Sgirish } 441344961713Sgirish 441444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 441552ccf843Smisaki nxgep->mac.portnum)); 441644961713Sgirish return (NXGE_OK); 441744961713Sgirish fail: 441844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 441952ccf843Smisaki "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 442052ccf843Smisaki nxgep->mac.portnum)); 442144961713Sgirish return (NXGE_ERROR | rs); 442244961713Sgirish } 442344961713Sgirish 442444961713Sgirish /* Enable RXMAC */ 442544961713Sgirish 442644961713Sgirish nxge_status_t 442744961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep) 442844961713Sgirish { 442944961713Sgirish npi_handle_t handle; 443044961713Sgirish uint8_t portn; 443144961713Sgirish npi_status_t rs = NPI_SUCCESS; 443244961713Sgirish nxge_status_t status = NXGE_OK; 443344961713Sgirish 4434678453a8Sspeer /* This is a service-domain-only activity. */ 4435678453a8Sspeer if (isLDOMguest(nxgep)) 4436678453a8Sspeer return (status); 4437678453a8Sspeer 443844961713Sgirish handle = nxgep->npi_handle; 443944961713Sgirish portn = nxgep->mac.portnum; 444044961713Sgirish 444144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 444252ccf843Smisaki portn)); 444344961713Sgirish 444444961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 444544961713Sgirish goto fail; 444644961713Sgirish 444744961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 444844961713Sgirish if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 4449678453a8Sspeer CFG_XMAC_RX)) != NPI_SUCCESS) 445044961713Sgirish goto fail; 445144961713Sgirish } else { 445244961713Sgirish if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 4453678453a8Sspeer CFG_BMAC_RX)) != NPI_SUCCESS) 445444961713Sgirish goto fail; 445544961713Sgirish } 445644961713Sgirish 4457678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4458678453a8Sspeer "<== nxge_rx_mac_enable: port<%d>", portn)); 445944961713Sgirish 446044961713Sgirish return (NXGE_OK); 446144961713Sgirish fail: 446244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4463678453a8Sspeer "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn)); 446444961713Sgirish 446544961713Sgirish if (rs != NPI_SUCCESS) 446644961713Sgirish return (NXGE_ERROR | rs); 446744961713Sgirish else 446844961713Sgirish return (status); 446944961713Sgirish } 447044961713Sgirish 447144961713Sgirish /* Disable RXMAC */ 447244961713Sgirish 447344961713Sgirish nxge_status_t 447444961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep) 447544961713Sgirish { 447644961713Sgirish npi_handle_t handle; 447744961713Sgirish uint8_t portn; 447844961713Sgirish npi_status_t rs = NPI_SUCCESS; 447944961713Sgirish 4480678453a8Sspeer /* If we are a guest domain driver, don't bother. */ 4481678453a8Sspeer if (isLDOMguest(nxgep)) 4482678453a8Sspeer return (NXGE_OK); 4483678453a8Sspeer 448444961713Sgirish handle = nxgep->npi_handle; 448544961713Sgirish portn = nxgep->mac.portnum; 448644961713Sgirish 448744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 448852ccf843Smisaki portn)); 448944961713Sgirish 449044961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 449144961713Sgirish if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 449252ccf843Smisaki CFG_XMAC_RX)) != NPI_SUCCESS) 449344961713Sgirish goto fail; 449444961713Sgirish } else { 449544961713Sgirish if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 449652ccf843Smisaki CFG_BMAC_RX)) != NPI_SUCCESS) 449744961713Sgirish goto fail; 449844961713Sgirish } 449944961713Sgirish 450044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 450152ccf843Smisaki portn)); 450244961713Sgirish return (NXGE_OK); 450344961713Sgirish fail: 450444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 450552ccf843Smisaki "nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn)); 450644961713Sgirish 450744961713Sgirish return (NXGE_ERROR | rs); 450844961713Sgirish } 450944961713Sgirish 451044961713Sgirish /* Reset TXMAC */ 451144961713Sgirish 451244961713Sgirish nxge_status_t 451344961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep) 451444961713Sgirish { 451544961713Sgirish npi_handle_t handle; 451644961713Sgirish uint8_t portn; 451744961713Sgirish npi_status_t rs = NPI_SUCCESS; 451844961713Sgirish 451944961713Sgirish handle = nxgep->npi_handle; 452044961713Sgirish portn = nxgep->mac.portnum; 452144961713Sgirish 452244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 452352ccf843Smisaki portn)); 452444961713Sgirish 452544961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 452644961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 452744961713Sgirish != NPI_SUCCESS) 452844961713Sgirish goto fail; 452944961713Sgirish } else { 453044961713Sgirish if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 453152ccf843Smisaki != NPI_SUCCESS) 453244961713Sgirish goto fail; 453344961713Sgirish } 453444961713Sgirish 453544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 453652ccf843Smisaki portn)); 453744961713Sgirish 453844961713Sgirish return (NXGE_OK); 453944961713Sgirish fail: 454044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 454152ccf843Smisaki "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn)); 454244961713Sgirish 454344961713Sgirish return (NXGE_ERROR | rs); 454444961713Sgirish } 454544961713Sgirish 454644961713Sgirish /* Reset RXMAC */ 454744961713Sgirish 454844961713Sgirish nxge_status_t 454944961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep) 455044961713Sgirish { 455144961713Sgirish npi_handle_t handle; 455244961713Sgirish uint8_t portn; 455344961713Sgirish npi_status_t rs = NPI_SUCCESS; 455444961713Sgirish 455544961713Sgirish handle = nxgep->npi_handle; 455644961713Sgirish portn = nxgep->mac.portnum; 455744961713Sgirish 455844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 455952ccf843Smisaki portn)); 456044961713Sgirish 456144961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 456244961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 456344961713Sgirish != NPI_SUCCESS) 456444961713Sgirish goto fail; 456544961713Sgirish } else { 456644961713Sgirish if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 456752ccf843Smisaki != NPI_SUCCESS) 456844961713Sgirish goto fail; 456944961713Sgirish } 457044961713Sgirish 457144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 457252ccf843Smisaki portn)); 457344961713Sgirish 457459ac0c16Sdavemq return (NXGE_OK); 457559ac0c16Sdavemq fail: 457659ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 457752ccf843Smisaki "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn)); 457859ac0c16Sdavemq return (NXGE_ERROR | rs); 457959ac0c16Sdavemq } 458059ac0c16Sdavemq 458159ac0c16Sdavemq /* 10G fiber link interrupt start routine */ 458259ac0c16Sdavemq 458359ac0c16Sdavemq static nxge_status_t 458459ac0c16Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep) 458559ac0c16Sdavemq { 458659ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 458759ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 458859ac0c16Sdavemq 458959ac0c16Sdavemq rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 459059ac0c16Sdavemq 459159ac0c16Sdavemq if (rs != NPI_SUCCESS) 459259ac0c16Sdavemq return (NXGE_ERROR | rs); 459359ac0c16Sdavemq else 459459ac0c16Sdavemq return (NXGE_OK); 459559ac0c16Sdavemq } 459659ac0c16Sdavemq 459759ac0c16Sdavemq /* 10G fiber link interrupt stop routine */ 459859ac0c16Sdavemq 459959ac0c16Sdavemq static nxge_status_t 460059ac0c16Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep) 460159ac0c16Sdavemq { 460259ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 460359ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 460459ac0c16Sdavemq 460559ac0c16Sdavemq rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 460659ac0c16Sdavemq 460759ac0c16Sdavemq if (rs != NPI_SUCCESS) 460859ac0c16Sdavemq return (NXGE_ERROR | rs); 460959ac0c16Sdavemq else 461059ac0c16Sdavemq return (NXGE_OK); 461159ac0c16Sdavemq } 461259ac0c16Sdavemq 461359ac0c16Sdavemq /* 1G fiber link interrupt start routine */ 461459ac0c16Sdavemq 461559ac0c16Sdavemq static nxge_status_t 461659ac0c16Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 461759ac0c16Sdavemq { 461859ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 461959ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 462059ac0c16Sdavemq 462159ac0c16Sdavemq rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 462259ac0c16Sdavemq if (rs != NPI_SUCCESS) 462359ac0c16Sdavemq return (NXGE_ERROR | rs); 462459ac0c16Sdavemq else 462559ac0c16Sdavemq return (NXGE_OK); 462659ac0c16Sdavemq } 462759ac0c16Sdavemq 462859ac0c16Sdavemq /* 1G fiber link interrupt stop routine */ 462959ac0c16Sdavemq 463059ac0c16Sdavemq static nxge_status_t 463159ac0c16Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 463259ac0c16Sdavemq { 463359ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 463459ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 463559ac0c16Sdavemq 463659ac0c16Sdavemq rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 463759ac0c16Sdavemq 463859ac0c16Sdavemq if (rs != NPI_SUCCESS) 463959ac0c16Sdavemq return (NXGE_ERROR | rs); 464059ac0c16Sdavemq else 464159ac0c16Sdavemq return (NXGE_OK); 464259ac0c16Sdavemq } 464359ac0c16Sdavemq 464459ac0c16Sdavemq /* 1G copper link interrupt start routine */ 464559ac0c16Sdavemq 464659ac0c16Sdavemq static nxge_status_t 464759ac0c16Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 464859ac0c16Sdavemq { 464959ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 465059ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 465159ac0c16Sdavemq 465259ac0c16Sdavemq rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 46536b438925Ssbehera MII_STATUS, MII_STATUS_LINKUP); 465459ac0c16Sdavemq 465559ac0c16Sdavemq if (rs != NPI_SUCCESS) 465659ac0c16Sdavemq return (NXGE_ERROR | rs); 465759ac0c16Sdavemq else 465859ac0c16Sdavemq return (NXGE_OK); 465944961713Sgirish } 466044961713Sgirish 466159ac0c16Sdavemq /* 1G copper link interrupt stop routine */ 466259ac0c16Sdavemq 466359ac0c16Sdavemq static nxge_status_t 466459ac0c16Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 466559ac0c16Sdavemq { 466659ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 466759ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 466859ac0c16Sdavemq 466959ac0c16Sdavemq rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 467059ac0c16Sdavemq 467159ac0c16Sdavemq if (rs != NPI_SUCCESS) 467259ac0c16Sdavemq return (NXGE_ERROR | rs); 467359ac0c16Sdavemq else 467459ac0c16Sdavemq return (NXGE_OK); 467559ac0c16Sdavemq } 467644961713Sgirish 467759ac0c16Sdavemq /* Enable/Disable Link Status change interrupt */ 467844961713Sgirish 467944961713Sgirish nxge_status_t 468044961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 468144961713Sgirish { 468259ac0c16Sdavemq uint8_t portn; 468359ac0c16Sdavemq nxge_status_t status = NXGE_OK; 468444961713Sgirish 468544961713Sgirish portn = nxgep->mac.portnum; 468644961713Sgirish 468744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 468859ac0c16Sdavemq if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 468959ac0c16Sdavemq return (NXGE_OK); 469044961713Sgirish 469159ac0c16Sdavemq if (enable == LINK_INTR_START) 469259ac0c16Sdavemq status = nxgep->xcvr.link_intr_start(nxgep); 469359ac0c16Sdavemq else if (enable == LINK_INTR_STOP) 469459ac0c16Sdavemq status = nxgep->xcvr.link_intr_stop(nxgep); 469559ac0c16Sdavemq if (status != NXGE_OK) 469659ac0c16Sdavemq goto fail; 469744961713Sgirish 469844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 469944961713Sgirish 470044961713Sgirish return (NXGE_OK); 470144961713Sgirish fail: 470244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 470352ccf843Smisaki "nxge_link_intr: Failed to set port<%d> mif intr mode", portn)); 470444961713Sgirish 470559ac0c16Sdavemq return (status); 470644961713Sgirish } 470744961713Sgirish 470844961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 470944961713Sgirish 471044961713Sgirish nxge_status_t 471144961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep) 471244961713Sgirish { 471344961713Sgirish p_nxge_param_t param_arr; 471444961713Sgirish p_nxge_stats_t statsp; 471544961713Sgirish uint8_t xcvr_portn; 471644961713Sgirish p_mii_regs_t mii_regs; 471744961713Sgirish mii_bmcr_t bmcr; 471844961713Sgirish mii_bmsr_t bmsr; 471944961713Sgirish mii_anar_t anar; 472044961713Sgirish mii_gcr_t gcr; 472144961713Sgirish mii_esr_t esr; 472244961713Sgirish mii_aux_ctl_t bcm5464r_aux; 472344961713Sgirish int status = NXGE_OK; 472444961713Sgirish 472544961713Sgirish uint_t delay; 472644961713Sgirish 472744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 472844961713Sgirish 472944961713Sgirish param_arr = nxgep->param_arr; 473044961713Sgirish statsp = nxgep->statsp; 473144961713Sgirish xcvr_portn = statsp->mac_stats.xcvr_portn; 473244961713Sgirish 473344961713Sgirish mii_regs = NULL; 473444961713Sgirish 473544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 473652ccf843Smisaki "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 473744961713Sgirish 4738d81011f0Ssbehera /* 4739d81011f0Ssbehera * The mif phy mode may be connected to either a copper link 4740d81011f0Ssbehera * or fiber link. Read the mode control register to get the fiber 4741d81011f0Ssbehera * configuration if it is hard-wired to fiber link. 4742d81011f0Ssbehera */ 4743d81011f0Ssbehera (void) nxge_mii_get_link_mode(nxgep); 4744d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 4745d81011f0Ssbehera return (nxge_mii_xcvr_fiber_init(nxgep)); 4746d81011f0Ssbehera } 4747d81011f0Ssbehera 474844961713Sgirish /* 474944961713Sgirish * Reset the transceiver. 475044961713Sgirish */ 475144961713Sgirish delay = 0; 475244961713Sgirish bmcr.value = 0; 475344961713Sgirish bmcr.bits.reset = 1; 475444961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4755adfcba55Sjoycey #if defined(__i386) 475652ccf843Smisaki (uint8_t)(uint32_t)&mii_regs->bmcr, 4757adfcba55Sjoycey #else 475852ccf843Smisaki (uint8_t)(uint64_t)&mii_regs->bmcr, 4759adfcba55Sjoycey #endif 476052ccf843Smisaki bmcr.value)) != NXGE_OK) 476144961713Sgirish goto fail; 476244961713Sgirish do { 476344961713Sgirish drv_usecwait(500); 476444961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 4765adfcba55Sjoycey #if defined(__i386) 476652ccf843Smisaki (uint8_t)(uint32_t)&mii_regs->bmcr, 4767adfcba55Sjoycey #else 476852ccf843Smisaki (uint8_t)(uint64_t)&mii_regs->bmcr, 4769adfcba55Sjoycey #endif 477052ccf843Smisaki &bmcr.value)) != NXGE_OK) 477144961713Sgirish goto fail; 477244961713Sgirish delay++; 477344961713Sgirish } while ((bmcr.bits.reset) && (delay < 1000)); 477444961713Sgirish if (delay == 1000) { 477544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 477644961713Sgirish goto fail; 477744961713Sgirish } 477844961713Sgirish 477944961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 4780adfcba55Sjoycey #if defined(__i386) 478152ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmsr), 4782adfcba55Sjoycey #else 478352ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmsr), 4784adfcba55Sjoycey #endif 478552ccf843Smisaki &bmsr.value)) != NXGE_OK) 478644961713Sgirish goto fail; 478744961713Sgirish 478844961713Sgirish param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 478944961713Sgirish param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 479044961713Sgirish param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 479144961713Sgirish param_arr[param_anar_100hdx].value = 0; 479244961713Sgirish param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 479344961713Sgirish param_arr[param_anar_10hdx].value = 0; 479444961713Sgirish 479544961713Sgirish /* 479658324dfcSspeer * Initialize the xcvr statistics. 479744961713Sgirish */ 479844961713Sgirish statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 479944961713Sgirish statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 480044961713Sgirish statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 480144961713Sgirish statsp->mac_stats.cap_100hdx = 0; 480244961713Sgirish statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 480344961713Sgirish statsp->mac_stats.cap_10hdx = 0; 480444961713Sgirish statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 480544961713Sgirish statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 480644961713Sgirish 480744961713Sgirish /* 480800161856Syc * Initialize the xcvr advertised capability statistics. 480944961713Sgirish */ 481044961713Sgirish statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 481144961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 481244961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 481344961713Sgirish statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 481444961713Sgirish statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 481544961713Sgirish statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 481644961713Sgirish statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 481744961713Sgirish statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 481844961713Sgirish statsp->mac_stats.adv_cap_asmpause = 481952ccf843Smisaki param_arr[param_anar_asmpause].value; 482044961713Sgirish statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 482144961713Sgirish 482244961713Sgirish 482344961713Sgirish /* 482444961713Sgirish * Check for extended status just in case we're 482544961713Sgirish * running a Gigibit phy. 482644961713Sgirish */ 482744961713Sgirish if (bmsr.bits.extend_status) { 482844961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 4829adfcba55Sjoycey #if defined(__i386) 483052ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->esr), 4831adfcba55Sjoycey #else 483252ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->esr), 4833adfcba55Sjoycey #endif 483452ccf843Smisaki &esr.value)) != NXGE_OK) 483544961713Sgirish goto fail; 483652ccf843Smisaki param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx; 483744961713Sgirish param_arr[param_anar_1000hdx].value = 0; 483844961713Sgirish 483944961713Sgirish statsp->mac_stats.cap_1000fdx = 484052ccf843Smisaki (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 484144961713Sgirish statsp->mac_stats.cap_1000hdx = 0; 484244961713Sgirish } else { 484344961713Sgirish param_arr[param_anar_1000fdx].value = 0; 484444961713Sgirish param_arr[param_anar_1000hdx].value = 0; 484544961713Sgirish } 484644961713Sgirish 484744961713Sgirish /* 484844961713Sgirish * Initialize 1G Statistics once the capability is established. 484944961713Sgirish */ 485044961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 485144961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 485244961713Sgirish 485344961713Sgirish /* 485400161856Syc * Initialize the link statistics. 485544961713Sgirish */ 485644961713Sgirish statsp->mac_stats.link_T4 = 0; 485744961713Sgirish statsp->mac_stats.link_asmpause = 0; 485844961713Sgirish statsp->mac_stats.link_pause = 0; 485944961713Sgirish statsp->mac_stats.link_speed = 0; 486044961713Sgirish statsp->mac_stats.link_duplex = 0; 486144961713Sgirish statsp->mac_stats.link_up = 0; 486244961713Sgirish 486344961713Sgirish /* 486444961713Sgirish * Switch off Auto-negotiation, 100M and full duplex. 486544961713Sgirish */ 486644961713Sgirish bmcr.value = 0; 486744961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4868adfcba55Sjoycey #if defined(__i386) 486952ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmcr), 4870adfcba55Sjoycey #else 487152ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmcr), 4872adfcba55Sjoycey #endif 487352ccf843Smisaki bmcr.value)) != NXGE_OK) 487444961713Sgirish goto fail; 487544961713Sgirish 487644961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 487752ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 487844961713Sgirish bmcr.bits.loopback = 1; 487944961713Sgirish bmcr.bits.enable_autoneg = 0; 488044961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 488144961713Sgirish bmcr.bits.speed_1000_sel = 1; 488244961713Sgirish bmcr.bits.duplex_mode = 1; 488344961713Sgirish param_arr[param_autoneg].value = 0; 488444961713Sgirish } else { 488544961713Sgirish bmcr.bits.loopback = 0; 488644961713Sgirish } 488744961713Sgirish 488844961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 488952ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_ext100) || 489052ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 489144961713Sgirish param_arr[param_autoneg].value = 0; 489244961713Sgirish bcm5464r_aux.value = 0; 489344961713Sgirish bcm5464r_aux.bits.ext_lb = 1; 489444961713Sgirish bcm5464r_aux.bits.write_1 = 1; 489544961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 489652ccf843Smisaki BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 489744961713Sgirish goto fail; 489844961713Sgirish } 489944961713Sgirish 490000161856Syc /* If auto-negotiation is desired */ 490144961713Sgirish if (param_arr[param_autoneg].value) { 490244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 490352ccf843Smisaki "Restarting Auto-negotiation.")); 490444961713Sgirish /* 490544961713Sgirish * Setup our Auto-negotiation advertisement register. 490644961713Sgirish */ 490744961713Sgirish anar.value = 0; 490844961713Sgirish anar.bits.selector = 1; 490944961713Sgirish anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 491044961713Sgirish anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 491144961713Sgirish anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 491244961713Sgirish anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 491344961713Sgirish anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 491444961713Sgirish anar.bits.cap_asmpause = 0; 491544961713Sgirish anar.bits.cap_pause = 0; 491644961713Sgirish if (param_arr[param_anar_1000fdx].value || 491752ccf843Smisaki param_arr[param_anar_100fdx].value || 491852ccf843Smisaki param_arr[param_anar_10fdx].value) { 491944961713Sgirish anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 492044961713Sgirish anar.bits.cap_pause = statsp->mac_stats.cap_pause; 492144961713Sgirish } 492244961713Sgirish 492300161856Syc /* Write to the auto-negotiation advertisement register */ 492444961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4925adfcba55Sjoycey #if defined(__i386) 492652ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->anar), 4927adfcba55Sjoycey #else 492852ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->anar), 4929adfcba55Sjoycey #endif 493052ccf843Smisaki anar.value)) != NXGE_OK) 493144961713Sgirish goto fail; 493244961713Sgirish if (bmsr.bits.extend_status) { 493344961713Sgirish gcr.value = 0; 493444961713Sgirish gcr.bits.ms_mode_en = 493552ccf843Smisaki param_arr[param_master_cfg_enable].value; 493644961713Sgirish gcr.bits.master = 493752ccf843Smisaki param_arr[param_master_cfg_value].value; 493844961713Sgirish gcr.bits.link_1000fdx = 493952ccf843Smisaki param_arr[param_anar_1000fdx].value; 494044961713Sgirish gcr.bits.link_1000hdx = 494152ccf843Smisaki param_arr[param_anar_1000hdx].value; 494244961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4943adfcba55Sjoycey #if defined(__i386) 494452ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gcr), 4945adfcba55Sjoycey #else 494652ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gcr), 4947adfcba55Sjoycey #endif 494852ccf843Smisaki gcr.value)) != NXGE_OK) 494944961713Sgirish goto fail; 495044961713Sgirish } 495144961713Sgirish 495244961713Sgirish bmcr.bits.enable_autoneg = 1; 495344961713Sgirish bmcr.bits.restart_autoneg = 1; 495444961713Sgirish 495544961713Sgirish } else { 495644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 495744961713Sgirish bmcr.bits.speed_1000_sel = 495852ccf843Smisaki param_arr[param_anar_1000fdx].value | 495952ccf843Smisaki param_arr[param_anar_1000hdx].value; 496044961713Sgirish bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 496152ccf843Smisaki (param_arr[param_anar_100fdx].value | 496252ccf843Smisaki param_arr[param_anar_100hdx].value); 496300161856Syc 496400161856Syc /* Force to 1G */ 496544961713Sgirish if (bmcr.bits.speed_1000_sel) { 496644961713Sgirish statsp->mac_stats.link_speed = 1000; 496744961713Sgirish gcr.value = 0; 496844961713Sgirish gcr.bits.ms_mode_en = 496952ccf843Smisaki param_arr[param_master_cfg_enable].value; 497044961713Sgirish gcr.bits.master = 497152ccf843Smisaki param_arr[param_master_cfg_value].value; 497244961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4973adfcba55Sjoycey #if defined(__i386) 497452ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gcr), 4975adfcba55Sjoycey #else 497652ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gcr), 4977adfcba55Sjoycey #endif 497852ccf843Smisaki gcr.value)) != NXGE_OK) 497944961713Sgirish goto fail; 498044961713Sgirish if (param_arr[param_anar_1000fdx].value) { 498144961713Sgirish bmcr.bits.duplex_mode = 1; 498244961713Sgirish statsp->mac_stats.link_duplex = 2; 498344961713Sgirish } else 498444961713Sgirish statsp->mac_stats.link_duplex = 1; 498500161856Syc 498600161856Syc /* Force to 100M */ 498744961713Sgirish } else if (bmcr.bits.speed_sel) { 498844961713Sgirish statsp->mac_stats.link_speed = 100; 498944961713Sgirish if (param_arr[param_anar_100fdx].value) { 499044961713Sgirish bmcr.bits.duplex_mode = 1; 499144961713Sgirish statsp->mac_stats.link_duplex = 2; 499244961713Sgirish } else 499344961713Sgirish statsp->mac_stats.link_duplex = 1; 499400161856Syc 499500161856Syc /* Force to 10M */ 499644961713Sgirish } else { 499744961713Sgirish statsp->mac_stats.link_speed = 10; 499844961713Sgirish if (param_arr[param_anar_10fdx].value) { 499944961713Sgirish bmcr.bits.duplex_mode = 1; 500044961713Sgirish statsp->mac_stats.link_duplex = 2; 500144961713Sgirish } else 500244961713Sgirish statsp->mac_stats.link_duplex = 1; 500344961713Sgirish } 500444961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 500544961713Sgirish statsp->mac_stats.link_asmpause = 500652ccf843Smisaki statsp->mac_stats.cap_asmpause; 500744961713Sgirish statsp->mac_stats.link_pause = 500852ccf843Smisaki statsp->mac_stats.cap_pause; 500944961713Sgirish } 501044961713Sgirish 501144961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 501252ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_ext100) || 501352ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 501444961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 501544961713Sgirish /* BCM5464R 1000mbps external loopback mode */ 501644961713Sgirish gcr.value = 0; 501744961713Sgirish gcr.bits.ms_mode_en = 1; 501844961713Sgirish gcr.bits.master = 1; 501944961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 5020adfcba55Sjoycey #if defined(__i386) 502152ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gcr), 5022adfcba55Sjoycey #else 502352ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gcr), 5024adfcba55Sjoycey #endif 502552ccf843Smisaki gcr.value)) != NXGE_OK) 502644961713Sgirish goto fail; 502744961713Sgirish bmcr.value = 0; 502844961713Sgirish bmcr.bits.speed_1000_sel = 1; 502944961713Sgirish statsp->mac_stats.link_speed = 1000; 503044961713Sgirish } else if (statsp->port_stats.lb_mode 503144961713Sgirish == nxge_lb_ext100) { 503244961713Sgirish /* BCM5464R 100mbps external loopback mode */ 503344961713Sgirish bmcr.value = 0; 503444961713Sgirish bmcr.bits.speed_sel = 1; 503544961713Sgirish bmcr.bits.duplex_mode = 1; 503644961713Sgirish statsp->mac_stats.link_speed = 100; 503744961713Sgirish } else if (statsp->port_stats.lb_mode 503844961713Sgirish == nxge_lb_ext10) { 503944961713Sgirish /* BCM5464R 10mbps external loopback mode */ 504044961713Sgirish bmcr.value = 0; 504144961713Sgirish bmcr.bits.duplex_mode = 1; 504244961713Sgirish statsp->mac_stats.link_speed = 10; 504344961713Sgirish } 504444961713Sgirish } 504544961713Sgirish } 504644961713Sgirish 504744961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 5048adfcba55Sjoycey #if defined(__i386) 504952ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmcr), 5050adfcba55Sjoycey #else 505152ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmcr), 5052adfcba55Sjoycey #endif 505352ccf843Smisaki bmcr.value)) != NXGE_OK) 505444961713Sgirish goto fail; 505544961713Sgirish 505644961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 5057adfcba55Sjoycey #if defined(__i386) 505852ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmcr), 5059adfcba55Sjoycey #else 506052ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmcr), 5061adfcba55Sjoycey #endif 506252ccf843Smisaki &bmcr.value)) != NXGE_OK) 506344961713Sgirish goto fail; 506444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 506544961713Sgirish 506644961713Sgirish /* 506744961713Sgirish * Initialize the xcvr status kept in the context structure. 506844961713Sgirish */ 506944961713Sgirish nxgep->soft_bmsr.value = 0; 507044961713Sgirish 507144961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 5072adfcba55Sjoycey #if defined(__i386) 507352ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmsr), 5074adfcba55Sjoycey #else 507552ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmsr), 5076adfcba55Sjoycey #endif 507752ccf843Smisaki &nxgep->bmsr.value)) != NXGE_OK) 507844961713Sgirish goto fail; 507944961713Sgirish 508044961713Sgirish statsp->mac_stats.xcvr_inits++; 508144961713Sgirish nxgep->bmsr.value = 0; 508244961713Sgirish 508344961713Sgirish fail: 508444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 508552ccf843Smisaki "<== nxge_mii_xcvr_init status 0x%x", status)); 508644961713Sgirish return (status); 508744961713Sgirish } 508844961713Sgirish 5089d81011f0Ssbehera nxge_status_t 5090d81011f0Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep) 5091d81011f0Ssbehera { 5092d81011f0Ssbehera p_nxge_param_t param_arr; 5093d81011f0Ssbehera p_nxge_stats_t statsp; 5094d81011f0Ssbehera uint8_t xcvr_portn; 5095d81011f0Ssbehera p_mii_regs_t mii_regs; 5096d81011f0Ssbehera mii_bmcr_t bmcr; 5097d81011f0Ssbehera mii_bmsr_t bmsr; 5098d81011f0Ssbehera mii_gcr_t gcr; 5099d81011f0Ssbehera mii_esr_t esr; 5100d81011f0Ssbehera mii_aux_ctl_t bcm5464r_aux; 5101d81011f0Ssbehera int status = NXGE_OK; 5102d81011f0Ssbehera 5103d81011f0Ssbehera uint_t delay; 5104d81011f0Ssbehera 5105d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init")); 5106d81011f0Ssbehera 5107d81011f0Ssbehera param_arr = nxgep->param_arr; 5108d81011f0Ssbehera statsp = nxgep->statsp; 5109d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 5110d81011f0Ssbehera 5111d81011f0Ssbehera mii_regs = NULL; 5112d81011f0Ssbehera 5113d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5114d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: " 5115d81011f0Ssbehera "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 5116d81011f0Ssbehera 5117d81011f0Ssbehera /* 5118d81011f0Ssbehera * Reset the transceiver. 5119d81011f0Ssbehera */ 5120d81011f0Ssbehera delay = 0; 5121d81011f0Ssbehera bmcr.value = 0; 5122d81011f0Ssbehera bmcr.bits.reset = 1; 5123d81011f0Ssbehera 5124d81011f0Ssbehera #if defined(__i386) 5125d81011f0Ssbehera 5126d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 5127d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 5128d81011f0Ssbehera goto fail; 5129d81011f0Ssbehera #else 5130d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 5131d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 5132d81011f0Ssbehera goto fail; 5133d81011f0Ssbehera #endif 5134d81011f0Ssbehera do { 5135d81011f0Ssbehera drv_usecwait(500); 5136d81011f0Ssbehera #if defined(__i386) 5137d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 5138d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) 5139d81011f0Ssbehera != NXGE_OK) 5140d81011f0Ssbehera goto fail; 5141d81011f0Ssbehera #else 5142d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 5143d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) 5144d81011f0Ssbehera != NXGE_OK) 5145d81011f0Ssbehera goto fail; 5146d81011f0Ssbehera #endif 5147d81011f0Ssbehera delay++; 5148d81011f0Ssbehera } while ((bmcr.bits.reset) && (delay < 1000)); 5149d81011f0Ssbehera if (delay == 1000) { 5150d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 5151d81011f0Ssbehera goto fail; 5152d81011f0Ssbehera } 5153d81011f0Ssbehera 5154d81011f0Ssbehera #if defined(__i386) 5155d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 5156d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 5157d81011f0Ssbehera goto fail; 5158d81011f0Ssbehera #else 5159d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 5160d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 5161d81011f0Ssbehera goto fail; 5162d81011f0Ssbehera #endif 5163d81011f0Ssbehera 5164d81011f0Ssbehera param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 5165d81011f0Ssbehera param_arr[param_anar_100T4].value = 0; 5166d81011f0Ssbehera param_arr[param_anar_100fdx].value = 0; 5167d81011f0Ssbehera param_arr[param_anar_100hdx].value = 0; 5168d81011f0Ssbehera param_arr[param_anar_10fdx].value = 0; 5169d81011f0Ssbehera param_arr[param_anar_10hdx].value = 0; 5170d81011f0Ssbehera 5171d81011f0Ssbehera /* 5172d81011f0Ssbehera * Initialize the xcvr statistics. 5173d81011f0Ssbehera */ 5174d81011f0Ssbehera statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 5175d81011f0Ssbehera statsp->mac_stats.cap_100T4 = 0; 5176d81011f0Ssbehera statsp->mac_stats.cap_100fdx = 0; 5177d81011f0Ssbehera statsp->mac_stats.cap_100hdx = 0; 5178d81011f0Ssbehera statsp->mac_stats.cap_10fdx = 0; 5179d81011f0Ssbehera statsp->mac_stats.cap_10hdx = 0; 5180d81011f0Ssbehera statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 5181d81011f0Ssbehera statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 5182d81011f0Ssbehera 5183d81011f0Ssbehera /* 5184d81011f0Ssbehera * Initialize the xcvr advertised capability statistics. 5185d81011f0Ssbehera */ 5186d81011f0Ssbehera statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 5187d81011f0Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 5188d81011f0Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 5189d81011f0Ssbehera statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 5190d81011f0Ssbehera statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 5191d81011f0Ssbehera statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 5192d81011f0Ssbehera statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 5193d81011f0Ssbehera statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 5194d81011f0Ssbehera statsp->mac_stats.adv_cap_asmpause = 5195d81011f0Ssbehera param_arr[param_anar_asmpause].value; 5196d81011f0Ssbehera statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 5197d81011f0Ssbehera 5198d81011f0Ssbehera /* 5199d81011f0Ssbehera * Check for extended status just in case we're 5200d81011f0Ssbehera * running a Gigibit phy. 5201d81011f0Ssbehera */ 5202d81011f0Ssbehera if (bmsr.bits.extend_status) { 5203d81011f0Ssbehera #if defined(__i386) 5204d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 5205d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) != 5206d81011f0Ssbehera NXGE_OK) 5207d81011f0Ssbehera goto fail; 5208d81011f0Ssbehera #else 5209d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 5210d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) != 5211d81011f0Ssbehera NXGE_OK) 5212d81011f0Ssbehera goto fail; 5213d81011f0Ssbehera #endif 5214d81011f0Ssbehera param_arr[param_anar_1000fdx].value &= 5215d81011f0Ssbehera esr.bits.link_1000fdx; 5216d81011f0Ssbehera param_arr[param_anar_1000hdx].value = 0; 5217d81011f0Ssbehera 5218d81011f0Ssbehera statsp->mac_stats.cap_1000fdx = 5219d81011f0Ssbehera (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 5220d81011f0Ssbehera statsp->mac_stats.cap_1000hdx = 0; 5221d81011f0Ssbehera } else { 5222d81011f0Ssbehera param_arr[param_anar_1000fdx].value = 0; 5223d81011f0Ssbehera param_arr[param_anar_1000hdx].value = 0; 5224d81011f0Ssbehera } 5225d81011f0Ssbehera 5226d81011f0Ssbehera /* 5227d81011f0Ssbehera * Initialize 1G Statistics once the capability is established. 5228d81011f0Ssbehera */ 5229d81011f0Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 5230d81011f0Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 5231d81011f0Ssbehera 5232d81011f0Ssbehera /* 5233d81011f0Ssbehera * Initialize the link statistics. 5234d81011f0Ssbehera */ 5235d81011f0Ssbehera statsp->mac_stats.link_T4 = 0; 5236d81011f0Ssbehera statsp->mac_stats.link_asmpause = 0; 5237d81011f0Ssbehera statsp->mac_stats.link_pause = 0; 5238d81011f0Ssbehera statsp->mac_stats.link_speed = 0; 5239d81011f0Ssbehera statsp->mac_stats.link_duplex = 0; 5240d81011f0Ssbehera statsp->mac_stats.link_up = 0; 5241d81011f0Ssbehera 5242d81011f0Ssbehera /* 5243d81011f0Ssbehera * Switch off Auto-negotiation, 100M and full duplex. 5244d81011f0Ssbehera */ 5245d81011f0Ssbehera bmcr.value = 0; 5246d81011f0Ssbehera #if defined(__i386) 5247d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 5248d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 5249d81011f0Ssbehera goto fail; 5250d81011f0Ssbehera #else 5251d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 5252d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 5253d81011f0Ssbehera goto fail; 5254d81011f0Ssbehera #endif 5255d81011f0Ssbehera 5256d81011f0Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 5257d81011f0Ssbehera (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 5258d81011f0Ssbehera bmcr.bits.loopback = 1; 5259d81011f0Ssbehera bmcr.bits.enable_autoneg = 0; 5260d81011f0Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 5261d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 5262d81011f0Ssbehera bmcr.bits.duplex_mode = 1; 5263d81011f0Ssbehera param_arr[param_autoneg].value = 0; 5264d81011f0Ssbehera } else { 5265d81011f0Ssbehera bmcr.bits.loopback = 0; 5266d81011f0Ssbehera } 5267d81011f0Ssbehera 5268d81011f0Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 5269d81011f0Ssbehera param_arr[param_autoneg].value = 0; 5270d81011f0Ssbehera bcm5464r_aux.value = 0; 5271d81011f0Ssbehera bcm5464r_aux.bits.ext_lb = 1; 5272d81011f0Ssbehera bcm5464r_aux.bits.write_1 = 1; 5273d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 5274d81011f0Ssbehera BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 5275d81011f0Ssbehera goto fail; 5276d81011f0Ssbehera } 5277d81011f0Ssbehera 5278d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 5279d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 5280d81011f0Ssbehera bmcr.bits.speed_sel = 0; 5281d81011f0Ssbehera bmcr.bits.duplex_mode = 1; 5282d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 5283d81011f0Ssbehera statsp->mac_stats.link_duplex = 2; 5284d81011f0Ssbehera 5285d81011f0Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) { 5286d81011f0Ssbehera /* BCM5464R 1000mbps external loopback mode */ 5287d81011f0Ssbehera gcr.value = 0; 5288d81011f0Ssbehera gcr.bits.ms_mode_en = 1; 5289d81011f0Ssbehera gcr.bits.master = 1; 5290d81011f0Ssbehera #if defined(__i386) 5291d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 5292d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->gcr), 5293d81011f0Ssbehera gcr.value)) != NXGE_OK) 5294d81011f0Ssbehera goto fail; 5295d81011f0Ssbehera #else 5296d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 5297d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->gcr), 5298d81011f0Ssbehera gcr.value)) != NXGE_OK) 5299d81011f0Ssbehera goto fail; 5300d81011f0Ssbehera #endif 5301d81011f0Ssbehera bmcr.value = 0; 5302d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 5303d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 5304d81011f0Ssbehera } 5305d81011f0Ssbehera 5306d81011f0Ssbehera #if defined(__i386) 5307d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 5308d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), 5309d81011f0Ssbehera bmcr.value)) != NXGE_OK) 5310d81011f0Ssbehera goto fail; 5311d81011f0Ssbehera #else 5312d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 5313d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), 5314d81011f0Ssbehera bmcr.value)) != NXGE_OK) 5315d81011f0Ssbehera goto fail; 5316d81011f0Ssbehera #endif 5317d81011f0Ssbehera 5318d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5319d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x", 5320d81011f0Ssbehera bmcr.value)); 5321d81011f0Ssbehera 5322d81011f0Ssbehera #if defined(__i386) 5323d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 5324d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 5325d81011f0Ssbehera goto fail; 5326d81011f0Ssbehera #else 5327d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 5328d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 5329d81011f0Ssbehera goto fail; 5330d81011f0Ssbehera #endif 5331d81011f0Ssbehera 5332d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5333d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value)); 5334d81011f0Ssbehera 5335d81011f0Ssbehera /* 5336d81011f0Ssbehera * Initialize the xcvr status kept in the context structure. 5337d81011f0Ssbehera */ 5338d81011f0Ssbehera nxgep->soft_bmsr.value = 0; 5339d81011f0Ssbehera #if defined(__i386) 5340d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 5341d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), 5342d81011f0Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 5343d81011f0Ssbehera goto fail; 5344d81011f0Ssbehera #else 5345d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 5346d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), 5347d81011f0Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 5348d81011f0Ssbehera goto fail; 5349d81011f0Ssbehera #endif 5350d81011f0Ssbehera 5351d81011f0Ssbehera statsp->mac_stats.xcvr_inits++; 5352d81011f0Ssbehera nxgep->bmsr.value = 0; 5353d81011f0Ssbehera 5354d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5355d81011f0Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 5356d81011f0Ssbehera return (status); 5357d81011f0Ssbehera 5358d81011f0Ssbehera fail: 5359d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5360d81011f0Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 5361d81011f0Ssbehera return (status); 5362d81011f0Ssbehera } 5363d81011f0Ssbehera 536444961713Sgirish /* Read from a MII compliant register */ 536544961713Sgirish 536644961713Sgirish nxge_status_t 536744961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 536844961713Sgirish uint16_t *value) 536944961713Sgirish { 537044961713Sgirish npi_status_t rs = NPI_SUCCESS; 537144961713Sgirish 537244961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 537352ccf843Smisaki "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 537444961713Sgirish 5375321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 537644961713Sgirish 5377d81011f0Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 5378d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 537944961713Sgirish if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 538052ccf843Smisaki xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 538144961713Sgirish goto fail; 53822e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 53832e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 538444961713Sgirish if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 538552ccf843Smisaki xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 538644961713Sgirish goto fail; 538744961713Sgirish } else 538844961713Sgirish goto fail; 538944961713Sgirish 5390321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 539144961713Sgirish 539244961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 539352ccf843Smisaki "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value)); 539444961713Sgirish return (NXGE_OK); 539544961713Sgirish fail: 5396321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 539744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 539852ccf843Smisaki "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn)); 539944961713Sgirish 540044961713Sgirish return (NXGE_ERROR | rs); 540144961713Sgirish } 540244961713Sgirish 540344961713Sgirish /* Write to a MII compliant Register */ 540444961713Sgirish 540544961713Sgirish nxge_status_t 540644961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 540744961713Sgirish uint16_t value) 540844961713Sgirish { 540944961713Sgirish npi_status_t rs = NPI_SUCCESS; 541044961713Sgirish 541144961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 541252ccf843Smisaki "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value)); 541344961713Sgirish 5414321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 541544961713Sgirish 5416d81011f0Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 5417d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 541844961713Sgirish if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 541952ccf843Smisaki xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 542044961713Sgirish goto fail; 54212e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 54222e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 542344961713Sgirish if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 542452ccf843Smisaki xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 542544961713Sgirish goto fail; 542644961713Sgirish } else 542744961713Sgirish goto fail; 542844961713Sgirish 5429321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 543044961713Sgirish 543144961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 543252ccf843Smisaki "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 543344961713Sgirish return (NXGE_OK); 543444961713Sgirish fail: 5435321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 543644961713Sgirish 543744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 543852ccf843Smisaki "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn)); 543944961713Sgirish 544044961713Sgirish return (NXGE_ERROR | rs); 544144961713Sgirish } 544244961713Sgirish 544300161856Syc /* 544400161856Syc * Perform write to Clause45 serdes / transceiver device 544500161856Syc * Arguments: 544600161856Syc * xcvr_portn: The IEEE 802.3 Clause45 PHYAD, it is the same as port 544700161856Syc * number if nxge_mdio_write is used for accessing the 544800161856Syc * internal LSIL serdes. Otherwise PHYAD is different 544900161856Syc * for different platforms. 545000161856Syc * device: With each PHYAD, the driver can use MDIO to control 545100161856Syc * multiple devices inside the PHY, here "device" is an 545200161856Syc * MMD (MDIO managable device). 545300161856Syc * xcvr_reg: Each device has multiple registers. xcvr_reg specifies 545400161856Syc * the register which the driver will write value to. 545500161856Syc * value: The register value will be filled in. 545600161856Syc */ 545744961713Sgirish nxge_status_t 545844961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 545944961713Sgirish uint16_t xcvr_reg, uint16_t *value) 546044961713Sgirish { 546144961713Sgirish npi_status_t rs = NPI_SUCCESS; 546244961713Sgirish 546344961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 546452ccf843Smisaki xcvr_portn)); 546544961713Sgirish 546653560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 546744961713Sgirish 546844961713Sgirish if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 546952ccf843Smisaki xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 547044961713Sgirish goto fail; 547144961713Sgirish 547253560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 547344961713Sgirish 547444961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 547552ccf843Smisaki xcvr_portn)); 547644961713Sgirish return (NXGE_OK); 547744961713Sgirish fail: 547853560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 547944961713Sgirish 548044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 548152ccf843Smisaki "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn)); 548244961713Sgirish 548344961713Sgirish return (NXGE_ERROR | rs); 548444961713Sgirish } 548544961713Sgirish 548644961713Sgirish /* Perform write to Clause45 serdes / transceiver device */ 548744961713Sgirish 548844961713Sgirish nxge_status_t 548944961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 549044961713Sgirish uint16_t xcvr_reg, uint16_t value) 549144961713Sgirish { 549244961713Sgirish npi_status_t rs = NPI_SUCCESS; 549344961713Sgirish 549444961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 549552ccf843Smisaki xcvr_portn)); 549644961713Sgirish 549753560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 549844961713Sgirish 549944961713Sgirish if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 550052ccf843Smisaki xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 550144961713Sgirish goto fail; 550244961713Sgirish 550353560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 550444961713Sgirish 550544961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 550652ccf843Smisaki xcvr_portn)); 550744961713Sgirish return (NXGE_OK); 550844961713Sgirish fail: 550953560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 551044961713Sgirish 551144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 551252ccf843Smisaki "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn)); 551344961713Sgirish 551444961713Sgirish return (NXGE_ERROR | rs); 551544961713Sgirish } 551644961713Sgirish 551744961713Sgirish 551844961713Sgirish /* Check MII to see if there is any link status change */ 551944961713Sgirish 552044961713Sgirish nxge_status_t 5521a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 5522a3c5bd6dSspeer nxge_link_state_t *link_up) 552344961713Sgirish { 552444961713Sgirish p_nxge_param_t param_arr; 552544961713Sgirish p_nxge_stats_t statsp; 552644961713Sgirish p_mii_regs_t mii_regs; 552744961713Sgirish p_mii_bmsr_t soft_bmsr; 552844961713Sgirish mii_anar_t anar; 552944961713Sgirish mii_anlpar_t anlpar; 553044961713Sgirish mii_anar_t an_common; 553144961713Sgirish mii_aner_t aner; 553244961713Sgirish mii_gsr_t gsr; 553344961713Sgirish nxge_status_t status = NXGE_OK; 553444961713Sgirish 553544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 553644961713Sgirish 553744961713Sgirish mii_regs = NULL; 553844961713Sgirish param_arr = nxgep->param_arr; 553944961713Sgirish statsp = nxgep->statsp; 554044961713Sgirish soft_bmsr = &nxgep->soft_bmsr; 5541a3c5bd6dSspeer *link_up = LINK_NO_CHANGE; 554244961713Sgirish 5543d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5544d81011f0Ssbehera "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x", 5545d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 5546d81011f0Ssbehera 554744961713Sgirish if (bmsr_ints.bits.link_status) { 5548d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5549d81011f0Ssbehera "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x", 5550d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 555144961713Sgirish if (bmsr.bits.link_status) { 555244961713Sgirish soft_bmsr->bits.link_status = 1; 5553d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5554d81011f0Ssbehera "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int " 5555d81011f0Ssbehera "0x%x", bmsr.value, bmsr_ints.value)); 555644961713Sgirish } else { 5557774da109Stc /* Only status change will update *link_up */ 5558774da109Stc if (statsp->mac_stats.link_up == 1) { 5559774da109Stc *link_up = LINK_IS_DOWN; 5560774da109Stc /* Will notify, turn off further msg */ 5561774da109Stc nxgep->link_notify = B_FALSE; 5562774da109Stc } 556344961713Sgirish statsp->mac_stats.link_up = 0; 556444961713Sgirish soft_bmsr->bits.link_status = 0; 556544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 556652ccf843Smisaki "Link down cable problem")); 556744961713Sgirish } 556844961713Sgirish } 556944961713Sgirish 5570d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 5571d81011f0Ssbehera param_arr[param_autoneg].value) { 557244961713Sgirish if (bmsr_ints.bits.auto_neg_complete) { 557344961713Sgirish if (bmsr.bits.auto_neg_complete) 557444961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 557544961713Sgirish else 557644961713Sgirish soft_bmsr->bits.auto_neg_complete = 0; 557744961713Sgirish } 557844961713Sgirish if (soft_bmsr->bits.link_status == 0) { 557944961713Sgirish statsp->mac_stats.link_T4 = 0; 558044961713Sgirish statsp->mac_stats.link_speed = 0; 558144961713Sgirish statsp->mac_stats.link_duplex = 0; 558244961713Sgirish statsp->mac_stats.link_asmpause = 0; 558344961713Sgirish statsp->mac_stats.link_pause = 0; 558444961713Sgirish statsp->mac_stats.lp_cap_autoneg = 0; 558544961713Sgirish statsp->mac_stats.lp_cap_100T4 = 0; 558644961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 0; 558744961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 0; 558844961713Sgirish statsp->mac_stats.lp_cap_100fdx = 0; 558944961713Sgirish statsp->mac_stats.lp_cap_100hdx = 0; 559044961713Sgirish statsp->mac_stats.lp_cap_10fdx = 0; 559144961713Sgirish statsp->mac_stats.lp_cap_10hdx = 0; 559244961713Sgirish statsp->mac_stats.lp_cap_10gfdx = 0; 559344961713Sgirish statsp->mac_stats.lp_cap_10ghdx = 0; 559444961713Sgirish statsp->mac_stats.lp_cap_asmpause = 0; 559544961713Sgirish statsp->mac_stats.lp_cap_pause = 0; 559644961713Sgirish } 559744961713Sgirish } else 559844961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 559944961713Sgirish 560044961713Sgirish if ((bmsr_ints.bits.link_status || 560152ccf843Smisaki bmsr_ints.bits.auto_neg_complete) && 560252ccf843Smisaki soft_bmsr->bits.link_status && 560352ccf843Smisaki soft_bmsr->bits.auto_neg_complete) { 5604774da109Stc if (statsp->mac_stats.link_up == 0) { 5605774da109Stc *link_up = LINK_IS_UP; 5606774da109Stc nxgep->link_notify = B_FALSE; 5607774da109Stc } 560844961713Sgirish statsp->mac_stats.link_up = 1; 5609d81011f0Ssbehera 5610d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5611d81011f0Ssbehera "==> nxge_mii_check " 5612d81011f0Ssbehera "(auto negotiation complete or link up) " 5613d81011f0Ssbehera "soft bmsr 0x%x bmsr_int 0x%x", 5614d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 5615d81011f0Ssbehera 5616d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 5617d81011f0Ssbehera param_arr[param_autoneg].value) { 561844961713Sgirish if ((status = nxge_mii_read(nxgep, 561952ccf843Smisaki statsp->mac_stats.xcvr_portn, 5620adfcba55Sjoycey #if defined(__i386) 562152ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->anar), 5622adfcba55Sjoycey #else 562352ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->anar), 5624adfcba55Sjoycey #endif 562552ccf843Smisaki &anar.value)) != NXGE_OK) 562644961713Sgirish goto fail; 562744961713Sgirish if ((status = nxge_mii_read(nxgep, 562852ccf843Smisaki statsp->mac_stats.xcvr_portn, 5629adfcba55Sjoycey #if defined(__i386) 563052ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->anlpar), 5631adfcba55Sjoycey #else 563252ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->anlpar), 5633adfcba55Sjoycey #endif 563452ccf843Smisaki &anlpar.value)) != NXGE_OK) 563544961713Sgirish goto fail; 563644961713Sgirish if ((status = nxge_mii_read(nxgep, 563752ccf843Smisaki statsp->mac_stats.xcvr_portn, 5638adfcba55Sjoycey #if defined(__i386) 563952ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->aner), 5640adfcba55Sjoycey #else 564152ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->aner), 5642adfcba55Sjoycey #endif 564352ccf843Smisaki &aner.value)) != NXGE_OK) 564444961713Sgirish goto fail; 564544961713Sgirish statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 564644961713Sgirish statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 564744961713Sgirish statsp->mac_stats.lp_cap_100fdx = 564852ccf843Smisaki anlpar.bits.cap_100fdx; 564944961713Sgirish statsp->mac_stats.lp_cap_100hdx = 565052ccf843Smisaki anlpar.bits.cap_100hdx; 565144961713Sgirish statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 565244961713Sgirish statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 565344961713Sgirish statsp->mac_stats.lp_cap_asmpause = 565452ccf843Smisaki anlpar.bits.cap_asmpause; 565544961713Sgirish statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 565644961713Sgirish an_common.value = anar.value & anlpar.value; 565744961713Sgirish if (param_arr[param_anar_1000fdx].value || 565852ccf843Smisaki param_arr[param_anar_1000hdx].value) { 565944961713Sgirish if ((status = nxge_mii_read(nxgep, 566052ccf843Smisaki statsp->mac_stats.xcvr_portn, 5661adfcba55Sjoycey #if defined(__i386) 566252ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gsr), 5663adfcba55Sjoycey #else 566452ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gsr), 5665adfcba55Sjoycey #endif 566652ccf843Smisaki &gsr.value)) != NXGE_OK) 566744961713Sgirish goto fail; 566844961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 566952ccf843Smisaki gsr.bits.link_1000fdx; 567044961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 567152ccf843Smisaki gsr.bits.link_1000hdx; 567244961713Sgirish if (param_arr[param_anar_1000fdx].value && 567352ccf843Smisaki gsr.bits.link_1000fdx) { 567444961713Sgirish statsp->mac_stats.link_speed = 1000; 567544961713Sgirish statsp->mac_stats.link_duplex = 2; 567644961713Sgirish } else if ( 567752ccf843Smisaki param_arr[param_anar_1000hdx].value && 567852ccf843Smisaki gsr.bits.link_1000hdx) { 567944961713Sgirish statsp->mac_stats.link_speed = 1000; 568044961713Sgirish statsp->mac_stats.link_duplex = 1; 568144961713Sgirish } 568244961713Sgirish } 568344961713Sgirish if ((an_common.value != 0) && 568452ccf843Smisaki !(statsp->mac_stats.link_speed)) { 568544961713Sgirish if (an_common.bits.cap_100T4) { 568644961713Sgirish statsp->mac_stats.link_T4 = 1; 568744961713Sgirish statsp->mac_stats.link_speed = 100; 568844961713Sgirish statsp->mac_stats.link_duplex = 1; 568944961713Sgirish } else if (an_common.bits.cap_100fdx) { 569044961713Sgirish statsp->mac_stats.link_speed = 100; 569144961713Sgirish statsp->mac_stats.link_duplex = 2; 569244961713Sgirish } else if (an_common.bits.cap_100hdx) { 569344961713Sgirish statsp->mac_stats.link_speed = 100; 569444961713Sgirish statsp->mac_stats.link_duplex = 1; 569544961713Sgirish } else if (an_common.bits.cap_10fdx) { 569644961713Sgirish statsp->mac_stats.link_speed = 10; 569744961713Sgirish statsp->mac_stats.link_duplex = 2; 569844961713Sgirish } else if (an_common.bits.cap_10hdx) { 569944961713Sgirish statsp->mac_stats.link_speed = 10; 570044961713Sgirish statsp->mac_stats.link_duplex = 1; 570144961713Sgirish } else { 570244961713Sgirish goto fail; 570344961713Sgirish } 570444961713Sgirish } 570544961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 570652ccf843Smisaki int link_pause; 570752ccf843Smisaki int cp, lcp; 570852ccf843Smisaki 570944961713Sgirish statsp->mac_stats.link_asmpause = 571052ccf843Smisaki an_common.bits.cap_asmpause; 571152ccf843Smisaki cp = statsp->mac_stats.cap_pause; 571252ccf843Smisaki lcp = statsp->mac_stats.lp_cap_pause; 571352ccf843Smisaki if (statsp->mac_stats.link_asmpause) { 571452ccf843Smisaki if ((cp == 0) && (lcp == 1)) { 571552ccf843Smisaki link_pause = 0; 571652ccf843Smisaki } else { 571752ccf843Smisaki link_pause = 1; 571852ccf843Smisaki } 571952ccf843Smisaki } else { 572052ccf843Smisaki link_pause = an_common.bits.cap_pause; 572152ccf843Smisaki } 572252ccf843Smisaki statsp->mac_stats.link_pause = link_pause; 572344961713Sgirish } 5724d81011f0Ssbehera } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 5725d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 5726d81011f0Ssbehera statsp->mac_stats.link_duplex = 2; 572744961713Sgirish } 5728a3c5bd6dSspeer } 5729774da109Stc /* Initial link_notify, delay link down msg */ 5730774da109Stc if (nxgep->link_notify && nxgep->nxge_mac_state == NXGE_MAC_STARTED && 5731774da109Stc (statsp->mac_stats.link_up == 1 || nxgep->link_check_count > 3)) { 5732a3c5bd6dSspeer *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 573352ccf843Smisaki LINK_IS_DOWN); 5734a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 573544961713Sgirish } 573644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 573744961713Sgirish return (NXGE_OK); 573844961713Sgirish fail: 573944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 574052ccf843Smisaki "nxge_mii_check: Unable to check MII")); 574144961713Sgirish return (status); 574244961713Sgirish } 574344961713Sgirish 574400161856Syc /* 574500161856Syc * Check PCS to see if there is any link status change. 574600161856Syc * This function is called by PORT_1G_SERDES only. 574700161856Syc */ 574800161856Syc void 57492e59129aSraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 57502e59129aSraghus { 57512e59129aSraghus p_nxge_stats_t statsp; 57522e59129aSraghus boolean_t linkup; 57532e59129aSraghus 57542e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 57552e59129aSraghus 57562e59129aSraghus statsp = nxgep->statsp; 57572e59129aSraghus *link_up = LINK_NO_CHANGE; 57582e59129aSraghus 57592e59129aSraghus (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 57602e59129aSraghus if (linkup) { 5761774da109Stc if ((nxgep->link_notify && 5762774da109Stc nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 57632e59129aSraghus nxgep->statsp->mac_stats.link_up == 0) { 57642e59129aSraghus statsp->mac_stats.link_up = 1; 57652e59129aSraghus statsp->mac_stats.link_speed = 1000; 57662e59129aSraghus statsp->mac_stats.link_duplex = 2; 57672e59129aSraghus *link_up = LINK_IS_UP; 57682e59129aSraghus nxgep->link_notify = B_FALSE; 57692e59129aSraghus } 57702e59129aSraghus } else { 5771774da109Stc if ((nxgep->link_notify && nxgep->link_check_count > 3 && 5772774da109Stc nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 57732e59129aSraghus nxgep->statsp->mac_stats.link_up == 1) { 57742e59129aSraghus statsp->mac_stats.link_up = 0; 57752e59129aSraghus statsp->mac_stats.link_speed = 0; 57762e59129aSraghus statsp->mac_stats.link_duplex = 0; 57772e59129aSraghus *link_up = LINK_IS_DOWN; 57782e59129aSraghus nxgep->link_notify = B_FALSE; 57792e59129aSraghus } 57802e59129aSraghus } 57812e59129aSraghus 57822e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 57832e59129aSraghus } 57842e59129aSraghus 578544961713Sgirish /* Add a multicast address entry into the HW hash table */ 578644961713Sgirish 578744961713Sgirish nxge_status_t 578844961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 578944961713Sgirish { 579044961713Sgirish uint32_t mchash; 579144961713Sgirish p_hash_filter_t hash_filter; 579244961713Sgirish uint16_t hash_bit; 579344961713Sgirish uint_t j; 579444961713Sgirish nxge_status_t status = NXGE_OK; 57950dc2366fSVenugopal Iyer npi_status_t rs; 579644961713Sgirish 579744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 579844961713Sgirish 579944961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 580044961713Sgirish mchash = crc32_mchash(addrp); 580144961713Sgirish if (nxgep->hash_filter == NULL) { 580244961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 580352ccf843Smisaki "Allocating hash filter storage.")); 580444961713Sgirish nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 580552ccf843Smisaki KM_SLEEP); 580644961713Sgirish } 58070dc2366fSVenugopal Iyer 580844961713Sgirish hash_filter = nxgep->hash_filter; 580944961713Sgirish j = mchash / HASH_REG_WIDTH; 581044961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 581144961713Sgirish hash_filter->hash_filter_regs[j] |= hash_bit; 581244961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]++; 581344961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 581444961713Sgirish hash_filter->hash_ref_cnt++; 581544961713Sgirish } 581644961713Sgirish 58170dc2366fSVenugopal Iyer rs = nxge_rx_mac_mcast_hash_table(nxgep); 58180dc2366fSVenugopal Iyer if (rs != NPI_SUCCESS) 58190dc2366fSVenugopal Iyer goto fail; 582044961713Sgirish 58210dc2366fSVenugopal Iyer RW_EXIT(&nxgep->filter_lock); 582244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 582344961713Sgirish return (NXGE_OK); 582444961713Sgirish fail: 582544961713Sgirish RW_EXIT(&nxgep->filter_lock); 582644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 582752ccf843Smisaki "Unable to add multicast address")); 582844961713Sgirish return (status); 582944961713Sgirish } 583044961713Sgirish 583144961713Sgirish /* Remove a multicast address entry from the HW hash table */ 583244961713Sgirish 583344961713Sgirish nxge_status_t 583444961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 583544961713Sgirish { 583644961713Sgirish uint32_t mchash; 583744961713Sgirish p_hash_filter_t hash_filter; 583844961713Sgirish uint16_t hash_bit; 583944961713Sgirish uint_t j; 584044961713Sgirish nxge_status_t status = NXGE_OK; 58410dc2366fSVenugopal Iyer npi_status_t rs; 584244961713Sgirish 584344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 584444961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 584544961713Sgirish mchash = crc32_mchash(addrp); 584644961713Sgirish if (nxgep->hash_filter == NULL) { 584744961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 584852ccf843Smisaki "Hash filter already de_allocated.")); 584944961713Sgirish RW_EXIT(&nxgep->filter_lock); 585044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 585144961713Sgirish return (NXGE_OK); 585244961713Sgirish } 585344961713Sgirish hash_filter = nxgep->hash_filter; 585444961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]--; 585544961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 585644961713Sgirish j = mchash / HASH_REG_WIDTH; 585744961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 585844961713Sgirish hash_filter->hash_filter_regs[j] &= ~hash_bit; 585944961713Sgirish hash_filter->hash_ref_cnt--; 586044961713Sgirish } 58610dc2366fSVenugopal Iyer 586244961713Sgirish if (hash_filter->hash_ref_cnt == 0) { 586344961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 586452ccf843Smisaki "De-allocating hash filter storage.")); 586544961713Sgirish KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 586644961713Sgirish nxgep->hash_filter = NULL; 586744961713Sgirish } 586844961713Sgirish 58690dc2366fSVenugopal Iyer rs = nxge_rx_mac_mcast_hash_table(nxgep); 58700dc2366fSVenugopal Iyer if (rs != NPI_SUCCESS) 58710dc2366fSVenugopal Iyer goto fail; 58720dc2366fSVenugopal Iyer 587344961713Sgirish RW_EXIT(&nxgep->filter_lock); 587444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 587544961713Sgirish 587644961713Sgirish return (NXGE_OK); 587744961713Sgirish fail: 587844961713Sgirish RW_EXIT(&nxgep->filter_lock); 587944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 588052ccf843Smisaki "Unable to remove multicast address")); 588144961713Sgirish 588244961713Sgirish return (status); 588344961713Sgirish } 588444961713Sgirish 588544961713Sgirish /* Set MAC address into MAC address HW registers */ 588644961713Sgirish 588744961713Sgirish nxge_status_t 588844961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 588944961713Sgirish { 589044961713Sgirish nxge_status_t status = NXGE_OK; 589144961713Sgirish 589244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 589344961713Sgirish 589444961713Sgirish MUTEX_ENTER(&nxgep->ouraddr_lock); 589544961713Sgirish /* 589644961713Sgirish * Exit if the address is same as ouraddr or multicast or broadcast 589744961713Sgirish */ 589844961713Sgirish if (((addrp->ether_addr_octet[0] & 01) == 1) || 589952ccf843Smisaki (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 590052ccf843Smisaki (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 590144961713Sgirish goto nxge_set_mac_addr_exit; 590244961713Sgirish } 590344961713Sgirish nxgep->ouraddr = *addrp; 590444961713Sgirish /* 590544961713Sgirish * Set new interface local address and re-init device. 590644961713Sgirish * This is destructive to any other streams attached 590744961713Sgirish * to this device. 590844961713Sgirish */ 590944961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 591044961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 591144961713Sgirish goto fail; 591244961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 591344961713Sgirish goto fail; 591444961713Sgirish 591544961713Sgirish RW_EXIT(&nxgep->filter_lock); 591644961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 591744961713Sgirish goto nxge_set_mac_addr_end; 591844961713Sgirish nxge_set_mac_addr_exit: 591944961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 592044961713Sgirish nxge_set_mac_addr_end: 592144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 592244961713Sgirish 592344961713Sgirish return (NXGE_OK); 592444961713Sgirish fail: 592544961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 592644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 592752ccf843Smisaki "Unable to set mac address")); 592844961713Sgirish return (status); 592944961713Sgirish } 593044961713Sgirish 593198ecde52Stm static 593298ecde52Stm check_link_state_t 593300161856Syc nxge_check_link_stop(nxge_t *nxge) 593498ecde52Stm { 593598ecde52Stm /* If the poll has been cancelled, return STOP. */ 593698ecde52Stm MUTEX_ENTER(&nxge->poll_lock); 593798ecde52Stm if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 593898ecde52Stm nxge->poll_state = LINK_MONITOR_STOP; 593998ecde52Stm nxge->nxge_link_poll_timerid = 0; 594098ecde52Stm cv_broadcast(&nxge->poll_cv); 594198ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 594298ecde52Stm 594398ecde52Stm NXGE_DEBUG_MSG((nxge, MAC_CTL, 594498ecde52Stm "nxge_check_%s_link(port<%d>) stopped.", 594598ecde52Stm nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 594698ecde52Stm nxge->mac.portnum)); 594798ecde52Stm return (CHECK_LINK_STOP); 594898ecde52Stm } 594998ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 595098ecde52Stm 595198ecde52Stm return (CHECK_LINK_RESCHEDULE); 595298ecde52Stm } 595398ecde52Stm 595400161856Syc /* 595500161856Syc * Check status of MII (MIF or PCS) link. 595600161856Syc * This function is called once per second, that is because this function 595700161856Syc * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to 595800161856Syc * call this function recursively. 595900161856Syc */ 596059ac0c16Sdavemq static nxge_status_t 596144961713Sgirish nxge_check_mii_link(p_nxge_t nxgep) 596244961713Sgirish { 596344961713Sgirish mii_bmsr_t bmsr_ints, bmsr_data; 596444961713Sgirish mii_anlpar_t anlpar; 596544961713Sgirish mii_gsr_t gsr; 596644961713Sgirish p_mii_regs_t mii_regs; 596744961713Sgirish nxge_status_t status = NXGE_OK; 596844961713Sgirish uint8_t portn; 5969a3c5bd6dSspeer nxge_link_state_t link_up; 597044961713Sgirish 597198ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 597298ecde52Stm return (NXGE_ERROR); 597398ecde52Stm 597498ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 597598ecde52Stm return (NXGE_OK); 597698ecde52Stm 597744961713Sgirish portn = nxgep->mac.portnum; 597844961713Sgirish 597944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 598098ecde52Stm portn)); 598144961713Sgirish 598244961713Sgirish mii_regs = NULL; 598344961713Sgirish 598444961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 598544961713Sgirish 598644961713Sgirish if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 598744961713Sgirish goto nxge_check_mii_link_exit; 598844961713Sgirish 59892e59129aSraghus switch (nxgep->mac.portmode) { 59902e59129aSraghus default: 5991d81011f0Ssbehera bmsr_data.value = 0; 599244961713Sgirish if ((status = nxge_mii_read(nxgep, 59932e59129aSraghus nxgep->statsp->mac_stats.xcvr_portn, 5994adfcba55Sjoycey #if defined(__i386) 5995adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 5996adfcba55Sjoycey #else 59972e59129aSraghus (uint8_t)(uint64_t)(&mii_regs->bmsr), 5998adfcba55Sjoycey #endif 59992e59129aSraghus &bmsr_data.value)) != NXGE_OK) { 600044961713Sgirish goto fail; 600144961713Sgirish } 600244961713Sgirish 6003d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6004d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> " 6005d81011f0Ssbehera "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 60062d17280bSsbehera portn, bmsr_data.value, nxgep->bmsr.value)); 6007d81011f0Ssbehera 60082e59129aSraghus if (nxgep->param_arr[param_autoneg].value) { 60092e59129aSraghus if ((status = nxge_mii_read(nxgep, 601052ccf843Smisaki nxgep->statsp->mac_stats.xcvr_portn, 6011adfcba55Sjoycey #if defined(__i386) 601252ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gsr), 6013adfcba55Sjoycey #else 601452ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gsr), 6015adfcba55Sjoycey #endif 601652ccf843Smisaki &gsr.value)) != NXGE_OK) 60172e59129aSraghus goto fail; 60182e59129aSraghus if ((status = nxge_mii_read(nxgep, 601952ccf843Smisaki nxgep->statsp->mac_stats.xcvr_portn, 6020adfcba55Sjoycey #if defined(__i386) 602152ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->anlpar), 6022adfcba55Sjoycey #else 602352ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->anlpar), 6024adfcba55Sjoycey #endif 602552ccf843Smisaki &anlpar.value)) != NXGE_OK) 60262e59129aSraghus goto fail; 6027d81011f0Ssbehera if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 6028d81011f0Ssbehera 6029d81011f0Ssbehera if (nxgep->statsp->mac_stats.link_up && 6030d81011f0Ssbehera ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 6031d81011f0Ssbehera gsr.bits.link_1000fdx) || 6032d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 6033d81011f0Ssbehera gsr.bits.link_1000hdx) || 6034d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 6035d81011f0Ssbehera anlpar.bits.cap_100T4) || 6036d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 6037d81011f0Ssbehera anlpar.bits.cap_100fdx) || 6038d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 6039d81011f0Ssbehera anlpar.bits.cap_100hdx) || 6040d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 6041d81011f0Ssbehera anlpar.bits.cap_10fdx) || 6042d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 6043d81011f0Ssbehera anlpar.bits.cap_10hdx))) { 6044d81011f0Ssbehera bmsr_data.bits.link_status = 0; 6045d81011f0Ssbehera } 60462e59129aSraghus } 60472e59129aSraghus } 604844961713Sgirish 60492e59129aSraghus /* Workaround for link down issue */ 60502e59129aSraghus if (bmsr_data.value == 0) { 60512e59129aSraghus cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 60522e59129aSraghus goto nxge_check_mii_link_exit; 60532e59129aSraghus } 60542e59129aSraghus 6055d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6056d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> :" 6057d81011f0Ssbehera "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 60582d17280bSsbehera portn, nxgep->bmsr.value, bmsr_data.value)); 6059d81011f0Ssbehera 60602e59129aSraghus bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 60612e59129aSraghus nxgep->bmsr.value = bmsr_data.value; 6062d81011f0Ssbehera 6063d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6064d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> CALLING " 6065d81011f0Ssbehera "bmsr_data 0x%x bmsr_ints.value 0x%x", 60662d17280bSsbehera portn, bmsr_data.value, bmsr_ints.value)); 6067d81011f0Ssbehera 60682e59129aSraghus if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 60692e59129aSraghus &link_up)) != NXGE_OK) { 60702e59129aSraghus goto fail; 60712e59129aSraghus } 60722e59129aSraghus break; 60732e59129aSraghus 60742e59129aSraghus case PORT_1G_SERDES: 607500161856Syc /* 607600161856Syc * Above default is for all cases except PORT_1G_SERDES. 607700161856Syc * The default case gets information from the PHY, but a 607800161856Syc * nxge whose portmode equals PORT_1G_SERDES does not 607900161856Syc * have a PHY. 608000161856Syc */ 60812e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 60822e59129aSraghus "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 608300161856Syc nxge_pcs_check(nxgep, portn, &link_up); 60842e59129aSraghus break; 60852e59129aSraghus } 608644961713Sgirish 608744961713Sgirish nxge_check_mii_link_exit: 608844961713Sgirish RW_EXIT(&nxgep->filter_lock); 6089a3c5bd6dSspeer if (link_up == LINK_IS_UP) { 6090a3c5bd6dSspeer nxge_link_is_up(nxgep); 6091a3c5bd6dSspeer } else if (link_up == LINK_IS_DOWN) { 6092a3c5bd6dSspeer nxge_link_is_down(nxgep); 6093a3c5bd6dSspeer } 609444961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 609544961713Sgirish 609644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 609752ccf843Smisaki portn)); 609844961713Sgirish return (NXGE_OK); 609944961713Sgirish 610044961713Sgirish fail: 610144961713Sgirish RW_EXIT(&nxgep->filter_lock); 610244961713Sgirish 610344961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 610444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 610552ccf843Smisaki "nxge_check_mii_link: Failed to check link port<%d>", portn)); 610644961713Sgirish return (status); 610744961713Sgirish } 610844961713Sgirish 610944961713Sgirish /*ARGSUSED*/ 611059ac0c16Sdavemq static nxge_status_t 611144961713Sgirish nxge_check_10g_link(p_nxge_t nxgep) 611244961713Sgirish { 611344961713Sgirish uint8_t portn; 611444961713Sgirish nxge_status_t status = NXGE_OK; 6115763fcc44Ssbehera boolean_t link_up; 61162e59129aSraghus uint32_t val; 61172e59129aSraghus npi_status_t rs; 611844961713Sgirish 611998ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 612098ecde52Stm return (NXGE_ERROR); 612198ecde52Stm 612298ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 612398ecde52Stm return (NXGE_OK); 612498ecde52Stm 612544961713Sgirish portn = nxgep->mac.portnum; 6126d81011f0Ssbehera val = 0; 6127d81011f0Ssbehera rs = NPI_SUCCESS; 612844961713Sgirish 612944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 613098ecde52Stm portn)); 613144961713Sgirish 61322e59129aSraghus switch (nxgep->mac.portmode) { 61332e59129aSraghus default: 61342d17280bSsbehera /* 61352d17280bSsbehera * Check if the phy is present in case of hot swappable phy 61362d17280bSsbehera */ 61372d17280bSsbehera if (nxgep->hot_swappable_phy) { 61382d17280bSsbehera boolean_t phy_present_now = B_FALSE; 61392d17280bSsbehera 6140*89282175SSantwona Behera if (nxge_hswap_phy_present(nxgep, portn)) 61412d17280bSsbehera phy_present_now = B_TRUE; 61422d17280bSsbehera 61431c7408c9Stc /* Check back-to-back XAUI connect to detect Opus NEM */ 61441c7408c9Stc rs = npi_xmac_xpcs_read(nxgep->npi_handle, 61451c7408c9Stc nxgep->mac.portnum, XPCS_REG_STATUS, &val); 61461c7408c9Stc if (rs != 0) 61471c7408c9Stc goto fail; 61481c7408c9Stc 61491c7408c9Stc link_up = B_FALSE; 61501c7408c9Stc if (val & XPCS_STATUS_LANE_ALIGN) { 61511c7408c9Stc link_up = B_TRUE; 61521c7408c9Stc } 61531c7408c9Stc 61542d17280bSsbehera if (nxgep->phy_absent) { 61552d17280bSsbehera if (phy_present_now) { 61562d17280bSsbehera /* 61572d17280bSsbehera * Detect, Initialize phy and do link up 61582d17280bSsbehera * set xcvr vals, link_init, nxge_init 61592d17280bSsbehera */ 61602d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61612d17280bSsbehera "Hot swappable phy DETECTED!!")); 61622d17280bSsbehera nxgep->phy_absent = B_FALSE; 61632d17280bSsbehera (void) nxge_xcvr_find(nxgep); 61642d17280bSsbehera (void) nxge_link_init(nxgep); 61652d17280bSsbehera if (!(nxgep->drv_state & 61662d17280bSsbehera STATE_HW_INITIALIZED)) { 61672d17280bSsbehera status = nxge_init(nxgep); 61682d17280bSsbehera if (status != NXGE_OK) { 61692d17280bSsbehera NXGE_ERROR_MSG((nxgep, 61702d17280bSsbehera NXGE_ERR_CTL, 61712d17280bSsbehera "Hot swappable " 61722d17280bSsbehera "phy present, but" 61732d17280bSsbehera " driver init" 61742d17280bSsbehera " failed...")); 61752d17280bSsbehera goto fail; 61762d17280bSsbehera } 61772d17280bSsbehera } 61781c7408c9Stc } else if (link_up) { /* XAUI linkup, no PHY */ 617948056c53SMichael Speer /* 61801c7408c9Stc * This is the back-to-back XAUI 61811c7408c9Stc * connect case for Opus NEM. 61821c7408c9Stc */ 61831c7408c9Stc nxgep->statsp->mac_stats.xcvr_inuse = 61841c7408c9Stc XPCS_XCVR; 61851c7408c9Stc nxgep->mac.portmode = PORT_10G_SERDES; 61861c7408c9Stc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61871c7408c9Stc "HSP 10G Serdes DETECTED!!")); 61881c7408c9Stc break; 61892d17280bSsbehera } 61902d17280bSsbehera 6191774da109Stc if (nxgep->link_notify && 6192774da109Stc nxgep->link_check_count > 3 && 6193774da109Stc nxgep->nxge_mac_state == NXGE_MAC_STARTED || 6194774da109Stc nxgep->statsp->mac_stats.link_up == 1) { 6195774da109Stc nxgep->statsp->mac_stats.link_up = 0; 6196774da109Stc nxgep->statsp->mac_stats.link_speed = 0; 6197774da109Stc nxgep->statsp->mac_stats.link_duplex = 6198774da109Stc 0; 6199774da109Stc 6200774da109Stc nxge_link_is_down(nxgep); 6201774da109Stc nxgep->link_notify = B_FALSE; 6202774da109Stc } 6203774da109Stc 62042d17280bSsbehera goto start_link_check; 62052d17280bSsbehera 62062d17280bSsbehera } else if (!phy_present_now) { 62072d17280bSsbehera /* 62082d17280bSsbehera * Phy gone, bring link down reset xcvr vals 62092d17280bSsbehera */ 62102d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 62112d17280bSsbehera "Hot swappable phy REMOVED!!")); 62122d17280bSsbehera nxgep->phy_absent = B_TRUE; 62132d17280bSsbehera nxgep->statsp->mac_stats.link_up = 0; 62142d17280bSsbehera nxgep->statsp->mac_stats.link_speed = 0; 62152d17280bSsbehera nxgep->statsp->mac_stats.link_duplex = 0; 62162d17280bSsbehera nxge_link_is_down(nxgep); 62172d17280bSsbehera nxgep->link_notify = B_FALSE; 62182d17280bSsbehera 62192d17280bSsbehera (void) nxge_xcvr_find(nxgep); 62202d17280bSsbehera 62212d17280bSsbehera goto start_link_check; 62222d17280bSsbehera 62232d17280bSsbehera } 62242d17280bSsbehera } 6225*89282175SSantwona Behera 6226*89282175SSantwona Behera switch (nxgep->chip_id) { 6227*89282175SSantwona Behera case MRVL88X201X_CHIP_ID: 622800161856Syc status = nxge_check_mrvl88x2011_link(nxgep, &link_up); 6229*89282175SSantwona Behera break; 6230*89282175SSantwona Behera case NLP2020_CHIP_ID: 6231*89282175SSantwona Behera status = nxge_check_nlp2020_link(nxgep, &link_up); 6232*89282175SSantwona Behera break; 6233*89282175SSantwona Behera default: 623452cdd236Ssbehera status = nxge_check_bcm8704_link(nxgep, &link_up); 6235*89282175SSantwona Behera break; 623652cdd236Ssbehera } 6237*89282175SSantwona Behera 62382e59129aSraghus if (status != NXGE_OK) 62392e59129aSraghus goto fail; 62402e59129aSraghus break; 62412e59129aSraghus case PORT_10G_SERDES: 62422e59129aSraghus rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 6243763fcc44Ssbehera XPCS_REG_STATUS, &val); 62442e59129aSraghus if (rs != 0) 62452e59129aSraghus goto fail; 62462e59129aSraghus 62472e59129aSraghus link_up = B_FALSE; 6248763fcc44Ssbehera if (val & XPCS_STATUS_LANE_ALIGN) { 6249763fcc44Ssbehera link_up = B_TRUE; 62502e59129aSraghus } 62512e59129aSraghus 62522e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 62532e59129aSraghus "==> nxge_check_10g_link port<%d> " 6254763fcc44Ssbehera "XPCS_REG_STATUS2 0x%x link_up %d", 6255763fcc44Ssbehera portn, val, link_up)); 62562e59129aSraghus 62572e59129aSraghus break; 62582e59129aSraghus } 625944961713Sgirish 626044961713Sgirish if (link_up) { 6261774da109Stc if ((nxgep->link_notify && 6262774da109Stc nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 626352ccf843Smisaki nxgep->statsp->mac_stats.link_up == 0) { 626444961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 626544961713Sgirish goto fail; 626644961713Sgirish nxgep->statsp->mac_stats.link_up = 1; 626744961713Sgirish nxgep->statsp->mac_stats.link_speed = 10000; 626844961713Sgirish nxgep->statsp->mac_stats.link_duplex = 2; 626944961713Sgirish 627044961713Sgirish nxge_link_is_up(nxgep); 6271a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 627244961713Sgirish } 627344961713Sgirish } else { 6274774da109Stc if ((nxgep->link_notify && nxgep->link_check_count > 3 && 6275774da109Stc nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 627652ccf843Smisaki nxgep->statsp->mac_stats.link_up == 1) { 627744961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 627844961713Sgirish goto fail; 627944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 628052ccf843Smisaki "Link down cable problem")); 628144961713Sgirish nxgep->statsp->mac_stats.link_up = 0; 628244961713Sgirish nxgep->statsp->mac_stats.link_speed = 0; 628344961713Sgirish nxgep->statsp->mac_stats.link_duplex = 0; 628444961713Sgirish 628544961713Sgirish nxge_link_is_down(nxgep); 6286a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 62871c7408c9Stc 62881c7408c9Stc if (nxgep->mac.portmode == PORT_10G_SERDES) { 62891c7408c9Stc /* 62901c7408c9Stc * NEM was unplugged, set up xcvr table 62911c7408c9Stc * to find another xcvr in the future. 62921c7408c9Stc */ 62931c7408c9Stc (void) nxge_xcvr_find(nxgep); 62941c7408c9Stc } 629544961713Sgirish } 629644961713Sgirish } 629744961713Sgirish 62982d17280bSsbehera start_link_check: 629944961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 630044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 630198ecde52Stm portn)); 630244961713Sgirish return (NXGE_OK); 630344961713Sgirish 630444961713Sgirish fail: 630598ecde52Stm (void) nxge_check_link_stop(nxgep); 630698ecde52Stm 630744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 630898ecde52Stm "nxge_check_10g_link: Failed to check link port<%d>", 630998ecde52Stm portn)); 631044961713Sgirish return (status); 631144961713Sgirish } 631244961713Sgirish 631344961713Sgirish 631444961713Sgirish /* Declare link down */ 631544961713Sgirish 631644961713Sgirish void 631744961713Sgirish nxge_link_is_down(p_nxge_t nxgep) 631844961713Sgirish { 631959ac0c16Sdavemq p_nxge_stats_t statsp; 632059ac0c16Sdavemq char link_stat_msg[64]; 632159ac0c16Sdavemq 632244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 632344961713Sgirish 632459ac0c16Sdavemq statsp = nxgep->statsp; 632559ac0c16Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 632659ac0c16Sdavemq statsp->mac_stats.xcvr_portn); 632759ac0c16Sdavemq 632859ac0c16Sdavemq if (nxge_no_msg == B_FALSE) { 632959ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 633059ac0c16Sdavemq } 633159ac0c16Sdavemq 633244961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_DOWN); 633344961713Sgirish 633444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 633544961713Sgirish } 633644961713Sgirish 633744961713Sgirish /* Declare link up */ 633844961713Sgirish 633944961713Sgirish void 634044961713Sgirish nxge_link_is_up(p_nxge_t nxgep) 634144961713Sgirish { 634259ac0c16Sdavemq p_nxge_stats_t statsp; 634359ac0c16Sdavemq char link_stat_msg[64]; 634444961713Sgirish uint32_t val; 634544961713Sgirish 634644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 634744961713Sgirish 634859ac0c16Sdavemq statsp = nxgep->statsp; 634959ac0c16Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 635059ac0c16Sdavemq statsp->mac_stats.xcvr_portn, 635159ac0c16Sdavemq statsp->mac_stats.link_speed); 635259ac0c16Sdavemq 635359ac0c16Sdavemq if (statsp->mac_stats.link_T4) 635459ac0c16Sdavemq (void) strcat(link_stat_msg, "T4"); 635559ac0c16Sdavemq else if (statsp->mac_stats.link_duplex == 2) 635659ac0c16Sdavemq (void) strcat(link_stat_msg, "full duplex"); 635759ac0c16Sdavemq else 635859ac0c16Sdavemq (void) strcat(link_stat_msg, "half duplex"); 635959ac0c16Sdavemq 636044961713Sgirish 636144961713Sgirish /* Clean up symbol errors incurred during link transition */ 63622e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 6363*89282175SSantwona Behera (nxgep->mac.portmode == PORT_10G_COPPER) || 63642e59129aSraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 636544961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 636652ccf843Smisaki XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 636744961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 636852ccf843Smisaki XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 636944961713Sgirish } 637044961713Sgirish 637100161856Syc /* 637200161856Syc * If the driver was plumbed without a link (therefore auto-negotiation 637300161856Syc * could not complete), the driver will detect a link up when a cable 637400161856Syc * conneting to a link partner is plugged into the port. By the time 637500161856Syc * link-up is detected, auto-negotiation should have completed (The 637600161856Syc * TN1010 tries to contact a link partner every 8~24ms). Here we re- 637700161856Syc * configure the Neptune/NIU according to the newly negotiated speed. 637800161856Syc * This is necessary only for the TN1010 basad device because only the 637900161856Syc * TN1010 supports dual speeds. 638000161856Syc */ 638100161856Syc if (nxgep->mac.portmode == PORT_1G_TN1010 || 638200161856Syc nxgep->mac.portmode == PORT_10G_TN1010) { 638300161856Syc 638400161856Syc (void) nxge_set_tn1010_param(nxgep); 638500161856Syc 638600161856Syc /* 638700161856Syc * nxge_xcvr_find calls nxge_get_xcvr_type (which sets 638800161856Syc * nxgep->portmode) and nxge_setup_xcvr_table (which sets 638900161856Syc * the nxgep->xcvr to the proper nxge_xcvr_table_t struct). 639000161856Syc */ 639100161856Syc if (nxge_xcvr_find(nxgep) != NXGE_OK) { 639200161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 639300161856Syc "nxge_link_is_up: nxge_xcvr_find failed")); 639400161856Syc } 639500161856Syc 639600161856Syc /* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */ 639700161856Syc if (nxge_link_init(nxgep) != NXGE_OK) { 639800161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 639900161856Syc "nxge_link_is_up: nxge_link_init failed")); 640000161856Syc } 640100161856Syc 640200161856Syc /* 640300161856Syc * nxge_mac_init calls many subroutines including 640400161856Syc * nxge_xif_init which sets XGMII or GMII mode 640500161856Syc */ 640600161856Syc if (nxge_mac_init(nxgep) != NXGE_OK) { 640700161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 640800161856Syc "nxge_link_is_up: nxge_mac_init failed")); 640900161856Syc } 641000161856Syc } else { 641100161856Syc (void) nxge_xif_init(nxgep); 641200161856Syc } 641300161856Syc 641459ac0c16Sdavemq if (nxge_no_msg == B_FALSE) { 641559ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 641659ac0c16Sdavemq } 641759ac0c16Sdavemq 641844961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UP); 641944961713Sgirish 642044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 642144961713Sgirish } 642244961713Sgirish 642300161856Syc #ifdef NXGE_DEBUG 642400161856Syc /* Dump all TN1010 Status registers */ 642500161856Syc static void 642600161856Syc nxge_dump_tn1010_status_regs(p_nxge_t nxgep) 642700161856Syc { 642800161856Syc uint16_t val; 642900161856Syc 643000161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 643100161856Syc TN1010_PMA_PMD_DEV_ADDR, 1, &val); 643200161856Syc cmn_err(CE_NOTE, "PMA status1 = 0x%x", val); 643300161856Syc 643400161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 643500161856Syc TN1010_PMA_PMD_DEV_ADDR, 8, &val); 643600161856Syc cmn_err(CE_NOTE, "PMA status2 = 0x%x", val); 643700161856Syc 643800161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 643900161856Syc TN1010_PMA_PMD_DEV_ADDR, 129, &val); 644000161856Syc cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val); 644100161856Syc 644200161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 644300161856Syc TN1010_PCS_DEV_ADDR, 1, &val); 644400161856Syc cmn_err(CE_NOTE, "PCS status1 = 0x%x", val); 644500161856Syc 644600161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 644700161856Syc TN1010_PCS_DEV_ADDR, 8, &val); 644800161856Syc cmn_err(CE_NOTE, "PCS status2 = 0x%x", val); 644900161856Syc 645000161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 645100161856Syc TN1010_PCS_DEV_ADDR, 32, &val); 645200161856Syc cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val); 645300161856Syc 645400161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 645500161856Syc TN1010_PCS_DEV_ADDR, 33, &val); 645600161856Syc cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val); 645700161856Syc 645800161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 645900161856Syc TN1010_PHYXS_DEV_ADDR, 1, &val); 646000161856Syc cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val); 646100161856Syc 646200161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 646300161856Syc TN1010_PHYXS_DEV_ADDR, 8, &val); 646400161856Syc cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val); 646500161856Syc 646600161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 646700161856Syc TN1010_PHYXS_DEV_ADDR, 24, &val); 646800161856Syc cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val); 646900161856Syc 647000161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 647100161856Syc TN1010_AUTONEG_DEV_ADDR, 1, &val); 647200161856Syc cmn_err(CE_NOTE, "Autoneg status = 0x%x", val); 647300161856Syc 647400161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 647500161856Syc TN1010_AUTONEG_DEV_ADDR, 33, &val); 647600161856Syc cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val); 647700161856Syc 647800161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 647900161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val); 648000161856Syc cmn_err(CE_NOTE, "TN1010 status = 0x%x", val); 648100161856Syc 648200161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 648300161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val); 648400161856Syc cmn_err(CE_NOTE, "Device status = 0x%x", val); 648500161856Syc 648600161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 648700161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val); 648800161856Syc cmn_err(CE_NOTE, "DDR status = 0x%x", val); 648900161856Syc 649000161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 649100161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val); 649200161856Syc cmn_err(CE_NOTE, "DDR fault status = 0x%x", val); 649300161856Syc 649400161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 649500161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val); 649600161856Syc cmn_err(CE_NOTE, "Firmware Revision = 0x%x Major = 0x%x Minor = 0x%x", 649700161856Syc val, (val & 0xFF00) >> 8, val & 0x00FF); 649800161856Syc } 649900161856Syc #endif 650000161856Syc 650144961713Sgirish /* 650244961713Sgirish * Calculate the bit in the multicast address filter 650344961713Sgirish * that selects the given * address. 650444961713Sgirish * Note: For GEM, the last 8-bits are used. 650544961713Sgirish */ 650644961713Sgirish uint32_t 650744961713Sgirish crc32_mchash(p_ether_addr_t addr) 650844961713Sgirish { 650944961713Sgirish uint8_t *cp; 651044961713Sgirish uint32_t crc; 651144961713Sgirish uint32_t c; 651244961713Sgirish int byte; 651344961713Sgirish int bit; 651444961713Sgirish 651544961713Sgirish cp = (uint8_t *)addr; 651644961713Sgirish crc = (uint32_t)0xffffffff; 651744961713Sgirish for (byte = 0; byte < 6; byte++) { 651844961713Sgirish c = (uint32_t)cp[byte]; 651944961713Sgirish for (bit = 0; bit < 8; bit++) { 652044961713Sgirish if ((c & 0x1) ^ (crc & 0x1)) 652144961713Sgirish crc = (crc >> 1)^0xedb88320; 652244961713Sgirish else 652344961713Sgirish crc = (crc >> 1); 652444961713Sgirish c >>= 1; 652544961713Sgirish } 652644961713Sgirish } 652744961713Sgirish return ((~crc) >> (32 - HASH_BITS)); 652844961713Sgirish } 652944961713Sgirish 653044961713Sgirish /* Reset serdes */ 653144961713Sgirish 653244961713Sgirish nxge_status_t 653344961713Sgirish nxge_serdes_reset(p_nxge_t nxgep) 653444961713Sgirish { 653544961713Sgirish npi_handle_t handle; 653644961713Sgirish 653744961713Sgirish handle = nxgep->npi_handle; 653844961713Sgirish 653944961713Sgirish ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 654044961713Sgirish drv_usecwait(500); 654144961713Sgirish ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 654244961713Sgirish 654344961713Sgirish return (NXGE_OK); 654444961713Sgirish } 654544961713Sgirish 654600161856Syc /* 654700161856Syc * This function monitors link status using interrupt or polling. 654800161856Syc * It calls nxgep->xcvr.check_link, a member function of 654900161856Syc * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this 655000161856Syc * function back, that is why the check_link routine is 655100161856Syc * executed periodically. 655200161856Syc */ 655344961713Sgirish nxge_status_t 655444961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 655544961713Sgirish { 655644961713Sgirish nxge_status_t status = NXGE_OK; 655744961713Sgirish 6558678453a8Sspeer /* If we are a guest domain driver, don't bother. */ 6559678453a8Sspeer if (isLDOMguest(nxgep)) 6560678453a8Sspeer return (status); 6561678453a8Sspeer 656244961713Sgirish /* 656398ecde52Stm * Return immediately if this is an imaginary XMAC port. 656498ecde52Stm * (At least, we don't have 4-port XMAC cards yet.) 656544961713Sgirish */ 65662e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER || 6567*89282175SSantwona Behera nxgep->mac.portmode == PORT_10G_COPPER || 65682e59129aSraghus nxgep->mac.portmode == PORT_10G_SERDES) && 65692e59129aSraghus (nxgep->mac.portnum > 1)) 657044961713Sgirish return (NXGE_OK); 657144961713Sgirish 657244961713Sgirish if (nxgep->statsp == NULL) { 657344961713Sgirish /* stats has not been allocated. */ 657444961713Sgirish return (NXGE_OK); 657544961713Sgirish } 6576321febdeSsbehera /* Don't check link if we're in internal loopback mode */ 6577321febdeSsbehera if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g) 657844961713Sgirish return (NXGE_OK); 657944961713Sgirish 658044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 658198ecde52Stm "==> nxge_link_monitor port<%d> enable=%d", 658298ecde52Stm nxgep->mac.portnum, enable)); 658344961713Sgirish if (enable == LINK_MONITOR_START) { 658444961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 658544961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 658698ecde52Stm != NXGE_OK) 658744961713Sgirish goto fail; 658844961713Sgirish } else { 658998ecde52Stm timeout_id_t timerid; 659000161856Syc /* 659100161856Syc * check_link_stop means "Stop the link check", so 659200161856Syc * we return without starting the timer. 659300161856Syc */ 659498ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 659598ecde52Stm return (NXGE_OK); 659698ecde52Stm 659700161856Syc /* 659800161856Syc * Otherwise fire the timer for the nxge to check 659900161856Syc * the link using the check_link function 660000161856Syc * of the nxge_xcvr_table and pass "nxgep" as the 660100161856Syc * argument to the check_link function. 660200161856Syc */ 660359ac0c16Sdavemq if (nxgep->xcvr.check_link) { 660459ac0c16Sdavemq timerid = timeout( 660559ac0c16Sdavemq (fptrv_t)(nxgep->xcvr.check_link), 660698ecde52Stm nxgep, 660798ecde52Stm drv_usectohz(LINK_MONITOR_PERIOD)); 660859ac0c16Sdavemq MUTEX_ENTER(&nxgep->poll_lock); 660959ac0c16Sdavemq nxgep->nxge_link_poll_timerid = timerid; 661059ac0c16Sdavemq MUTEX_EXIT(&nxgep->poll_lock); 6611774da109Stc nxgep->link_check_count ++; 661259ac0c16Sdavemq } else { 661398ecde52Stm return (NXGE_ERROR); 661444961713Sgirish } 661544961713Sgirish } 661644961713Sgirish } else { 661744961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 661844961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 661998ecde52Stm != NXGE_OK) 662044961713Sgirish goto fail; 662144961713Sgirish } else { 662298ecde52Stm clock_t rv; 662398ecde52Stm 662498ecde52Stm MUTEX_ENTER(&nxgep->poll_lock); 662598ecde52Stm 662698ecde52Stm /* If <timerid> == 0, the link monitor has */ 662798ecde52Stm /* never been started, or just now stopped. */ 662898ecde52Stm if (nxgep->nxge_link_poll_timerid == 0) { 662998ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 663098ecde52Stm return (NXGE_OK); 663198ecde52Stm } 663298ecde52Stm 663398ecde52Stm nxgep->poll_state = LINK_MONITOR_STOPPING; 6634d3d50737SRafael Vanoni rv = cv_reltimedwait(&nxgep->poll_cv, &nxgep->poll_lock, 663598ecde52Stm drv_usectohz(LM_WAIT_MULTIPLIER * 6636d3d50737SRafael Vanoni LINK_MONITOR_PERIOD), TR_CLOCK_TICK); 663798ecde52Stm if (rv == -1) { 663898ecde52Stm NXGE_DEBUG_MSG((nxgep, MAC_CTL, 663998ecde52Stm "==> stopping port %d: " 664098ecde52Stm "cv_timedwait(%d) timed out", 664198ecde52Stm nxgep->mac.portnum, nxgep->poll_state)); 664298ecde52Stm nxgep->poll_state = LINK_MONITOR_STOP; 664344961713Sgirish nxgep->nxge_link_poll_timerid = 0; 664444961713Sgirish } 664598ecde52Stm 664698ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 664744961713Sgirish } 664844961713Sgirish } 664944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 665098ecde52Stm "<== nxge_link_monitor port<%d> enable=%d", 665198ecde52Stm nxgep->mac.portnum, enable)); 6652678453a8Sspeer 665344961713Sgirish return (NXGE_OK); 665444961713Sgirish fail: 665544961713Sgirish return (status); 665600161856Syc 665700161856Syc } 665800161856Syc 665900161856Syc nxge_status_t 666000161856Syc nxge_check_tn1010_link(p_nxge_t nxgep) 666100161856Syc { 666200161856Syc nxge_status_t status = NXGE_OK; 666300161856Syc nxge_link_state_t link_up; 666400161856Syc 666500161856Syc if (nxgep->nxge_magic != NXGE_MAGIC) { 666600161856Syc /* magic is 0 if driver is not attached */ 666700161856Syc return (NXGE_ERROR); 666800161856Syc } 666900161856Syc 667000161856Syc /* Link has been stopped, no need to continue */ 667100161856Syc if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) { 667200161856Syc return (NXGE_OK); 667300161856Syc } 667400161856Syc 667500161856Syc if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 667600161856Syc goto nxge_check_tn1010_link_exit; 667700161856Syc 667800161856Syc if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK) 667900161856Syc goto fail; 668000161856Syc 668100161856Syc nxge_check_tn1010_link_exit: 668200161856Syc if (link_up == LINK_IS_UP) 668300161856Syc nxge_link_is_up(nxgep); 668400161856Syc else if (link_up == LINK_IS_DOWN) 668500161856Syc nxge_link_is_down(nxgep); 668600161856Syc 668700161856Syc /* 668800161856Syc * nxge_link_monitor will call (nxgep->xcvr.check_link) 668900161856Syc * which could be THIS function. 669000161856Syc */ 669100161856Syc (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 669200161856Syc 669300161856Syc return (NXGE_OK); 669400161856Syc 669500161856Syc fail: 669600161856Syc (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 669700161856Syc 669800161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 669900161856Syc "nxge_check_tn1010_link: Failed to check link")); 670000161856Syc return (status); 670100161856Syc } 670200161856Syc 670300161856Syc 670400161856Syc /* 670500161856Syc * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN. 670600161856Syc */ 670700161856Syc static nxge_status_t 670800161856Syc nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up) 670900161856Syc { 671000161856Syc nxge_status_t status = NXGE_OK; 671100161856Syc p_nxge_stats_t statsp; 671200161856Syc uint8_t phy_port_addr, portn; 671300161856Syc uint16_t val; 671400161856Syc 671500161856Syc *link_up = LINK_NO_CHANGE; 671600161856Syc 671700161856Syc portn = NXGE_GET_PORT_NUM(nxgep->function_num); 671800161856Syc phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 671900161856Syc statsp = nxgep->statsp; 672000161856Syc 672100161856Syc /* Check if link is up */ 672200161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 672300161856Syc TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val)) 672400161856Syc != NXGE_OK) { 672500161856Syc goto fail; 672600161856Syc } 672700161856Syc /* 672800161856Syc * nxge_link_is_up has called nxge_set_tn1010_param and set 672900161856Syc * portmode and link_speed 673000161856Syc */ 673100161856Syc if (val & TN1010_AN_LINK_STAT_BIT) { 6732774da109Stc if ((nxgep->link_notify && 6733774da109Stc nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 673400161856Syc nxgep->statsp->mac_stats.link_up == 0) { 673500161856Syc statsp->mac_stats.link_up = 1; 673600161856Syc statsp->mac_stats.link_duplex = 2; 673700161856Syc *link_up = LINK_IS_UP; 673800161856Syc nxgep->link_notify = B_FALSE; 673900161856Syc } 674000161856Syc } else { 6741774da109Stc if ((nxgep->link_notify && nxgep->link_check_count > 3 && 6742774da109Stc nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 674300161856Syc nxgep->statsp->mac_stats.link_up == 1) { 674400161856Syc statsp->mac_stats.link_up = 0; 674500161856Syc statsp->mac_stats.link_speed = 0; 674600161856Syc statsp->mac_stats.link_duplex = 0; 674700161856Syc *link_up = LINK_IS_DOWN; 674800161856Syc nxgep->link_notify = B_FALSE; 674900161856Syc } 675000161856Syc } 675100161856Syc return (NXGE_OK); 675200161856Syc 675300161856Syc fail: 675400161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 675500161856Syc "nxge_tn1010_check: Unable to check TN1010")); 675600161856Syc return (status); 675744961713Sgirish } 675844961713Sgirish 675900161856Syc 676044961713Sgirish /* Set promiscous mode */ 676144961713Sgirish 676244961713Sgirish nxge_status_t 676344961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 676444961713Sgirish { 676544961713Sgirish nxge_status_t status = NXGE_OK; 676644961713Sgirish 676759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 676844961713Sgirish 676944961713Sgirish nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 677044961713Sgirish 677144961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 677244961713Sgirish 677344961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 677444961713Sgirish goto fail; 677544961713Sgirish } 677644961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 677744961713Sgirish goto fail; 677844961713Sgirish } 677944961713Sgirish 678044961713Sgirish RW_EXIT(&nxgep->filter_lock); 678144961713Sgirish 678244961713Sgirish if (on) 678344961713Sgirish nxgep->statsp->mac_stats.promisc = B_TRUE; 678444961713Sgirish else 678544961713Sgirish nxgep->statsp->mac_stats.promisc = B_FALSE; 678644961713Sgirish 678744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 678844961713Sgirish 678944961713Sgirish return (NXGE_OK); 679044961713Sgirish fail: 679144961713Sgirish RW_EXIT(&nxgep->filter_lock); 679244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 679359ac0c16Sdavemq "Unable to set promisc (%d)", on)); 679444961713Sgirish 679544961713Sgirish return (status); 679644961713Sgirish } 679744961713Sgirish 679844961713Sgirish /*ARGSUSED*/ 679944961713Sgirish uint_t 680044961713Sgirish nxge_mif_intr(void *arg1, void *arg2) 680144961713Sgirish { 680244961713Sgirish #ifdef NXGE_DEBUG 680344961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 680444961713Sgirish #endif 680544961713Sgirish #if NXGE_MIF 680644961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 680744961713Sgirish uint32_t status; 680844961713Sgirish npi_handle_t handle; 680944961713Sgirish uint8_t portn; 681044961713Sgirish p_nxge_stats_t statsp; 681144961713Sgirish #endif 681244961713Sgirish 681344961713Sgirish #ifdef NXGE_MIF 681444961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 681544961713Sgirish nxgep = ldvp->nxgep; 681644961713Sgirish } 681744961713Sgirish nxgep = ldvp->nxgep; 681844961713Sgirish #endif 681944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 682044961713Sgirish 682144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 682244961713Sgirish return (DDI_INTR_CLAIMED); 682344961713Sgirish 682444961713Sgirish mif_intr_fail: 682544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 682644961713Sgirish return (DDI_INTR_UNCLAIMED); 682744961713Sgirish } 682844961713Sgirish 682944961713Sgirish /*ARGSUSED*/ 683044961713Sgirish uint_t 683144961713Sgirish nxge_mac_intr(void *arg1, void *arg2) 683244961713Sgirish { 683344961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 683444961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 683544961713Sgirish p_nxge_ldg_t ldgp; 683644961713Sgirish uint32_t status; 683744961713Sgirish npi_handle_t handle; 683844961713Sgirish uint8_t portn; 683944961713Sgirish p_nxge_stats_t statsp; 684044961713Sgirish npi_status_t rs = NPI_SUCCESS; 684144961713Sgirish 684244961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 684344961713Sgirish nxgep = ldvp->nxgep; 684444961713Sgirish } 684544961713Sgirish 684644961713Sgirish ldgp = ldvp->ldgp; 684744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 684859ac0c16Sdavemq "group %d", ldgp->ldg)); 684944961713Sgirish 685044961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 685144961713Sgirish /* 685244961713Sgirish * This interrupt handler is for a specific 685344961713Sgirish * mac port. 685444961713Sgirish */ 685544961713Sgirish statsp = (p_nxge_stats_t)nxgep->statsp; 685644961713Sgirish portn = nxgep->mac.portnum; 685744961713Sgirish 685844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 685959ac0c16Sdavemq "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 686044961713Sgirish 686144961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 686244961713Sgirish rs = npi_xmac_tx_get_istatus(handle, portn, 686352ccf843Smisaki (xmac_tx_iconfig_t *)&status); 686444961713Sgirish if (rs != NPI_SUCCESS) 686544961713Sgirish goto npi_fail; 686644961713Sgirish if (status & ICFG_XMAC_TX_ALL) { 686744961713Sgirish if (status & ICFG_XMAC_TX_UNDERRUN) { 686844961713Sgirish statsp->xmac_stats.tx_underflow_err++; 686944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 687052ccf843Smisaki NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 687144961713Sgirish } 687244961713Sgirish if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 687344961713Sgirish statsp->xmac_stats.tx_maxpktsize_err++; 6874f6485eecSyc /* 6875f6485eecSyc * Do not send FMA ereport because this 6876f6485eecSyc * error does not indicate HW failure. 6877f6485eecSyc */ 687844961713Sgirish } 687944961713Sgirish if (status & ICFG_XMAC_TX_OVERFLOW) { 688044961713Sgirish statsp->xmac_stats.tx_overflow_err++; 688144961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 688252ccf843Smisaki NXGE_FM_EREPORT_TXMAC_OVERFLOW); 688344961713Sgirish } 688444961713Sgirish if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 688544961713Sgirish statsp->xmac_stats.tx_fifo_xfr_err++; 688644961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 688752ccf843Smisaki NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 688844961713Sgirish } 688944961713Sgirish if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 689044961713Sgirish statsp->xmac_stats.tx_byte_cnt += 689152ccf843Smisaki XTXMAC_BYTE_CNT_MASK; 689244961713Sgirish } 689344961713Sgirish if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 689444961713Sgirish statsp->xmac_stats.tx_frame_cnt += 689552ccf843Smisaki XTXMAC_FRM_CNT_MASK; 689644961713Sgirish } 689744961713Sgirish } 689844961713Sgirish 689944961713Sgirish rs = npi_xmac_rx_get_istatus(handle, portn, 690052ccf843Smisaki (xmac_rx_iconfig_t *)&status); 690144961713Sgirish if (rs != NPI_SUCCESS) 690244961713Sgirish goto npi_fail; 690344961713Sgirish if (status & ICFG_XMAC_RX_ALL) { 690444961713Sgirish if (status & ICFG_XMAC_RX_OVERFLOW) 690544961713Sgirish statsp->xmac_stats.rx_overflow_err++; 690644961713Sgirish if (status & ICFG_XMAC_RX_UNDERFLOW) { 690744961713Sgirish statsp->xmac_stats.rx_underflow_err++; 690844961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 690952ccf843Smisaki NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 691044961713Sgirish } 6911f6485eecSyc /* 6912f6485eecSyc * Do not send FMA ereport for the following 3 errors 6913f6485eecSyc * because they do not indicate HW failures. 6914f6485eecSyc */ 691544961713Sgirish if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 691644961713Sgirish statsp->xmac_stats.rx_crc_err_cnt += 691752ccf843Smisaki XRXMAC_CRC_ER_CNT_MASK; 691844961713Sgirish } 691944961713Sgirish if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 692044961713Sgirish statsp->xmac_stats.rx_len_err_cnt += 692152ccf843Smisaki MAC_LEN_ER_CNT_MASK; 692244961713Sgirish } 692344961713Sgirish if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 692444961713Sgirish statsp->xmac_stats.rx_viol_err_cnt += 692552ccf843Smisaki XRXMAC_CD_VIO_CNT_MASK; 692644961713Sgirish } 692744961713Sgirish if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 692844961713Sgirish statsp->xmac_stats.rx_byte_cnt += 692952ccf843Smisaki XRXMAC_BT_CNT_MASK; 693044961713Sgirish } 693144961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 693244961713Sgirish statsp->xmac_stats.rx_hist1_cnt += 693352ccf843Smisaki XRXMAC_HIST_CNT1_MASK; 693444961713Sgirish } 693544961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 693644961713Sgirish statsp->xmac_stats.rx_hist2_cnt += 693752ccf843Smisaki XRXMAC_HIST_CNT2_MASK; 693844961713Sgirish } 693944961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 694044961713Sgirish statsp->xmac_stats.rx_hist3_cnt += 694152ccf843Smisaki XRXMAC_HIST_CNT3_MASK; 694244961713Sgirish } 694344961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 694444961713Sgirish statsp->xmac_stats.rx_hist4_cnt += 694552ccf843Smisaki XRXMAC_HIST_CNT4_MASK; 694644961713Sgirish } 694744961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 694844961713Sgirish statsp->xmac_stats.rx_hist5_cnt += 694952ccf843Smisaki XRXMAC_HIST_CNT5_MASK; 695044961713Sgirish } 695144961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 695244961713Sgirish statsp->xmac_stats.rx_hist6_cnt += 695352ccf843Smisaki XRXMAC_HIST_CNT6_MASK; 695444961713Sgirish } 695544961713Sgirish if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 695644961713Sgirish statsp->xmac_stats.rx_broadcast_cnt += 695752ccf843Smisaki XRXMAC_BC_FRM_CNT_MASK; 695844961713Sgirish } 695944961713Sgirish if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 696044961713Sgirish statsp->xmac_stats.rx_mult_cnt += 696152ccf843Smisaki XRXMAC_MC_FRM_CNT_MASK; 696244961713Sgirish } 6963f6485eecSyc /* 6964f6485eecSyc * Do not send FMA ereport for the following 3 errors 6965f6485eecSyc * because they do not indicate HW failures. 6966f6485eecSyc */ 696744961713Sgirish if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 696844961713Sgirish statsp->xmac_stats.rx_frag_cnt += 696952ccf843Smisaki XRXMAC_FRAG_CNT_MASK; 697044961713Sgirish } 697144961713Sgirish if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 697244961713Sgirish statsp->xmac_stats.rx_frame_align_err_cnt += 697352ccf843Smisaki XRXMAC_AL_ER_CNT_MASK; 697444961713Sgirish } 697544961713Sgirish if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 697644961713Sgirish statsp->xmac_stats.rx_linkfault_err_cnt += 697752ccf843Smisaki XMAC_LINK_FLT_CNT_MASK; 697844961713Sgirish } 697944961713Sgirish if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 698044961713Sgirish statsp->xmac_stats.rx_remotefault_err++; 698144961713Sgirish } 698244961713Sgirish if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 698344961713Sgirish statsp->xmac_stats.rx_localfault_err++; 698444961713Sgirish } 698544961713Sgirish } 698644961713Sgirish 698744961713Sgirish rs = npi_xmac_ctl_get_istatus(handle, portn, 698852ccf843Smisaki (xmac_ctl_iconfig_t *)&status); 698944961713Sgirish if (rs != NPI_SUCCESS) 699044961713Sgirish goto npi_fail; 699144961713Sgirish if (status & ICFG_XMAC_CTRL_ALL) { 699244961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 699344961713Sgirish statsp->xmac_stats.rx_pause_cnt++; 699444961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 699544961713Sgirish statsp->xmac_stats.tx_pause_state++; 699644961713Sgirish if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 699744961713Sgirish statsp->xmac_stats.tx_nopause_state++; 699844961713Sgirish } 699944961713Sgirish } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 700044961713Sgirish rs = npi_bmac_tx_get_istatus(handle, portn, 700152ccf843Smisaki (bmac_tx_iconfig_t *)&status); 700244961713Sgirish if (rs != NPI_SUCCESS) 700344961713Sgirish goto npi_fail; 700444961713Sgirish if (status & ICFG_BMAC_TX_ALL) { 700544961713Sgirish if (status & ICFG_BMAC_TX_UNDERFLOW) { 700644961713Sgirish statsp->bmac_stats.tx_underrun_err++; 700744961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 700852ccf843Smisaki NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 700944961713Sgirish } 701044961713Sgirish if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 701144961713Sgirish statsp->bmac_stats.tx_max_pkt_err++; 701244961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 701352ccf843Smisaki NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 701444961713Sgirish } 701544961713Sgirish if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 701644961713Sgirish statsp->bmac_stats.tx_byte_cnt += 701752ccf843Smisaki BTXMAC_BYTE_CNT_MASK; 701844961713Sgirish } 701944961713Sgirish if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 702044961713Sgirish statsp->bmac_stats.tx_frame_cnt += 702152ccf843Smisaki BTXMAC_FRM_CNT_MASK; 702244961713Sgirish } 702344961713Sgirish } 702444961713Sgirish 702544961713Sgirish rs = npi_bmac_rx_get_istatus(handle, portn, 702652ccf843Smisaki (bmac_rx_iconfig_t *)&status); 702744961713Sgirish if (rs != NPI_SUCCESS) 702844961713Sgirish goto npi_fail; 702944961713Sgirish if (status & ICFG_BMAC_RX_ALL) { 703044961713Sgirish if (status & ICFG_BMAC_RX_OVERFLOW) { 703144961713Sgirish statsp->bmac_stats.rx_overflow_err++; 703244961713Sgirish } 703344961713Sgirish if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 703444961713Sgirish statsp->bmac_stats.rx_frame_cnt += 703552ccf843Smisaki RXMAC_FRM_CNT_MASK; 703644961713Sgirish } 703744961713Sgirish if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 703844961713Sgirish statsp->bmac_stats.rx_crc_err_cnt += 703952ccf843Smisaki BMAC_CRC_ER_CNT_MASK; 704044961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 704152ccf843Smisaki NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 704244961713Sgirish } 704344961713Sgirish if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 704444961713Sgirish statsp->bmac_stats.rx_len_err_cnt += 704552ccf843Smisaki MAC_LEN_ER_CNT_MASK; 704644961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 704752ccf843Smisaki NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 704844961713Sgirish } 704944961713Sgirish if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 705044961713Sgirish statsp->bmac_stats.rx_viol_err_cnt += 705152ccf843Smisaki BMAC_CD_VIO_CNT_MASK; 705244961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 705352ccf843Smisaki NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 705444961713Sgirish } 705544961713Sgirish if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 705644961713Sgirish statsp->bmac_stats.rx_byte_cnt += 705752ccf843Smisaki BRXMAC_BYTE_CNT_MASK; 705844961713Sgirish } 705944961713Sgirish if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 706044961713Sgirish statsp->bmac_stats.rx_align_err_cnt += 706152ccf843Smisaki BMAC_AL_ER_CNT_MASK; 706244961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 706352ccf843Smisaki NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 706444961713Sgirish } 706544961713Sgirish 706644961713Sgirish rs = npi_bmac_ctl_get_istatus(handle, portn, 706752ccf843Smisaki (bmac_ctl_iconfig_t *)&status); 706844961713Sgirish if (rs != NPI_SUCCESS) 706944961713Sgirish goto npi_fail; 707044961713Sgirish 707144961713Sgirish if (status & ICFG_BMAC_CTL_ALL) { 707244961713Sgirish if (status & ICFG_BMAC_CTL_RCVPAUSE) 707344961713Sgirish statsp->bmac_stats.rx_pause_cnt++; 707444961713Sgirish if (status & ICFG_BMAC_CTL_INPAUSE_ST) 707544961713Sgirish statsp->bmac_stats.tx_pause_state++; 707644961713Sgirish if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 707744961713Sgirish statsp->bmac_stats.tx_nopause_state++; 707844961713Sgirish } 707944961713Sgirish } 708044961713Sgirish 708144961713Sgirish if (ldgp->nldvs == 1) { 708244961713Sgirish (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 708352ccf843Smisaki B_TRUE, ldgp->ldg_timer); 708444961713Sgirish } 708544961713Sgirish 708644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 708744961713Sgirish return (DDI_INTR_CLAIMED); 708844961713Sgirish 708944961713Sgirish npi_fail: 709044961713Sgirish NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 709144961713Sgirish return (DDI_INTR_UNCLAIMED); 709244961713Sgirish } 709344961713Sgirish 709444961713Sgirish nxge_status_t 709544961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 709644961713Sgirish { 709744961713Sgirish uint8_t phy_port_addr; 709844961713Sgirish nxge_status_t status = NXGE_OK; 709944961713Sgirish boolean_t rx_sig_ok; 710044961713Sgirish boolean_t pcs_blk_lock; 710144961713Sgirish boolean_t link_align; 710244961713Sgirish uint16_t val1, val2, val3; 710344961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 710444961713Sgirish uint16_t val_debug; 71054df55fdeSJanie Lu uint32_t val; 710644961713Sgirish #endif 710744961713Sgirish 710844961713Sgirish phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 710944961713Sgirish 711044961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 711144961713Sgirish /* Check Device 3 Register Device 3 0xC809 */ 711244961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 711344961713Sgirish if ((val_debug & ~0x200) != 0) { 711444961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 711552ccf843Smisaki nxgep->mac.portnum, val_debug); 711644961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 711752ccf843Smisaki &val_debug); 711844961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 711952ccf843Smisaki nxgep->mac.portnum, val_debug); 712044961713Sgirish } 712144961713Sgirish 712244961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 712352ccf843Smisaki XPCS_REG_DESCWERR_COUNTER, &val); 712444961713Sgirish if (val != 0) 712544961713Sgirish cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 712644961713Sgirish 712744961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 712852ccf843Smisaki XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 712944961713Sgirish if (val != 0) 713044961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 713144961713Sgirish 713244961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 713352ccf843Smisaki XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 713444961713Sgirish if (val != 0) 713544961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 713644961713Sgirish #endif 713744961713Sgirish 713844961713Sgirish /* Check from BCM8704 if 10G link is up or down */ 713944961713Sgirish 714044961713Sgirish /* Check Device 1 Register 0xA bit0 */ 714152ccf843Smisaki status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR, 714252ccf843Smisaki BCM8704_PMD_RECEIVE_SIG_DETECT, &val1); 714344961713Sgirish if (status != NXGE_OK) 714444961713Sgirish goto fail; 714544961713Sgirish rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 714644961713Sgirish 714744961713Sgirish /* Check Device 3 Register 0x20 bit0 */ 714852ccf843Smisaki if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR, 714952ccf843Smisaki BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS) 715044961713Sgirish goto fail; 715144961713Sgirish pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 715244961713Sgirish 715344961713Sgirish /* Check Device 4 Register 0x18 bit12 */ 715452ccf843Smisaki status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 715552ccf843Smisaki BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3); 715644961713Sgirish if (status != NXGE_OK) 715744961713Sgirish goto fail; 71582d17280bSsbehera 71592d17280bSsbehera switch (nxgep->chip_id) { 71602d17280bSsbehera case BCM8704_CHIP_ID: 71612d17280bSsbehera link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | 71622d17280bSsbehera XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 71632d17280bSsbehera XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 71642d17280bSsbehera break; 71652d17280bSsbehera case BCM8706_CHIP_ID: 71662d17280bSsbehera link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) && 71672d17280bSsbehera (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) && 71682d17280bSsbehera (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ? 71692d17280bSsbehera B_TRUE : B_FALSE; 71702d17280bSsbehera break; 71712d17280bSsbehera default: 71722d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:" 71732d17280bSsbehera "Unknown chip ID [0x%x]", nxgep->chip_id)); 71742d17280bSsbehera goto fail; 71752d17280bSsbehera } 71762d17280bSsbehera 717744961713Sgirish #ifdef NXGE_DEBUG_ALIGN_ERR 717844961713Sgirish /* Temp workaround for link down issue */ 717944961713Sgirish if (pcs_blk_lock == B_FALSE) { 718044961713Sgirish if (val2 != 0x4) { 718144961713Sgirish pcs_blk_lock = B_TRUE; 718252ccf843Smisaki cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 " 718352ccf843Smisaki "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2); 718444961713Sgirish } 718544961713Sgirish } 718644961713Sgirish 718744961713Sgirish if (link_align == B_FALSE) { 718844961713Sgirish if (val3 != 0x140f) { 718944961713Sgirish link_align = B_TRUE; 719052ccf843Smisaki cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 " 719152ccf843Smisaki "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3); 719244961713Sgirish } 719344961713Sgirish } 719444961713Sgirish 719544961713Sgirish if (rx_sig_ok == B_FALSE) { 719644961713Sgirish if ((val2 == 0) || (val3 == 0)) { 719744961713Sgirish rx_sig_ok = B_TRUE; 719844961713Sgirish cmn_err(CE_NOTE, 719952ccf843Smisaki "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 720052ccf843Smisaki nxgep->mac.portnum); 720144961713Sgirish } 720244961713Sgirish } 720344961713Sgirish #endif 720444961713Sgirish 720544961713Sgirish *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 720652ccf843Smisaki (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 720744961713Sgirish 720844961713Sgirish return (NXGE_OK); 720944961713Sgirish fail: 721044961713Sgirish return (status); 721144961713Sgirish } 721244961713Sgirish 721352cdd236Ssbehera static nxge_status_t 721400161856Syc nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up) 721552cdd236Ssbehera { 721652cdd236Ssbehera uint8_t phy; 721752cdd236Ssbehera nxge_status_t status = NXGE_OK; 721852cdd236Ssbehera boolean_t pma_status; 721952cdd236Ssbehera boolean_t pcs_status; 722052cdd236Ssbehera boolean_t xgxs_status; 722152cdd236Ssbehera uint16_t val; 722252cdd236Ssbehera 722352cdd236Ssbehera phy = nxgep->statsp->mac_stats.xcvr_portn; 722452cdd236Ssbehera 722552cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 722652cdd236Ssbehera MRVL_88X2011_10G_PMD_STAT_2, &val); 722752cdd236Ssbehera 722852cdd236Ssbehera *link_up = B_FALSE; 722952cdd236Ssbehera 723052cdd236Ssbehera /* Check from Marvell 88X2011 if 10G link is up or down */ 723152cdd236Ssbehera 723252cdd236Ssbehera /* Check PMA/PMD Register: 1.0001.2 == 1 */ 723352cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 723452cdd236Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 723552cdd236Ssbehera 723652cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 723752cdd236Ssbehera "nxge_check_mrvl88x2011_link: pmd=0x%x", val)); 723852cdd236Ssbehera 723952cdd236Ssbehera pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 724052cdd236Ssbehera 724152cdd236Ssbehera /* Check PMC Register : 3.0001.2 == 1: read twice */ 724252cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 724352cdd236Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 724452cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 724552cdd236Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 724652cdd236Ssbehera 724752cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 724852cdd236Ssbehera "nxge_check_mrvl88x2011_link: pcs=0x%x", val)); 724952cdd236Ssbehera 725052cdd236Ssbehera pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 725152cdd236Ssbehera 725252cdd236Ssbehera /* Check XGXS Register : 4.0018.[0-3,12] */ 725352cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR, 725452cdd236Ssbehera MRVL_88X2011_10G_XGXS_LANE_STAT, &val); 725552cdd236Ssbehera 725652cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 725752cdd236Ssbehera "nxge_check_mrvl88x2011_link: xgxs=0x%x", val)); 725852cdd236Ssbehera 725952cdd236Ssbehera xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 726052cdd236Ssbehera XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 726152cdd236Ssbehera XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY | 726252cdd236Ssbehera XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE; 726352cdd236Ssbehera 726452cdd236Ssbehera *link_up = (pma_status && pcs_status && xgxs_status) ? 726552cdd236Ssbehera B_TRUE : B_FALSE; 726652cdd236Ssbehera 726752cdd236Ssbehera fail: 726852cdd236Ssbehera 726952cdd236Ssbehera if (*link_up == B_FALSE) { 727052cdd236Ssbehera /* PCS OFF */ 727152cdd236Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF); 727252cdd236Ssbehera } else { 727352cdd236Ssbehera /* PCS Activity */ 727452cdd236Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT); 727552cdd236Ssbehera } 727652cdd236Ssbehera 727752cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 727852cdd236Ssbehera " <== nxge_check_mrvl88x2011_link: up=%d", *link_up)); 727952cdd236Ssbehera 728052cdd236Ssbehera return (status); 728152cdd236Ssbehera } 728252cdd236Ssbehera 7283*89282175SSantwona Behera static nxge_status_t 7284*89282175SSantwona Behera nxge_check_nlp2020_link(p_nxge_t nxgep, boolean_t *link_up) 7285*89282175SSantwona Behera { 7286*89282175SSantwona Behera uint8_t phy; 7287*89282175SSantwona Behera nxge_status_t status = NXGE_OK; 7288*89282175SSantwona Behera uint16_t pmd_rx_sig, pcs_10gbr_stat1, phy_xs_ln_stat; 7289*89282175SSantwona Behera uint8_t connector = 0; 7290*89282175SSantwona Behera 7291*89282175SSantwona Behera phy = nxgep->statsp->mac_stats.xcvr_portn; 7292*89282175SSantwona Behera *link_up = B_FALSE; 7293*89282175SSantwona Behera 7294*89282175SSantwona Behera /* Check from Netlogic AEL2020 if 10G link is up or down */ 7295*89282175SSantwona Behera 7296*89282175SSantwona Behera status = nxge_mdio_read(nxgep, phy, NLP2020_PMA_PMD_ADDR, 7297*89282175SSantwona Behera NLP2020_PMA_PMD_RX_SIG_DET_REG, &pmd_rx_sig); 7298*89282175SSantwona Behera if (status != NXGE_OK) 7299*89282175SSantwona Behera goto fail; 7300*89282175SSantwona Behera 7301*89282175SSantwona Behera status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_PCS_ADDR, 7302*89282175SSantwona Behera NLP2020_PHY_PCS_10GBR_STAT1_REG, &pcs_10gbr_stat1); 7303*89282175SSantwona Behera if (status != NXGE_OK) 7304*89282175SSantwona Behera goto fail; 7305*89282175SSantwona Behera 7306*89282175SSantwona Behera status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_XS_ADDR, 7307*89282175SSantwona Behera NLP2020_PHY_XS_LN_ST_REG, &phy_xs_ln_stat); 7308*89282175SSantwona Behera if (status != NXGE_OK) 7309*89282175SSantwona Behera goto fail; 7310*89282175SSantwona Behera 7311*89282175SSantwona Behera if ((pmd_rx_sig & NLP2020_PMA_PMD_RX_SIG_ON) && 7312*89282175SSantwona Behera (pcs_10gbr_stat1 & NLP2020_PHY_PCS_10GBR_RX_LINK_UP) && 7313*89282175SSantwona Behera (phy_xs_ln_stat & NLP2020_PHY_XS_LN_ALIGN_SYNC)) 7314*89282175SSantwona Behera *link_up = B_TRUE; 7315*89282175SSantwona Behera /* 7316*89282175SSantwona Behera * If previously link was down, check the connector type as 7317*89282175SSantwona Behera * it might have been changed. 7318*89282175SSantwona Behera */ 7319*89282175SSantwona Behera if (nxgep->statsp->mac_stats.link_up == 0) { 7320*89282175SSantwona Behera (void) nxge_nlp2020_i2c_read(nxgep, phy, 7321*89282175SSantwona Behera NLP2020_XCVR_I2C_ADDR, QSFP_MSA_CONN_REG, &connector); 7322*89282175SSantwona Behera 7323*89282175SSantwona Behera switch (connector) { 7324*89282175SSantwona Behera case SFPP_FIBER: 7325*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7326*89282175SSantwona Behera "nxge_check_nlp2020_link: SFPP_FIBER")); 7327*89282175SSantwona Behera if (nxgep->mac.portmode != PORT_10G_FIBER) { 7328*89282175SSantwona Behera nxgep->mac.portmode = PORT_10G_FIBER; 7329*89282175SSantwona Behera (void) nxge_nlp2020_xcvr_init(nxgep); 7330*89282175SSantwona Behera } 7331*89282175SSantwona Behera break; 7332*89282175SSantwona Behera case QSFP_FIBER: 7333*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7334*89282175SSantwona Behera "nxge_check_nlp2020_link: QSFP_FIBER")); 7335*89282175SSantwona Behera if (nxgep->mac.portmode != PORT_10G_FIBER) { 7336*89282175SSantwona Behera nxgep->mac.portmode = PORT_10G_FIBER; 7337*89282175SSantwona Behera (void) nxge_nlp2020_xcvr_init(nxgep); 7338*89282175SSantwona Behera } 7339*89282175SSantwona Behera break; 7340*89282175SSantwona Behera case QSFP_COPPER_TWINAX: 7341*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7342*89282175SSantwona Behera "nxge_check_nlp2020_link: " 7343*89282175SSantwona Behera "QSFP_COPPER_TWINAX/" 7344*89282175SSantwona Behera "SFPP_COPPER_TWINAX")); 7345*89282175SSantwona Behera if (nxgep->mac.portmode != PORT_10G_COPPER) { 7346*89282175SSantwona Behera nxgep->mac.portmode = PORT_10G_COPPER; 7347*89282175SSantwona Behera (void) nxge_nlp2020_xcvr_init(nxgep); 7348*89282175SSantwona Behera } else { 7349*89282175SSantwona Behera uint8_t len = 0; 7350*89282175SSantwona Behera (void) nxge_nlp2020_i2c_read(nxgep, phy, 7351*89282175SSantwona Behera NLP2020_XCVR_I2C_ADDR, QSFP_MSA_LEN_REG, 7352*89282175SSantwona Behera &len); 7353*89282175SSantwona Behera if (((len < 7) && 7354*89282175SSantwona Behera (nxgep->nlp_conn == 7355*89282175SSantwona Behera NXGE_NLP_CONN_COPPER_7M_ABOVE)) || 7356*89282175SSantwona Behera ((len >= 7) && 7357*89282175SSantwona Behera (nxgep->nlp_conn == 7358*89282175SSantwona Behera NXGE_NLP_CONN_COPPER_LT_7M))) { 7359*89282175SSantwona Behera (void) nxge_nlp2020_xcvr_init(nxgep); 7360*89282175SSantwona Behera } 7361*89282175SSantwona Behera } 7362*89282175SSantwona Behera break; 7363*89282175SSantwona Behera default: 7364*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7365*89282175SSantwona Behera "nxge_check_nlp2020_link: Unknown type [0x%x] " 7366*89282175SSantwona Behera "detected...setting to QSFP_FIBER", 7367*89282175SSantwona Behera connector)); 7368*89282175SSantwona Behera if (nxgep->mac.portmode != PORT_10G_FIBER) { 7369*89282175SSantwona Behera nxgep->mac.portmode = PORT_10G_FIBER; 7370*89282175SSantwona Behera (void) nxge_nlp2020_xcvr_init(nxgep); 7371*89282175SSantwona Behera } 7372*89282175SSantwona Behera break; 7373*89282175SSantwona Behera } 7374*89282175SSantwona Behera } 7375*89282175SSantwona Behera fail: 7376*89282175SSantwona Behera if (*link_up == B_FALSE && nxgep->statsp->mac_stats.link_up == 1) { 7377*89282175SSantwona Behera /* Turn link LED OFF */ 7378*89282175SSantwona Behera (void) nxge_mdio_write(nxgep, phy, 7379*89282175SSantwona Behera NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xb000); 7380*89282175SSantwona Behera (void) nxge_mdio_write(nxgep, phy, 7381*89282175SSantwona Behera NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0x0); 7382*89282175SSantwona Behera } else if (*link_up == B_TRUE && 7383*89282175SSantwona Behera nxgep->statsp->mac_stats.link_up == 0) { 7384*89282175SSantwona Behera /* Turn link LED ON */ 7385*89282175SSantwona Behera (void) nxge_mdio_write(nxgep, phy, 7386*89282175SSantwona Behera NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xd000); 7387*89282175SSantwona Behera (void) nxge_mdio_write(nxgep, phy, 7388*89282175SSantwona Behera NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0xfbff); 7389*89282175SSantwona Behera (void) nxge_mdio_write(nxgep, phy, 7390*89282175SSantwona Behera NLP2020_GPIO_ADDR, 0xff2a, 0x004a); 7391*89282175SSantwona Behera } 7392*89282175SSantwona Behera 7393*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7394*89282175SSantwona Behera " <== nxge_check_nlp2020_link: up=%d", *link_up)); 7395*89282175SSantwona Behera return (status); 7396*89282175SSantwona Behera } 7397*89282175SSantwona Behera 7398*89282175SSantwona Behera 739959ac0c16Sdavemq nxge_status_t 740059ac0c16Sdavemq nxge_10g_link_led_on(p_nxge_t nxgep) 740159ac0c16Sdavemq { 740259ac0c16Sdavemq if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 740359ac0c16Sdavemq != NPI_SUCCESS) 740459ac0c16Sdavemq return (NXGE_ERROR); 740559ac0c16Sdavemq else 740659ac0c16Sdavemq return (NXGE_OK); 740759ac0c16Sdavemq } 740844961713Sgirish 740944961713Sgirish nxge_status_t 741059ac0c16Sdavemq nxge_10g_link_led_off(p_nxge_t nxgep) 741144961713Sgirish { 741259ac0c16Sdavemq if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 741359ac0c16Sdavemq != NPI_SUCCESS) 741459ac0c16Sdavemq return (NXGE_ERROR); 741559ac0c16Sdavemq else 741659ac0c16Sdavemq return (NXGE_OK); 741759ac0c16Sdavemq } 741844961713Sgirish 7419*89282175SSantwona Behera static boolean_t 7420*89282175SSantwona Behera nxge_hswap_phy_present(p_nxge_t nxgep, uint8_t portn) 7421*89282175SSantwona Behera { 7422*89282175SSantwona Behera /* 7423*89282175SSantwona Behera * check for BCM PHY (GOA NEM) 7424*89282175SSantwona Behera */ 7425*89282175SSantwona Behera /* 7426*89282175SSantwona Behera * If this is the 2nd NIU port, then check 2 addresses 7427*89282175SSantwona Behera * to take care of the Goa NEM card. Port 1 can have addr 17 7428*89282175SSantwona Behera * (in the eval board) or 20 (in the P0 board). 7429*89282175SSantwona Behera */ 7430*89282175SSantwona Behera if (portn == 1) { 7431*89282175SSantwona Behera if (nxge_is_phy_present(nxgep, ALT_GOA_CLAUSE45_PORT1_ADDR, 7432*89282175SSantwona Behera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 7433*89282175SSantwona Behera nxgep->xcvr_addr = ALT_GOA_CLAUSE45_PORT1_ADDR; 7434*89282175SSantwona Behera goto found_phy; 7435*89282175SSantwona Behera } 7436*89282175SSantwona Behera } 7437*89282175SSantwona Behera if (nxge_is_phy_present(nxgep, GOA_CLAUSE45_PORT_ADDR_BASE + portn, 7438*89282175SSantwona Behera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 7439*89282175SSantwona Behera nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE + portn; 7440*89282175SSantwona Behera goto found_phy; 7441*89282175SSantwona Behera } 7442*89282175SSantwona Behera 7443*89282175SSantwona Behera /* 7444*89282175SSantwona Behera * check for NLP2020 PHY on C4 NEM 7445*89282175SSantwona Behera */ 7446*89282175SSantwona Behera switch (portn) { 7447*89282175SSantwona Behera case 0: 7448*89282175SSantwona Behera if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR0, 7449*89282175SSantwona Behera NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7450*89282175SSantwona Behera nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR0; 7451*89282175SSantwona Behera goto found_phy; 7452*89282175SSantwona Behera } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR1, 7453*89282175SSantwona Behera NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7454*89282175SSantwona Behera nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR1; 7455*89282175SSantwona Behera goto found_phy; 7456*89282175SSantwona Behera } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR2, 7457*89282175SSantwona Behera NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7458*89282175SSantwona Behera nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR2; 7459*89282175SSantwona Behera goto found_phy; 7460*89282175SSantwona Behera } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR3, 7461*89282175SSantwona Behera NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7462*89282175SSantwona Behera nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR3; 7463*89282175SSantwona Behera goto found_phy; 7464*89282175SSantwona Behera } 7465*89282175SSantwona Behera break; 7466*89282175SSantwona Behera 7467*89282175SSantwona Behera case 1: 7468*89282175SSantwona Behera if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR0, 7469*89282175SSantwona Behera NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7470*89282175SSantwona Behera nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR0; 7471*89282175SSantwona Behera goto found_phy; 7472*89282175SSantwona Behera } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR1, 7473*89282175SSantwona Behera NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7474*89282175SSantwona Behera nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR1; 7475*89282175SSantwona Behera goto found_phy; 7476*89282175SSantwona Behera } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR2, 7477*89282175SSantwona Behera NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7478*89282175SSantwona Behera nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR2; 7479*89282175SSantwona Behera goto found_phy; 7480*89282175SSantwona Behera } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR3, 7481*89282175SSantwona Behera NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7482*89282175SSantwona Behera nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR3; 7483*89282175SSantwona Behera goto found_phy; 7484*89282175SSantwona Behera } 7485*89282175SSantwona Behera break; 7486*89282175SSantwona Behera default: 7487*89282175SSantwona Behera break; 7488*89282175SSantwona Behera } 7489*89282175SSantwona Behera 7490*89282175SSantwona Behera return (B_FALSE); 7491*89282175SSantwona Behera found_phy: 7492*89282175SSantwona Behera return (B_TRUE); 7493*89282175SSantwona Behera 7494*89282175SSantwona Behera } 7495*89282175SSantwona Behera 74962d17280bSsbehera static boolean_t 74972d17280bSsbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask) 74982d17280bSsbehera { 74992d17280bSsbehera uint32_t pma_pmd_id = 0; 75002d17280bSsbehera uint32_t pcs_id = 0; 75012d17280bSsbehera uint32_t phy_id = 0; 75022d17280bSsbehera 75032d17280bSsbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr); 75042d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 75052d17280bSsbehera "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id)); 75062d17280bSsbehera if ((pma_pmd_id & mask) == (id & mask)) 75072d17280bSsbehera goto found_phy; 75082d17280bSsbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, addr); 75092d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 75102d17280bSsbehera "nxge_is_phy_present: pcs_id[0x%x]", pcs_id)); 75112d17280bSsbehera if ((pcs_id & mask) == (id & mask)) 75122d17280bSsbehera goto found_phy; 75132d17280bSsbehera phy_id = nxge_get_cl22_phy_id(nxgep, addr); 75142d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 75152d17280bSsbehera "nxge_is_phy_present: phy_id[0x%x]", phy_id)); 75162d17280bSsbehera if ((phy_id & mask) == (id & mask)) 75172d17280bSsbehera goto found_phy; 75182d17280bSsbehera 75192d17280bSsbehera return (B_FALSE); 75202d17280bSsbehera 75212d17280bSsbehera found_phy: 75222d17280bSsbehera return (B_TRUE); 75232d17280bSsbehera } 75242d17280bSsbehera 752559ac0c16Sdavemq /* Check if the given id read using the given MDIO Clause is supported */ 752659ac0c16Sdavemq 752759ac0c16Sdavemq static boolean_t 752859ac0c16Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type) 752959ac0c16Sdavemq { 753059ac0c16Sdavemq int i; 753159ac0c16Sdavemq boolean_t found = B_FALSE; 753259ac0c16Sdavemq 753359ac0c16Sdavemq switch (type) { 753459ac0c16Sdavemq case CLAUSE_45_TYPE: 753500161856Syc for (i = 0; i < NUM_CLAUSE_45_IDS; i++) { 753600161856Syc if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 753700161856Syc (id & BCM_PHY_ID_MASK)) || 7538*89282175SSantwona Behera (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK)) || 7539*89282175SSantwona Behera (NLP2020_DEV_ID == (id & NLP2020_DEV_ID_MASK))) { 754059ac0c16Sdavemq found = B_TRUE; 754159ac0c16Sdavemq break; 754259ac0c16Sdavemq } 754359ac0c16Sdavemq } 754459ac0c16Sdavemq break; 754559ac0c16Sdavemq case CLAUSE_22_TYPE: 754600161856Syc for (i = 0; i < NUM_CLAUSE_22_IDS; i++) { 754730505775Ssbehera if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 754830505775Ssbehera (id & BCM_PHY_ID_MASK)) { 754959ac0c16Sdavemq found = B_TRUE; 755059ac0c16Sdavemq break; 755156d930aeSspeer } 755244961713Sgirish } 755359ac0c16Sdavemq break; 755459ac0c16Sdavemq default: 755559ac0c16Sdavemq break; 755656d930aeSspeer } 755756d930aeSspeer 755859ac0c16Sdavemq return (found); 755959ac0c16Sdavemq } 756059ac0c16Sdavemq 75612e59129aSraghus static uint32_t 75622e59129aSraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 75632e59129aSraghus { 75642e59129aSraghus uint16_t val1 = 0; 75652e59129aSraghus uint16_t val2 = 0; 75662e59129aSraghus uint32_t pma_pmd_dev_id = 0; 75672e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 75682e59129aSraghus 756953560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 75702e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 75712e59129aSraghus NXGE_DEV_ID_REG_1, &val1); 75722e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 75732e59129aSraghus NXGE_DEV_ID_REG_2, &val2); 757453560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 75752e59129aSraghus 757600161856Syc /* Concatenate the Device ID stored in two registers. */ 75772e59129aSraghus pma_pmd_dev_id = val1; 75782e59129aSraghus pma_pmd_dev_id = (pma_pmd_dev_id << 16); 75792e59129aSraghus pma_pmd_dev_id |= val2; 75802e59129aSraghus 75812e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 75822e59129aSraghus "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 75832e59129aSraghus 75842e59129aSraghus return (pma_pmd_dev_id); 75852e59129aSraghus } 75862e59129aSraghus 75872e59129aSraghus static uint32_t 75882e59129aSraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 75892e59129aSraghus { 75902e59129aSraghus uint16_t val1 = 0; 75912e59129aSraghus uint16_t val2 = 0; 75922e59129aSraghus uint32_t pcs_dev_id = 0; 75932e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 75942e59129aSraghus 759553560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 75962e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 75972e59129aSraghus NXGE_DEV_ID_REG_1, &val1); 75982e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 75992e59129aSraghus NXGE_DEV_ID_REG_2, &val2); 760053560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 76012e59129aSraghus 76022e59129aSraghus pcs_dev_id = val1; 76032e59129aSraghus pcs_dev_id = (pcs_dev_id << 16); 76042e59129aSraghus pcs_dev_id |= val2; 76052e59129aSraghus 76062e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 76072e59129aSraghus "devid[0x%llx]", phy_port, pcs_dev_id)); 76082e59129aSraghus 76092e59129aSraghus return (pcs_dev_id); 76102e59129aSraghus } 76112e59129aSraghus 76122e59129aSraghus static uint32_t 76132e59129aSraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 76142e59129aSraghus { 76152e59129aSraghus uint16_t val1 = 0; 76162e59129aSraghus uint16_t val2 = 0; 76172e59129aSraghus uint32_t phy_id = 0; 76182e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 76192e59129aSraghus npi_status_t npi_status = NPI_SUCCESS; 76202e59129aSraghus 7621321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 76222e59129aSraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 76232e59129aSraghus &val1); 76242e59129aSraghus if (npi_status != NPI_SUCCESS) { 76252e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 76262e59129aSraghus "clause 22 read to reg 2 failed!!!")); 76272e59129aSraghus goto exit; 76282e59129aSraghus } 76292e59129aSraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 76302e59129aSraghus &val2); 76312e59129aSraghus if (npi_status != 0) { 76322e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 76332e59129aSraghus "clause 22 read to reg 3 failed!!!")); 76342e59129aSraghus goto exit; 76352e59129aSraghus } 76362e59129aSraghus phy_id = val1; 76372e59129aSraghus phy_id = (phy_id << 16); 76382e59129aSraghus phy_id |= val2; 76392e59129aSraghus 76402e59129aSraghus exit: 7641321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 76422e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 76432e59129aSraghus phy_port, phy_id)); 76442e59129aSraghus 76452e59129aSraghus return (phy_id); 76462e59129aSraghus } 76472e59129aSraghus 764859ac0c16Sdavemq /* 764959ac0c16Sdavemq * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 765059ac0c16Sdavemq * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 765159ac0c16Sdavemq * read. Then use the values obtained to determine the phy type of each port 765259ac0c16Sdavemq * and the Neptune type. 765300161856Syc * 765400161856Syc * This function sets hw_p->xcvr_addr[i] for future MDIO access and set 765500161856Syc * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode 765600161856Syc * in case the portmode information is not available via OBP, nxge.conf, 765700161856Syc * VPD or SEEPROM. 765859ac0c16Sdavemq */ 765959ac0c16Sdavemq nxge_status_t 766059ac0c16Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 766159ac0c16Sdavemq { 766259a835ddSjoycey int i, j, l; 766359ac0c16Sdavemq uint32_t pma_pmd_dev_id = 0; 766459ac0c16Sdavemq uint32_t pcs_dev_id = 0; 766559ac0c16Sdavemq uint32_t phy_id = 0; 766630505775Ssbehera uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 766730505775Ssbehera uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 766830505775Ssbehera uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 766959ac0c16Sdavemq uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 767059ac0c16Sdavemq uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 76712d17280bSsbehera uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS]; 76722d17280bSsbehera uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS]; 767359ac0c16Sdavemq uint8_t total_port_fd, total_phy_fd; 767400161856Syc uint8_t num_xaui; 767559ac0c16Sdavemq nxge_status_t status = NXGE_OK; 767656d930aeSspeer 767759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 767856d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 767959ac0c16Sdavemq "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 768059ac0c16Sdavemq nxgep->niu_type)); 768159ac0c16Sdavemq 7682678453a8Sspeer if (isLDOMguest(nxgep)) { 7683678453a8Sspeer hw_p->niu_type = NIU_TYPE_NONE; 7684678453a8Sspeer hw_p->platform_type = P_NEPTUNE_NONE; 7685678453a8Sspeer return (NXGE_OK); 7686678453a8Sspeer } 7687678453a8Sspeer 768859a835ddSjoycey j = l = 0; 768959ac0c16Sdavemq total_port_fd = total_phy_fd = 0; 769056d930aeSspeer /* 769123b952a3SSantwona Behera * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved 769223b952a3SSantwona Behera * for on chip serdes usages. "i" in the following for loop starts at 6. 769356d930aeSspeer */ 769459ac0c16Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 76952e59129aSraghus 76962e59129aSraghus pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 769759ac0c16Sdavemq 769859ac0c16Sdavemq if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 769959ac0c16Sdavemq pma_pmd_dev_fd[i] = 1; 770059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 770152cdd236Ssbehera "PMA/PMD dev %x found", i, pma_pmd_dev_id)); 770230505775Ssbehera if (j < NXGE_PORTS_NEPTUNE) { 770300161856Syc if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK) 770400161856Syc == TN1010_DEV_ID) { 770500161856Syc port_pma_pmd_dev_id[j] = TN1010_DEV_ID; 7706*89282175SSantwona Behera } else if ((pma_pmd_dev_id & 7707*89282175SSantwona Behera NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID) { 7708*89282175SSantwona Behera port_pma_pmd_dev_id[j] = 7709*89282175SSantwona Behera NLP2020_DEV_ID; 771000161856Syc } else { 771100161856Syc port_pma_pmd_dev_id[j] = 771252ccf843Smisaki pma_pmd_dev_id & BCM_PHY_ID_MASK; 771300161856Syc } 77142d17280bSsbehera port_fd_arr[j] = (uint8_t)i; 771559ac0c16Sdavemq j++; 771659ac0c16Sdavemq } 771759ac0c16Sdavemq } else { 771859ac0c16Sdavemq pma_pmd_dev_fd[i] = 0; 771959ac0c16Sdavemq } 772059ac0c16Sdavemq 77212e59129aSraghus pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 772259ac0c16Sdavemq 772359ac0c16Sdavemq if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 772459ac0c16Sdavemq pcs_dev_fd[i] = 1; 772559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 772652cdd236Ssbehera "dev %x found", i, pcs_dev_id)); 772759a835ddSjoycey if (pma_pmd_dev_fd[i] == 1) { 772800161856Syc if ((pcs_dev_id & TN1010_DEV_ID_MASK) 772900161856Syc == TN1010_DEV_ID) { 773000161856Syc port_pcs_dev_id[j - 1] = 773100161856Syc TN1010_DEV_ID; 7732*89282175SSantwona Behera } else if ((pcs_dev_id & NLP2020_DEV_ID_MASK) 7733*89282175SSantwona Behera == NLP2020_DEV_ID) { 7734*89282175SSantwona Behera port_pcs_dev_id[j - 1] = 7735*89282175SSantwona Behera NLP2020_DEV_ID; 773600161856Syc } else { 773700161856Syc port_pcs_dev_id[j - 1] = 773800161856Syc pcs_dev_id & 773900161856Syc BCM_PHY_ID_MASK; 774000161856Syc } 774159a835ddSjoycey } else { 774259a835ddSjoycey if (j < NXGE_PORTS_NEPTUNE) { 774300161856Syc if ((pcs_dev_id & TN1010_DEV_ID_MASK) 774452ccf843Smisaki == TN1010_DEV_ID) { 774500161856Syc port_pcs_dev_id[j] = 774600161856Syc TN1010_DEV_ID; 7747*89282175SSantwona Behera } else if ((pcs_dev_id & 7748*89282175SSantwona Behera NLP2020_DEV_ID_MASK) 7749*89282175SSantwona Behera == NLP2020_DEV_ID) { 7750*89282175SSantwona Behera port_pcs_dev_id[j] = 7751*89282175SSantwona Behera NLP2020_DEV_ID; 775200161856Syc } else { 775300161856Syc port_pcs_dev_id[j] = 775400161856Syc pcs_dev_id & 775500161856Syc BCM_PHY_ID_MASK; 775600161856Syc } 775759a835ddSjoycey port_fd_arr[j] = (uint8_t)i; 775859a835ddSjoycey j++; 775959a835ddSjoycey } 776059ac0c16Sdavemq } 776159ac0c16Sdavemq } else { 776259ac0c16Sdavemq pcs_dev_fd[i] = 0; 776359ac0c16Sdavemq } 776459ac0c16Sdavemq 77652d17280bSsbehera if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) { 77662d17280bSsbehera total_port_fd ++; 77672d17280bSsbehera } 776859ac0c16Sdavemq 77692e59129aSraghus phy_id = nxge_get_cl22_phy_id(nxgep, i); 777059ac0c16Sdavemq if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 77712d17280bSsbehera total_phy_fd ++; 777259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 777352cdd236Ssbehera "%x found", i, phy_id)); 777430505775Ssbehera if (l < NXGE_PORTS_NEPTUNE) { 777500161856Syc if ((phy_id & TN1010_DEV_ID_MASK) 777600161856Syc == TN1010_DEV_ID) { 777700161856Syc port_phy_id[l] = TN1010_DEV_ID; 777800161856Syc } else { 777900161856Syc port_phy_id[l] 778000161856Syc = phy_id & BCM_PHY_ID_MASK; 778100161856Syc } 77822d17280bSsbehera phy_fd_arr[l] = (uint8_t)i; 778359ac0c16Sdavemq l++; 778459ac0c16Sdavemq } 778559ac0c16Sdavemq } 778659ac0c16Sdavemq } 778759ac0c16Sdavemq 778859ac0c16Sdavemq switch (total_port_fd) { 778959ac0c16Sdavemq case 2: 779059ac0c16Sdavemq switch (total_phy_fd) { 779159ac0c16Sdavemq case 2: 779223b952a3SSantwona Behera /* 2 10G, 2 1G RGMII Fiber / copper */ 779359a835ddSjoycey if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 779459a835ddSjoycey (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 779559a835ddSjoycey ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 779659a835ddSjoycey (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 779759a835ddSjoycey ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 779859a835ddSjoycey (port_phy_id[1] == PHY_BCM5482_FAMILY))) { 779959a835ddSjoycey 780023b952a3SSantwona Behera switch (hw_p->platform_type) { 780123b952a3SSantwona Behera case P_NEPTUNE_ROCK: 780223b952a3SSantwona Behera hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 780323b952a3SSantwona Behera /* 780423b952a3SSantwona Behera * ROCK platform has assigned a lower 780523b952a3SSantwona Behera * addr to port 1. (port 0 = 0x9 and 780623b952a3SSantwona Behera * port 1 = 0x8). 780723b952a3SSantwona Behera */ 780823b952a3SSantwona Behera hw_p->xcvr_addr[1] = port_fd_arr[0]; 780923b952a3SSantwona Behera hw_p->xcvr_addr[0] = port_fd_arr[1]; 781023b952a3SSantwona Behera 781123b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 781223b952a3SSantwona Behera "Rock with 2 10G, 2 1GC")); 781323b952a3SSantwona Behera break; 781423b952a3SSantwona Behera 781523b952a3SSantwona Behera case P_NEPTUNE_NONE: 781623b952a3SSantwona Behera default: 781723b952a3SSantwona Behera hw_p->platform_type = 781823b952a3SSantwona Behera P_NEPTUNE_GENERIC; 781923b952a3SSantwona Behera hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF; 782059a835ddSjoycey 782123b952a3SSantwona Behera hw_p->xcvr_addr[0] = port_fd_arr[0]; 782223b952a3SSantwona Behera hw_p->xcvr_addr[1] = port_fd_arr[1]; 782323b952a3SSantwona Behera 782423b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 782523b952a3SSantwona Behera "ARTM card with 2 10G, 2 1GF")); 782623b952a3SSantwona Behera break; 782723b952a3SSantwona Behera } 782859a835ddSjoycey 782959a835ddSjoycey hw_p->xcvr_addr[2] = phy_fd_arr[0]; 783059a835ddSjoycey hw_p->xcvr_addr[3] = phy_fd_arr[1]; 783159a835ddSjoycey 783259a835ddSjoycey } else { 783359a835ddSjoycey NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 783459a835ddSjoycey "Unsupported neptune type 1")); 783559a835ddSjoycey goto error_exit; 783659a835ddSjoycey } 783759a835ddSjoycey break; 783859a835ddSjoycey 783959ac0c16Sdavemq case 1: 784059ac0c16Sdavemq /* TODO - 2 10G, 1 1G */ 784159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 784259ac0c16Sdavemq "Unsupported neptune type 2 10G, 1 1G")); 784359ac0c16Sdavemq goto error_exit; 784459ac0c16Sdavemq case 0: 784500161856Syc /* 784600161856Syc * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI 784700161856Syc * cards, etc. 784800161856Syc */ 784930505775Ssbehera if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 785030505775Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 785130505775Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 785252cdd236Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) || 785352cdd236Ssbehera ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) && 785452cdd236Ssbehera (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) || 785552cdd236Ssbehera ((port_pma_pmd_dev_id[0] == 785652cdd236Ssbehera MARVELL_88X201X_PHY_ID) && 785752cdd236Ssbehera (port_pma_pmd_dev_id[1] == 785852cdd236Ssbehera MARVELL_88X201X_PHY_ID))) { 78592e59129aSraghus 78602e59129aSraghus /* 78612e59129aSraghus * Check the first phy port address against 78622e59129aSraghus * the known phy start addresses to determine 78632e59129aSraghus * the platform type. 78642e59129aSraghus */ 78652d17280bSsbehera 78662d17280bSsbehera switch (port_fd_arr[0]) { 786700161856Syc case NEPTUNE_CLAUSE45_PORT_ADDR_BASE: 786852cdd236Ssbehera /* 786952cdd236Ssbehera * The Marvell case also falls into 787052cdd236Ssbehera * this case as 787152cdd236Ssbehera * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE 787200161856Syc * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE. 787352cdd236Ssbehera * This is OK for the 2 10G case. 787452cdd236Ssbehera */ 78752e59129aSraghus hw_p->niu_type = NEPTUNE_2_10GF; 78762e59129aSraghus hw_p->platform_type = 78772e59129aSraghus P_NEPTUNE_ATLAS_2PORT; 78782d17280bSsbehera break; 787900161856Syc case GOA_CLAUSE45_PORT_ADDR_BASE: 78802d17280bSsbehera if (hw_p->platform_type != 78812d17280bSsbehera P_NEPTUNE_NIU) { 78822d17280bSsbehera hw_p->platform_type = 78832d17280bSsbehera P_NEPTUNE_GENERIC; 78842d17280bSsbehera hw_p->niu_type = 78852d17280bSsbehera NEPTUNE_2_10GF; 78862d17280bSsbehera } 78872d17280bSsbehera break; 78882d17280bSsbehera default: 78892d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 78902e59129aSraghus "Unsupported neptune type 2 - 1")); 78912e59129aSraghus goto error_exit; 78922e59129aSraghus } 78932d17280bSsbehera 78942d17280bSsbehera for (i = 0; i < 2; i++) { 78952d17280bSsbehera hw_p->xcvr_addr[i] = port_fd_arr[i]; 78962d17280bSsbehera } 789700161856Syc 7898*89282175SSantwona Behera /* 2 10G optical Netlogic AEL2020 ports */ 7899*89282175SSantwona Behera } else if (((port_pcs_dev_id[0] == NLP2020_DEV_ID) && 7900*89282175SSantwona Behera (port_pcs_dev_id[1] == NLP2020_DEV_ID)) || 7901*89282175SSantwona Behera ((port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) && 7902*89282175SSantwona Behera (port_pma_pmd_dev_id[1] == NLP2020_DEV_ID))) { 7903*89282175SSantwona Behera if (hw_p->platform_type != P_NEPTUNE_NIU) { 7904*89282175SSantwona Behera hw_p->platform_type = 7905*89282175SSantwona Behera P_NEPTUNE_GENERIC; 7906*89282175SSantwona Behera hw_p->niu_type = 7907*89282175SSantwona Behera NEPTUNE_2_10GF; 7908*89282175SSantwona Behera } 7909*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7910*89282175SSantwona Behera "Found 2 NL PHYs at addrs 0x%x and 0x%x", 7911*89282175SSantwona Behera port_fd_arr[0], port_fd_arr[1])); 7912*89282175SSantwona Behera hw_p->xcvr_addr[0] = port_fd_arr[0]; 7913*89282175SSantwona Behera hw_p->xcvr_addr[1] = port_fd_arr[1]; 7914*89282175SSantwona Behera 791500161856Syc /* Both XAUI slots have copper XAUI cards */ 791600161856Syc } else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 791700161856Syc == TN1010_DEV_ID) && 791800161856Syc ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 791900161856Syc == TN1010_DEV_ID)) || 792000161856Syc (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 792100161856Syc == TN1010_DEV_ID) && 792200161856Syc ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 792300161856Syc == TN1010_DEV_ID))) { 792400161856Syc hw_p->niu_type = NEPTUNE_2_TN1010; 792500161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 792600161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 792700161856Syc 792800161856Syc /* Slot0 has fiber XAUI, slot1 has copper XAUI */ 792900161856Syc } else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 793000161856Syc (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 793100161856Syc == TN1010_DEV_ID) || 793200161856Syc (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 793300161856Syc (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) == 793400161856Syc TN1010_DEV_ID)) { 793500161856Syc hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010; 793600161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 793700161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 793800161856Syc 793900161856Syc /* Slot0 has copper XAUI, slot1 has fiber XAUI */ 794000161856Syc } else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY && 794100161856Syc (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 794200161856Syc == TN1010_DEV_ID) || 794300161856Syc (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 794400161856Syc (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 794500161856Syc == TN1010_DEV_ID)) { 794600161856Syc hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF; 794700161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 794800161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 794900161856Syc 795059ac0c16Sdavemq } else { 795159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 795259ac0c16Sdavemq "Unsupported neptune type 2")); 795359ac0c16Sdavemq goto error_exit; 795459ac0c16Sdavemq } 795559ac0c16Sdavemq break; 795600161856Syc 795759ac0c16Sdavemq case 4: 795800161856Syc if (nxge_get_num_of_xaui( 795900161856Syc port_pma_pmd_dev_id, port_pcs_dev_id, 796000161856Syc port_phy_id, &num_xaui) == NXGE_ERROR) { 796100161856Syc goto error_exit; 796200161856Syc } 796300161856Syc if (num_xaui != 2) 796400161856Syc goto error_exit; 796559ac0c16Sdavemq 796600161856Syc /* 796700161856Syc * Maramba with 2 XAUIs (either fiber or copper) 796800161856Syc * 796900161856Syc * Check the first phy port address against 797000161856Syc * the known phy start addresses to determine 797100161856Syc * the platform type. 797200161856Syc */ 797300161856Syc switch (phy_fd_arr[0]) { 797400161856Syc case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 797500161856Syc hw_p->platform_type = 797600161856Syc P_NEPTUNE_MARAMBA_P0; 797700161856Syc break; 797800161856Syc case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 797900161856Syc hw_p->platform_type = 798000161856Syc P_NEPTUNE_MARAMBA_P1; 798100161856Syc break; 798200161856Syc default: 798300161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 798400161856Syc "Unknown port %d...Cannot " 798500161856Syc "determine platform type", i)); 798600161856Syc goto error_exit; 798700161856Syc } 79882d17280bSsbehera 798900161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 799000161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 799100161856Syc hw_p->xcvr_addr[2] = phy_fd_arr[2]; 799200161856Syc hw_p->xcvr_addr[3] = phy_fd_arr[3]; 799300161856Syc 799400161856Syc /* slot0 has fiber XAUI, slot1 has Cu XAUI */ 799500161856Syc if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 799600161856Syc (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 799700161856Syc == TN1010_DEV_ID) { 799800161856Syc hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC; 799900161856Syc 800000161856Syc /* slot0 has Cu XAUI, slot1 has fiber XAUI */ 800100161856Syc } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 800200161856Syc == TN1010_DEV_ID) && 800300161856Syc port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 800400161856Syc hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC; 800500161856Syc 800600161856Syc /* Both slots have fiber XAUI */ 800700161856Syc } else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 800800161856Syc port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 80092e59129aSraghus hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 80102e59129aSraghus 801100161856Syc /* Both slots have copper XAUI */ 801200161856Syc } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 801300161856Syc == TN1010_DEV_ID) && 801400161856Syc (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 801500161856Syc == TN1010_DEV_ID) { 801600161856Syc hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC; 80172d17280bSsbehera 801859ac0c16Sdavemq } else { 801959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 802059ac0c16Sdavemq "Unsupported neptune type 3")); 802159ac0c16Sdavemq goto error_exit; 802259ac0c16Sdavemq } 802359ac0c16Sdavemq break; 802459ac0c16Sdavemq default: 802559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 802659ac0c16Sdavemq "Unsupported neptune type 5")); 802759ac0c16Sdavemq goto error_exit; 802859ac0c16Sdavemq } 802930505775Ssbehera break; 803000161856Syc case 1: /* Only one clause45 port */ 803100161856Syc switch (total_phy_fd) { /* Number of clause22 ports */ 803259ac0c16Sdavemq case 3: 80332e59129aSraghus /* 80342e59129aSraghus * TODO 3 1G, 1 10G mode. 80352e59129aSraghus * Differentiate between 1_1G_1_10G_2_1G and 80362e59129aSraghus * 1_10G_3_1G 80372e59129aSraghus */ 80382e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 80392e59129aSraghus "Unsupported neptune type 7")); 80402e59129aSraghus goto error_exit; 804159ac0c16Sdavemq case 2: 804259ac0c16Sdavemq /* 804359ac0c16Sdavemq * TODO 2 1G, 1 10G mode. 804459ac0c16Sdavemq * Differentiate between 1_1G_1_10G_1_1G and 804559ac0c16Sdavemq * 1_10G_2_1G 804659ac0c16Sdavemq */ 804759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 804859ac0c16Sdavemq "Unsupported neptune type 8")); 804959ac0c16Sdavemq goto error_exit; 805059ac0c16Sdavemq case 1: 805159ac0c16Sdavemq /* 805259ac0c16Sdavemq * TODO 1 1G, 1 10G mode. 805359ac0c16Sdavemq * Differentiate between 1_1G_1_10G and 805459ac0c16Sdavemq * 1_10G_1_1G 805559ac0c16Sdavemq */ 805659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 805759ac0c16Sdavemq "Unsupported neptune type 9")); 805859ac0c16Sdavemq goto error_exit; 805900161856Syc case 0: /* N2 with 1 XAUI (fiber or copper) */ 806000161856Syc /* Fiber XAUI */ 80612d17280bSsbehera if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 80622d17280bSsbehera port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) { 80632d17280bSsbehera 80642d17280bSsbehera /* 80652d17280bSsbehera * Check the first phy port address against 80662d17280bSsbehera * the known phy start addresses to determine 80672d17280bSsbehera * the platform type. 80682d17280bSsbehera */ 80692d17280bSsbehera 80702d17280bSsbehera switch (port_fd_arr[0]) { 807100161856Syc case N2_CLAUSE45_PORT_ADDR_BASE: 807200161856Syc case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 807300161856Syc case ALT_GOA_CLAUSE45_PORT1_ADDR: 807400161856Syc /* 807500161856Syc * If hw_p->platform_type == 807600161856Syc * P_NEPTUNE_NIU, then portmode 807700161856Syc * is already known, so there is 807800161856Syc * no need to figure out hw_p-> 807900161856Syc * platform_type because 808000161856Syc * platform_type is only for 808100161856Syc * figuring out portmode. 808200161856Syc */ 80832d17280bSsbehera if (hw_p->platform_type != 80842d17280bSsbehera P_NEPTUNE_NIU) { 80852d17280bSsbehera hw_p->platform_type = 80862d17280bSsbehera P_NEPTUNE_GENERIC; 80872d17280bSsbehera hw_p->niu_type = 80882d17280bSsbehera NEPTUNE_2_10GF; 80892d17280bSsbehera } 80902d17280bSsbehera break; 80912d17280bSsbehera default: 80922d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 80932d17280bSsbehera "Unsupported neptune type 10")); 80942d17280bSsbehera goto error_exit; 80952d17280bSsbehera } 8096321febdeSsbehera /* 8097321febdeSsbehera * For GOA, which is a hot swappable PHY, the 8098321febdeSsbehera * phy address to function number mapping 8099321febdeSsbehera * should be preserved, i.e., addr 16 is 8100321febdeSsbehera * assigned to function 0 and 20 to function 1 8101321febdeSsbehera * But for Huron XAUI, the assignment should 8102321febdeSsbehera * be by function number, i.e., whichever 8103321febdeSsbehera * function number attaches should be 8104321febdeSsbehera * assigned the available PHY (this is required 8105321febdeSsbehera * primarily to support pre-production Huron 8106321febdeSsbehera * boards where function 0 is mapped to addr 17 8107321febdeSsbehera */ 8108321febdeSsbehera if (port_fd_arr[0] == 810900161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR) { 8110321febdeSsbehera hw_p->xcvr_addr[1] = port_fd_arr[0]; 8111321febdeSsbehera } else { 8112321febdeSsbehera hw_p->xcvr_addr[nxgep->function_num] = 8113321febdeSsbehera port_fd_arr[0]; 8114321febdeSsbehera } 8115*89282175SSantwona Behera } else if (port_pcs_dev_id[0] == NLP2020_DEV_ID || 8116*89282175SSantwona Behera port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) { 8117*89282175SSantwona Behera /* A 10G NLP2020 PHY in slot0 or slot1 */ 8118*89282175SSantwona Behera switch (port_fd_arr[0]) { 8119*89282175SSantwona Behera case NLP2020_CL45_PORT0_ADDR0: 8120*89282175SSantwona Behera case NLP2020_CL45_PORT0_ADDR1: 8121*89282175SSantwona Behera case NLP2020_CL45_PORT0_ADDR2: 8122*89282175SSantwona Behera case NLP2020_CL45_PORT0_ADDR3: 8123*89282175SSantwona Behera case NLP2020_CL45_PORT1_ADDR0: 8124*89282175SSantwona Behera case NLP2020_CL45_PORT1_ADDR1: 8125*89282175SSantwona Behera case NLP2020_CL45_PORT1_ADDR2: 8126*89282175SSantwona Behera case NLP2020_CL45_PORT1_ADDR3: 8127*89282175SSantwona Behera /* 8128*89282175SSantwona Behera * If hw_p->platform_type == 8129*89282175SSantwona Behera * P_NEPTUNE_NIU, then portmode 8130*89282175SSantwona Behera * is already known, so there is 8131*89282175SSantwona Behera * no need to figure out hw_p-> 8132*89282175SSantwona Behera * platform_type because 8133*89282175SSantwona Behera * platform_type is only for 8134*89282175SSantwona Behera * figuring out portmode. 8135*89282175SSantwona Behera */ 8136*89282175SSantwona Behera if (hw_p->platform_type != 8137*89282175SSantwona Behera P_NEPTUNE_NIU) { 8138*89282175SSantwona Behera hw_p->platform_type = 8139*89282175SSantwona Behera P_NEPTUNE_GENERIC; 8140*89282175SSantwona Behera hw_p->niu_type = 8141*89282175SSantwona Behera NEPTUNE_2_10GF; 8142*89282175SSantwona Behera } 8143*89282175SSantwona Behera break; 8144*89282175SSantwona Behera default: 8145*89282175SSantwona Behera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8146*89282175SSantwona Behera "Unsupported neptune type 10-1")); 8147*89282175SSantwona Behera goto error_exit; 8148*89282175SSantwona Behera } 8149*89282175SSantwona Behera switch (port_fd_arr[0]) { 8150*89282175SSantwona Behera case NLP2020_CL45_PORT0_ADDR0: 8151*89282175SSantwona Behera case NLP2020_CL45_PORT0_ADDR1: 8152*89282175SSantwona Behera case NLP2020_CL45_PORT0_ADDR2: 8153*89282175SSantwona Behera case NLP2020_CL45_PORT0_ADDR3: 8154*89282175SSantwona Behera hw_p->xcvr_addr[0] = port_fd_arr[0]; 8155*89282175SSantwona Behera break; 8156*89282175SSantwona Behera case NLP2020_CL45_PORT1_ADDR0: 8157*89282175SSantwona Behera case NLP2020_CL45_PORT1_ADDR1: 8158*89282175SSantwona Behera case NLP2020_CL45_PORT1_ADDR2: 8159*89282175SSantwona Behera case NLP2020_CL45_PORT1_ADDR3: 8160*89282175SSantwona Behera hw_p->xcvr_addr[1] = port_fd_arr[0]; 8161*89282175SSantwona Behera break; 8162*89282175SSantwona Behera default: 8163*89282175SSantwona Behera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8164*89282175SSantwona Behera "Unsupported neptune type 10-11")); 8165*89282175SSantwona Behera goto error_exit; 8166*89282175SSantwona Behera } 8167*89282175SSantwona Behera 8168*89282175SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8169*89282175SSantwona Behera "Found 1 NL PHYs at addr 0x%x", 8170*89282175SSantwona Behera port_fd_arr[0])); 817100161856Syc 817200161856Syc /* A 10G copper XAUI in either slot0 or slot1 */ 817300161856Syc } else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 817400161856Syc == TN1010_DEV_ID || 817500161856Syc (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 817600161856Syc == TN1010_DEV_ID) { 817700161856Syc switch (port_fd_arr[0]) { 817800161856Syc /* The XAUI is in slot0 */ 817900161856Syc case N2_CLAUSE45_PORT_ADDR_BASE: 818000161856Syc hw_p->niu_type = NEPTUNE_1_TN1010; 818100161856Syc break; 818200161856Syc 818300161856Syc /* The XAUI is in slot1 */ 818400161856Syc case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 818500161856Syc hw_p->niu_type 818600161856Syc = NEPTUNE_1_NONE_1_TN1010; 818700161856Syc break; 818800161856Syc default: 818900161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 819000161856Syc "Unsupported XAUI port address")); 819100161856Syc goto error_exit; 819200161856Syc } 819300161856Syc hw_p->xcvr_addr[nxgep->function_num] 819400161856Syc = port_fd_arr[0]; 819500161856Syc 81962d17280bSsbehera } else { 81972d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 819800161856Syc "Unsupported PHY type")); 81992d17280bSsbehera goto error_exit; 82002d17280bSsbehera } 82012d17280bSsbehera break; 820200161856Syc case 4: /* Maramba always have 4 clause 45 ports */ 820359ac0c16Sdavemq 820400161856Syc /* Maramba with 1 XAUI */ 820552ccf843Smisaki if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) && 820652ccf843Smisaki (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) && 820700161856Syc ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 820852ccf843Smisaki != TN1010_DEV_ID) && 820900161856Syc ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 821052ccf843Smisaki != TN1010_DEV_ID)) { 821152ccf843Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, 821252ccf843Smisaki "Unsupported neptune type 12")); 821352ccf843Smisaki goto error_exit; 821452ccf843Smisaki } 82152e59129aSraghus 821652ccf843Smisaki /* 821752ccf843Smisaki * Check the first phy port address against 821852ccf843Smisaki * the known phy start addresses to determine 821952ccf843Smisaki * the platform type. 822052ccf843Smisaki */ 822152ccf843Smisaki switch (phy_fd_arr[0]) { 822252ccf843Smisaki case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 822352ccf843Smisaki hw_p->platform_type = 822452ccf843Smisaki P_NEPTUNE_MARAMBA_P0; 822552ccf843Smisaki break; 822652ccf843Smisaki case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 822752ccf843Smisaki hw_p->platform_type = 822852ccf843Smisaki P_NEPTUNE_MARAMBA_P1; 822952ccf843Smisaki break; 823052ccf843Smisaki default: 823152ccf843Smisaki NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 823252ccf843Smisaki "Unknown port %d...Cannot " 823352ccf843Smisaki "determine platform type 10 - 2", 823452ccf843Smisaki i)); 823552ccf843Smisaki goto error_exit; 823652ccf843Smisaki } 823752ccf843Smisaki 823852ccf843Smisaki /* 823952ccf843Smisaki * Check the clause45 address to determine 824052ccf843Smisaki * if XAUI is in port 0 or port 1. 824152ccf843Smisaki */ 824252ccf843Smisaki switch (port_fd_arr[0]) { 824352ccf843Smisaki case MARAMBA_CLAUSE45_PORT_ADDR_BASE: 824452ccf843Smisaki if (port_pcs_dev_id[0] 824552ccf843Smisaki == PHY_BCM8704_FAMILY || 824652ccf843Smisaki port_pma_pmd_dev_id[0] 824752ccf843Smisaki == PHY_BCM8704_FAMILY) { 824852ccf843Smisaki hw_p->niu_type 824952ccf843Smisaki = NEPTUNE_1_10GF_3_1GC; 825052ccf843Smisaki } else { 825152ccf843Smisaki hw_p->niu_type 825252ccf843Smisaki = NEPTUNE_1_TN1010_3_1GC; 825359ac0c16Sdavemq } 825452ccf843Smisaki hw_p->xcvr_addr[0] = port_fd_arr[0]; 825552ccf843Smisaki for (i = 1; i < NXGE_MAX_PORTS; i++) { 825652ccf843Smisaki hw_p->xcvr_addr[i] = 825752ccf843Smisaki phy_fd_arr[i]; 825852ccf843Smisaki } 825952ccf843Smisaki break; 826052ccf843Smisaki case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1): 826152ccf843Smisaki if (port_pcs_dev_id[0] 826252ccf843Smisaki == PHY_BCM8704_FAMILY || 826352ccf843Smisaki port_pma_pmd_dev_id[0] 826452ccf843Smisaki == PHY_BCM8704_FAMILY) { 826552ccf843Smisaki hw_p->niu_type = 826652ccf843Smisaki NEPTUNE_1_1GC_1_10GF_2_1GC; 826752ccf843Smisaki } else { 826852ccf843Smisaki hw_p->niu_type = 826952ccf843Smisaki NEPTUNE_1_1GC_1_TN1010_2_1GC; 827052ccf843Smisaki } 827152ccf843Smisaki hw_p->xcvr_addr[0] = phy_fd_arr[0]; 827252ccf843Smisaki hw_p->xcvr_addr[1] = port_fd_arr[0]; 827352ccf843Smisaki hw_p->xcvr_addr[2] = phy_fd_arr[2]; 827452ccf843Smisaki hw_p->xcvr_addr[3] = phy_fd_arr[3]; 827552ccf843Smisaki break; 827652ccf843Smisaki default: 827759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 827852ccf843Smisaki "Unsupported neptune type 11")); 827959ac0c16Sdavemq goto error_exit; 828059ac0c16Sdavemq } 828152ccf843Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, 828252ccf843Smisaki "Maramba with 1 XAUI (fiber or copper)")); 828359ac0c16Sdavemq break; 828459ac0c16Sdavemq default: 828559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 828659ac0c16Sdavemq "Unsupported neptune type 13")); 828759ac0c16Sdavemq goto error_exit; 828859ac0c16Sdavemq } 828959ac0c16Sdavemq break; 829000161856Syc case 0: /* 4 ports Neptune based NIC */ 829159ac0c16Sdavemq switch (total_phy_fd) { 829259ac0c16Sdavemq case 4: 829330505775Ssbehera if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 829430505775Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 829530505775Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 829630505775Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 829759ac0c16Sdavemq 829859ac0c16Sdavemq /* 829959ac0c16Sdavemq * Check the first phy port address against 830059ac0c16Sdavemq * the known phy start addresses to determine 830159ac0c16Sdavemq * the platform type. 830259ac0c16Sdavemq */ 83032d17280bSsbehera switch (phy_fd_arr[0]) { 830400161856Syc case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 830559ac0c16Sdavemq hw_p->platform_type = 830659ac0c16Sdavemq P_NEPTUNE_MARAMBA_P1; 83072d17280bSsbehera break; 830800161856Syc case NEPTUNE_CLAUSE22_PORT_ADDR_BASE: 83092e59129aSraghus hw_p->platform_type = 83102e59129aSraghus P_NEPTUNE_ATLAS_4PORT; 83112d17280bSsbehera break; 83122d17280bSsbehera default: 83132e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 83142e59129aSraghus "Unknown port %d...Cannot " 83152e59129aSraghus "determine platform type", i)); 83162e59129aSraghus goto error_exit; 831759ac0c16Sdavemq } 83182e59129aSraghus hw_p->niu_type = NEPTUNE_4_1GC; 83192d17280bSsbehera for (i = 0; i < NXGE_MAX_PORTS; i++) { 83202d17280bSsbehera hw_p->xcvr_addr[i] = phy_fd_arr[i]; 83212d17280bSsbehera } 832259ac0c16Sdavemq } else { 832359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 832459ac0c16Sdavemq "Unsupported neptune type 14")); 832559ac0c16Sdavemq goto error_exit; 832659ac0c16Sdavemq } 832759ac0c16Sdavemq break; 832859ac0c16Sdavemq case 3: 832959ac0c16Sdavemq /* TODO 3 1G mode */ 833059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 833159ac0c16Sdavemq "Unsupported neptune type 15")); 833259ac0c16Sdavemq goto error_exit; 833359ac0c16Sdavemq case 2: 833459ac0c16Sdavemq /* TODO 2 1G mode */ 833559a835ddSjoycey if ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 833659a835ddSjoycey (port_phy_id[1] == PHY_BCM5482_FAMILY)) { 833759a835ddSjoycey hw_p->platform_type = P_NEPTUNE_GENERIC; 833859a835ddSjoycey hw_p->niu_type = NEPTUNE_2_1GRF; 833959a835ddSjoycey hw_p->xcvr_addr[2] = phy_fd_arr[0]; 834059a835ddSjoycey hw_p->xcvr_addr[3] = phy_fd_arr[1]; 834159a835ddSjoycey } else { 834259a835ddSjoycey NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 834359a835ddSjoycey "Unsupported neptune type 16")); 834459a835ddSjoycey goto error_exit; 834559a835ddSjoycey } 834659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 834759a835ddSjoycey "2 RGMII Fiber ports - RTM")); 834859a835ddSjoycey break; 834959a835ddSjoycey 835059ac0c16Sdavemq case 1: 835159ac0c16Sdavemq /* TODO 1 1G mode */ 835259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 835359ac0c16Sdavemq "Unsupported neptune type 17")); 835459ac0c16Sdavemq goto error_exit; 835559ac0c16Sdavemq default: 835659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 835759ac0c16Sdavemq "Unsupported neptune type 18, total phy fd %d", 835859ac0c16Sdavemq total_phy_fd)); 835959ac0c16Sdavemq goto error_exit; 836059ac0c16Sdavemq } 836159ac0c16Sdavemq break; 836259ac0c16Sdavemq default: 836356d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 836459ac0c16Sdavemq "Unsupported neptune type 19")); 836559ac0c16Sdavemq goto error_exit; 836644961713Sgirish } 836744961713Sgirish 836859ac0c16Sdavemq scan_exit: 836944961713Sgirish 837059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 837159ac0c16Sdavemq "niu type [0x%x]\n", hw_p->niu_type)); 837259ac0c16Sdavemq return (status); 837344961713Sgirish 837459ac0c16Sdavemq error_exit: 837559ac0c16Sdavemq return (NXGE_ERROR); 837644961713Sgirish } 837756d930aeSspeer 837856d930aeSspeer boolean_t 837956d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr) 838056d930aeSspeer { 838156d930aeSspeer if ((mac_addr.ether_addr_octet[0] & 0x01) || 838256d930aeSspeer (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 838356d930aeSspeer (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 838456d930aeSspeer return (B_FALSE); 838556d930aeSspeer else 838656d930aeSspeer return (B_TRUE); 838756d930aeSspeer } 838859ac0c16Sdavemq 838959ac0c16Sdavemq static void 839059ac0c16Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 839159ac0c16Sdavemq 839259ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 839359ac0c16Sdavemq uint8_t xcvr_portn; 839459ac0c16Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 839559ac0c16Sdavemq 839659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 839759ac0c16Sdavemq 839859ac0c16Sdavemq if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 839900161856Syc xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE; 840059ac0c16Sdavemq } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 840100161856Syc xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE; 840259ac0c16Sdavemq } 840359ac0c16Sdavemq /* 840459ac0c16Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 840559ac0c16Sdavemq * swapped with ethernet port number. This is 840659ac0c16Sdavemq * designed for better signal integrity in routing. 840759ac0c16Sdavemq */ 840859ac0c16Sdavemq switch (portn) { 840959ac0c16Sdavemq case 0: 841059ac0c16Sdavemq xcvr_portn += 3; 841159ac0c16Sdavemq break; 841259ac0c16Sdavemq case 1: 841359ac0c16Sdavemq xcvr_portn += 2; 841459ac0c16Sdavemq break; 841559ac0c16Sdavemq case 2: 841659ac0c16Sdavemq xcvr_portn += 1; 841759ac0c16Sdavemq break; 841859ac0c16Sdavemq case 3: 841959ac0c16Sdavemq default: 842059ac0c16Sdavemq break; 842159ac0c16Sdavemq } 842259ac0c16Sdavemq 8423321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 842459ac0c16Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 842559ac0c16Sdavemq xcvr_portn, BCM5464R_MISC, 0xb4ee); 842659ac0c16Sdavemq if (rs != NPI_SUCCESS) { 842759ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 842859ac0c16Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 842959ac0c16Sdavemq "returned error 0x[%x]", rs)); 8430321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 843159ac0c16Sdavemq return; 843259ac0c16Sdavemq } 843359ac0c16Sdavemq 843459ac0c16Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 843559ac0c16Sdavemq xcvr_portn, BCM5464R_MISC, 0xb8ee); 843659ac0c16Sdavemq if (rs != NPI_SUCCESS) { 843759ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 843859ac0c16Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 843959ac0c16Sdavemq "returned error 0x[%x]", rs)); 844059ac0c16Sdavemq } 844159ac0c16Sdavemq 8442321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 844359ac0c16Sdavemq } 8444d81011f0Ssbehera 8445d81011f0Ssbehera static nxge_status_t 8446d81011f0Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep) 8447d81011f0Ssbehera { 8448d81011f0Ssbehera p_nxge_stats_t statsp; 8449d81011f0Ssbehera uint8_t xcvr_portn; 8450d81011f0Ssbehera p_mii_regs_t mii_regs; 8451d81011f0Ssbehera mii_mode_control_stat_t mode; 8452d81011f0Ssbehera int status = NXGE_OK; 8453d81011f0Ssbehera 8454d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 8455d81011f0Ssbehera 8456d81011f0Ssbehera statsp = nxgep->statsp; 8457d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 8458d81011f0Ssbehera mii_regs = NULL; 8459d81011f0Ssbehera mode.value = 0; 84606b438925Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 8461d81011f0Ssbehera #if defined(__i386) 8462d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 8463d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 8464d81011f0Ssbehera mode.value)) != NXGE_OK) { 8465d81011f0Ssbehera goto fail; 8466d81011f0Ssbehera #else 8467d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 8468d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 8469d81011f0Ssbehera mode.value)) != NXGE_OK) { 8470d81011f0Ssbehera goto fail; 8471d81011f0Ssbehera #endif 8472d81011f0Ssbehera } 8473d81011f0Ssbehera #if defined(__i386) 8474d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 8475d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 8476d81011f0Ssbehera &mode.value)) != NXGE_OK) { 8477d81011f0Ssbehera goto fail; 8478d81011f0Ssbehera } 8479d81011f0Ssbehera #else 8480d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 8481d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 8482d81011f0Ssbehera &mode.value)) != NXGE_OK) { 8483d81011f0Ssbehera goto fail; 8484d81011f0Ssbehera } 8485d81011f0Ssbehera #endif 8486d81011f0Ssbehera 8487d81011f0Ssbehera if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 8488d81011f0Ssbehera nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 8489d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8490d81011f0Ssbehera "nxge_mii_get_link_mode: fiber mode")); 8491d81011f0Ssbehera } 8492d81011f0Ssbehera 8493d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8494d81011f0Ssbehera "nxge_mii_get_link_mode: " 8495d81011f0Ssbehera "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 84966b438925Ssbehera NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 8497d81011f0Ssbehera mode.value, nxgep->mac.portmode)); 8498d81011f0Ssbehera 8499d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8500d81011f0Ssbehera "<== nxge_mii_get_link_mode")); 8501d81011f0Ssbehera return (status); 8502d81011f0Ssbehera fail: 8503d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8504d81011f0Ssbehera "<== nxge_mii_get_link_mode (failed)")); 8505d81011f0Ssbehera return (NXGE_ERROR); 8506d81011f0Ssbehera } 8507d81011f0Ssbehera 85081bd6825cSml nxge_status_t 85091bd6825cSml nxge_mac_set_framesize(p_nxge_t nxgep) 85101bd6825cSml { 85111bd6825cSml npi_attr_t ap; 85121bd6825cSml uint8_t portn; 85131bd6825cSml npi_handle_t handle; 85141bd6825cSml npi_status_t rs = NPI_SUCCESS; 85151bd6825cSml 85161bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize")); 85171bd6825cSml 85181bd6825cSml portn = NXGE_GET_PORT_NUM(nxgep->function_num); 85191bd6825cSml handle = nxgep->npi_handle; 85201bd6825cSml 85211bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 85221bd6825cSml "==> nxge_mac_sec_framesize: port<%d> " 85231bd6825cSml "min framesize %d max framesize %d ", 85241bd6825cSml portn, 85251bd6825cSml nxgep->mac.minframesize, 85261bd6825cSml nxgep->mac.maxframesize)); 85271bd6825cSml 85281bd6825cSml SET_MAC_ATTR2(handle, ap, portn, 85291bd6825cSml MAC_PORT_FRAME_SIZE, 85301bd6825cSml nxgep->mac.minframesize, 85311bd6825cSml nxgep->mac.maxframesize, 85321bd6825cSml rs); 85331bd6825cSml if (rs != NPI_SUCCESS) { 85341bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 85351bd6825cSml "<== nxge_mac_set_framesize: failed to configure " 85361bd6825cSml "max/min frame size port %d", portn)); 85371bd6825cSml 85381bd6825cSml return (NXGE_ERROR | rs); 85391bd6825cSml } 85401bd6825cSml 85411bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 85421bd6825cSml "<== nxge_mac_set_framesize: port<%d>", portn)); 85431bd6825cSml 85441bd6825cSml return (NXGE_OK); 85451bd6825cSml } 85461bd6825cSml 854700161856Syc static nxge_status_t 854800161856Syc nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id, 854900161856Syc uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui) 855000161856Syc { 855100161856Syc uint8_t i; 855200161856Syc 855300161856Syc for (i = 0; i < 4; i++) { 855400161856Syc if (port_phy_id[i] != PHY_BCM5464R_FAMILY) 855500161856Syc return (NXGE_ERROR); 855600161856Syc } 855700161856Syc 855800161856Syc *num_xaui = 0; 855900161856Syc if ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 856000161856Syc port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 856100161856Syc (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 856200161856Syc == TN1010_DEV_ID) && 856300161856Syc ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 856400161856Syc == TN1010_DEV_ID))) { 856500161856Syc (*num_xaui) ++; 856600161856Syc } 856700161856Syc if ((port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 856800161856Syc port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) || 856900161856Syc (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 857000161856Syc == TN1010_DEV_ID) && 857100161856Syc ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 857200161856Syc == TN1010_DEV_ID))) { 857300161856Syc (*num_xaui) ++; 857400161856Syc } 857500161856Syc return (NXGE_OK); 857600161856Syc } 857700161856Syc 857800161856Syc /* 857900161856Syc * Instruction from Teranetics: Once you detect link is up, go 858000161856Syc * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You 858100161856Syc * may want to qualify it by first checking Register 30.1.7:6 and 858200161856Syc * making sure it reads "01" (Auto-Neg Complete). 858300161856Syc * 858400161856Syc * If this function is called when the link is down or before auto- 858500161856Syc * negotiation has completed, then the speed of the PHY is not certain. 858600161856Syc * In such cases, this function returns 1G as the default speed with 858700161856Syc * NXGE_OK status instead of NXGE_ERROR. It is OK to initialize the 858800161856Syc * driver based on a default speed because this function will be called 858900161856Syc * again when the link comes up. Returning NXGE_ERROR, which may 859000161856Syc * cause brutal chain reaction in caller functions, is not necessary. 859100161856Syc */ 859200161856Syc static nxge_status_t 859300161856Syc nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed) 859400161856Syc { 859500161856Syc uint8_t phy_port_addr, autoneg_stat, link_up; 859600161856Syc nxge_status_t status = NXGE_OK; 859700161856Syc uint16_t val; 859800161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 859900161856Syc 860000161856Syc /* Set default speed to 10G */ 860100161856Syc *speed = TN1010_SPEED_10G; 860200161856Syc 860300161856Syc /* Set Clause 45 */ 860400161856Syc npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 860500161856Syc 860600161856Syc phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 860700161856Syc 860800161856Syc /* Check Device 1 Register 0xA bit0 for link up status */ 860900161856Syc status = nxge_mdio_read(nxgep, phy_port_addr, 861000161856Syc TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val); 861100161856Syc if (status != NXGE_OK) 861200161856Syc goto fail; 861300161856Syc 861400161856Syc link_up = ((val & TN1010_AN_LINK_STAT_BIT) 861500161856Syc ? B_TRUE : B_FALSE); 861600161856Syc if (link_up == B_FALSE) { 861700161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 861800161856Syc "nxge_get_tn1010_speed: link is down")); 861900161856Syc goto nxge_get_tn1010_speed_exit; 862000161856Syc } 862100161856Syc 862200161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 862300161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG, 862400161856Syc &val)) != NXGE_OK) { 862500161856Syc goto fail; 862600161856Syc } 862700161856Syc autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >> 862800161856Syc TN1010_VENDOR_MMD1_AN_STAT_SHIFT; 862900161856Syc 863000161856Syc /* 863100161856Syc * Return NXGE_OK even when we can not get a settled speed. In 863200161856Syc * such case, the speed reported should not be trusted but that 863300161856Syc * is OK, we will call this function periodically and will get 863400161856Syc * the correct speed after the link is up. 863500161856Syc */ 863600161856Syc switch (autoneg_stat) { 863700161856Syc case TN1010_AN_IN_PROG: 863800161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 863900161856Syc "nxge_get_tn1010_speed: Auto-negotiation in progress")); 864000161856Syc break; 864100161856Syc case TN1010_AN_COMPLETE: 864200161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 864300161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 864400161856Syc TN1010_VENDOR_MMD1_STATUS_REG, 864500161856Syc &val)) != NXGE_OK) { 864600161856Syc goto fail; 864700161856Syc } 864800161856Syc *speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >> 864900161856Syc TN1010_VENDOR_MMD1_AN_SPEED_SHIFT; 865000161856Syc break; 865100161856Syc case TN1010_AN_RSVD: 865200161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 865300161856Syc "nxge_get_tn1010_speed: Autoneg status undefined")); 865400161856Syc break; 865500161856Syc case TN1010_AN_FAILED: 865600161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 865700161856Syc "nxge_get_tn1010_speed: Auto-negotiation failed")); 865800161856Syc break; 865900161856Syc default: 866000161856Syc break; 866100161856Syc } 866200161856Syc nxge_get_tn1010_speed_exit: 866300161856Syc return (NXGE_OK); 866400161856Syc fail: 866500161856Syc return (status); 866600161856Syc } 866700161856Syc 866800161856Syc 866900161856Syc /* 867000161856Syc * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function 867100161856Syc * figures out the speed of the PHY determined by the autonegotiation 867200161856Syc * process and sets the following 3 parameters, 867300161856Syc * nxgep->mac.portmode 867400161856Syc * nxgep->statsp->mac_stats.link_speed 867500161856Syc * nxgep->statsp->mac_stats.xcvr_inuse 867600161856Syc */ 867700161856Syc static nxge_status_t 867800161856Syc nxge_set_tn1010_param(p_nxge_t nxgep) 867900161856Syc { 868000161856Syc uint16_t speed; 868100161856Syc 868200161856Syc if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 868300161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 868400161856Syc "nxge_set_tn1010_param: " 868500161856Syc "Failed to get TN1010 speed")); 868600161856Syc return (NXGE_ERROR); 868700161856Syc } 868800161856Syc if (speed == TN1010_SPEED_1G) { 868900161856Syc nxgep->mac.portmode = PORT_1G_TN1010; 869000161856Syc nxgep->statsp->mac_stats.link_speed = 1000; 869100161856Syc nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 869200161856Syc } else { 869300161856Syc nxgep->mac.portmode = PORT_10G_TN1010; 869400161856Syc nxgep->statsp->mac_stats.link_speed = 10000; 869500161856Syc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 869600161856Syc } 869700161856Syc return (NXGE_OK); 869800161856Syc } 869900161856Syc 8700d81011f0Ssbehera #ifdef NXGE_DEBUG 8701d81011f0Ssbehera static void 8702d81011f0Ssbehera nxge_mii_dump(p_nxge_t nxgep) 8703d81011f0Ssbehera { 8704d81011f0Ssbehera p_nxge_stats_t statsp; 8705d81011f0Ssbehera uint8_t xcvr_portn; 8706d81011f0Ssbehera p_mii_regs_t mii_regs; 8707d81011f0Ssbehera mii_bmcr_t bmcr; 8708d81011f0Ssbehera mii_bmsr_t bmsr; 8709d81011f0Ssbehera mii_idr1_t idr1; 8710d81011f0Ssbehera mii_idr2_t idr2; 8711d81011f0Ssbehera mii_mode_control_stat_t mode; 8712678453a8Sspeer p_nxge_param_t param_arr; 8713d81011f0Ssbehera 8714d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 8715d81011f0Ssbehera 8716d81011f0Ssbehera statsp = nxgep->statsp; 8717d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 8718d81011f0Ssbehera 8719d81011f0Ssbehera mii_regs = NULL; 8720d81011f0Ssbehera 8721d81011f0Ssbehera #if defined(__i386) 8722d81011f0Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 8723d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value); 8724d81011f0Ssbehera #else 8725d81011f0Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 8726d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 8727d81011f0Ssbehera #endif 8728d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8729d81011f0Ssbehera "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 8730d81011f0Ssbehera xcvr_portn, bmcr.value)); 8731d81011f0Ssbehera 8732d81011f0Ssbehera #if defined(__i386) 8733d81011f0Ssbehera (void) nxge_mii_read(nxgep, 8734d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 8735d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value); 8736d81011f0Ssbehera #else 8737d81011f0Ssbehera (void) nxge_mii_read(nxgep, 8738d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 8739d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 8740d81011f0Ssbehera #endif 8741d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8742d81011f0Ssbehera "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 8743d81011f0Ssbehera xcvr_portn, bmsr.value)); 8744d81011f0Ssbehera 8745d81011f0Ssbehera #if defined(__i386) 8746d81011f0Ssbehera (void) nxge_mii_read(nxgep, 8747d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 8748d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value); 8749d81011f0Ssbehera #else 8750d81011f0Ssbehera (void) nxge_mii_read(nxgep, 8751d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 8752d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 8753d81011f0Ssbehera #endif 8754d81011f0Ssbehera 8755d81011f0Ssbehera 8756d81011f0Ssbehera #if defined(__i386) 8757d81011f0Ssbehera (void) nxge_mii_read(nxgep, 8758d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 8759d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value); 8760d81011f0Ssbehera #else 8761d81011f0Ssbehera (void) nxge_mii_read(nxgep, 8762d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 8763d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 8764d81011f0Ssbehera #endif 8765d81011f0Ssbehera 8766d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8767d81011f0Ssbehera "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 8768d81011f0Ssbehera xcvr_portn, idr1.value)); 8769d81011f0Ssbehera 8770d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8771d81011f0Ssbehera "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 8772d81011f0Ssbehera xcvr_portn, idr2.value)); 8773d81011f0Ssbehera 8774d81011f0Ssbehera mode.value = 0; 87756b438925Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 8776d81011f0Ssbehera 8777d81011f0Ssbehera #if defined(__i386) 8778d81011f0Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 8779d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value); 8780d81011f0Ssbehera 8781d81011f0Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 8782d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value); 8783d81011f0Ssbehera #else 8784d81011f0Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 8785d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 8786d81011f0Ssbehera 8787d81011f0Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 8788d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 8789d81011f0Ssbehera #endif 8790d81011f0Ssbehera 8791d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8792d81011f0Ssbehera "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 8793d81011f0Ssbehera xcvr_portn, mode.value)); 8794d81011f0Ssbehera } 8795d81011f0Ssbehera #endif 8796