1/*- 2 * Copyright (c) 2003-2012 Broadcom Corporation 3 * All Rights Reserved 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD$"); 31#include <sys/types.h> 32#include <sys/systm.h> 33 34#include <mips/nlm/hal/mips-extns.h> 35#include <mips/nlm/hal/haldefs.h> 36#include <mips/nlm/hal/iomap.h> 37#include <mips/nlm/hal/sys.h> 38#include <mips/nlm/hal/nae.h> 39#include <mips/nlm/hal/mdio.h> 40#include <mips/nlm/hal/sgmii.h> 41#include <mips/nlm/hal/xaui.h> 42 43#include <mips/nlm/xlp.h> 44void 45nlm_xaui_pcs_init(uint64_t nae_base, int xaui_cplx_mask) 46{ 47 int block, lane_ctrl, reg; 48 int cplx_lane_enable; 49 int lane_enable = 0; 50 uint32_t regval; 51 52 cplx_lane_enable = LM_XAUI | 53 (LM_XAUI << 4) | 54 (LM_XAUI << 8) | 55 (LM_XAUI << 12); 56 57 if (xaui_cplx_mask == 0) 58 return; 59 60 /* write 0x2 to enable SGMII for all lane */ 61 block = 7; 62 63 if (xaui_cplx_mask & 0x3) { /* Complexes 0, 1 */ 64 lane_enable = nlm_read_nae_reg(nae_base, 65 NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_0_1)); 66 if (xaui_cplx_mask & 0x1) { /* Complex 0 */ 67 lane_enable &= ~(0xFFFF); 68 lane_enable |= cplx_lane_enable; 69 } 70 if (xaui_cplx_mask & 0x2) { /* Complex 1 */ 71 lane_enable &= ~(0xFFFF<<16); 72 lane_enable |= (cplx_lane_enable << 16); 73 } 74 nlm_write_nae_reg(nae_base, 75 NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_0_1), 76 lane_enable); 77 } 78 lane_enable = 0; 79 if (xaui_cplx_mask & 0xc) { /* Complexes 2, 3 */ 80 lane_enable = nlm_read_nae_reg(nae_base, 81 NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_2_3)); 82 if (xaui_cplx_mask & 0x4) { /* Complex 2 */ 83 lane_enable &= ~(0xFFFF); 84 lane_enable |= cplx_lane_enable; 85 } 86 if (xaui_cplx_mask & 0x8) { /* Complex 3 */ 87 lane_enable &= ~(0xFFFF<<16); 88 lane_enable |= (cplx_lane_enable << 16); 89 } 90 nlm_write_nae_reg(nae_base, 91 NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_2_3), 92 lane_enable); 93 } 94 95 /* Bring txpll out of reset */ 96 for (block = 0; block < 4; block++) { 97 if ((xaui_cplx_mask & (1 << block)) == 0) 98 continue; 99 100 for (lane_ctrl = PHY_LANE_0_CTRL; 101 lane_ctrl <= PHY_LANE_3_CTRL; lane_ctrl++) { 102 if (!nlm_is_xlp8xx_ax()) 103 xlp_nae_lane_reset_txpll(nae_base, 104 block, lane_ctrl, PHYMODE_XAUI); 105 else 106 xlp_ax_nae_lane_reset_txpll(nae_base, block, 107 lane_ctrl, PHYMODE_XAUI); 108 } 109 } 110 111 /* Wait for Rx & TX clock stable */ 112 for (block = 0; block < 4; block++) { 113 if ((xaui_cplx_mask & (1 << block)) == 0) 114 continue; 115 116 for (lane_ctrl = PHY_LANE_0_CTRL; 117 lane_ctrl <= PHY_LANE_3_CTRL; lane_ctrl++) { 118 119 reg = NAE_REG(block, PHY, lane_ctrl - 4); 120 /* Wait for TX clock to be set */ 121 do { 122 regval = nlm_read_nae_reg(nae_base, reg); 123 } while ((regval & LANE_TX_CLK) == 0); 124 125 /* Wait for RX clock to be set */ 126 do { 127 regval = nlm_read_nae_reg(nae_base, reg); 128 } while ((regval & LANE_RX_CLK) == 0); 129 130 /* Wait for XAUI Lane fault to be cleared */ 131 do { 132 regval = nlm_read_nae_reg(nae_base, reg); 133 } while ((regval & XAUI_LANE_FAULT) != 0); 134 } 135 } 136} 137 138void 139nlm_nae_setup_rx_mode_xaui(uint64_t base, int nblock, int iface, int port_type, 140 int broadcast_en, int multicast_en, int pause_en, int promisc_en) 141{ 142 uint32_t val; 143 144 val = ((broadcast_en & 0x1) << 10) | 145 ((pause_en & 0x1) << 9) | 146 ((multicast_en & 0x1) << 8) | 147 ((promisc_en & 0x1) << 7) | /* unicast_enable - enables promisc mode */ 148 1; /* MAC address is always valid */ 149 150 nlm_write_nae_reg(base, XAUI_MAC_FILTER_CFG(nblock), val); 151} 152 153void 154nlm_nae_setup_mac_addr_xaui(uint64_t base, int nblock, int iface, 155 int port_type, unsigned char *mac_addr) 156{ 157 nlm_write_nae_reg(base, 158 XAUI_MAC_ADDR0_LO(nblock), 159 (mac_addr[5] << 24) | 160 (mac_addr[4] << 16) | 161 (mac_addr[3] << 8) | 162 mac_addr[2]); 163 164 nlm_write_nae_reg(base, 165 XAUI_MAC_ADDR0_HI(nblock), 166 (mac_addr[1] << 24) | 167 (mac_addr[0] << 16)); 168 169 nlm_write_nae_reg(base, 170 XAUI_MAC_ADDR_MASK0_LO(nblock), 171 0xffffffff); 172 nlm_write_nae_reg(base, 173 XAUI_MAC_ADDR_MASK0_HI(nblock), 174 0xffffffff); 175 176 nlm_nae_setup_rx_mode_xaui(base, nblock, iface, 177 XAUIC, 178 1, /* broadcast enabled */ 179 1, /* multicast enabled */ 180 0, /* do not accept pause frames */ 181 0 /* promisc mode disabled */ 182 ); 183} 184 185void 186nlm_config_xaui_mtu(uint64_t nae_base, int nblock, 187 int max_tx_frame_sz, int max_rx_frame_sz) 188{ 189 uint32_t tx_words = max_tx_frame_sz >> 2; /* max_tx_frame_sz / 4 */ 190 191 /* write max frame length */ 192 nlm_write_nae_reg(nae_base, 193 XAUI_MAX_FRAME_LEN(nblock), 194 ((tx_words & 0x3ff) << 16) | (max_rx_frame_sz & 0xffff)); 195} 196 197void 198nlm_config_xaui(uint64_t nae_base, int nblock, 199 int max_tx_frame_sz, int max_rx_frame_sz, int vlan_pri_en) 200{ 201 uint32_t val; 202 203 val = nlm_read_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock)); 204 val &= ~(0x1 << 11); /* clear soft reset */ 205 nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock), val); 206 207 val = nlm_read_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock)); 208 val &= ~(0x3 << 11); /* clear soft reset and hard reset */ 209 nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock), val); 210 nlm_write_nae_reg(nae_base, XAUI_CONFIG0(nblock), 0xffffffff); 211 nlm_write_nae_reg(nae_base, XAUI_CONFIG0(nblock), 0); 212 213 /* Enable tx/rx frame */ 214 val = 0x000010A8; 215 val |= XAUI_CONFIG_LENCHK; 216 val |= XAUI_CONFIG_GENFCS; 217 val |= XAUI_CONFIG_PAD_64; 218 nlm_write_nae_reg(nae_base, XAUI_CONFIG1(nblock), val); 219 220 /* write max frame length */ 221 nlm_config_xaui_mtu(nae_base, nblock, max_tx_frame_sz, 222 max_rx_frame_sz); 223 224 /* set stats counter */ 225 val = nlm_read_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock)); 226 val |= (0x1 << NETIOR_XGMAC_VLAN_DC_POS); 227 val |= (0x1 << NETIOR_XGMAC_STATS_EN_POS); 228 if (vlan_pri_en) { 229 val |= (0x1 << NETIOR_XGMAC_TX_PFC_EN_POS); 230 val |= (0x1 << NETIOR_XGMAC_RX_PFC_EN_POS); 231 val |= (0x1 << NETIOR_XGMAC_TX_PAUSE_POS); 232 } else { 233 val &= ~(0x1 << NETIOR_XGMAC_TX_PFC_EN_POS); 234 val |= (0x1 << NETIOR_XGMAC_TX_PAUSE_POS); 235 } 236 nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock), val); 237 /* configure on / off timer */ 238 if (vlan_pri_en) 239 val = 0xF1230000; /* PFC mode, offtimer = 0xf123, ontimer = 0 */ 240 else 241 val = 0x0000F123; /* link level FC mode, offtimer = 0xf123 */ 242 nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL2(nblock), val); 243 244 /* set xaui tx threshold */ 245 val = nlm_read_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL3(nblock)); 246 val &= ~(0x1f << 10); 247 val |= ~(15 << 10); 248 nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL3(nblock), val); 249} 250