1233545Sjchandra/*- 2233545Sjchandra * Copyright (c) 2003-2012 Broadcom Corporation 3233545Sjchandra * All Rights Reserved 4233545Sjchandra * 5233545Sjchandra * Redistribution and use in source and binary forms, with or without 6233545Sjchandra * modification, are permitted provided that the following conditions 7233545Sjchandra * are met: 8233545Sjchandra * 9233545Sjchandra * 1. Redistributions of source code must retain the above copyright 10233545Sjchandra * notice, this list of conditions and the following disclaimer. 11233545Sjchandra * 2. Redistributions in binary form must reproduce the above copyright 12233545Sjchandra * notice, this list of conditions and the following disclaimer in 13233545Sjchandra * the documentation and/or other materials provided with the 14233545Sjchandra * distribution. 15279388Sjchandra * 16233545Sjchandra * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR 17233545Sjchandra * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18233545Sjchandra * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19233545Sjchandra * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE 20233545Sjchandra * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21233545Sjchandra * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22233545Sjchandra * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23233545Sjchandra * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24233545Sjchandra * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25233545Sjchandra * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26233545Sjchandra * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27233545Sjchandra */ 28233545Sjchandra 29233545Sjchandra#include <sys/cdefs.h> 30233545Sjchandra__FBSDID("$FreeBSD$"); 31233545Sjchandra#include <sys/types.h> 32233545Sjchandra#include <sys/systm.h> 33233545Sjchandra 34233545Sjchandra#include <mips/nlm/hal/mips-extns.h> 35233545Sjchandra#include <mips/nlm/hal/haldefs.h> 36233545Sjchandra#include <mips/nlm/hal/iomap.h> 37233545Sjchandra#include <mips/nlm/hal/sys.h> 38233545Sjchandra#include <mips/nlm/hal/nae.h> 39233545Sjchandra#include <mips/nlm/hal/mdio.h> 40233545Sjchandra#include <mips/nlm/hal/sgmii.h> 41233545Sjchandra#include <mips/nlm/hal/xaui.h> 42233545Sjchandra 43233545Sjchandra#include <mips/nlm/xlp.h> 44233545Sjchandravoid 45233545Sjchandranlm_xaui_pcs_init(uint64_t nae_base, int xaui_cplx_mask) 46233545Sjchandra{ 47233545Sjchandra int block, lane_ctrl, reg; 48233545Sjchandra int cplx_lane_enable; 49233545Sjchandra int lane_enable = 0; 50233545Sjchandra uint32_t regval; 51233545Sjchandra 52233545Sjchandra cplx_lane_enable = LM_XAUI | 53233545Sjchandra (LM_XAUI << 4) | 54233545Sjchandra (LM_XAUI << 8) | 55233545Sjchandra (LM_XAUI << 12); 56233545Sjchandra 57233545Sjchandra if (xaui_cplx_mask == 0) 58233545Sjchandra return; 59233545Sjchandra 60233545Sjchandra /* write 0x2 to enable SGMII for all lane */ 61233545Sjchandra block = 7; 62233545Sjchandra 63233545Sjchandra if (xaui_cplx_mask & 0x3) { /* Complexes 0, 1 */ 64233545Sjchandra lane_enable = nlm_read_nae_reg(nae_base, 65233545Sjchandra NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_0_1)); 66233545Sjchandra if (xaui_cplx_mask & 0x1) { /* Complex 0 */ 67233545Sjchandra lane_enable &= ~(0xFFFF); 68233545Sjchandra lane_enable |= cplx_lane_enable; 69233545Sjchandra } 70233545Sjchandra if (xaui_cplx_mask & 0x2) { /* Complex 1 */ 71233545Sjchandra lane_enable &= ~(0xFFFF<<16); 72233545Sjchandra lane_enable |= (cplx_lane_enable << 16); 73233545Sjchandra } 74233545Sjchandra nlm_write_nae_reg(nae_base, 75233545Sjchandra NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_0_1), 76233545Sjchandra lane_enable); 77233545Sjchandra } 78233545Sjchandra lane_enable = 0; 79233545Sjchandra if (xaui_cplx_mask & 0xc) { /* Complexes 2, 3 */ 80233545Sjchandra lane_enable = nlm_read_nae_reg(nae_base, 81233545Sjchandra NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_2_3)); 82233545Sjchandra if (xaui_cplx_mask & 0x4) { /* Complex 2 */ 83233545Sjchandra lane_enable &= ~(0xFFFF); 84233545Sjchandra lane_enable |= cplx_lane_enable; 85233545Sjchandra } 86233545Sjchandra if (xaui_cplx_mask & 0x8) { /* Complex 3 */ 87233545Sjchandra lane_enable &= ~(0xFFFF<<16); 88233545Sjchandra lane_enable |= (cplx_lane_enable << 16); 89233545Sjchandra } 90233545Sjchandra nlm_write_nae_reg(nae_base, 91233545Sjchandra NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_2_3), 92233545Sjchandra lane_enable); 93233545Sjchandra } 94233545Sjchandra 95233545Sjchandra /* Bring txpll out of reset */ 96233545Sjchandra for (block = 0; block < 4; block++) { 97233545Sjchandra if ((xaui_cplx_mask & (1 << block)) == 0) 98233545Sjchandra continue; 99233545Sjchandra 100233545Sjchandra for (lane_ctrl = PHY_LANE_0_CTRL; 101233545Sjchandra lane_ctrl <= PHY_LANE_3_CTRL; lane_ctrl++) { 102233545Sjchandra if (!nlm_is_xlp8xx_ax()) 103233545Sjchandra xlp_nae_lane_reset_txpll(nae_base, 104233545Sjchandra block, lane_ctrl, PHYMODE_XAUI); 105233545Sjchandra else 106233545Sjchandra xlp_ax_nae_lane_reset_txpll(nae_base, block, 107233545Sjchandra lane_ctrl, PHYMODE_XAUI); 108233545Sjchandra } 109233545Sjchandra } 110233545Sjchandra 111233545Sjchandra /* Wait for Rx & TX clock stable */ 112233545Sjchandra for (block = 0; block < 4; block++) { 113233545Sjchandra if ((xaui_cplx_mask & (1 << block)) == 0) 114233545Sjchandra continue; 115233545Sjchandra 116233545Sjchandra for (lane_ctrl = PHY_LANE_0_CTRL; 117233545Sjchandra lane_ctrl <= PHY_LANE_3_CTRL; lane_ctrl++) { 118233545Sjchandra 119233545Sjchandra reg = NAE_REG(block, PHY, lane_ctrl - 4); 120233545Sjchandra /* Wait for TX clock to be set */ 121233545Sjchandra do { 122233545Sjchandra regval = nlm_read_nae_reg(nae_base, reg); 123233545Sjchandra } while ((regval & LANE_TX_CLK) == 0); 124233545Sjchandra 125233545Sjchandra /* Wait for RX clock to be set */ 126233545Sjchandra do { 127233545Sjchandra regval = nlm_read_nae_reg(nae_base, reg); 128233545Sjchandra } while ((regval & LANE_RX_CLK) == 0); 129233545Sjchandra 130233545Sjchandra /* Wait for XAUI Lane fault to be cleared */ 131233545Sjchandra do { 132233545Sjchandra regval = nlm_read_nae_reg(nae_base, reg); 133233545Sjchandra } while ((regval & XAUI_LANE_FAULT) != 0); 134233545Sjchandra } 135233545Sjchandra } 136233545Sjchandra} 137233545Sjchandra 138233545Sjchandravoid 139233545Sjchandranlm_nae_setup_rx_mode_xaui(uint64_t base, int nblock, int iface, int port_type, 140233545Sjchandra int broadcast_en, int multicast_en, int pause_en, int promisc_en) 141233545Sjchandra{ 142233545Sjchandra uint32_t val; 143233545Sjchandra 144233545Sjchandra val = ((broadcast_en & 0x1) << 10) | 145233545Sjchandra ((pause_en & 0x1) << 9) | 146233545Sjchandra ((multicast_en & 0x1) << 8) | 147233545Sjchandra ((promisc_en & 0x1) << 7) | /* unicast_enable - enables promisc mode */ 148233545Sjchandra 1; /* MAC address is always valid */ 149233545Sjchandra 150233545Sjchandra nlm_write_nae_reg(base, XAUI_MAC_FILTER_CFG(nblock), val); 151233545Sjchandra} 152233545Sjchandra 153233545Sjchandravoid 154233545Sjchandranlm_nae_setup_mac_addr_xaui(uint64_t base, int nblock, int iface, 155233545Sjchandra int port_type, unsigned char *mac_addr) 156233545Sjchandra{ 157233545Sjchandra nlm_write_nae_reg(base, 158233545Sjchandra XAUI_MAC_ADDR0_LO(nblock), 159233545Sjchandra (mac_addr[5] << 24) | 160233545Sjchandra (mac_addr[4] << 16) | 161233545Sjchandra (mac_addr[3] << 8) | 162233545Sjchandra mac_addr[2]); 163233545Sjchandra 164233545Sjchandra nlm_write_nae_reg(base, 165233545Sjchandra XAUI_MAC_ADDR0_HI(nblock), 166233545Sjchandra (mac_addr[1] << 24) | 167233545Sjchandra (mac_addr[0] << 16)); 168233545Sjchandra 169233545Sjchandra nlm_write_nae_reg(base, 170233545Sjchandra XAUI_MAC_ADDR_MASK0_LO(nblock), 171233545Sjchandra 0xffffffff); 172233545Sjchandra nlm_write_nae_reg(base, 173233545Sjchandra XAUI_MAC_ADDR_MASK0_HI(nblock), 174233545Sjchandra 0xffffffff); 175233545Sjchandra 176233545Sjchandra nlm_nae_setup_rx_mode_xaui(base, nblock, iface, 177233545Sjchandra XAUIC, 178233545Sjchandra 1, /* broadcast enabled */ 179233545Sjchandra 1, /* multicast enabled */ 180233545Sjchandra 0, /* do not accept pause frames */ 181233545Sjchandra 0 /* promisc mode disabled */ 182233545Sjchandra ); 183233545Sjchandra} 184233545Sjchandra 185233545Sjchandravoid 186233545Sjchandranlm_config_xaui_mtu(uint64_t nae_base, int nblock, 187233545Sjchandra int max_tx_frame_sz, int max_rx_frame_sz) 188233545Sjchandra{ 189233545Sjchandra uint32_t tx_words = max_tx_frame_sz >> 2; /* max_tx_frame_sz / 4 */ 190233545Sjchandra 191233545Sjchandra /* write max frame length */ 192233545Sjchandra nlm_write_nae_reg(nae_base, 193233545Sjchandra XAUI_MAX_FRAME_LEN(nblock), 194233545Sjchandra ((tx_words & 0x3ff) << 16) | (max_rx_frame_sz & 0xffff)); 195233545Sjchandra} 196233545Sjchandra 197233545Sjchandravoid 198233545Sjchandranlm_config_xaui(uint64_t nae_base, int nblock, 199233545Sjchandra int max_tx_frame_sz, int max_rx_frame_sz, int vlan_pri_en) 200233545Sjchandra{ 201233545Sjchandra uint32_t val; 202233545Sjchandra 203233545Sjchandra val = nlm_read_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock)); 204233545Sjchandra val &= ~(0x1 << 11); /* clear soft reset */ 205233545Sjchandra nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock), val); 206233545Sjchandra 207233545Sjchandra val = nlm_read_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock)); 208233545Sjchandra val &= ~(0x3 << 11); /* clear soft reset and hard reset */ 209233545Sjchandra nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock), val); 210233545Sjchandra nlm_write_nae_reg(nae_base, XAUI_CONFIG0(nblock), 0xffffffff); 211233545Sjchandra nlm_write_nae_reg(nae_base, XAUI_CONFIG0(nblock), 0); 212233545Sjchandra 213233545Sjchandra /* Enable tx/rx frame */ 214255368Sjchandra val = 0x000010A8; 215233545Sjchandra val |= XAUI_CONFIG_LENCHK; 216233545Sjchandra val |= XAUI_CONFIG_GENFCS; 217233545Sjchandra val |= XAUI_CONFIG_PAD_64; 218233545Sjchandra nlm_write_nae_reg(nae_base, XAUI_CONFIG1(nblock), val); 219233545Sjchandra 220233545Sjchandra /* write max frame length */ 221233545Sjchandra nlm_config_xaui_mtu(nae_base, nblock, max_tx_frame_sz, 222233545Sjchandra max_rx_frame_sz); 223233545Sjchandra 224233545Sjchandra /* set stats counter */ 225233545Sjchandra val = nlm_read_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock)); 226233545Sjchandra val |= (0x1 << NETIOR_XGMAC_VLAN_DC_POS); 227233545Sjchandra val |= (0x1 << NETIOR_XGMAC_STATS_EN_POS); 228233545Sjchandra if (vlan_pri_en) { 229233545Sjchandra val |= (0x1 << NETIOR_XGMAC_TX_PFC_EN_POS); 230233545Sjchandra val |= (0x1 << NETIOR_XGMAC_RX_PFC_EN_POS); 231233545Sjchandra val |= (0x1 << NETIOR_XGMAC_TX_PAUSE_POS); 232233545Sjchandra } else { 233233545Sjchandra val &= ~(0x1 << NETIOR_XGMAC_TX_PFC_EN_POS); 234233545Sjchandra val |= (0x1 << NETIOR_XGMAC_TX_PAUSE_POS); 235233545Sjchandra } 236233545Sjchandra nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock), val); 237233545Sjchandra /* configure on / off timer */ 238233545Sjchandra if (vlan_pri_en) 239233545Sjchandra val = 0xF1230000; /* PFC mode, offtimer = 0xf123, ontimer = 0 */ 240233545Sjchandra else 241233545Sjchandra val = 0x0000F123; /* link level FC mode, offtimer = 0xf123 */ 242233545Sjchandra nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL2(nblock), val); 243233545Sjchandra 244233545Sjchandra /* set xaui tx threshold */ 245233545Sjchandra val = nlm_read_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL3(nblock)); 246233545Sjchandra val &= ~(0x1f << 10); 247233545Sjchandra val |= ~(15 << 10); 248233545Sjchandra nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL3(nblock), val); 249233545Sjchandra} 250