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