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