xref: /trueos/sys/mips/nlm/dev/net/xaui.c (revision d5d1038c7e8fb81fcbf4d3e4d444d685e4af1e4b)
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>
44 void
nlm_xaui_pcs_init(uint64_t nae_base,int xaui_cplx_mask)45 nlm_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 
138 void
nlm_nae_setup_rx_mode_xaui(uint64_t base,int nblock,int iface,int port_type,int broadcast_en,int multicast_en,int pause_en,int promisc_en)139 nlm_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 
153 void
nlm_nae_setup_mac_addr_xaui(uint64_t base,int nblock,int iface,int port_type,unsigned char * mac_addr)154 nlm_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 
185 void
nlm_config_xaui_mtu(uint64_t nae_base,int nblock,int max_tx_frame_sz,int max_rx_frame_sz)186 nlm_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 
197 void
nlm_config_xaui(uint64_t nae_base,int nblock,int max_tx_frame_sz,int max_rx_frame_sz,int vlan_pri_en)198 nlm_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