octeon_gmx.c revision 1.17 1 1.17 thorpej /* $NetBSD: octeon_gmx.c,v 1.17 2021/04/24 23:36:42 thorpej Exp $ */
2 1.1 hikaru
3 1.1 hikaru /*
4 1.1 hikaru * Copyright (c) 2007 Internet Initiative Japan, Inc.
5 1.1 hikaru * All rights reserved.
6 1.1 hikaru *
7 1.1 hikaru * Redistribution and use in source and binary forms, with or without
8 1.1 hikaru * modification, are permitted provided that the following conditions
9 1.1 hikaru * are met:
10 1.1 hikaru * 1. Redistributions of source code must retain the above copyright
11 1.1 hikaru * notice, this list of conditions and the following disclaimer.
12 1.1 hikaru * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 hikaru * notice, this list of conditions and the following disclaimer in the
14 1.1 hikaru * documentation and/or other materials provided with the distribution.
15 1.1 hikaru *
16 1.1 hikaru * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17 1.1 hikaru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 1.1 hikaru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 1.1 hikaru * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 1.1 hikaru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 1.1 hikaru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 1.1 hikaru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 1.1 hikaru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 1.1 hikaru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.1 hikaru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.1 hikaru * SUCH DAMAGE.
27 1.1 hikaru */
28 1.1 hikaru
29 1.1 hikaru #include <sys/cdefs.h>
30 1.17 thorpej __KERNEL_RCSID(0, "$NetBSD: octeon_gmx.c,v 1.17 2021/04/24 23:36:42 thorpej Exp $");
31 1.1 hikaru
32 1.1 hikaru #include <sys/param.h>
33 1.1 hikaru #include <sys/systm.h>
34 1.15 simonb #include <sys/bus.h>
35 1.1 hikaru #include <sys/cpu.h>
36 1.1 hikaru #include <sys/device.h>
37 1.1 hikaru #include <sys/lock.h>
38 1.1 hikaru #include <sys/cdefs.h>
39 1.16 thorpej #include <sys/kmem.h>
40 1.1 hikaru #include <sys/syslog.h>
41 1.1 hikaru
42 1.1 hikaru #include <mips/locore.h>
43 1.1 hikaru #include <mips/include/cpuregs.h>
44 1.1 hikaru
45 1.15 simonb #include <mips/cavium/dev/octeon_asxvar.h>
46 1.1 hikaru #include <mips/cavium/dev/octeon_ciureg.h>
47 1.1 hikaru #include <mips/cavium/dev/octeon_gmxreg.h>
48 1.15 simonb #include <mips/cavium/dev/octeon_gmxvar.h>
49 1.15 simonb #include <mips/cavium/dev/octeon_ipdvar.h>
50 1.15 simonb #include <mips/cavium/dev/octeon_pipvar.h>
51 1.15 simonb #include <mips/cavium/dev/octeon_smivar.h>
52 1.15 simonb
53 1.1 hikaru #include <mips/cavium/include/iobusvar.h>
54 1.15 simonb
55 1.15 simonb /*
56 1.15 simonb * CNnnXX packet interface
57 1.15 simonb *
58 1.15 simonb *
59 1.15 simonb * CN30XX - 1 GMX interface x 3 ports
60 1.15 simonb * CN31XX - 1 GMX interface x 3 ports
61 1.15 simonb * CN38XX - 2 GMX interfaces x 4 ports
62 1.15 simonb * CN50XX - 1 GMX interface x 3 ports
63 1.15 simonb * CN52XX - 1 GMX interface x 4 ports
64 1.15 simonb * CN56XX - 2 GMX interfaces x 4 ports
65 1.15 simonb * CN58XX - 2 GMX interfaces x 4 ports
66 1.15 simonb * CN61XX - 2 GMX interfaces x 4 ports
67 1.15 simonb * CN63XX - 1 GMX interface x 4 ports
68 1.15 simonb * CN66XX - 2 GMX interfaces x 4 ports
69 1.15 simonb * CN68XX - 5 GMX interfaces x 4 ports
70 1.15 simonb * CN70XX - 2 GMX interfaces x 4 ports
71 1.15 simonb * CNF71XX - 1 GMX interface x 2 ports
72 1.15 simonb */
73 1.1 hikaru
74 1.1 hikaru #define dprintf(...)
75 1.11 simonb #define CNMAC_KASSERT KASSERT
76 1.1 hikaru
77 1.1 hikaru #define ADDR2UINT64(u, a) \
78 1.1 hikaru do { \
79 1.1 hikaru u = \
80 1.1 hikaru (((uint64_t)a[0] << 40) | ((uint64_t)a[1] << 32) | \
81 1.1 hikaru ((uint64_t)a[2] << 24) | ((uint64_t)a[3] << 16) | \
82 1.1 hikaru ((uint64_t)a[4] << 8) | ((uint64_t)a[5] << 0)); \
83 1.1 hikaru } while (0)
84 1.1 hikaru #define UINT642ADDR(a, u) \
85 1.1 hikaru do { \
86 1.1 hikaru a[0] = (uint8_t)((u) >> 40); a[1] = (uint8_t)((u) >> 32); \
87 1.1 hikaru a[2] = (uint8_t)((u) >> 24); a[3] = (uint8_t)((u) >> 16); \
88 1.1 hikaru a[4] = (uint8_t)((u) >> 8); a[5] = (uint8_t)((u) >> 0); \
89 1.1 hikaru } while (0)
90 1.1 hikaru
91 1.1 hikaru #define _GMX_RD8(sc, off) \
92 1.1 hikaru bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off))
93 1.1 hikaru #define _GMX_WR8(sc, off, v) \
94 1.1 hikaru bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off), (v))
95 1.1 hikaru #define _GMX_PORT_RD8(sc, off) \
96 1.1 hikaru bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off))
97 1.1 hikaru #define _GMX_PORT_WR8(sc, off, v) \
98 1.1 hikaru bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off), (v))
99 1.1 hikaru
100 1.15 simonb #define PCS_READ_8(sc, reg) \
101 1.15 simonb bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_pcs_regh, (reg))
102 1.15 simonb #define PCS_WRITE_8(sc, reg, val) \
103 1.15 simonb bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_pcs_regh, (reg), (val))
104 1.15 simonb
105 1.11 simonb struct octgmx_port_ops {
106 1.11 simonb int (*port_ops_enable)(struct octgmx_port_softc *, int);
107 1.11 simonb int (*port_ops_speed)(struct octgmx_port_softc *);
108 1.11 simonb int (*port_ops_timing)(struct octgmx_port_softc *);
109 1.1 hikaru };
110 1.1 hikaru
111 1.11 simonb static int octgmx_match(device_t, struct cfdata *, void *);
112 1.11 simonb static void octgmx_attach(device_t, device_t, void *);
113 1.11 simonb static int octgmx_print(void *, const char *);
114 1.11 simonb static int octgmx_init(struct octgmx_softc *);
115 1.15 simonb
116 1.15 simonb static int octgmx_link_enable(struct octgmx_port_softc *, int);
117 1.11 simonb static int octgmx_rx_frm_ctl_xable(struct octgmx_port_softc *, uint64_t,
118 1.11 simonb int);
119 1.15 simonb static void octgmx_tx_int_enable(struct octgmx_port_softc *, int);
120 1.15 simonb static void octgmx_rx_int_enable(struct octgmx_port_softc *, int);
121 1.15 simonb static int octgmx_rx_frm_ctl_enable(struct octgmx_port_softc *, uint64_t);
122 1.15 simonb static int octgmx_rx_frm_ctl_disable(struct octgmx_port_softc *, uint64_t);
123 1.15 simonb static int octgmx_tx_thresh(struct octgmx_port_softc *, int);
124 1.11 simonb
125 1.11 simonb static int octgmx_rgmii_enable(struct octgmx_port_softc *, int);
126 1.11 simonb static int octgmx_rgmii_speed(struct octgmx_port_softc *);
127 1.11 simonb static int octgmx_rgmii_speed_newlink(struct octgmx_port_softc *,
128 1.1 hikaru uint64_t *);
129 1.11 simonb static int octgmx_rgmii_speed_speed(struct octgmx_port_softc *);
130 1.11 simonb static int octgmx_rgmii_timing(struct octgmx_port_softc *);
131 1.15 simonb
132 1.15 simonb static int octgmx_sgmii_enable(struct octgmx_port_softc *, int);
133 1.15 simonb static int octgmx_sgmii_speed(struct octgmx_port_softc *);
134 1.15 simonb static int octgmx_sgmii_timing(struct octgmx_port_softc *);
135 1.11 simonb
136 1.11 simonb static const int octgmx_rx_adr_cam_regs[] = {
137 1.1 hikaru GMX0_RX0_ADR_CAM0, GMX0_RX0_ADR_CAM1, GMX0_RX0_ADR_CAM2,
138 1.1 hikaru GMX0_RX0_ADR_CAM3, GMX0_RX0_ADR_CAM4, GMX0_RX0_ADR_CAM5
139 1.1 hikaru };
140 1.1 hikaru
141 1.11 simonb struct octgmx_port_ops octgmx_port_ops_mii = {
142 1.1 hikaru /* XXX not implemented */
143 1.1 hikaru };
144 1.1 hikaru
145 1.11 simonb struct octgmx_port_ops octgmx_port_ops_gmii = {
146 1.11 simonb .port_ops_enable = octgmx_rgmii_enable,
147 1.11 simonb .port_ops_speed = octgmx_rgmii_speed,
148 1.11 simonb .port_ops_timing = octgmx_rgmii_timing,
149 1.1 hikaru };
150 1.1 hikaru
151 1.11 simonb struct octgmx_port_ops octgmx_port_ops_rgmii = {
152 1.11 simonb .port_ops_enable = octgmx_rgmii_enable,
153 1.11 simonb .port_ops_speed = octgmx_rgmii_speed,
154 1.11 simonb .port_ops_timing = octgmx_rgmii_timing,
155 1.15 simonb };
156 1.15 simonb
157 1.15 simonb struct octgmx_port_ops octgmx_port_ops_sgmii = {
158 1.15 simonb .port_ops_enable = octgmx_sgmii_enable,
159 1.15 simonb .port_ops_speed = octgmx_sgmii_speed,
160 1.15 simonb .port_ops_timing = octgmx_sgmii_timing,
161 1.1 hikaru };
162 1.1 hikaru
163 1.11 simonb struct octgmx_port_ops octgmx_port_ops_spi42 = {
164 1.1 hikaru /* XXX not implemented */
165 1.1 hikaru };
166 1.1 hikaru
167 1.11 simonb struct octgmx_port_ops *octgmx_port_ops[] = {
168 1.11 simonb [GMX_MII_PORT] = &octgmx_port_ops_mii,
169 1.11 simonb [GMX_GMII_PORT] = &octgmx_port_ops_gmii,
170 1.11 simonb [GMX_RGMII_PORT] = &octgmx_port_ops_rgmii,
171 1.15 simonb [GMX_SGMII_PORT] = &octgmx_port_ops_sgmii,
172 1.11 simonb [GMX_SPI42_PORT] = &octgmx_port_ops_spi42
173 1.1 hikaru };
174 1.15 simonb static const char *octgmx_port_types[] = {
175 1.15 simonb [GMX_MII_PORT] = "MII",
176 1.15 simonb [GMX_GMII_PORT] = "GMII",
177 1.15 simonb [GMX_RGMII_PORT] = "RGMII",
178 1.15 simonb [GMX_SGMII_PORT] = "SGMII",
179 1.15 simonb [GMX_SPI42_PORT] = "SPI-4.2"
180 1.15 simonb };
181 1.1 hikaru
182 1.11 simonb CFATTACH_DECL_NEW(octgmx, sizeof(struct octgmx_softc),
183 1.11 simonb octgmx_match, octgmx_attach, NULL, NULL);
184 1.1 hikaru
185 1.1 hikaru static int
186 1.11 simonb octgmx_match(device_t parent, struct cfdata *cf, void *aux)
187 1.1 hikaru {
188 1.1 hikaru struct iobus_attach_args *aa = aux;
189 1.1 hikaru
190 1.1 hikaru if (strcmp(cf->cf_name, aa->aa_name) != 0)
191 1.1 hikaru return 0;
192 1.1 hikaru if (cf->cf_unit != aa->aa_unitno)
193 1.1 hikaru return 0;
194 1.1 hikaru return 1;
195 1.1 hikaru }
196 1.1 hikaru
197 1.1 hikaru static void
198 1.11 simonb octgmx_attach(device_t parent, device_t self, void *aux)
199 1.1 hikaru {
200 1.11 simonb struct octgmx_softc *sc = device_private(self);
201 1.1 hikaru struct iobus_attach_args *aa = aux;
202 1.15 simonb struct octsmi_softc *smi;
203 1.15 simonb struct octgmx_port_softc *port_sc;
204 1.11 simonb struct octgmx_attach_args gmx_aa;
205 1.15 simonb int port, status;
206 1.1 hikaru int i;
207 1.1 hikaru
208 1.1 hikaru sc->sc_dev = self;
209 1.1 hikaru sc->sc_regt = aa->aa_bust;
210 1.1 hikaru sc->sc_unitno = aa->aa_unitno;
211 1.1 hikaru
212 1.1 hikaru aprint_normal("\n");
213 1.1 hikaru
214 1.1 hikaru status = bus_space_map(sc->sc_regt, aa->aa_unit->addr,
215 1.15 simonb GMX_PORT_SIZE, 0, &sc->sc_regh);
216 1.1 hikaru if (status != 0)
217 1.1 hikaru panic(": can't map register");
218 1.1 hikaru
219 1.11 simonb octgmx_init(sc);
220 1.1 hikaru
221 1.16 thorpej sc->sc_ports = kmem_zalloc(sizeof(*sc->sc_ports) * sc->sc_nports,
222 1.16 thorpej KM_SLEEP);
223 1.1 hikaru
224 1.1 hikaru for (i = 0; i < sc->sc_nports; i++) {
225 1.15 simonb port = GMX_PORT_NUM(sc->sc_unitno, i);
226 1.15 simonb smi = octsmi_lookup(/*XXX*/0, port);
227 1.15 simonb if (smi == NULL)
228 1.15 simonb continue;
229 1.15 simonb
230 1.1 hikaru port_sc = &sc->sc_ports[i];
231 1.1 hikaru port_sc->sc_port_gmx = sc;
232 1.15 simonb port_sc->sc_port_no = port;
233 1.1 hikaru port_sc->sc_port_type = sc->sc_port_types[i];
234 1.11 simonb port_sc->sc_port_ops = octgmx_port_ops[port_sc->sc_port_type];
235 1.1 hikaru status = bus_space_map(sc->sc_regt,
236 1.15 simonb aa->aa_unit->addr + GMX_PORT_SIZE * i,
237 1.15 simonb GMX_PORT_SIZE, 0, &port_sc->sc_port_regh);
238 1.1 hikaru if (status != 0)
239 1.1 hikaru panic(": can't map port register");
240 1.1 hikaru
241 1.15 simonb switch (port_sc->sc_port_type) {
242 1.15 simonb case GMX_MII_PORT:
243 1.15 simonb case GMX_GMII_PORT:
244 1.15 simonb case GMX_RGMII_PORT: {
245 1.15 simonb struct octasx_attach_args asx_aa;
246 1.15 simonb
247 1.15 simonb asx_aa.aa_port = i;
248 1.15 simonb asx_aa.aa_regt = aa->aa_bust;
249 1.15 simonb octasx_init(&asx_aa, &port_sc->sc_port_asx);
250 1.15 simonb break;
251 1.15 simonb }
252 1.15 simonb case GMX_SGMII_PORT:
253 1.15 simonb if (bus_space_map(sc->sc_regt,
254 1.15 simonb PCS_BASE(sc->sc_unitno, i), PCS_SIZE, 0,
255 1.15 simonb &port_sc->sc_port_pcs_regh))
256 1.15 simonb panic("could not map PCS registers");
257 1.15 simonb break;
258 1.15 simonb default:
259 1.15 simonb /* nothing */
260 1.15 simonb break;
261 1.15 simonb }
262 1.15 simonb
263 1.1 hikaru (void)memset(&gmx_aa, 0, sizeof(gmx_aa));
264 1.1 hikaru gmx_aa.ga_regt = aa->aa_bust;
265 1.1 hikaru gmx_aa.ga_addr = aa->aa_unit->addr;
266 1.1 hikaru gmx_aa.ga_name = "cnmac";
267 1.15 simonb gmx_aa.ga_portno = port_sc->sc_port_no;
268 1.1 hikaru gmx_aa.ga_port_type = sc->sc_port_types[i];
269 1.15 simonb gmx_aa.ga_smi = smi;
270 1.1 hikaru gmx_aa.ga_gmx = sc;
271 1.1 hikaru gmx_aa.ga_gmx_port = port_sc;
272 1.17 thorpej config_found(self, &gmx_aa, octgmx_print, CFARG_EOL);
273 1.1 hikaru }
274 1.1 hikaru }
275 1.1 hikaru
276 1.1 hikaru static int
277 1.11 simonb octgmx_print(void *aux, const char *pnp)
278 1.1 hikaru {
279 1.11 simonb struct octgmx_attach_args *ga = aux;
280 1.1 hikaru
281 1.15 simonb aprint_normal(": address=0x%" PRIx64 ": %s\n", ga->ga_addr,
282 1.15 simonb octgmx_port_types[ga->ga_port_type]);
283 1.1 hikaru
284 1.1 hikaru return UNCONF;
285 1.1 hikaru }
286 1.1 hikaru
287 1.1 hikaru static int
288 1.11 simonb octgmx_init(struct octgmx_softc *sc)
289 1.1 hikaru {
290 1.1 hikaru int result = 0;
291 1.1 hikaru uint64_t inf_mode;
292 1.1 hikaru const mips_prid_t cpu_id = mips_options.mips_cpu_id;
293 1.1 hikaru
294 1.1 hikaru inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh, GMX0_INF_MODE);
295 1.1 hikaru if ((inf_mode & INF_MODE_EN) == 0) {
296 1.15 simonb aprint_normal("ports are disabled\n");
297 1.1 hikaru sc->sc_nports = 0;
298 1.1 hikaru return 1;
299 1.1 hikaru }
300 1.1 hikaru
301 1.1 hikaru if (MIPS_PRID_CID(cpu_id) != MIPS_PRID_CID_CAVIUM)
302 1.1 hikaru return 1;
303 1.1 hikaru
304 1.1 hikaru switch (MIPS_PRID_IMPL(cpu_id)) {
305 1.1 hikaru case MIPS_CN31XX:
306 1.1 hikaru /*
307 1.1 hikaru * Packet Interface Configuration
308 1.1 hikaru * GMX Registers, Interface Mode Register, GMX0_INF_MODE
309 1.1 hikaru */
310 1.1 hikaru if ((inf_mode & INF_MODE_TYPE) == 0) {
311 1.1 hikaru /* all three ports configured as RGMII */
312 1.1 hikaru sc->sc_nports = 3;
313 1.1 hikaru sc->sc_port_types[0] = GMX_RGMII_PORT;
314 1.1 hikaru sc->sc_port_types[1] = GMX_RGMII_PORT;
315 1.1 hikaru sc->sc_port_types[2] = GMX_RGMII_PORT;
316 1.1 hikaru } else {
317 1.1 hikaru /* port 0: RGMII, port 1: GMII, port 2: disabled */
318 1.1 hikaru sc->sc_nports = 2;
319 1.1 hikaru sc->sc_port_types[0] = GMX_RGMII_PORT;
320 1.1 hikaru sc->sc_port_types[1] = GMX_GMII_PORT;
321 1.1 hikaru }
322 1.1 hikaru break;
323 1.1 hikaru case MIPS_CN30XX:
324 1.1 hikaru case MIPS_CN50XX:
325 1.1 hikaru /*
326 1.1 hikaru * Packet Interface Configuration
327 1.1 hikaru * GMX Registers, Interface Mode Register, GMX0_INF_MODE
328 1.1 hikaru */
329 1.1 hikaru if ((inf_mode & INF_MODE_P0MII) == 0)
330 1.1 hikaru sc->sc_port_types[0] = GMX_RGMII_PORT;
331 1.1 hikaru else
332 1.1 hikaru sc->sc_port_types[0] = GMX_MII_PORT;
333 1.1 hikaru if ((inf_mode & INF_MODE_TYPE) == 0) {
334 1.1 hikaru /* port 1 and 2 are configred as RGMII ports */
335 1.1 hikaru sc->sc_nports = 3;
336 1.1 hikaru sc->sc_port_types[1] = GMX_RGMII_PORT;
337 1.1 hikaru sc->sc_port_types[2] = GMX_RGMII_PORT;
338 1.1 hikaru } else {
339 1.1 hikaru /* port 1: GMII/MII, port 2: disabled */
340 1.1 hikaru /* GMII or MII port is slected by GMX_PRT1_CFG[SPEED] */
341 1.1 hikaru sc->sc_nports = 2;
342 1.1 hikaru sc->sc_port_types[1] = GMX_GMII_PORT;
343 1.1 hikaru }
344 1.1 hikaru #if 0 /* XXX XXX XXX */
345 1.1 hikaru /* port 2 is in CN3010/CN5010 only */
346 1.1 hikaru if ((octeon_model(id) != OCTEON_MODEL_CN3010) &&
347 1.1 hikaru (octeon_model(id) != OCTEON_MODEL_CN5010))
348 1.1 hikaru if (sc->sc_nports == 3)
349 1.1 hikaru sc->sc_nports = 2;
350 1.1 hikaru #endif
351 1.1 hikaru break;
352 1.15 simonb case MIPS_CN70XX:
353 1.15 simonb switch (inf_mode & INF_MODE_MODE) {
354 1.15 simonb case INF_MODE_MODE_SGMII:
355 1.15 simonb sc->sc_nports = 4;
356 1.15 simonb for (int i = 0; i < sc->sc_nports; i++)
357 1.15 simonb sc->sc_port_types[i] = GMX_SGMII_PORT;
358 1.15 simonb break;
359 1.15 simonb #ifdef notyet
360 1.15 simonb case INF_MODE_MODE_XAUI:
361 1.15 simonb #endif
362 1.15 simonb default:
363 1.15 simonb sc->sc_nports = 0;
364 1.15 simonb result = 1;
365 1.15 simonb }
366 1.15 simonb break;
367 1.1 hikaru default:
368 1.1 hikaru aprint_normal("unsupported octeon model: 0x%x\n", cpu_id);
369 1.1 hikaru sc->sc_nports = 0;
370 1.1 hikaru result = 1;
371 1.1 hikaru break;
372 1.1 hikaru }
373 1.1 hikaru
374 1.1 hikaru return result;
375 1.1 hikaru }
376 1.1 hikaru
377 1.1 hikaru /* XXX RGMII specific */
378 1.15 simonb static int
379 1.11 simonb octgmx_link_enable(struct octgmx_port_softc *sc, int enable)
380 1.1 hikaru {
381 1.1 hikaru uint64_t prt_cfg;
382 1.1 hikaru
383 1.11 simonb octgmx_tx_int_enable(sc, enable);
384 1.11 simonb octgmx_rx_int_enable(sc, enable);
385 1.1 hikaru
386 1.1 hikaru prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
387 1.1 hikaru if (enable) {
388 1.11 simonb if (octgmx_link_status(sc)) {
389 1.1 hikaru SET(prt_cfg, PRTN_CFG_EN);
390 1.1 hikaru }
391 1.1 hikaru } else {
392 1.1 hikaru CLR(prt_cfg, PRTN_CFG_EN);
393 1.1 hikaru }
394 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
395 1.1 hikaru /* software should read back to flush the write operation. */
396 1.1 hikaru (void)_GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
397 1.1 hikaru
398 1.1 hikaru return 0;
399 1.1 hikaru }
400 1.1 hikaru
401 1.1 hikaru /* XXX RGMII specific */
402 1.1 hikaru int
403 1.11 simonb octgmx_stats_init(struct octgmx_port_softc *sc)
404 1.1 hikaru {
405 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS, 0);
406 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_DRP, 0);
407 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_BAD, 0);
408 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_STAT0, 0);
409 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_STAT1, 0);
410 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_STAT3, 0);
411 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_STAT9, 0);
412 1.1 hikaru
413 1.1 hikaru return 0;
414 1.1 hikaru }
415 1.1 hikaru
416 1.1 hikaru int
417 1.11 simonb octgmx_tx_stats_rd_clr(struct octgmx_port_softc *sc, int enable)
418 1.1 hikaru {
419 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_STATS_CTL, enable ? 1 : 0);
420 1.1 hikaru return 0;
421 1.1 hikaru }
422 1.1 hikaru
423 1.1 hikaru int
424 1.11 simonb octgmx_rx_stats_rd_clr(struct octgmx_port_softc *sc, int enable)
425 1.1 hikaru {
426 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_STATS_CTL, enable ? 1 : 0);
427 1.1 hikaru return 0;
428 1.1 hikaru }
429 1.1 hikaru
430 1.1 hikaru static int
431 1.11 simonb octgmx_tx_ovr_bp_enable(struct octgmx_port_softc *sc, int enable)
432 1.1 hikaru {
433 1.1 hikaru uint64_t ovr_bp;
434 1.15 simonb int index = GMX_PORT_INDEX(sc->sc_port_no);
435 1.1 hikaru
436 1.1 hikaru ovr_bp = _GMX_RD8(sc, GMX0_TX_OVR_BP);
437 1.1 hikaru if (enable) {
438 1.15 simonb CLR(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_EN));
439 1.15 simonb SET(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_BP));
440 1.1 hikaru /* XXX really??? */
441 1.15 simonb SET(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_IGN_FULL));
442 1.1 hikaru } else {
443 1.15 simonb SET(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_EN));
444 1.15 simonb CLR(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_BP));
445 1.1 hikaru /* XXX really??? */
446 1.15 simonb SET(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_IGN_FULL));
447 1.1 hikaru }
448 1.1 hikaru _GMX_WR8(sc, GMX0_TX_OVR_BP, ovr_bp);
449 1.1 hikaru return 0;
450 1.1 hikaru }
451 1.1 hikaru
452 1.1 hikaru static int
453 1.11 simonb octgmx_rx_pause_enable(struct octgmx_port_softc *sc, int enable)
454 1.1 hikaru {
455 1.1 hikaru if (enable) {
456 1.11 simonb octgmx_rx_frm_ctl_enable(sc, RXN_FRM_CTL_CTL_BCK);
457 1.1 hikaru } else {
458 1.11 simonb octgmx_rx_frm_ctl_disable(sc, RXN_FRM_CTL_CTL_BCK);
459 1.1 hikaru }
460 1.1 hikaru
461 1.1 hikaru return 0;
462 1.1 hikaru }
463 1.1 hikaru
464 1.15 simonb static void
465 1.11 simonb octgmx_tx_int_enable(struct octgmx_port_softc *sc, int enable)
466 1.1 hikaru {
467 1.1 hikaru uint64_t tx_int_xxx = 0;
468 1.1 hikaru
469 1.1 hikaru SET(tx_int_xxx,
470 1.1 hikaru TX_INT_REG_LATE_COL |
471 1.1 hikaru TX_INT_REG_XSDEF |
472 1.1 hikaru TX_INT_REG_XSCOL |
473 1.1 hikaru TX_INT_REG_UNDFLW |
474 1.1 hikaru TX_INT_REG_PKO_NXA);
475 1.1 hikaru _GMX_WR8(sc, GMX0_TX_INT_REG, tx_int_xxx);
476 1.1 hikaru _GMX_WR8(sc, GMX0_TX_INT_EN, enable ? tx_int_xxx : 0);
477 1.1 hikaru }
478 1.1 hikaru
479 1.15 simonb static void
480 1.11 simonb octgmx_rx_int_enable(struct octgmx_port_softc *sc, int enable)
481 1.1 hikaru {
482 1.1 hikaru uint64_t rx_int_xxx = 0;
483 1.1 hikaru
484 1.1 hikaru SET(rx_int_xxx, 0 |
485 1.1 hikaru RXN_INT_REG_PHY_DUPX |
486 1.1 hikaru RXN_INT_REG_PHY_SPD |
487 1.1 hikaru RXN_INT_REG_PHY_LINK |
488 1.1 hikaru RXN_INT_REG_IFGERR |
489 1.1 hikaru RXN_INT_REG_COLDET |
490 1.1 hikaru RXN_INT_REG_FALERR |
491 1.1 hikaru RXN_INT_REG_RSVERR |
492 1.1 hikaru RXN_INT_REG_PCTERR |
493 1.1 hikaru RXN_INT_REG_OVRERR |
494 1.1 hikaru RXN_INT_REG_NIBERR |
495 1.1 hikaru RXN_INT_REG_SKPERR |
496 1.1 hikaru RXN_INT_REG_RCVERR |
497 1.1 hikaru RXN_INT_REG_LENERR |
498 1.1 hikaru RXN_INT_REG_ALNERR |
499 1.1 hikaru RXN_INT_REG_FCSERR |
500 1.1 hikaru RXN_INT_REG_JABBER |
501 1.1 hikaru RXN_INT_REG_MAXERR |
502 1.1 hikaru RXN_INT_REG_CAREXT |
503 1.1 hikaru RXN_INT_REG_MINERR);
504 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_INT_REG, rx_int_xxx);
505 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_INT_EN, enable ? rx_int_xxx : 0);
506 1.1 hikaru }
507 1.1 hikaru
508 1.15 simonb static int
509 1.11 simonb octgmx_rx_frm_ctl_enable(struct octgmx_port_softc *sc, uint64_t rx_frm_ctl)
510 1.1 hikaru {
511 1.15 simonb struct ifnet *ifp = &sc->sc_port_ec->ec_if;
512 1.15 simonb unsigned int maxlen;
513 1.15 simonb
514 1.15 simonb maxlen = roundup(ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN +
515 1.15 simonb ETHER_VLAN_ENCAP_LEN, 8);
516 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_JABBER, maxlen);
517 1.1 hikaru
518 1.11 simonb return octgmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 1);
519 1.1 hikaru }
520 1.1 hikaru
521 1.15 simonb static int
522 1.11 simonb octgmx_rx_frm_ctl_disable(struct octgmx_port_softc *sc, uint64_t rx_frm_ctl)
523 1.1 hikaru {
524 1.11 simonb return octgmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 0);
525 1.1 hikaru }
526 1.1 hikaru
527 1.1 hikaru static int
528 1.11 simonb octgmx_rx_frm_ctl_xable(struct octgmx_port_softc *sc, uint64_t rx_frm_ctl,
529 1.11 simonb int enable)
530 1.1 hikaru {
531 1.1 hikaru uint64_t tmp;
532 1.1 hikaru
533 1.1 hikaru tmp = _GMX_PORT_RD8(sc, GMX0_RX0_FRM_CTL);
534 1.1 hikaru if (enable)
535 1.1 hikaru SET(tmp, rx_frm_ctl);
536 1.1 hikaru else
537 1.1 hikaru CLR(tmp, rx_frm_ctl);
538 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_FRM_CTL, tmp);
539 1.1 hikaru
540 1.1 hikaru return 0;
541 1.1 hikaru }
542 1.1 hikaru
543 1.15 simonb static int
544 1.11 simonb octgmx_tx_thresh(struct octgmx_port_softc *sc, int cnt)
545 1.1 hikaru {
546 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_THRESH, cnt);
547 1.1 hikaru return 0;
548 1.1 hikaru }
549 1.1 hikaru
550 1.1 hikaru int
551 1.15 simonb octgmx_set_mac_addr(struct octgmx_port_softc *sc, const uint8_t *addr)
552 1.1 hikaru {
553 1.15 simonb uint64_t mac;
554 1.15 simonb int i;
555 1.1 hikaru
556 1.1 hikaru ADDR2UINT64(mac, addr);
557 1.15 simonb
558 1.15 simonb octgmx_link_enable(sc, 0);
559 1.15 simonb sc->sc_mac = mac;
560 1.15 simonb
561 1.15 simonb _GMX_PORT_WR8(sc, GMX0_SMAC0, mac);
562 1.15 simonb for (i = 0; i < 6; i++)
563 1.15 simonb _GMX_PORT_WR8(sc, octgmx_rx_adr_cam_regs[i], addr[i]);
564 1.15 simonb
565 1.15 simonb octgmx_link_enable(sc, 1);
566 1.15 simonb
567 1.1 hikaru return 0;
568 1.1 hikaru }
569 1.1 hikaru
570 1.1 hikaru int
571 1.11 simonb octgmx_set_filter(struct octgmx_port_softc *sc)
572 1.1 hikaru {
573 1.15 simonb struct ethercom *ec = sc->sc_port_ec;
574 1.15 simonb struct ifnet *ifp = &ec->ec_if;
575 1.15 simonb struct ether_multi *enm;
576 1.15 simonb struct ether_multistep step;
577 1.15 simonb uint64_t ctl = 0;
578 1.15 simonb int multi = 0;
579 1.15 simonb uint64_t cam_en = 1; /* enable CAM 0 for self MAC addr */
580 1.15 simonb
581 1.15 simonb octgmx_link_enable(sc, 0);
582 1.15 simonb
583 1.15 simonb if (ISSET(ifp->if_flags, IFF_BROADCAST)) {
584 1.15 simonb dprintf("accept broadcast\n");
585 1.15 simonb SET(ctl, RXN_ADR_CTL_BCST);
586 1.15 simonb }
587 1.15 simonb if (ISSET(ifp->if_flags, IFF_PROMISC)) {
588 1.15 simonb dprintf("promiscas(reject cam)\n");
589 1.15 simonb CLR(ctl, RXN_ADR_CTL_CAM_MODE);
590 1.15 simonb } else {
591 1.15 simonb dprintf("not promiscas(accept cam)\n");
592 1.15 simonb SET(ctl, RXN_ADR_CTL_CAM_MODE);
593 1.15 simonb }
594 1.15 simonb
595 1.15 simonb /*
596 1.15 simonb * Note first entry is self MAC address; other 7 entires are available
597 1.15 simonb * for multicast addresses.
598 1.15 simonb */
599 1.15 simonb
600 1.15 simonb ETHER_LOCK(ec);
601 1.15 simonb ETHER_FIRST_MULTI(step, ec, enm);
602 1.15 simonb while (enm != NULL) {
603 1.15 simonb int i;
604 1.15 simonb
605 1.15 simonb dprintf("%d: lo(%02x:%02x:%02x:%02x:%02x:%02x) - "
606 1.15 simonb "hi(%02x:%02x:%02x:%02x:%02x:%02x)\n",
607 1.15 simonb multi + 1,
608 1.15 simonb enm->enm_addrlo[0], enm->enm_addrlo[1],
609 1.15 simonb enm->enm_addrlo[2], enm->enm_addrlo[3],
610 1.15 simonb enm->enm_addrlo[4], enm->enm_addrlo[5],
611 1.15 simonb enm->enm_addrhi[0], enm->enm_addrhi[1],
612 1.15 simonb enm->enm_addrhi[2], enm->enm_addrhi[3],
613 1.15 simonb enm->enm_addrhi[4], enm->enm_addrhi[5]);
614 1.15 simonb if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
615 1.15 simonb dprintf("all multicast\n");
616 1.15 simonb SET(ifp->if_flags, IFF_ALLMULTI);
617 1.15 simonb ETHER_UNLOCK(ec);
618 1.15 simonb goto setmulti;
619 1.15 simonb }
620 1.15 simonb multi++;
621 1.15 simonb
622 1.15 simonb /* XXX XXX XXX */
623 1.15 simonb if (multi >= 8) {
624 1.15 simonb SET(ifp->if_flags, IFF_ALLMULTI);
625 1.15 simonb ETHER_UNLOCK(ec);
626 1.15 simonb goto setmulti;
627 1.15 simonb }
628 1.15 simonb /* XXX XXX XXX */
629 1.15 simonb
630 1.15 simonb /* XXX XXX XXX */
631 1.15 simonb SET(cam_en, __BIT(multi));
632 1.15 simonb /* XXX XXX XXX */
633 1.15 simonb
634 1.15 simonb for (i = 0; i < 6; i++) {
635 1.15 simonb uint64_t tmp;
636 1.15 simonb
637 1.15 simonb /* XXX XXX XXX */
638 1.15 simonb tmp = _GMX_PORT_RD8(sc, octgmx_rx_adr_cam_regs[i]);
639 1.15 simonb CLR(tmp, 0xffULL << (8 * multi));
640 1.15 simonb SET(tmp, (uint64_t)enm->enm_addrlo[i] << (8 * multi));
641 1.15 simonb _GMX_PORT_WR8(sc, octgmx_rx_adr_cam_regs[i], tmp);
642 1.15 simonb /* XXX XXX XXX */
643 1.15 simonb
644 1.15 simonb }
645 1.15 simonb for (i = 0; i < 6; i++)
646 1.15 simonb dprintf("cam%d = 0x%016lx\n", i,
647 1.15 simonb _GMX_PORT_RD8(sc, octgmx_rx_adr_cam_regs[i]));
648 1.15 simonb ETHER_NEXT_MULTI(step, enm);
649 1.15 simonb }
650 1.15 simonb ETHER_UNLOCK(ec);
651 1.15 simonb CLR(ifp->if_flags, IFF_ALLMULTI);
652 1.15 simonb
653 1.15 simonb CNMAC_KASSERT(enm == NULL);
654 1.15 simonb
655 1.15 simonb setmulti:
656 1.15 simonb /* XXX XXX XXX */
657 1.15 simonb if (ISSET(ifp->if_flags, IFF_ALLMULTI) ||
658 1.15 simonb ISSET(ifp->if_flags, IFF_PROMISC)) {
659 1.15 simonb /* XXX XXX XXX */
660 1.15 simonb dprintf("accept all multicast\n");
661 1.15 simonb ctl |= __SHIFTIN(RXN_ADR_CTL_MCST_ACCEPT, RXN_ADR_CTL_MCST);
662 1.15 simonb /* XXX XXX XXX */
663 1.15 simonb } else if (multi) {
664 1.15 simonb /* XXX XXX XXX */
665 1.15 simonb dprintf("use cam\n");
666 1.15 simonb ctl |= __SHIFTIN(RXN_ADR_CTL_MCST_AFCAM, RXN_ADR_CTL_MCST);
667 1.15 simonb /* XXX XXX XXX */
668 1.15 simonb } else {
669 1.15 simonb /* XXX XXX XXX */
670 1.15 simonb dprintf("reject all multicast\n");
671 1.15 simonb ctl |= __SHIFTIN(RXN_ADR_CTL_MCST_REJECT, RXN_ADR_CTL_MCST);
672 1.15 simonb /* XXX XXX XXX */
673 1.15 simonb }
674 1.15 simonb /* XXX XXX XXX */
675 1.15 simonb
676 1.15 simonb /* XXX XXX XXX */
677 1.15 simonb if (ISSET(ifp->if_flags, IFF_PROMISC)) {
678 1.15 simonb cam_en = 0x00ULL;
679 1.15 simonb } else if (ISSET(ifp->if_flags, IFF_ALLMULTI)) {
680 1.15 simonb cam_en = 0x01ULL;
681 1.15 simonb }
682 1.15 simonb /* XXX XXX XXX */
683 1.15 simonb
684 1.15 simonb dprintf("ctl = %#lx, cam_en = %#lx\n", ctl, cam_en);
685 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, ctl);
686 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, cam_en);
687 1.15 simonb
688 1.15 simonb octgmx_link_enable(sc, 1);
689 1.15 simonb
690 1.1 hikaru return 0;
691 1.1 hikaru }
692 1.1 hikaru
693 1.1 hikaru int
694 1.11 simonb octgmx_port_enable(struct octgmx_port_softc *sc, int enable)
695 1.1 hikaru {
696 1.1 hikaru (*sc->sc_port_ops->port_ops_enable)(sc, enable);
697 1.1 hikaru return 0;
698 1.1 hikaru }
699 1.1 hikaru
700 1.1 hikaru int
701 1.11 simonb octgmx_reset_speed(struct octgmx_port_softc *sc)
702 1.1 hikaru {
703 1.1 hikaru struct ifnet *ifp = &sc->sc_port_ec->ec_if;
704 1.1 hikaru if (ISSET(sc->sc_port_mii->mii_flags, MIIF_DOINGAUTO)) {
705 1.1 hikaru log(LOG_WARNING,
706 1.1 hikaru "%s: autonegotiation has not been completed yet\n",
707 1.1 hikaru ifp->if_xname);
708 1.1 hikaru return 1;
709 1.1 hikaru }
710 1.1 hikaru (*sc->sc_port_ops->port_ops_speed)(sc);
711 1.1 hikaru return 0;
712 1.1 hikaru }
713 1.1 hikaru
714 1.1 hikaru int
715 1.11 simonb octgmx_reset_timing(struct octgmx_port_softc *sc)
716 1.1 hikaru {
717 1.1 hikaru (*sc->sc_port_ops->port_ops_timing)(sc);
718 1.1 hikaru return 0;
719 1.1 hikaru }
720 1.1 hikaru
721 1.1 hikaru int
722 1.11 simonb octgmx_reset_flowctl(struct octgmx_port_softc *sc)
723 1.1 hikaru {
724 1.1 hikaru struct ifmedia_entry *ife = sc->sc_port_mii->mii_media.ifm_cur;
725 1.1 hikaru
726 1.1 hikaru /*
727 1.1 hikaru * Get flow control negotiation result.
728 1.1 hikaru */
729 1.1 hikaru if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO &&
730 1.1 hikaru (sc->sc_port_mii->mii_media_active & IFM_ETH_FMASK) !=
731 1.1 hikaru sc->sc_port_flowflags) {
732 1.1 hikaru sc->sc_port_flowflags =
733 1.1 hikaru sc->sc_port_mii->mii_media_active & IFM_ETH_FMASK;
734 1.1 hikaru sc->sc_port_mii->mii_media_active &= ~IFM_ETH_FMASK;
735 1.1 hikaru }
736 1.1 hikaru
737 1.1 hikaru /*
738 1.1 hikaru * 802.3x Flow Control Capabilities
739 1.1 hikaru */
740 1.1 hikaru if (sc->sc_port_flowflags & IFM_ETH_TXPAUSE) {
741 1.11 simonb octgmx_tx_ovr_bp_enable(sc, 1);
742 1.1 hikaru } else {
743 1.11 simonb octgmx_tx_ovr_bp_enable(sc, 0);
744 1.1 hikaru }
745 1.1 hikaru if (sc->sc_port_flowflags & IFM_ETH_RXPAUSE) {
746 1.11 simonb octgmx_rx_pause_enable(sc, 1);
747 1.1 hikaru } else {
748 1.11 simonb octgmx_rx_pause_enable(sc, 0);
749 1.1 hikaru }
750 1.1 hikaru
751 1.1 hikaru return 0;
752 1.1 hikaru }
753 1.1 hikaru
754 1.1 hikaru static int
755 1.11 simonb octgmx_rgmii_enable(struct octgmx_port_softc *sc, int enable)
756 1.1 hikaru {
757 1.1 hikaru uint64_t mode;
758 1.1 hikaru
759 1.1 hikaru /* XXX XXX XXX */
760 1.1 hikaru mode = _GMX_RD8(sc, GMX0_INF_MODE);
761 1.1 hikaru if (ISSET(mode, INF_MODE_EN)) {
762 1.11 simonb octasx_enable(sc->sc_port_asx, 1);
763 1.1 hikaru }
764 1.1 hikaru /* XXX XXX XXX */
765 1.1 hikaru return 0;
766 1.1 hikaru }
767 1.1 hikaru
768 1.1 hikaru static int
769 1.11 simonb octgmx_rgmii_speed(struct octgmx_port_softc *sc)
770 1.1 hikaru {
771 1.1 hikaru struct ifnet *ifp = &sc->sc_port_ec->ec_if;
772 1.1 hikaru uint64_t newlink;
773 1.1 hikaru int baudrate;
774 1.1 hikaru
775 1.1 hikaru /* XXX XXX XXX */
776 1.11 simonb octgmx_link_enable(sc, 1);
777 1.1 hikaru
778 1.11 simonb octgmx_rgmii_speed_newlink(sc, &newlink);
779 1.1 hikaru if (sc->sc_link == newlink) {
780 1.1 hikaru return 0;
781 1.1 hikaru }
782 1.1 hikaru sc->sc_link = newlink;
783 1.1 hikaru
784 1.12 simonb switch (__SHIFTOUT(sc->sc_link, RXN_RX_INBND_SPEED)) {
785 1.1 hikaru case RXN_RX_INBND_SPEED_2_5:
786 1.1 hikaru baudrate = IF_Mbps(10);
787 1.1 hikaru break;
788 1.1 hikaru case RXN_RX_INBND_SPEED_25:
789 1.1 hikaru baudrate = IF_Mbps(100);
790 1.1 hikaru break;
791 1.1 hikaru case RXN_RX_INBND_SPEED_125:
792 1.1 hikaru baudrate = IF_Mbps(1000);
793 1.1 hikaru break;
794 1.1 hikaru default:
795 1.1 hikaru baudrate = 0/* XXX */;
796 1.3 maxv panic("unable to get baudrate");
797 1.1 hikaru break;
798 1.1 hikaru }
799 1.1 hikaru ifp->if_baudrate = baudrate;
800 1.1 hikaru
801 1.11 simonb octgmx_link_enable(sc, 0);
802 1.1 hikaru
803 1.1 hikaru /*
804 1.1 hikaru * wait a max_packet_time
805 1.1 hikaru * max_packet_time(us) = (max_packet_size(bytes) * 8) / link_speed(Mbps)
806 1.1 hikaru */
807 1.1 hikaru delay((GMX_FRM_MAX_SIZ * 8) / (baudrate / 1000000));
808 1.1 hikaru
809 1.11 simonb octgmx_rgmii_speed_speed(sc);
810 1.1 hikaru
811 1.11 simonb octgmx_link_enable(sc, 1);
812 1.11 simonb octasx_enable(sc->sc_port_asx, 1);
813 1.1 hikaru
814 1.1 hikaru return 0;
815 1.1 hikaru }
816 1.1 hikaru
817 1.1 hikaru static int
818 1.11 simonb octgmx_rgmii_speed_newlink(struct octgmx_port_softc *sc, uint64_t *rnewlink)
819 1.1 hikaru {
820 1.15 simonb uint64_t newlink;
821 1.1 hikaru
822 1.15 simonb /* Inband status does not seem to work */
823 1.15 simonb newlink = _GMX_PORT_RD8(sc, GMX0_RX0_RX_INBND);
824 1.1 hikaru
825 1.1 hikaru *rnewlink = newlink;
826 1.1 hikaru return 0;
827 1.1 hikaru }
828 1.1 hikaru
829 1.1 hikaru static int
830 1.11 simonb octgmx_rgmii_speed_speed(struct octgmx_port_softc *sc)
831 1.1 hikaru {
832 1.1 hikaru uint64_t prt_cfg;
833 1.1 hikaru uint64_t tx_clk, tx_slot, tx_burst;
834 1.1 hikaru
835 1.1 hikaru prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
836 1.1 hikaru
837 1.1 hikaru switch (sc->sc_link & RXN_RX_INBND_SPEED) {
838 1.1 hikaru case RXN_RX_INBND_SPEED_2_5:
839 1.1 hikaru /* 10Mbps */
840 1.1 hikaru /*
841 1.1 hikaru * GMX Tx Clock Generation Registers
842 1.1 hikaru * 8ns x 50 = 400ns (2.5MHz TXC clock)
843 1.1 hikaru */
844 1.1 hikaru tx_clk = 50;
845 1.1 hikaru /*
846 1.1 hikaru * TX Slottime Counter Registers
847 1.1 hikaru * 10/100Mbps: set SLOT to 0x40
848 1.1 hikaru */
849 1.1 hikaru tx_slot = 0x40;
850 1.1 hikaru /*
851 1.1 hikaru * TX Burst-Counter Registers
852 1.1 hikaru * 10/100Mbps: set BURST to 0x0
853 1.1 hikaru */
854 1.1 hikaru tx_burst = 0;
855 1.1 hikaru /*
856 1.1 hikaru * GMX Tx Port Configuration Registers
857 1.1 hikaru * Slot time for half-duplex operation
858 1.1 hikaru * 0 = 512 bittimes (10/100Mbps operation)
859 1.1 hikaru */
860 1.1 hikaru CLR(prt_cfg, PRTN_CFG_SLOTTIME);
861 1.1 hikaru /*
862 1.1 hikaru * GMX Port Configuration Registers
863 1.1 hikaru * Link speed
864 1.1 hikaru * 0 = 10/100Mbps operation
865 1.1 hikaru * in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
866 1.1 hikaru */
867 1.1 hikaru CLR(prt_cfg, PRTN_CFG_SPEED);
868 1.1 hikaru break;
869 1.1 hikaru case RXN_RX_INBND_SPEED_25:
870 1.1 hikaru /* 100Mbps */
871 1.1 hikaru /*
872 1.1 hikaru * GMX Tx Clock Generation Registers
873 1.1 hikaru * 8ns x 5 = 40ns (25.0MHz TXC clock)
874 1.1 hikaru */
875 1.1 hikaru tx_clk = 5;
876 1.1 hikaru /*
877 1.1 hikaru * TX Slottime Counter Registers
878 1.1 hikaru * 10/100Mbps: set SLOT to 0x40
879 1.1 hikaru */
880 1.1 hikaru tx_slot = 0x40;
881 1.1 hikaru /*
882 1.1 hikaru * TX Burst-Counter Registers
883 1.1 hikaru * 10/100Mbps: set BURST to 0x0
884 1.1 hikaru */
885 1.1 hikaru tx_burst = 0;
886 1.1 hikaru /*
887 1.1 hikaru * GMX Tx Port Configuration Registers
888 1.1 hikaru * Slot time for half-duplex operation
889 1.1 hikaru * 0 = 512 bittimes (10/100Mbps operation)
890 1.1 hikaru */
891 1.1 hikaru CLR(prt_cfg, PRTN_CFG_SLOTTIME);
892 1.1 hikaru /*
893 1.1 hikaru * GMX Port Configuration Registers
894 1.1 hikaru * Link speed
895 1.1 hikaru * 0 = 10/100Mbps operation
896 1.1 hikaru * in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
897 1.1 hikaru */
898 1.1 hikaru CLR(prt_cfg, PRTN_CFG_SPEED);
899 1.1 hikaru break;
900 1.1 hikaru case RXN_RX_INBND_SPEED_125:
901 1.1 hikaru /* 1000Mbps */
902 1.1 hikaru /*
903 1.1 hikaru * GMX Tx Clock Generation Registers
904 1.1 hikaru * 8ns x 1 = 8ns (125.0MHz TXC clock)
905 1.1 hikaru */
906 1.1 hikaru tx_clk = 1;
907 1.1 hikaru /*
908 1.1 hikaru * TX Slottime Counter Registers
909 1.1 hikaru * > 1000Mbps: set SLOT to 0x200
910 1.1 hikaru */
911 1.1 hikaru tx_slot = 0x200;
912 1.1 hikaru /*
913 1.1 hikaru * "TX Burst-Counter Registers
914 1.1 hikaru * > 1000Mbps: set BURST to 0x2000
915 1.1 hikaru */
916 1.1 hikaru tx_burst = 0x2000;
917 1.1 hikaru /*
918 1.1 hikaru * GMX Tx Port Configuration Registers
919 1.1 hikaru * Slot time for half-duplex operation
920 1.1 hikaru * 1 = 4096 bittimes (1000Mbps operation)
921 1.1 hikaru */
922 1.1 hikaru SET(prt_cfg, PRTN_CFG_SLOTTIME);
923 1.1 hikaru /*
924 1.1 hikaru * GMX Port Configuration Registers
925 1.1 hikaru * Link speed
926 1.1 hikaru * 1 = 1000Mbps operation
927 1.1 hikaru */
928 1.1 hikaru SET(prt_cfg, PRTN_CFG_SPEED);
929 1.1 hikaru break;
930 1.1 hikaru default:
931 1.1 hikaru /* NOT REACHED! */
932 1.1 hikaru /* Following configuration is default value of system.
933 1.1 hikaru */
934 1.1 hikaru tx_clk = 1;
935 1.1 hikaru tx_slot = 0x200;
936 1.1 hikaru tx_burst = 0x2000;
937 1.1 hikaru SET(prt_cfg, PRTN_CFG_SLOTTIME);
938 1.1 hikaru SET(prt_cfg, PRTN_CFG_SPEED);
939 1.1 hikaru break;
940 1.1 hikaru }
941 1.1 hikaru
942 1.1 hikaru /* Setup Duplex mode(negotiated) */
943 1.1 hikaru /*
944 1.1 hikaru * GMX Port Configuration Registers
945 1.1 hikaru * Duplex mode: 0 = half-duplex mode, 1=full-duplex
946 1.1 hikaru */
947 1.12 simonb if (__SHIFTOUT(sc->sc_link, RXN_RX_INBND_DUPLEX)) {
948 1.1 hikaru /* Full-Duplex */
949 1.1 hikaru SET(prt_cfg, PRTN_CFG_DUPLEX);
950 1.1 hikaru } else {
951 1.1 hikaru /* Half-Duplex */
952 1.1 hikaru CLR(prt_cfg, PRTN_CFG_DUPLEX);
953 1.1 hikaru }
954 1.1 hikaru
955 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_CLK, tx_clk);
956 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot);
957 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst);
958 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
959 1.1 hikaru
960 1.1 hikaru return 0;
961 1.1 hikaru }
962 1.1 hikaru
963 1.1 hikaru static int
964 1.11 simonb octgmx_rgmii_timing(struct octgmx_port_softc *sc)
965 1.1 hikaru {
966 1.1 hikaru uint64_t rx_frm_ctl;
967 1.1 hikaru
968 1.1 hikaru /* RGMII TX Threshold Registers
969 1.1 hikaru * Number of 16-byte ticks to accumulate in the TX FIFO before
970 1.1 hikaru * sending on the RGMII interface. This field should be large
971 1.1 hikaru * enough to prevent underflow on the RGMII interface and must
972 1.1 hikaru * never be set to less than 0x4. This register cannot exceed
973 1.1 hikaru * the TX FIFO depth of 0x40 words.
974 1.1 hikaru */
975 1.1 hikaru /* Default parameter of CN30XX */
976 1.11 simonb octgmx_tx_thresh(sc, 32);
977 1.1 hikaru
978 1.1 hikaru rx_frm_ctl = 0 |
979 1.1 hikaru /* RXN_FRM_CTL_NULL_DIS | (cn5xxx only) */
980 1.1 hikaru /* RXN_FRM_CTL_PRE_ALIGN | (cn5xxx only) */
981 1.1 hikaru /* RXN_FRM_CTL_PAD_LEN | (cn3xxx only) */
982 1.1 hikaru /* RXN_FRM_CTL_VLAN_LEN | (cn3xxx only) */
983 1.1 hikaru RXN_FRM_CTL_PRE_FREE |
984 1.1 hikaru RXN_FRM_CTL_CTL_SMAC |
985 1.1 hikaru RXN_FRM_CTL_CTL_MCST |
986 1.1 hikaru RXN_FRM_CTL_CTL_DRP |
987 1.1 hikaru RXN_FRM_CTL_PRE_STRP |
988 1.1 hikaru RXN_FRM_CTL_PRE_CHK;
989 1.11 simonb octgmx_rx_frm_ctl_enable(sc, rx_frm_ctl);
990 1.1 hikaru
991 1.1 hikaru /* RGMII RX Clock-Delay Registers
992 1.1 hikaru * Delay setting to place n RXC (RGMII receive clock) delay line.
993 1.1 hikaru * The intrinsic delay can range from 50ps to 80ps per tap,
994 1.1 hikaru * which corresponds to skews of 1.25ns to 2.00ns at 25 taps(CSR+1).
995 1.1 hikaru * This is the best match for the RGMII specification which wants
996 1.1 hikaru * 1ns - 2.6ns of skew.
997 1.1 hikaru */
998 1.1 hikaru /* RGMII TX Clock-Delay Registers
999 1.1 hikaru * Delay setting to place n TXC (RGMII transmit clock) delay line.
1000 1.1 hikaru */
1001 1.1 hikaru
1002 1.11 simonb octasx_clk_set(sc->sc_port_asx,
1003 1.9 mrg sc->sc_clk_tx_setting, sc->sc_clk_rx_setting);
1004 1.1 hikaru
1005 1.1 hikaru return 0;
1006 1.1 hikaru }
1007 1.1 hikaru
1008 1.1 hikaru static int
1009 1.15 simonb octgmx_sgmii_enable(struct octgmx_port_softc *sc, int enable)
1010 1.1 hikaru {
1011 1.15 simonb uint64_t ctl_reg, status, timer_count;
1012 1.15 simonb uint64_t cpu_freq_mhz = curcpu()->ci_cpu_freq / 1000000;
1013 1.15 simonb int done;
1014 1.1 hikaru int i;
1015 1.1 hikaru
1016 1.15 simonb if (!enable)
1017 1.15 simonb return 0;
1018 1.1 hikaru
1019 1.15 simonb /* Set link timer interval to 1.6ms. Timer multiple is 1024 (2^10). */
1020 1.15 simonb /*
1021 1.15 simonb * XXX Should set timer to 10ms if not in SGMII mode (ie,
1022 1.15 simonb * "cavium,sgmii-mac-1000x-mode" property exists
1023 1.15 simonb */
1024 1.15 simonb timer_count = PCS_READ_8(sc, PCS_LINK_TIMER_COUNT);
1025 1.15 simonb CLR(timer_count, PCS_LINK_TIMER_COUNT_MASK);
1026 1.15 simonb SET(timer_count,
1027 1.15 simonb __SHIFTIN((1600 * cpu_freq_mhz) >> 10, PCS_LINK_TIMER_COUNT_MASK));
1028 1.15 simonb PCS_WRITE_8(sc, PCS_LINK_TIMER_COUNT, timer_count);
1029 1.15 simonb
1030 1.15 simonb /* Reset the PCS. */
1031 1.15 simonb ctl_reg = PCS_READ_8(sc, PCS_MR_CONTROL);
1032 1.15 simonb SET(ctl_reg, PCS_MR_CONTROL_RESET);
1033 1.15 simonb PCS_WRITE_8(sc, PCS_MR_CONTROL, ctl_reg);
1034 1.15 simonb
1035 1.15 simonb /* Wait for the reset to complete. */
1036 1.15 simonb done = 0;
1037 1.15 simonb for (i = 0; i < 1000000; i++) {
1038 1.15 simonb ctl_reg = PCS_READ_8(sc, PCS_MR_CONTROL);
1039 1.15 simonb if (!ISSET(ctl_reg, PCS_MR_CONTROL_RESET)) {
1040 1.15 simonb done = 1;
1041 1.15 simonb break;
1042 1.15 simonb }
1043 1.15 simonb }
1044 1.15 simonb if (!done) {
1045 1.15 simonb printf("SGMII reset timeout on port %d\n", sc->sc_port_no);
1046 1.15 simonb return 1;
1047 1.15 simonb }
1048 1.1 hikaru
1049 1.15 simonb /* Start a new SGMII autonegotiation. */
1050 1.15 simonb SET(ctl_reg, PCS_MR_CONTROL_AN_EN);
1051 1.15 simonb SET(ctl_reg, PCS_MR_CONTROL_RST_AN);
1052 1.15 simonb CLR(ctl_reg, PCS_MR_CONTROL_PWR_DN);
1053 1.15 simonb PCS_WRITE_8(sc, PCS_MR_CONTROL, ctl_reg);
1054 1.15 simonb
1055 1.15 simonb /* Wait for the SGMII autonegotiation to complete. */
1056 1.15 simonb done = 0;
1057 1.15 simonb for (i = 0; i < 1000000; i++) {
1058 1.15 simonb status = PCS_READ_8(sc, PCS_MR_STATUS);
1059 1.15 simonb if (ISSET(status, PCS_MR_STATUS_AN_CPT)) {
1060 1.15 simonb done = 1;
1061 1.15 simonb break;
1062 1.15 simonb }
1063 1.15 simonb }
1064 1.15 simonb if (!done) {
1065 1.15 simonb printf("SGMII autonegotiation timeout on port %d\n",
1066 1.15 simonb sc->sc_port_no);
1067 1.15 simonb return 1;
1068 1.15 simonb }
1069 1.1 hikaru
1070 1.1 hikaru return 0;
1071 1.1 hikaru }
1072 1.1 hikaru
1073 1.1 hikaru static int
1074 1.15 simonb octgmx_sgmii_speed(struct octgmx_port_softc *sc)
1075 1.1 hikaru {
1076 1.15 simonb uint64_t misc_ctl, prt_cfg;
1077 1.15 simonb int tx_burst, tx_slot;
1078 1.1 hikaru
1079 1.11 simonb octgmx_link_enable(sc, 0);
1080 1.1 hikaru
1081 1.15 simonb prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
1082 1.1 hikaru
1083 1.15 simonb if (ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX))
1084 1.15 simonb SET(prt_cfg, PRTN_CFG_DUPLEX);
1085 1.15 simonb else
1086 1.15 simonb CLR(prt_cfg, PRTN_CFG_DUPLEX);
1087 1.1 hikaru
1088 1.15 simonb misc_ctl = PCS_READ_8(sc, PCS_MISC_CTL);
1089 1.15 simonb CLR(misc_ctl, PCS_MISC_CTL_SAMP_PT);
1090 1.1 hikaru
1091 1.15 simonb /* Disable the GMX port if the link is down. */
1092 1.15 simonb if (octgmx_link_status(sc))
1093 1.15 simonb CLR(misc_ctl, PCS_MISC_CTL_GMXENO);
1094 1.15 simonb else
1095 1.15 simonb SET(misc_ctl, PCS_MISC_CTL_GMXENO);
1096 1.1 hikaru
1097 1.15 simonb switch (sc->sc_port_ec->ec_if.if_baudrate) {
1098 1.15 simonb case IF_Mbps(10):
1099 1.15 simonb tx_slot = 0x40;
1100 1.15 simonb tx_burst = 0;
1101 1.15 simonb CLR(prt_cfg, PRTN_CFG_SPEED);
1102 1.15 simonb SET(prt_cfg, PRTN_CFG_SPEED_MSB);
1103 1.15 simonb CLR(prt_cfg, PRTN_CFG_SLOTTIME);
1104 1.15 simonb misc_ctl |= 25 & PCS_MISC_CTL_SAMP_PT;
1105 1.15 simonb break;
1106 1.15 simonb case IF_Mbps(100):
1107 1.15 simonb tx_slot = 0x40;
1108 1.15 simonb tx_burst = 0;
1109 1.15 simonb CLR(prt_cfg, PRTN_CFG_SPEED);
1110 1.15 simonb CLR(prt_cfg, PRTN_CFG_SPEED_MSB);
1111 1.15 simonb CLR(prt_cfg, PRTN_CFG_SLOTTIME);
1112 1.15 simonb misc_ctl |= 5 & PCS_MISC_CTL_SAMP_PT;
1113 1.15 simonb break;
1114 1.15 simonb case IF_Gbps(1):
1115 1.15 simonb default:
1116 1.15 simonb tx_slot = 0x200;
1117 1.15 simonb tx_burst = 0x2000;
1118 1.15 simonb SET(prt_cfg, PRTN_CFG_SPEED);
1119 1.15 simonb CLR(prt_cfg, PRTN_CFG_SPEED_MSB);
1120 1.15 simonb SET(prt_cfg, PRTN_CFG_SLOTTIME);
1121 1.15 simonb misc_ctl |= 1 & PCS_MISC_CTL_SAMP_PT;
1122 1.15 simonb break;
1123 1.15 simonb }
1124 1.1 hikaru
1125 1.15 simonb PCS_WRITE_8(sc, PCS_MISC_CTL, misc_ctl);
1126 1.1 hikaru
1127 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot);
1128 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst);
1129 1.15 simonb _GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
1130 1.1 hikaru
1131 1.15 simonb octgmx_link_enable(sc, 1);
1132 1.1 hikaru
1133 1.15 simonb return 0;
1134 1.15 simonb }
1135 1.1 hikaru
1136 1.15 simonb static int
1137 1.15 simonb octgmx_sgmii_timing(struct octgmx_port_softc *sc)
1138 1.15 simonb {
1139 1.15 simonb uint64_t rx_frm_ctl;
1140 1.1 hikaru
1141 1.15 simonb octgmx_tx_thresh(sc, 32);
1142 1.1 hikaru
1143 1.15 simonb rx_frm_ctl =
1144 1.15 simonb RXN_FRM_CTL_PRE_FREE |
1145 1.15 simonb RXN_FRM_CTL_CTL_SMAC |
1146 1.15 simonb RXN_FRM_CTL_CTL_MCST |
1147 1.15 simonb RXN_FRM_CTL_CTL_DRP |
1148 1.15 simonb RXN_FRM_CTL_PRE_STRP |
1149 1.15 simonb RXN_FRM_CTL_PRE_CHK;
1150 1.15 simonb octgmx_rx_frm_ctl_enable(sc, rx_frm_ctl);
1151 1.1 hikaru
1152 1.1 hikaru return 0;
1153 1.1 hikaru }
1154 1.1 hikaru
1155 1.1 hikaru void
1156 1.11 simonb octgmx_stats(struct octgmx_port_softc *sc)
1157 1.1 hikaru {
1158 1.1 hikaru struct ifnet *ifp = &sc->sc_port_ec->ec_if;
1159 1.1 hikaru uint64_t tmp;
1160 1.1 hikaru
1161 1.1 hikaru /*
1162 1.1 hikaru * GMX0_RX0_STATS_PKTS is not count.
1163 1.1 hikaru * input packet is counted when recepted packet in if_cnmac.
1164 1.1 hikaru */
1165 1.1 hikaru /*
1166 1.1 hikaru * GMX0_RX0_STATS_PKTS_BAD count is included
1167 1.1 hikaru * receive error of work queue entry.
1168 1.1 hikaru * this is not add to input packet errors of interface.
1169 1.1 hikaru */
1170 1.8 thorpej net_stat_ref_t nsr = IF_STAT_GETREF(ifp);
1171 1.8 thorpej if_statadd_ref(nsr, if_iqdrops,
1172 1.8 thorpej (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_DRP));
1173 1.8 thorpej if_statadd_ref(nsr, if_opackets,
1174 1.8 thorpej (uint32_t)_GMX_PORT_RD8(sc, GMX0_TX0_STAT3));
1175 1.1 hikaru
1176 1.1 hikaru tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT0);
1177 1.8 thorpej if_statadd_ref(nsr, if_oerrors,
1178 1.8 thorpej (uint32_t)tmp + ((uint32_t)(tmp >> 32) * 16));
1179 1.8 thorpej if_statadd_ref(nsr, if_collisions, (uint32_t)tmp);
1180 1.1 hikaru
1181 1.1 hikaru tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT1);
1182 1.8 thorpej if_statadd_ref(nsr, if_collisions,
1183 1.8 thorpej (uint32_t)tmp + (uint32_t)(tmp >> 32));
1184 1.1 hikaru
1185 1.1 hikaru tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT9);
1186 1.8 thorpej if_statadd_ref(nsr, if_oerrors, (uint32_t)(tmp >> 32));
1187 1.8 thorpej IF_STAT_PUTREF(ifp);
1188 1.1 hikaru }
1189