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
44 void
nlm_configure_sgmii_interface(uint64_t nae_base,int block,int port,int mtu,int loopback)45 nlm_configure_sgmii_interface(uint64_t nae_base, int block, int port,
46 int mtu, int loopback)
47 {
48 uint32_t data1, data2;
49
50 /* Apply a soft reset */
51 data1 = (0x1 << 31); /* soft reset */
52 if (loopback)
53 data1 |= (0x01 << 8);
54 data1 |= (0x01 << 2); /* Rx enable */
55 data1 |= 0x01; /* Tx enable */
56 nlm_write_nae_reg(nae_base, NAE_REG(block, port, MAC_CONF1), data1);
57
58 data2 = (0x7 << 12) | /* pre-amble length=7 */
59 (0x2 << 8) | /* byteMode */
60 0x1; /* fullDuplex */
61 nlm_write_nae_reg(nae_base, NAE_REG(block, port, MAC_CONF2), data2);
62
63 /* Remove a soft reset */
64 data1 &= ~(0x01 << 31);
65 nlm_write_nae_reg(nae_base, NAE_REG(block, port, MAC_CONF1), data1);
66
67 /* setup sgmii max frame length */
68 nlm_write_nae_reg(nae_base, SGMII_MAX_FRAME(block, port), mtu);
69 }
70
71 void
nlm_sgmii_pcs_init(uint64_t nae_base,uint32_t cplx_mask)72 nlm_sgmii_pcs_init(uint64_t nae_base, uint32_t cplx_mask)
73 {
74 xlp_nae_config_lane_gmac(nae_base, cplx_mask);
75 }
76
77 void
nlm_nae_setup_mac(uint64_t nae_base,int nblock,int iface,int reset,int rx_en,int tx_en,int speed,int duplex)78 nlm_nae_setup_mac(uint64_t nae_base, int nblock, int iface, int reset,
79 int rx_en, int tx_en, int speed, int duplex)
80 {
81 uint32_t mac_cfg1, mac_cfg2, netwk_inf;
82
83 mac_cfg1 = nlm_read_nae_reg(nae_base,
84 SGMII_MAC_CONF1(nblock,iface));
85 mac_cfg2 = nlm_read_nae_reg(nae_base,
86 SGMII_MAC_CONF2(nblock,iface));
87 netwk_inf = nlm_read_nae_reg(nae_base,
88 SGMII_NET_IFACE_CTRL(nblock, iface));
89
90 mac_cfg1 &= ~(0x1 << 31); /* remove reset */
91 mac_cfg1 &= ~(0x1 << 2); /* remove rx */
92 mac_cfg1 &= ~(0x1); /* remove tx */
93 mac_cfg2 &= ~(0x3 << 8); /* remove interface mode bits */
94 mac_cfg2 &= ~(0x1); /* remove duplex */
95 netwk_inf &= ~(0x1 << 2); /* remove tx */
96 netwk_inf &= ~(0x3); /* remove speed */
97
98 switch (speed) {
99 case NLM_SGMII_SPEED_10:
100 netwk_inf |= 0x0; /* 2.5 Mhz clock for 10 Mbps */
101 mac_cfg2 |= (0x1 << 8); /* enable 10/100 Mbps */
102 break;
103 case NLM_SGMII_SPEED_100:
104 netwk_inf |= 0x1; /* 25 Mhz clock for 100 Mbps */
105 mac_cfg2 |= (0x1 << 8); /* enable 10/100 Mbps */
106 break;
107 default: /* make it as 1G */
108 netwk_inf |= 0x2; /* 125 Mhz clock for 1G */
109 mac_cfg2 |= (0x2 << 8); /* enable 1G */
110 break;
111 }
112
113 if (reset)
114 mac_cfg1 |= (0x1 << 31); /* set reset */
115
116 if (rx_en)
117 mac_cfg1 |= (0x1 << 2); /* set rx */
118
119 nlm_write_nae_reg(nae_base,
120 SGMII_NET_IFACE_CTRL(nblock, iface),
121 netwk_inf);
122
123 if (tx_en) {
124 mac_cfg1 |= 0x1; /* set tx */
125 netwk_inf |= (0x1 << 2); /* set tx */
126 }
127
128 switch (duplex) {
129 case NLM_SGMII_DUPLEX_HALF:
130 /* duplexity is already set to half duplex */
131 break;
132 default:
133 mac_cfg2 |= 0x1; /* set full duplex */
134 }
135
136 nlm_write_nae_reg(nae_base, SGMII_MAC_CONF1(nblock, iface), mac_cfg1);
137 nlm_write_nae_reg(nae_base, SGMII_MAC_CONF2(nblock, iface), mac_cfg2);
138 nlm_write_nae_reg(nae_base, SGMII_NET_IFACE_CTRL(nblock, iface),
139 netwk_inf);
140 }
141
142 void
nlm_nae_setup_rx_mode_sgmii(uint64_t base,int nblock,int iface,int port_type,int broadcast_en,int multicast_en,int pause_en,int promisc_en)143 nlm_nae_setup_rx_mode_sgmii(uint64_t base, int nblock, int iface, int port_type,
144 int broadcast_en, int multicast_en, int pause_en, int promisc_en)
145 {
146 uint32_t val;
147
148 /* bit[17] of vlan_typefilter - allows packet matching in MAC.
149 * When DA filtering is disabled, this bit and bit[16] should
150 * be zero.
151 * bit[16] of vlan_typefilter - Allows hash matching to be used
152 * for DA filtering. When DA filtering is disabled, this bit and
153 * bit[17] should be zero.
154 * Both bits have to be set only if you want to turn on both
155 * features / modes.
156 */
157 if (promisc_en == 1) {
158 val = nlm_read_nae_reg(base,
159 SGMII_NETIOR_VLANTYPE_FILTER(nblock, iface));
160 val &= (~(0x3 << 16));
161 nlm_write_nae_reg(base,
162 SGMII_NETIOR_VLANTYPE_FILTER(nblock, iface), val);
163 } else {
164 val = nlm_read_nae_reg(base,
165 SGMII_NETIOR_VLANTYPE_FILTER(nblock, iface));
166 val |= (0x1 << 17);
167 nlm_write_nae_reg(base,
168 SGMII_NETIOR_VLANTYPE_FILTER(nblock, iface), val);
169 }
170
171 val = ((broadcast_en & 0x1) << 10) |
172 ((pause_en & 0x1) << 9) |
173 ((multicast_en & 0x1) << 8) |
174 ((promisc_en & 0x1) << 7) | /* unicast_enable - enables promisc mode */
175 1; /* MAC address is always valid */
176
177 nlm_write_nae_reg(base, SGMII_MAC_FILTER_CONFIG(nblock, iface), val);
178
179 }
180
181 void
nlm_nae_setup_mac_addr_sgmii(uint64_t base,int nblock,int iface,int port_type,uint8_t * mac_addr)182 nlm_nae_setup_mac_addr_sgmii(uint64_t base, int nblock, int iface,
183 int port_type, uint8_t *mac_addr)
184 {
185 nlm_write_nae_reg(base,
186 SGMII_MAC_ADDR0_LO(nblock, iface),
187 (mac_addr[5] << 24) |
188 (mac_addr[4] << 16) |
189 (mac_addr[3] << 8) |
190 mac_addr[2]);
191
192 nlm_write_nae_reg(base,
193 SGMII_MAC_ADDR0_HI(nblock, iface),
194 (mac_addr[1] << 24) |
195 (mac_addr[0] << 16));
196
197 nlm_write_nae_reg(base,
198 SGMII_MAC_ADDR_MASK0_LO(nblock, iface),
199 0xffffffff);
200 nlm_write_nae_reg(base,
201 SGMII_MAC_ADDR_MASK0_HI(nblock, iface),
202 0xffffffff);
203
204 nlm_nae_setup_rx_mode_sgmii(base, nblock, iface,
205 SGMIIC,
206 1, /* broadcast enabled */
207 1, /* multicast enabled */
208 0, /* do not accept pause frames */
209 0 /* promisc mode disabled */
210 );
211 }
212