octeon_gmx.c revision 1.5 1 1.5 msaitoh /* $NetBSD: octeon_gmx.c,v 1.5 2019/05/28 14:20:09 msaitoh 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 /*
30 1.1 hikaru * support GMX0 interface only
31 1.1 hikaru * take no thought for other GMX interface
32 1.1 hikaru */
33 1.1 hikaru
34 1.1 hikaru #include <sys/cdefs.h>
35 1.5 msaitoh __KERNEL_RCSID(0, "$NetBSD: octeon_gmx.c,v 1.5 2019/05/28 14:20:09 msaitoh Exp $");
36 1.1 hikaru
37 1.1 hikaru #include "opt_octeon.h"
38 1.1 hikaru
39 1.1 hikaru #include <sys/param.h>
40 1.1 hikaru #include <sys/systm.h>
41 1.1 hikaru #include <sys/types.h>
42 1.1 hikaru #include <sys/cpu.h>
43 1.1 hikaru #include <sys/device.h>
44 1.1 hikaru #include <sys/lock.h>
45 1.1 hikaru #include <sys/cdefs.h>
46 1.1 hikaru #include <sys/malloc.h>
47 1.1 hikaru #include <sys/syslog.h>
48 1.1 hikaru
49 1.1 hikaru #include <mips/locore.h>
50 1.1 hikaru #include <mips/include/cpuregs.h>
51 1.1 hikaru #include <sys/bus.h>
52 1.1 hikaru
53 1.1 hikaru #include <mips/cavium/dev/octeon_ciureg.h>
54 1.1 hikaru #include <mips/cavium/dev/octeon_gmxreg.h>
55 1.1 hikaru #include <mips/cavium/include/iobusvar.h>
56 1.1 hikaru #include <mips/cavium/dev/octeon_ipdvar.h>
57 1.1 hikaru #include <mips/cavium/dev/octeon_asxvar.h>
58 1.1 hikaru #include <mips/cavium/dev/octeon_gmxvar.h>
59 1.1 hikaru
60 1.1 hikaru #define dprintf(...)
61 1.1 hikaru #define OCTEON_ETH_KASSERT KASSERT
62 1.1 hikaru
63 1.1 hikaru #define ADDR2UINT64(u, a) \
64 1.1 hikaru do { \
65 1.1 hikaru u = \
66 1.1 hikaru (((uint64_t)a[0] << 40) | ((uint64_t)a[1] << 32) | \
67 1.1 hikaru ((uint64_t)a[2] << 24) | ((uint64_t)a[3] << 16) | \
68 1.1 hikaru ((uint64_t)a[4] << 8) | ((uint64_t)a[5] << 0)); \
69 1.1 hikaru } while (0)
70 1.1 hikaru #define UINT642ADDR(a, u) \
71 1.1 hikaru do { \
72 1.1 hikaru a[0] = (uint8_t)((u) >> 40); a[1] = (uint8_t)((u) >> 32); \
73 1.1 hikaru a[2] = (uint8_t)((u) >> 24); a[3] = (uint8_t)((u) >> 16); \
74 1.1 hikaru a[4] = (uint8_t)((u) >> 8); a[5] = (uint8_t)((u) >> 0); \
75 1.1 hikaru } while (0)
76 1.1 hikaru
77 1.1 hikaru #define _GMX_RD8(sc, off) \
78 1.1 hikaru bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off))
79 1.1 hikaru #define _GMX_WR8(sc, off, v) \
80 1.1 hikaru bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off), (v))
81 1.1 hikaru #define _GMX_PORT_RD8(sc, off) \
82 1.1 hikaru bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off))
83 1.1 hikaru #define _GMX_PORT_WR8(sc, off, v) \
84 1.1 hikaru bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off), (v))
85 1.1 hikaru
86 1.1 hikaru struct octeon_gmx_port_ops {
87 1.1 hikaru int (*port_ops_enable)(struct octeon_gmx_port_softc *, int);
88 1.1 hikaru int (*port_ops_speed)(struct octeon_gmx_port_softc *);
89 1.1 hikaru int (*port_ops_timing)(struct octeon_gmx_port_softc *);
90 1.1 hikaru int (*port_ops_set_mac_addr)(struct octeon_gmx_port_softc *,
91 1.1 hikaru uint8_t *, uint64_t);
92 1.1 hikaru int (*port_ops_set_filter)(struct octeon_gmx_port_softc *);
93 1.1 hikaru };
94 1.1 hikaru
95 1.1 hikaru static int octeon_gmx_match(device_t, struct cfdata *, void *);
96 1.1 hikaru static void octeon_gmx_attach(device_t, device_t, void *);
97 1.1 hikaru static int octeon_gmx_print(void *, const char *);
98 1.1 hikaru static int octeon_gmx_submatch(device_t, struct cfdata *,
99 1.1 hikaru const int *, void *);
100 1.1 hikaru static int octeon_gmx_init(struct octeon_gmx_softc *);
101 1.1 hikaru static int octeon_gmx_rx_frm_ctl_xable(struct octeon_gmx_port_softc *,
102 1.1 hikaru uint64_t, int);
103 1.1 hikaru
104 1.1 hikaru static int octeon_gmx_rgmii_enable(struct octeon_gmx_port_softc *, int);
105 1.1 hikaru static int octeon_gmx_rgmii_speed(struct octeon_gmx_port_softc *);
106 1.1 hikaru static int octeon_gmx_rgmii_speed_newlink(struct octeon_gmx_port_softc *,
107 1.1 hikaru uint64_t *);
108 1.1 hikaru static int octeon_gmx_rgmii_speed_speed(struct octeon_gmx_port_softc *);
109 1.1 hikaru static int octeon_gmx_rgmii_timing(struct octeon_gmx_port_softc *);
110 1.1 hikaru static int octeon_gmx_rgmii_set_mac_addr(struct octeon_gmx_port_softc *,
111 1.1 hikaru uint8_t *, uint64_t);
112 1.1 hikaru static int octeon_gmx_rgmii_set_filter(struct octeon_gmx_port_softc *);
113 1.1 hikaru
114 1.1 hikaru #ifdef OCTEON_ETH_DEBUG
115 1.1 hikaru void octeon_gmx_intr_evcnt_attach(struct octeon_gmx_softc *);
116 1.1 hikaru void octeon_gmx_dump(void);
117 1.1 hikaru void octeon_gmx_debug_reset(void);
118 1.1 hikaru int octeon_gmx_intr_drop(void *);
119 1.1 hikaru #endif
120 1.1 hikaru
121 1.1 hikaru static const int octeon_gmx_rx_adr_cam_regs[] = {
122 1.1 hikaru GMX0_RX0_ADR_CAM0, GMX0_RX0_ADR_CAM1, GMX0_RX0_ADR_CAM2,
123 1.1 hikaru GMX0_RX0_ADR_CAM3, GMX0_RX0_ADR_CAM4, GMX0_RX0_ADR_CAM5
124 1.1 hikaru };
125 1.1 hikaru
126 1.1 hikaru struct octeon_gmx_port_ops octeon_gmx_port_ops_mii = {
127 1.1 hikaru /* XXX not implemented */
128 1.1 hikaru };
129 1.1 hikaru
130 1.1 hikaru struct octeon_gmx_port_ops octeon_gmx_port_ops_gmii = {
131 1.1 hikaru .port_ops_enable = octeon_gmx_rgmii_enable,
132 1.1 hikaru .port_ops_speed = octeon_gmx_rgmii_speed,
133 1.1 hikaru .port_ops_timing = octeon_gmx_rgmii_timing,
134 1.1 hikaru .port_ops_set_mac_addr = octeon_gmx_rgmii_set_mac_addr,
135 1.1 hikaru .port_ops_set_filter = octeon_gmx_rgmii_set_filter
136 1.1 hikaru };
137 1.1 hikaru
138 1.1 hikaru struct octeon_gmx_port_ops octeon_gmx_port_ops_rgmii = {
139 1.1 hikaru .port_ops_enable = octeon_gmx_rgmii_enable,
140 1.1 hikaru .port_ops_speed = octeon_gmx_rgmii_speed,
141 1.1 hikaru .port_ops_timing = octeon_gmx_rgmii_timing,
142 1.1 hikaru .port_ops_set_mac_addr = octeon_gmx_rgmii_set_mac_addr,
143 1.1 hikaru .port_ops_set_filter = octeon_gmx_rgmii_set_filter
144 1.1 hikaru };
145 1.1 hikaru
146 1.1 hikaru struct octeon_gmx_port_ops octeon_gmx_port_ops_spi42 = {
147 1.1 hikaru /* XXX not implemented */
148 1.1 hikaru };
149 1.1 hikaru
150 1.1 hikaru struct octeon_gmx_port_ops *octeon_gmx_port_ops[] = {
151 1.1 hikaru [GMX_MII_PORT] = &octeon_gmx_port_ops_mii,
152 1.1 hikaru [GMX_GMII_PORT] = &octeon_gmx_port_ops_gmii,
153 1.1 hikaru [GMX_RGMII_PORT] = &octeon_gmx_port_ops_rgmii,
154 1.1 hikaru [GMX_SPI42_PORT] = &octeon_gmx_port_ops_spi42
155 1.1 hikaru };
156 1.1 hikaru
157 1.1 hikaru #ifdef OCTEON_ETH_DEBUG
158 1.1 hikaru static void *octeon_gmx_intr_drop_ih;
159 1.1 hikaru struct evcnt octeon_gmx_intr_drop_evcnt =
160 1.1 hikaru EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "octeon",
161 1.1 hikaru "gmx drop intr");
162 1.1 hikaru struct evcnt octeon_gmx_intr_evcnt =
163 1.1 hikaru EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "octeon",
164 1.1 hikaru "gmx intr");
165 1.1 hikaru EVCNT_ATTACH_STATIC(octeon_gmx_intr_drop_evcnt);
166 1.1 hikaru EVCNT_ATTACH_STATIC(octeon_gmx_intr_evcnt);
167 1.1 hikaru
168 1.1 hikaru struct octeon_gmx_port_softc *__octeon_gmx_port_softc[3/* XXX */];
169 1.1 hikaru #endif
170 1.1 hikaru
171 1.1 hikaru CFATTACH_DECL_NEW(octeon_gmx, sizeof(struct octeon_gmx_softc),
172 1.1 hikaru octeon_gmx_match, octeon_gmx_attach, NULL, NULL);
173 1.1 hikaru
174 1.1 hikaru static int
175 1.1 hikaru octeon_gmx_match(device_t parent, struct cfdata *cf, void *aux)
176 1.1 hikaru {
177 1.1 hikaru struct iobus_attach_args *aa = aux;
178 1.1 hikaru
179 1.1 hikaru if (strcmp(cf->cf_name, aa->aa_name) != 0)
180 1.1 hikaru return 0;
181 1.1 hikaru if (cf->cf_unit != aa->aa_unitno)
182 1.1 hikaru return 0;
183 1.1 hikaru return 1;
184 1.1 hikaru }
185 1.1 hikaru
186 1.1 hikaru static void
187 1.1 hikaru octeon_gmx_attach(device_t parent, device_t self, void *aux)
188 1.1 hikaru {
189 1.1 hikaru struct octeon_gmx_softc *sc = device_private(self);
190 1.1 hikaru struct iobus_attach_args *aa = aux;
191 1.1 hikaru struct octeon_gmx_attach_args gmx_aa;
192 1.1 hikaru int status;
193 1.1 hikaru int i;
194 1.1 hikaru struct octeon_gmx_port_softc *port_sc;
195 1.1 hikaru
196 1.1 hikaru sc->sc_dev = self;
197 1.1 hikaru sc->sc_regt = aa->aa_bust;
198 1.1 hikaru sc->sc_unitno = aa->aa_unitno;
199 1.1 hikaru
200 1.1 hikaru aprint_normal("\n");
201 1.1 hikaru
202 1.1 hikaru status = bus_space_map(sc->sc_regt, aa->aa_unit->addr,
203 1.1 hikaru GMX0_BASE_IF_SIZE, 0, &sc->sc_regh);
204 1.1 hikaru if (status != 0)
205 1.1 hikaru panic(": can't map register");
206 1.1 hikaru
207 1.1 hikaru octeon_gmx_init(sc);
208 1.1 hikaru
209 1.1 hikaru sc->sc_ports = malloc(sizeof(*sc->sc_ports) * sc->sc_nports, M_DEVBUF,
210 1.1 hikaru M_NOWAIT | M_ZERO);
211 1.1 hikaru
212 1.1 hikaru for (i = 0; i < sc->sc_nports; i++) {
213 1.1 hikaru port_sc = &sc->sc_ports[i];
214 1.1 hikaru port_sc->sc_port_gmx = sc;
215 1.1 hikaru port_sc->sc_port_no = i;
216 1.1 hikaru port_sc->sc_port_type = sc->sc_port_types[i];
217 1.1 hikaru port_sc->sc_port_ops = octeon_gmx_port_ops[port_sc->sc_port_type];
218 1.1 hikaru status = bus_space_map(sc->sc_regt,
219 1.1 hikaru aa->aa_unit->addr + GMX0_BASE_PORT_SIZE * i,
220 1.1 hikaru GMX0_BASE_PORT_SIZE, 0, &port_sc->sc_port_regh);
221 1.1 hikaru if (status != 0)
222 1.1 hikaru panic(": can't map port register");
223 1.1 hikaru
224 1.1 hikaru (void)memset(&gmx_aa, 0, sizeof(gmx_aa));
225 1.1 hikaru gmx_aa.ga_regt = aa->aa_bust;
226 1.1 hikaru gmx_aa.ga_addr = aa->aa_unit->addr;
227 1.1 hikaru gmx_aa.ga_name = "cnmac";
228 1.1 hikaru gmx_aa.ga_portno = i;
229 1.1 hikaru gmx_aa.ga_port_type = sc->sc_port_types[i];
230 1.1 hikaru gmx_aa.ga_gmx = sc;
231 1.1 hikaru gmx_aa.ga_gmx_port = port_sc;
232 1.1 hikaru config_found_sm_loc(self, "octeon_gmx", NULL, &gmx_aa,
233 1.1 hikaru octeon_gmx_print, octeon_gmx_submatch);
234 1.1 hikaru
235 1.1 hikaru #ifdef OCTEON_ETH_DEBUG
236 1.1 hikaru __octeon_gmx_port_softc[i] = port_sc;
237 1.1 hikaru #endif
238 1.1 hikaru }
239 1.1 hikaru
240 1.1 hikaru #ifdef OCTEON_ETH_DEBUG
241 1.1 hikaru octeon_gmx_intr_evcnt_attach(sc);
242 1.1 hikaru if (octeon_gmx_intr_drop_ih == NULL)
243 1.1 hikaru octeon_gmx_intr_drop_ih = octeon_intr_establish(
244 1.2 matt ffs64(CIU_INTX_SUM0_GMX_DRP) - 1, IPL_NET,
245 1.1 hikaru octeon_gmx_intr_drop, NULL);
246 1.1 hikaru #endif
247 1.1 hikaru }
248 1.1 hikaru
249 1.1 hikaru static int
250 1.1 hikaru octeon_gmx_print(void *aux, const char *pnp)
251 1.1 hikaru {
252 1.1 hikaru struct octeon_gmx_attach_args *ga = aux;
253 1.1 hikaru static const char *types[] = {
254 1.1 hikaru [GMX_MII_PORT] = "MII",
255 1.1 hikaru [GMX_GMII_PORT] = "GMII",
256 1.1 hikaru [GMX_RGMII_PORT] = "RGMII"
257 1.1 hikaru };
258 1.1 hikaru
259 1.1 hikaru #if DEBUG
260 1.1 hikaru if (pnp)
261 1.1 hikaru aprint_normal("%s at %s\n", ga->ga_name, pnp);
262 1.1 hikaru #endif
263 1.1 hikaru
264 1.1 hikaru aprint_normal(": address=0x%016" PRIx64 ": %s\n", ga->ga_addr,
265 1.1 hikaru types[ga->ga_port_type]);
266 1.1 hikaru
267 1.1 hikaru return UNCONF;
268 1.1 hikaru }
269 1.1 hikaru
270 1.1 hikaru static int
271 1.1 hikaru octeon_gmx_submatch(device_t parent, struct cfdata *cf,
272 1.1 hikaru const int *ldesc, void *aux)
273 1.1 hikaru {
274 1.1 hikaru return config_match(parent, cf, aux);
275 1.1 hikaru }
276 1.1 hikaru
277 1.1 hikaru static int
278 1.1 hikaru octeon_gmx_init(struct octeon_gmx_softc *sc)
279 1.1 hikaru {
280 1.1 hikaru int result = 0;
281 1.1 hikaru uint64_t inf_mode;
282 1.1 hikaru /* XXX */
283 1.1 hikaru const mips_prid_t cpu_id = mips_options.mips_cpu_id;
284 1.1 hikaru
285 1.1 hikaru inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh, GMX0_INF_MODE);
286 1.1 hikaru if ((inf_mode & INF_MODE_EN) == 0) {
287 1.1 hikaru aprint_normal("port are disable\n");
288 1.1 hikaru sc->sc_nports = 0;
289 1.1 hikaru return 1;
290 1.1 hikaru }
291 1.1 hikaru
292 1.1 hikaru if (MIPS_PRID_CID(cpu_id) != MIPS_PRID_CID_CAVIUM)
293 1.1 hikaru return 1;
294 1.1 hikaru
295 1.1 hikaru switch (MIPS_PRID_IMPL(cpu_id)) {
296 1.1 hikaru case MIPS_CN31XX:
297 1.1 hikaru /*
298 1.1 hikaru * Packet Interface Configuration
299 1.1 hikaru * GMX Registers, Interface Mode Register, GMX0_INF_MODE
300 1.1 hikaru */
301 1.1 hikaru if ((inf_mode & INF_MODE_TYPE) == 0) {
302 1.1 hikaru /* all three ports configured as RGMII */
303 1.1 hikaru sc->sc_nports = 3;
304 1.1 hikaru sc->sc_port_types[0] = GMX_RGMII_PORT;
305 1.1 hikaru sc->sc_port_types[1] = GMX_RGMII_PORT;
306 1.1 hikaru sc->sc_port_types[2] = GMX_RGMII_PORT;
307 1.1 hikaru } else {
308 1.1 hikaru /* port 0: RGMII, port 1: GMII, port 2: disabled */
309 1.1 hikaru sc->sc_nports = 2;
310 1.1 hikaru sc->sc_port_types[0] = GMX_RGMII_PORT;
311 1.1 hikaru sc->sc_port_types[1] = GMX_GMII_PORT;
312 1.1 hikaru }
313 1.1 hikaru break;
314 1.1 hikaru case MIPS_CN30XX:
315 1.1 hikaru case MIPS_CN50XX:
316 1.1 hikaru /*
317 1.1 hikaru * Packet Interface Configuration
318 1.1 hikaru * GMX Registers, Interface Mode Register, GMX0_INF_MODE
319 1.1 hikaru */
320 1.1 hikaru if ((inf_mode & INF_MODE_P0MII) == 0)
321 1.1 hikaru sc->sc_port_types[0] = GMX_RGMII_PORT;
322 1.1 hikaru else
323 1.1 hikaru sc->sc_port_types[0] = GMX_MII_PORT;
324 1.1 hikaru if ((inf_mode & INF_MODE_TYPE) == 0) {
325 1.1 hikaru /* port 1 and 2 are configred as RGMII ports */
326 1.1 hikaru sc->sc_nports = 3;
327 1.1 hikaru sc->sc_port_types[1] = GMX_RGMII_PORT;
328 1.1 hikaru sc->sc_port_types[2] = GMX_RGMII_PORT;
329 1.1 hikaru } else {
330 1.1 hikaru /* port 1: GMII/MII, port 2: disabled */
331 1.1 hikaru /* GMII or MII port is slected by GMX_PRT1_CFG[SPEED] */
332 1.1 hikaru sc->sc_nports = 2;
333 1.1 hikaru sc->sc_port_types[1] = GMX_GMII_PORT;
334 1.1 hikaru }
335 1.1 hikaru #if 0 /* XXX XXX XXX */
336 1.1 hikaru /* port 2 is in CN3010/CN5010 only */
337 1.1 hikaru if ((octeon_model(id) != OCTEON_MODEL_CN3010) &&
338 1.1 hikaru (octeon_model(id) != OCTEON_MODEL_CN5010))
339 1.1 hikaru if (sc->sc_nports == 3)
340 1.1 hikaru sc->sc_nports = 2;
341 1.1 hikaru #endif
342 1.1 hikaru break;
343 1.1 hikaru default:
344 1.1 hikaru aprint_normal("unsupported octeon model: 0x%x\n", cpu_id);
345 1.1 hikaru sc->sc_nports = 0;
346 1.1 hikaru result = 1;
347 1.1 hikaru break;
348 1.1 hikaru }
349 1.1 hikaru
350 1.1 hikaru return result;
351 1.1 hikaru }
352 1.1 hikaru
353 1.1 hikaru /* XXX RGMII specific */
354 1.1 hikaru int
355 1.1 hikaru octeon_gmx_link_enable(struct octeon_gmx_port_softc *sc, int enable)
356 1.1 hikaru {
357 1.1 hikaru uint64_t prt_cfg;
358 1.1 hikaru
359 1.1 hikaru octeon_gmx_tx_int_enable(sc, enable);
360 1.1 hikaru octeon_gmx_rx_int_enable(sc, enable);
361 1.1 hikaru
362 1.1 hikaru prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
363 1.1 hikaru if (enable) {
364 1.1 hikaru if (octeon_gmx_link_status(sc)) {
365 1.1 hikaru SET(prt_cfg, PRTN_CFG_EN);
366 1.1 hikaru }
367 1.1 hikaru } else {
368 1.1 hikaru CLR(prt_cfg, PRTN_CFG_EN);
369 1.1 hikaru }
370 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
371 1.1 hikaru /* software should read back to flush the write operation. */
372 1.1 hikaru (void)_GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
373 1.1 hikaru
374 1.1 hikaru return 0;
375 1.1 hikaru }
376 1.1 hikaru
377 1.1 hikaru /* XXX RGMII specific */
378 1.1 hikaru int
379 1.1 hikaru octeon_gmx_stats_init(struct octeon_gmx_port_softc *sc)
380 1.1 hikaru {
381 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS, 0x0ULL);
382 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_DRP, 0x0ULL);
383 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_BAD, 0x0ULL);
384 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_STAT0, 0x0ULL);
385 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_STAT1, 0x0ULL);
386 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_STAT3, 0x0ULL);
387 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_STAT9, 0x0ULL);
388 1.1 hikaru
389 1.1 hikaru return 0;
390 1.1 hikaru }
391 1.1 hikaru
392 1.1 hikaru int
393 1.1 hikaru octeon_gmx_tx_stats_rd_clr(struct octeon_gmx_port_softc *sc, int enable)
394 1.1 hikaru {
395 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_STATS_CTL, enable ? 0x1ULL : 0x0ULL);
396 1.1 hikaru return 0;
397 1.1 hikaru }
398 1.1 hikaru
399 1.1 hikaru int
400 1.1 hikaru octeon_gmx_rx_stats_rd_clr(struct octeon_gmx_port_softc *sc, int enable)
401 1.1 hikaru {
402 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_STATS_CTL, enable ? 0x1ULL : 0x0ULL);
403 1.1 hikaru return 0;
404 1.1 hikaru }
405 1.1 hikaru
406 1.1 hikaru void
407 1.1 hikaru octeon_gmx_rx_stats_dec_bad(struct octeon_gmx_port_softc *sc)
408 1.1 hikaru {
409 1.1 hikaru uint64_t tmp;
410 1.1 hikaru
411 1.1 hikaru tmp = _GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_BAD);
412 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_BAD, tmp - 1);
413 1.1 hikaru }
414 1.1 hikaru
415 1.1 hikaru static int
416 1.1 hikaru octeon_gmx_tx_ovr_bp_enable(struct octeon_gmx_port_softc *sc, int enable)
417 1.1 hikaru {
418 1.1 hikaru uint64_t ovr_bp;
419 1.1 hikaru
420 1.1 hikaru ovr_bp = _GMX_RD8(sc, GMX0_TX_OVR_BP);
421 1.1 hikaru if (enable) {
422 1.1 hikaru CLR(ovr_bp, (1 << sc->sc_port_no) << TX_OVR_BP_EN_SHIFT);
423 1.1 hikaru SET(ovr_bp, (1 << sc->sc_port_no) << TX_OVR_BP_BP_SHIFT);
424 1.1 hikaru /* XXX really??? */
425 1.1 hikaru SET(ovr_bp, (1 << sc->sc_port_no) << TX_OVR_BP_IGN_FULL_SHIFT);
426 1.1 hikaru } else {
427 1.1 hikaru SET(ovr_bp, (1 << sc->sc_port_no) << TX_OVR_BP_EN_SHIFT);
428 1.1 hikaru CLR(ovr_bp, (1 << sc->sc_port_no) << TX_OVR_BP_BP_SHIFT);
429 1.1 hikaru /* XXX really??? */
430 1.1 hikaru SET(ovr_bp, (1 << sc->sc_port_no) << TX_OVR_BP_IGN_FULL_SHIFT);
431 1.1 hikaru }
432 1.1 hikaru _GMX_WR8(sc, GMX0_TX_OVR_BP, ovr_bp);
433 1.1 hikaru return 0;
434 1.1 hikaru }
435 1.1 hikaru
436 1.1 hikaru static int
437 1.1 hikaru octeon_gmx_rx_pause_enable(struct octeon_gmx_port_softc *sc, int enable)
438 1.1 hikaru {
439 1.1 hikaru if (enable) {
440 1.1 hikaru octeon_gmx_rx_frm_ctl_enable(sc, RXN_FRM_CTL_CTL_BCK);
441 1.1 hikaru } else {
442 1.1 hikaru octeon_gmx_rx_frm_ctl_disable(sc, RXN_FRM_CTL_CTL_BCK);
443 1.1 hikaru }
444 1.1 hikaru
445 1.1 hikaru return 0;
446 1.1 hikaru }
447 1.1 hikaru
448 1.1 hikaru void
449 1.1 hikaru octeon_gmx_tx_int_enable(struct octeon_gmx_port_softc *sc, int enable)
450 1.1 hikaru {
451 1.1 hikaru uint64_t tx_int_xxx = 0;
452 1.1 hikaru
453 1.1 hikaru SET(tx_int_xxx,
454 1.1 hikaru TX_INT_REG_LATE_COL |
455 1.1 hikaru TX_INT_REG_XSDEF |
456 1.1 hikaru TX_INT_REG_XSCOL |
457 1.1 hikaru TX_INT_REG_UNDFLW |
458 1.1 hikaru TX_INT_REG_PKO_NXA);
459 1.1 hikaru _GMX_WR8(sc, GMX0_TX_INT_REG, tx_int_xxx);
460 1.1 hikaru _GMX_WR8(sc, GMX0_TX_INT_EN, enable ? tx_int_xxx : 0);
461 1.1 hikaru }
462 1.1 hikaru
463 1.1 hikaru void
464 1.1 hikaru octeon_gmx_rx_int_enable(struct octeon_gmx_port_softc *sc, int enable)
465 1.1 hikaru {
466 1.1 hikaru uint64_t rx_int_xxx = 0;
467 1.1 hikaru
468 1.1 hikaru SET(rx_int_xxx, 0 |
469 1.1 hikaru RXN_INT_REG_PHY_DUPX |
470 1.1 hikaru RXN_INT_REG_PHY_SPD |
471 1.1 hikaru RXN_INT_REG_PHY_LINK |
472 1.1 hikaru RXN_INT_REG_IFGERR |
473 1.1 hikaru RXN_INT_REG_COLDET |
474 1.1 hikaru RXN_INT_REG_FALERR |
475 1.1 hikaru RXN_INT_REG_RSVERR |
476 1.1 hikaru RXN_INT_REG_PCTERR |
477 1.1 hikaru RXN_INT_REG_OVRERR |
478 1.1 hikaru RXN_INT_REG_NIBERR |
479 1.1 hikaru RXN_INT_REG_SKPERR |
480 1.1 hikaru RXN_INT_REG_RCVERR |
481 1.1 hikaru RXN_INT_REG_LENERR |
482 1.1 hikaru RXN_INT_REG_ALNERR |
483 1.1 hikaru RXN_INT_REG_FCSERR |
484 1.1 hikaru RXN_INT_REG_JABBER |
485 1.1 hikaru RXN_INT_REG_MAXERR |
486 1.1 hikaru RXN_INT_REG_CAREXT |
487 1.1 hikaru RXN_INT_REG_MINERR);
488 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_INT_REG, rx_int_xxx);
489 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_INT_EN, enable ? rx_int_xxx : 0);
490 1.1 hikaru }
491 1.1 hikaru
492 1.1 hikaru int
493 1.1 hikaru octeon_gmx_rx_frm_ctl_enable(struct octeon_gmx_port_softc *sc,
494 1.1 hikaru uint64_t rx_frm_ctl)
495 1.1 hikaru {
496 1.1 hikaru /*
497 1.1 hikaru * XXX Jumbo-frame Workarounds
498 1.1 hikaru * Current implementation of cnmac is required to
499 1.1 hikaru * configure GMX0_RX0_JABBER[CNT] as follows:
500 1.1 hikaru * RX0_FRM_MAX(1536) <= GMX0_RX0_JABBER <= 1536(0x600)
501 1.1 hikaru */
502 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_JABBER, GMX_FRM_MAX_SIZ);
503 1.1 hikaru
504 1.1 hikaru return octeon_gmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 1);
505 1.1 hikaru }
506 1.1 hikaru
507 1.1 hikaru int
508 1.1 hikaru octeon_gmx_rx_frm_ctl_disable(struct octeon_gmx_port_softc *sc,
509 1.1 hikaru uint64_t rx_frm_ctl)
510 1.1 hikaru {
511 1.1 hikaru return octeon_gmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 0);
512 1.1 hikaru }
513 1.1 hikaru
514 1.1 hikaru static int
515 1.1 hikaru octeon_gmx_rx_frm_ctl_xable(struct octeon_gmx_port_softc *sc,
516 1.1 hikaru uint64_t rx_frm_ctl, int enable)
517 1.1 hikaru {
518 1.1 hikaru uint64_t tmp;
519 1.1 hikaru
520 1.1 hikaru tmp = _GMX_PORT_RD8(sc, GMX0_RX0_FRM_CTL);
521 1.1 hikaru if (enable)
522 1.1 hikaru SET(tmp, rx_frm_ctl);
523 1.1 hikaru else
524 1.1 hikaru CLR(tmp, rx_frm_ctl);
525 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_FRM_CTL, tmp);
526 1.1 hikaru
527 1.1 hikaru return 0;
528 1.1 hikaru }
529 1.1 hikaru
530 1.1 hikaru int
531 1.1 hikaru octeon_gmx_tx_thresh(struct octeon_gmx_port_softc *sc, int cnt)
532 1.1 hikaru {
533 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_THRESH, cnt);
534 1.1 hikaru return 0;
535 1.1 hikaru }
536 1.1 hikaru
537 1.1 hikaru int
538 1.1 hikaru octeon_gmx_set_mac_addr(struct octeon_gmx_port_softc *sc, uint8_t *addr)
539 1.1 hikaru {
540 1.1 hikaru uint64_t mac = 0;
541 1.1 hikaru
542 1.1 hikaru ADDR2UINT64(mac, addr);
543 1.1 hikaru (*sc->sc_port_ops->port_ops_set_mac_addr)(sc, addr, mac);
544 1.1 hikaru return 0;
545 1.1 hikaru }
546 1.1 hikaru
547 1.1 hikaru int
548 1.1 hikaru octeon_gmx_set_filter(struct octeon_gmx_port_softc *sc)
549 1.1 hikaru {
550 1.1 hikaru (*sc->sc_port_ops->port_ops_set_filter)(sc);
551 1.1 hikaru return 0;
552 1.1 hikaru }
553 1.1 hikaru
554 1.1 hikaru int
555 1.1 hikaru octeon_gmx_port_enable(struct octeon_gmx_port_softc *sc, int enable)
556 1.1 hikaru {
557 1.1 hikaru (*sc->sc_port_ops->port_ops_enable)(sc, enable);
558 1.1 hikaru return 0;
559 1.1 hikaru }
560 1.1 hikaru
561 1.1 hikaru int
562 1.1 hikaru octeon_gmx_reset_speed(struct octeon_gmx_port_softc *sc)
563 1.1 hikaru {
564 1.1 hikaru struct ifnet *ifp = &sc->sc_port_ec->ec_if;
565 1.1 hikaru if (ISSET(sc->sc_port_mii->mii_flags, MIIF_DOINGAUTO)) {
566 1.1 hikaru log(LOG_WARNING,
567 1.1 hikaru "%s: autonegotiation has not been completed yet\n",
568 1.1 hikaru ifp->if_xname);
569 1.1 hikaru return 1;
570 1.1 hikaru }
571 1.1 hikaru (*sc->sc_port_ops->port_ops_speed)(sc);
572 1.1 hikaru return 0;
573 1.1 hikaru }
574 1.1 hikaru
575 1.1 hikaru int
576 1.1 hikaru octeon_gmx_reset_timing(struct octeon_gmx_port_softc *sc)
577 1.1 hikaru {
578 1.1 hikaru (*sc->sc_port_ops->port_ops_timing)(sc);
579 1.1 hikaru return 0;
580 1.1 hikaru }
581 1.1 hikaru
582 1.1 hikaru int
583 1.1 hikaru octeon_gmx_reset_flowctl(struct octeon_gmx_port_softc *sc)
584 1.1 hikaru {
585 1.1 hikaru struct ifmedia_entry *ife = sc->sc_port_mii->mii_media.ifm_cur;
586 1.1 hikaru
587 1.1 hikaru /*
588 1.1 hikaru * Get flow control negotiation result.
589 1.1 hikaru */
590 1.1 hikaru if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO &&
591 1.1 hikaru (sc->sc_port_mii->mii_media_active & IFM_ETH_FMASK) !=
592 1.1 hikaru sc->sc_port_flowflags) {
593 1.1 hikaru sc->sc_port_flowflags =
594 1.1 hikaru sc->sc_port_mii->mii_media_active & IFM_ETH_FMASK;
595 1.1 hikaru sc->sc_port_mii->mii_media_active &= ~IFM_ETH_FMASK;
596 1.1 hikaru }
597 1.1 hikaru
598 1.1 hikaru /*
599 1.1 hikaru * 802.3x Flow Control Capabilities
600 1.1 hikaru */
601 1.1 hikaru if (sc->sc_port_flowflags & IFM_ETH_TXPAUSE) {
602 1.1 hikaru octeon_gmx_tx_ovr_bp_enable(sc, 1);
603 1.1 hikaru } else {
604 1.1 hikaru octeon_gmx_tx_ovr_bp_enable(sc, 0);
605 1.1 hikaru }
606 1.1 hikaru if (sc->sc_port_flowflags & IFM_ETH_RXPAUSE) {
607 1.1 hikaru octeon_gmx_rx_pause_enable(sc, 1);
608 1.1 hikaru } else {
609 1.1 hikaru octeon_gmx_rx_pause_enable(sc, 0);
610 1.1 hikaru }
611 1.1 hikaru
612 1.1 hikaru return 0;
613 1.1 hikaru }
614 1.1 hikaru
615 1.1 hikaru static int
616 1.1 hikaru octeon_gmx_rgmii_enable(struct octeon_gmx_port_softc *sc, int enable)
617 1.1 hikaru {
618 1.1 hikaru uint64_t mode;
619 1.1 hikaru
620 1.1 hikaru /* XXX XXX XXX */
621 1.1 hikaru mode = _GMX_RD8(sc, GMX0_INF_MODE);
622 1.1 hikaru if (ISSET(mode, INF_MODE_EN)) {
623 1.1 hikaru octeon_asx_enable(sc->sc_port_asx, 1);
624 1.1 hikaru }
625 1.1 hikaru /* XXX XXX XXX */
626 1.1 hikaru return 0;
627 1.1 hikaru }
628 1.1 hikaru
629 1.1 hikaru static int
630 1.1 hikaru octeon_gmx_rgmii_speed(struct octeon_gmx_port_softc *sc)
631 1.1 hikaru {
632 1.1 hikaru struct ifnet *ifp = &sc->sc_port_ec->ec_if;
633 1.1 hikaru uint64_t newlink;
634 1.1 hikaru int baudrate;
635 1.1 hikaru
636 1.1 hikaru /* XXX XXX XXX */
637 1.1 hikaru octeon_gmx_link_enable(sc, 1);
638 1.1 hikaru
639 1.1 hikaru octeon_gmx_rgmii_speed_newlink(sc, &newlink);
640 1.1 hikaru if (sc->sc_link == newlink) {
641 1.1 hikaru return 0;
642 1.1 hikaru }
643 1.1 hikaru sc->sc_link = newlink;
644 1.1 hikaru
645 1.1 hikaru switch (sc->sc_link & RXN_RX_INBND_SPEED) {
646 1.1 hikaru case RXN_RX_INBND_SPEED_2_5:
647 1.1 hikaru baudrate = IF_Mbps(10);
648 1.1 hikaru break;
649 1.1 hikaru case RXN_RX_INBND_SPEED_25:
650 1.1 hikaru baudrate = IF_Mbps(100);
651 1.1 hikaru break;
652 1.1 hikaru case RXN_RX_INBND_SPEED_125:
653 1.1 hikaru baudrate = IF_Mbps(1000);
654 1.1 hikaru break;
655 1.1 hikaru default:
656 1.1 hikaru baudrate = 0/* XXX */;
657 1.3 maxv panic("unable to get baudrate");
658 1.1 hikaru break;
659 1.1 hikaru }
660 1.1 hikaru ifp->if_baudrate = baudrate;
661 1.1 hikaru
662 1.1 hikaru /* XXX XXX XXX */
663 1.1 hikaru
664 1.1 hikaru octeon_gmx_link_enable(sc, 0);
665 1.1 hikaru
666 1.1 hikaru /*
667 1.1 hikaru * wait a max_packet_time
668 1.1 hikaru * max_packet_time(us) = (max_packet_size(bytes) * 8) / link_speed(Mbps)
669 1.1 hikaru */
670 1.1 hikaru delay((GMX_FRM_MAX_SIZ * 8) / (baudrate / 1000000));
671 1.1 hikaru
672 1.1 hikaru octeon_gmx_rgmii_speed_speed(sc);
673 1.1 hikaru
674 1.1 hikaru octeon_gmx_link_enable(sc, 1);
675 1.1 hikaru octeon_asx_enable(sc->sc_port_asx, 1);
676 1.1 hikaru
677 1.1 hikaru return 0;
678 1.1 hikaru }
679 1.1 hikaru
680 1.1 hikaru static int
681 1.1 hikaru octeon_gmx_rgmii_speed_newlink(struct octeon_gmx_port_softc *sc,
682 1.1 hikaru uint64_t *rnewlink)
683 1.1 hikaru {
684 1.1 hikaru uint64_t newlink = 0;
685 1.1 hikaru
686 1.1 hikaru if (sc->sc_quirks & OCTEON_ETH_QUIRKS_NO_RX_INBND) {
687 1.1 hikaru newlink = 0;
688 1.1 hikaru switch (IFM_SUBTYPE(sc->sc_port_mii->mii_media_active)) {
689 1.1 hikaru default:
690 1.1 hikaru SET(newlink, RXN_RX_INBND_SPEED_125);
691 1.1 hikaru break;
692 1.1 hikaru case IFM_100_TX:
693 1.1 hikaru SET(newlink, RXN_RX_INBND_SPEED_25);
694 1.1 hikaru break;
695 1.1 hikaru case IFM_10_T:
696 1.1 hikaru SET(newlink, RXN_RX_INBND_SPEED_2_5);
697 1.1 hikaru break;
698 1.1 hikaru }
699 1.1 hikaru SET(newlink,
700 1.1 hikaru ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX) ?
701 1.1 hikaru RXN_RX_INBND_DUPLEX : 0);
702 1.1 hikaru SET(newlink,
703 1.1 hikaru ISSET(sc->sc_port_mii->mii_media_status, IFM_ACTIVE) ?
704 1.1 hikaru RXN_RX_INBND_STATUS : 0);
705 1.1 hikaru } else {
706 1.1 hikaru newlink = _GMX_PORT_RD8(sc, GMX0_RX0_RX_INBND);
707 1.1 hikaru }
708 1.1 hikaru
709 1.1 hikaru *rnewlink = newlink;
710 1.1 hikaru return 0;
711 1.1 hikaru }
712 1.1 hikaru
713 1.1 hikaru static int
714 1.1 hikaru octeon_gmx_rgmii_speed_speed(struct octeon_gmx_port_softc *sc)
715 1.1 hikaru {
716 1.1 hikaru uint64_t prt_cfg;
717 1.1 hikaru uint64_t tx_clk, tx_slot, tx_burst;
718 1.1 hikaru
719 1.1 hikaru prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
720 1.1 hikaru
721 1.1 hikaru switch (sc->sc_link & RXN_RX_INBND_SPEED) {
722 1.1 hikaru case RXN_RX_INBND_SPEED_2_5:
723 1.1 hikaru /* 10Mbps */
724 1.1 hikaru /*
725 1.1 hikaru * GMX Tx Clock Generation Registers
726 1.1 hikaru * 8ns x 50 = 400ns (2.5MHz TXC clock)
727 1.1 hikaru */
728 1.1 hikaru tx_clk = 50;
729 1.1 hikaru /*
730 1.1 hikaru * TX Slottime Counter Registers
731 1.1 hikaru * 10/100Mbps: set SLOT to 0x40
732 1.1 hikaru */
733 1.1 hikaru tx_slot = 0x40;
734 1.1 hikaru /*
735 1.1 hikaru * TX Burst-Counter Registers
736 1.1 hikaru * 10/100Mbps: set BURST to 0x0
737 1.1 hikaru */
738 1.1 hikaru tx_burst = 0;
739 1.1 hikaru /*
740 1.1 hikaru * GMX Tx Port Configuration Registers
741 1.1 hikaru * Slot time for half-duplex operation
742 1.1 hikaru * 0 = 512 bittimes (10/100Mbps operation)
743 1.1 hikaru */
744 1.1 hikaru CLR(prt_cfg, PRTN_CFG_SLOTTIME);
745 1.1 hikaru /*
746 1.1 hikaru * GMX Port Configuration Registers
747 1.1 hikaru * Link speed
748 1.1 hikaru * 0 = 10/100Mbps operation
749 1.1 hikaru * in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
750 1.1 hikaru */
751 1.1 hikaru CLR(prt_cfg, PRTN_CFG_SPEED);
752 1.1 hikaru break;
753 1.1 hikaru case RXN_RX_INBND_SPEED_25:
754 1.1 hikaru /* 100Mbps */
755 1.1 hikaru /*
756 1.1 hikaru * GMX Tx Clock Generation Registers
757 1.1 hikaru * 8ns x 5 = 40ns (25.0MHz TXC clock)
758 1.1 hikaru */
759 1.1 hikaru tx_clk = 5;
760 1.1 hikaru /*
761 1.1 hikaru * TX Slottime Counter Registers
762 1.1 hikaru * 10/100Mbps: set SLOT to 0x40
763 1.1 hikaru */
764 1.1 hikaru tx_slot = 0x40;
765 1.1 hikaru /*
766 1.1 hikaru * TX Burst-Counter Registers
767 1.1 hikaru * 10/100Mbps: set BURST to 0x0
768 1.1 hikaru */
769 1.1 hikaru tx_burst = 0;
770 1.1 hikaru /*
771 1.1 hikaru * GMX Tx Port Configuration Registers
772 1.1 hikaru * Slot time for half-duplex operation
773 1.1 hikaru * 0 = 512 bittimes (10/100Mbps operation)
774 1.1 hikaru */
775 1.1 hikaru CLR(prt_cfg, PRTN_CFG_SLOTTIME);
776 1.1 hikaru /*
777 1.1 hikaru * GMX Port Configuration Registers
778 1.1 hikaru * Link speed
779 1.1 hikaru * 0 = 10/100Mbps operation
780 1.1 hikaru * in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
781 1.1 hikaru */
782 1.1 hikaru CLR(prt_cfg, PRTN_CFG_SPEED);
783 1.1 hikaru break;
784 1.1 hikaru case RXN_RX_INBND_SPEED_125:
785 1.1 hikaru /* 1000Mbps */
786 1.1 hikaru /*
787 1.1 hikaru * GMX Tx Clock Generation Registers
788 1.1 hikaru * 8ns x 1 = 8ns (125.0MHz TXC clock)
789 1.1 hikaru */
790 1.1 hikaru tx_clk = 1;
791 1.1 hikaru /*
792 1.1 hikaru * TX Slottime Counter Registers
793 1.1 hikaru * > 1000Mbps: set SLOT to 0x200
794 1.1 hikaru */
795 1.1 hikaru tx_slot = 0x200;
796 1.1 hikaru /*
797 1.1 hikaru * "TX Burst-Counter Registers
798 1.1 hikaru * > 1000Mbps: set BURST to 0x2000
799 1.1 hikaru */
800 1.1 hikaru tx_burst = 0x2000;
801 1.1 hikaru /*
802 1.1 hikaru * GMX Tx Port Configuration Registers
803 1.1 hikaru * Slot time for half-duplex operation
804 1.1 hikaru * 1 = 4096 bittimes (1000Mbps operation)
805 1.1 hikaru */
806 1.1 hikaru SET(prt_cfg, PRTN_CFG_SLOTTIME);
807 1.1 hikaru /*
808 1.1 hikaru * GMX Port Configuration Registers
809 1.1 hikaru * Link speed
810 1.1 hikaru * 1 = 1000Mbps operation
811 1.1 hikaru */
812 1.1 hikaru SET(prt_cfg, PRTN_CFG_SPEED);
813 1.1 hikaru break;
814 1.1 hikaru default:
815 1.1 hikaru /* NOT REACHED! */
816 1.1 hikaru /* Following configuration is default value of system.
817 1.1 hikaru */
818 1.1 hikaru tx_clk = 1;
819 1.1 hikaru tx_slot = 0x200;
820 1.1 hikaru tx_burst = 0x2000;
821 1.1 hikaru SET(prt_cfg, PRTN_CFG_SLOTTIME);
822 1.1 hikaru SET(prt_cfg, PRTN_CFG_SPEED);
823 1.1 hikaru break;
824 1.1 hikaru }
825 1.1 hikaru
826 1.1 hikaru /* Setup Duplex mode(negotiated) */
827 1.1 hikaru /*
828 1.1 hikaru * GMX Port Configuration Registers
829 1.1 hikaru * Duplex mode: 0 = half-duplex mode, 1=full-duplex
830 1.1 hikaru */
831 1.1 hikaru if (ISSET(sc->sc_link, RXN_RX_INBND_DUPLEX)) {
832 1.1 hikaru /* Full-Duplex */
833 1.1 hikaru SET(prt_cfg, PRTN_CFG_DUPLEX);
834 1.1 hikaru } else {
835 1.1 hikaru /* Half-Duplex */
836 1.1 hikaru CLR(prt_cfg, PRTN_CFG_DUPLEX);
837 1.1 hikaru }
838 1.1 hikaru
839 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_CLK, tx_clk);
840 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot);
841 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst);
842 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
843 1.1 hikaru
844 1.1 hikaru return 0;
845 1.1 hikaru }
846 1.1 hikaru
847 1.1 hikaru static int
848 1.1 hikaru octeon_gmx_rgmii_timing(struct octeon_gmx_port_softc *sc)
849 1.1 hikaru {
850 1.1 hikaru prop_dictionary_t dict = device_properties(sc->sc_port_gmx->sc_dev);
851 1.1 hikaru prop_object_t clk;
852 1.1 hikaru int clk_tx_setting, clk_rx_setting;
853 1.1 hikaru uint64_t rx_frm_ctl;
854 1.1 hikaru
855 1.1 hikaru /* RGMII TX Threshold Registers
856 1.1 hikaru * Number of 16-byte ticks to accumulate in the TX FIFO before
857 1.1 hikaru * sending on the RGMII interface. This field should be large
858 1.1 hikaru * enough to prevent underflow on the RGMII interface and must
859 1.1 hikaru * never be set to less than 0x4. This register cannot exceed
860 1.1 hikaru * the TX FIFO depth of 0x40 words.
861 1.1 hikaru */
862 1.1 hikaru /* Default parameter of CN30XX */
863 1.1 hikaru octeon_gmx_tx_thresh(sc, 32);
864 1.1 hikaru
865 1.1 hikaru rx_frm_ctl = 0 |
866 1.1 hikaru /* RXN_FRM_CTL_NULL_DIS | (cn5xxx only) */
867 1.1 hikaru /* RXN_FRM_CTL_PRE_ALIGN | (cn5xxx only) */
868 1.1 hikaru /* RXN_FRM_CTL_PAD_LEN | (cn3xxx only) */
869 1.1 hikaru /* RXN_FRM_CTL_VLAN_LEN | (cn3xxx only) */
870 1.1 hikaru RXN_FRM_CTL_PRE_FREE |
871 1.1 hikaru RXN_FRM_CTL_CTL_SMAC |
872 1.1 hikaru RXN_FRM_CTL_CTL_MCST |
873 1.1 hikaru RXN_FRM_CTL_CTL_DRP |
874 1.1 hikaru RXN_FRM_CTL_PRE_STRP |
875 1.1 hikaru RXN_FRM_CTL_PRE_CHK;
876 1.1 hikaru if (!(sc->sc_quirks & OCTEON_ETH_QUIRKS_NO_PRE_ALIGN))
877 1.1 hikaru rx_frm_ctl |= RXN_FRM_CTL_PRE_ALIGN;
878 1.1 hikaru octeon_gmx_rx_frm_ctl_enable(sc, rx_frm_ctl);
879 1.1 hikaru
880 1.1 hikaru /* RGMII RX Clock-Delay Registers
881 1.1 hikaru * Delay setting to place n RXC (RGMII receive clock) delay line.
882 1.1 hikaru * The intrinsic delay can range from 50ps to 80ps per tap,
883 1.1 hikaru * which corresponds to skews of 1.25ns to 2.00ns at 25 taps(CSR+1).
884 1.1 hikaru * This is the best match for the RGMII specification which wants
885 1.1 hikaru * 1ns - 2.6ns of skew.
886 1.1 hikaru */
887 1.1 hikaru /* RGMII TX Clock-Delay Registers
888 1.1 hikaru * Delay setting to place n TXC (RGMII transmit clock) delay line.
889 1.1 hikaru */
890 1.1 hikaru clk = prop_dictionary_get(dict, "rgmii-tx");
891 1.1 hikaru KASSERT(clk != NULL);
892 1.1 hikaru clk_tx_setting = prop_number_integer_value(clk);
893 1.1 hikaru clk = prop_dictionary_get(dict, "rgmii-rx");
894 1.1 hikaru KASSERT(clk != NULL);
895 1.1 hikaru clk_rx_setting = prop_number_integer_value(clk);
896 1.1 hikaru
897 1.1 hikaru octeon_asx_clk_set(sc->sc_port_asx, clk_tx_setting, clk_rx_setting);
898 1.1 hikaru
899 1.1 hikaru return 0;
900 1.1 hikaru }
901 1.1 hikaru
902 1.1 hikaru static int
903 1.1 hikaru octeon_gmx_rgmii_set_mac_addr(struct octeon_gmx_port_softc *sc, uint8_t *addr,
904 1.1 hikaru uint64_t mac)
905 1.1 hikaru {
906 1.1 hikaru int i;
907 1.1 hikaru
908 1.1 hikaru octeon_gmx_link_enable(sc, 0);
909 1.1 hikaru
910 1.1 hikaru sc->sc_mac = mac;
911 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_SMAC0, mac);
912 1.1 hikaru for (i = 0; i < 6; i++)
913 1.1 hikaru _GMX_PORT_WR8(sc, octeon_gmx_rx_adr_cam_regs[i], addr[i]);
914 1.1 hikaru
915 1.1 hikaru octeon_gmx_link_enable(sc, 1);
916 1.1 hikaru
917 1.1 hikaru return 0;
918 1.1 hikaru }
919 1.1 hikaru
920 1.1 hikaru #define OCTEON_ETH_USE_GMX_CAM
921 1.1 hikaru
922 1.1 hikaru static int
923 1.1 hikaru octeon_gmx_rgmii_set_filter(struct octeon_gmx_port_softc *sc)
924 1.1 hikaru {
925 1.5 msaitoh struct ethercom *ec = sc->sc_port_ec;
926 1.4 msaitoh struct ifnet *ifp = &ec->ec_if;
927 1.1 hikaru #ifdef OCTEON_ETH_USE_GMX_CAM
928 1.1 hikaru struct ether_multi *enm;
929 1.1 hikaru struct ether_multistep step;
930 1.1 hikaru #endif
931 1.1 hikaru uint64_t ctl = 0;
932 1.1 hikaru int multi = 0;
933 1.1 hikaru /* XXX XXX XXX */
934 1.1 hikaru uint64_t cam_en = 0x01ULL;
935 1.1 hikaru /* XXX XXX XXX */
936 1.1 hikaru
937 1.1 hikaru octeon_gmx_link_enable(sc, 0);
938 1.1 hikaru
939 1.1 hikaru if (ISSET(ifp->if_flags, IFF_BROADCAST)) {
940 1.1 hikaru dprintf("accept broadcast\n");
941 1.1 hikaru SET(ctl, RXN_ADR_CTL_BCST);
942 1.1 hikaru }
943 1.1 hikaru if (ISSET(ifp->if_flags, IFF_PROMISC)) {
944 1.1 hikaru dprintf("promiscas(reject cam)\n");
945 1.1 hikaru CLR(ctl, RXN_ADR_CTL_CAM_MODE);
946 1.1 hikaru } else {
947 1.1 hikaru dprintf("not promiscas(accept cam)\n");
948 1.1 hikaru SET(ctl, RXN_ADR_CTL_CAM_MODE);
949 1.1 hikaru }
950 1.1 hikaru
951 1.1 hikaru #ifdef OCTEON_ETH_USE_GMX_CAM
952 1.1 hikaru /*
953 1.1 hikaru * Note first entry is self MAC address; other 7 entires are available
954 1.1 hikaru * for multicast addresses.
955 1.1 hikaru */
956 1.1 hikaru
957 1.4 msaitoh ETHER_LOCK(ec);
958 1.4 msaitoh ETHER_FIRST_MULTI(step, ec, enm);
959 1.1 hikaru while (enm != NULL) {
960 1.1 hikaru int i;
961 1.1 hikaru
962 1.1 hikaru dprintf("%d: lo(%02x:%02x:%02x:%02x:%02x:%02x) - "
963 1.1 hikaru "hi(%02x:%02x:%02x:%02x:%02x:%02x)\n",
964 1.1 hikaru multi + 1,
965 1.1 hikaru enm->enm_addrlo[0], enm->enm_addrlo[1],
966 1.1 hikaru enm->enm_addrlo[2], enm->enm_addrlo[3],
967 1.1 hikaru enm->enm_addrlo[4], enm->enm_addrlo[5],
968 1.1 hikaru enm->enm_addrhi[0], enm->enm_addrhi[1],
969 1.1 hikaru enm->enm_addrhi[2], enm->enm_addrhi[3],
970 1.1 hikaru enm->enm_addrhi[4], enm->enm_addrhi[5]);
971 1.1 hikaru if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
972 1.1 hikaru dprintf("all multicast\n");
973 1.1 hikaru SET(ifp->if_flags, IFF_ALLMULTI);
974 1.4 msaitoh ETHER_UNLOCK(ec);
975 1.1 hikaru goto setmulti;
976 1.1 hikaru }
977 1.1 hikaru multi++;
978 1.1 hikaru
979 1.1 hikaru /* XXX XXX XXX */
980 1.1 hikaru if (multi >= 8) {
981 1.1 hikaru SET(ifp->if_flags, IFF_ALLMULTI);
982 1.4 msaitoh ETHER_UNLOCK(ec);
983 1.1 hikaru goto setmulti;
984 1.1 hikaru }
985 1.1 hikaru /* XXX XXX XXX */
986 1.1 hikaru
987 1.1 hikaru /* XXX XXX XXX */
988 1.1 hikaru SET(cam_en, 1ULL << multi);
989 1.1 hikaru /* XXX XXX XXX */
990 1.1 hikaru
991 1.1 hikaru for (i = 0; i < 6; i++) {
992 1.1 hikaru uint64_t tmp;
993 1.1 hikaru
994 1.1 hikaru /* XXX XXX XXX */
995 1.1 hikaru tmp = _GMX_PORT_RD8(sc, octeon_gmx_rx_adr_cam_regs[i]);
996 1.1 hikaru CLR(tmp, 0xffULL << (8 * multi));
997 1.1 hikaru SET(tmp, (uint64_t)enm->enm_addrlo[i] << (8 * multi));
998 1.1 hikaru _GMX_PORT_WR8(sc, octeon_gmx_rx_adr_cam_regs[i], tmp);
999 1.1 hikaru /* XXX XXX XXX */
1000 1.1 hikaru
1001 1.1 hikaru }
1002 1.1 hikaru for (i = 0; i < 6; i++)
1003 1.1 hikaru dprintf("cam%d = %016llx\n", i,
1004 1.1 hikaru _GMX_PORT_RD8(sc, octeon_gmx_rx_adr_cam_regs[i]));
1005 1.1 hikaru ETHER_NEXT_MULTI(step, enm);
1006 1.1 hikaru }
1007 1.4 msaitoh ETHER_UNLOCK(ec);
1008 1.1 hikaru CLR(ifp->if_flags, IFF_ALLMULTI);
1009 1.1 hikaru
1010 1.1 hikaru OCTEON_ETH_KASSERT(enm == NULL);
1011 1.1 hikaru #else
1012 1.1 hikaru /*
1013 1.1 hikaru * XXX
1014 1.1 hikaru * Never use DMAC filter for multicast addresses, but register only
1015 1.1 hikaru * single entry for self address. FreeBSD code do so.
1016 1.1 hikaru */
1017 1.1 hikaru SET(ifp->if_flags, IFF_ALLMULTI);
1018 1.1 hikaru goto setmulti;
1019 1.1 hikaru #endif
1020 1.1 hikaru
1021 1.1 hikaru setmulti:
1022 1.1 hikaru /* XXX XXX XXX */
1023 1.1 hikaru if (ISSET(ifp->if_flags, IFF_ALLMULTI) ||
1024 1.1 hikaru ISSET(ifp->if_flags, IFF_PROMISC)) {
1025 1.1 hikaru /* XXX XXX XXX */
1026 1.1 hikaru dprintf("accept all multicast\n");
1027 1.1 hikaru SET(ctl, RXN_ADR_CTL_MCST_ACCEPT);
1028 1.1 hikaru /* XXX XXX XXX */
1029 1.1 hikaru } else if (multi) {
1030 1.1 hikaru /* XXX XXX XXX */
1031 1.1 hikaru dprintf("use cam\n");
1032 1.1 hikaru SET(ctl, RXN_ADR_CTL_MCST_AFCAM);
1033 1.1 hikaru /* XXX XXX XXX */
1034 1.1 hikaru } else {
1035 1.1 hikaru /* XXX XXX XXX */
1036 1.1 hikaru dprintf("reject all multicast\n");
1037 1.1 hikaru SET(ctl, RXN_ADR_CTL_MCST_REJECT);
1038 1.1 hikaru /* XXX XXX XXX */
1039 1.1 hikaru }
1040 1.1 hikaru /* XXX XXX XXX */
1041 1.1 hikaru
1042 1.1 hikaru /* XXX XXX XXX */
1043 1.1 hikaru if (ISSET(ifp->if_flags, IFF_PROMISC)) {
1044 1.1 hikaru cam_en = 0x00ULL;
1045 1.1 hikaru } else if (ISSET(ifp->if_flags, IFF_ALLMULTI)) {
1046 1.1 hikaru cam_en = 0x01ULL;
1047 1.1 hikaru }
1048 1.1 hikaru /* XXX XXX XXX */
1049 1.1 hikaru
1050 1.1 hikaru dprintf("ctl = %llx, cam_en = %llx\n", ctl, cam_en);
1051 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, ctl);
1052 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, cam_en);
1053 1.1 hikaru
1054 1.1 hikaru octeon_gmx_link_enable(sc, 1);
1055 1.1 hikaru
1056 1.1 hikaru return 0;
1057 1.1 hikaru }
1058 1.1 hikaru
1059 1.1 hikaru void
1060 1.1 hikaru octeon_gmx_stats(struct octeon_gmx_port_softc *sc)
1061 1.1 hikaru {
1062 1.1 hikaru struct ifnet *ifp = &sc->sc_port_ec->ec_if;
1063 1.1 hikaru uint64_t tmp;
1064 1.1 hikaru
1065 1.1 hikaru /*
1066 1.1 hikaru * GMX0_RX0_STATS_PKTS is not count.
1067 1.1 hikaru * input packet is counted when recepted packet in if_cnmac.
1068 1.1 hikaru */
1069 1.1 hikaru /*
1070 1.1 hikaru * GMX0_RX0_STATS_PKTS_BAD count is included
1071 1.1 hikaru * receive error of work queue entry.
1072 1.1 hikaru * this is not add to input packet errors of interface.
1073 1.1 hikaru */
1074 1.1 hikaru ifp->if_iqdrops +=
1075 1.1 hikaru (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_DRP);
1076 1.1 hikaru ifp->if_opackets +=
1077 1.1 hikaru (uint32_t)_GMX_PORT_RD8(sc, GMX0_TX0_STAT3);
1078 1.1 hikaru
1079 1.1 hikaru tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT0);
1080 1.1 hikaru ifp->if_oerrors +=
1081 1.1 hikaru (uint32_t)tmp + ((uint32_t)(tmp >> 32) * 16);
1082 1.1 hikaru ifp->if_collisions += (uint32_t)tmp;
1083 1.1 hikaru #if IFETHER_DOT3STATS
1084 1.1 hikaru /* dot3StatsExcessiveCollisions */
1085 1.1 hikaru ifp->if_data.ifi_dot3stats.if_oexsvcols += (uint32_t)tmp;
1086 1.1 hikaru #endif
1087 1.1 hikaru
1088 1.1 hikaru tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT1);
1089 1.1 hikaru ifp->if_collisions +=
1090 1.1 hikaru (uint32_t)tmp + (uint32_t)(tmp >> 32);
1091 1.1 hikaru #if IFETHER_DOT3STATS
1092 1.1 hikaru /* dot3StatsSingleCollisionFrames */
1093 1.1 hikaru ifp->if_data.ifi_dot3stats.if_oscols += (uint32_t)(tmp >> 32);
1094 1.1 hikaru /* dot3StatsMultipleCollisionFrames */
1095 1.1 hikaru ifp->if_data.ifi_dot3stats.if_omcols += (uint32_t)tmp;
1096 1.1 hikaru #endif
1097 1.1 hikaru
1098 1.1 hikaru tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT9);
1099 1.1 hikaru ifp->if_oerrors += (uint32_t)(tmp >> 32);
1100 1.1 hikaru }
1101 1.1 hikaru
1102 1.1 hikaru /* ---- DMAC filter */
1103 1.1 hikaru
1104 1.1 hikaru #ifdef notyet
1105 1.1 hikaru /*
1106 1.1 hikaru * DMAC filter configuration
1107 1.1 hikaru * accept all
1108 1.1 hikaru * reject 0 addrs (virtually accept all?)
1109 1.1 hikaru * reject N addrs
1110 1.1 hikaru * accept N addrs
1111 1.1 hikaru * accept 0 addrs (virtually reject all?)
1112 1.1 hikaru * reject all
1113 1.1 hikaru */
1114 1.1 hikaru
1115 1.1 hikaru /* XXX local namespace */
1116 1.1 hikaru #define _POLICY CN30XXGMX_FILTER_POLICY
1117 1.1 hikaru #define _POLICY_ACCEPT_ALL CN30XXGMX_FILTER_POLICY_ACCEPT_ALL
1118 1.1 hikaru #define _POLICY_ACCEPT CN30XXGMX_FILTER_POLICY_ACCEPT
1119 1.1 hikaru #define _POLICY_REJECT CN30XXGMX_FILTER_POLICY_REJECT
1120 1.1 hikaru #define _POLICY_REJECT_ALL CN30XXGMX_FILTER_POLICY_REJECT_ALL
1121 1.1 hikaru
1122 1.1 hikaru static int octeon_gmx_setfilt_addrs(struct octeon_gmx_port_softc *,
1123 1.1 hikaru size_t, uint8_t **);
1124 1.1 hikaru
1125 1.1 hikaru int
1126 1.1 hikaru octeon_gmx_setfilt(struct octeon_gmx_port_softc *sc, enum _POLICY policy,
1127 1.1 hikaru size_t naddrs, uint8_t **addrs)
1128 1.1 hikaru {
1129 1.1 hikaru uint64_t rx_adr_ctl;
1130 1.1 hikaru
1131 1.1 hikaru KASSERT(policy >= _POLICY_ACCEPT_ALL);
1132 1.1 hikaru KASSERT(policy <= _POLICY_REJECT_ALL);
1133 1.1 hikaru
1134 1.1 hikaru rx_adr_ctl = _GMX_PORT_RD8(sc, GMX0_RX0_ADR_CTL);
1135 1.1 hikaru CLR(rx_adr_ctl, RXN_ADR_CTL_CAM_MODE | RXN_ADR_CTL_MCST);
1136 1.1 hikaru
1137 1.1 hikaru switch (policy) {
1138 1.1 hikaru case _POLICY_ACCEPT_ALL:
1139 1.1 hikaru case _POLICY_REJECT_ALL:
1140 1.1 hikaru KASSERT(naddrs == 0);
1141 1.1 hikaru KASSERT(addrs == NULL);
1142 1.1 hikaru
1143 1.1 hikaru SET(rx_adr_ctl, (policy == _POLICY_ACCEPT_ALL) ?
1144 1.1 hikaru RXN_ADR_CTL_MCST_ACCEPT : RXN_ADR_CTL_MCST_REJECT);
1145 1.1 hikaru break;
1146 1.1 hikaru case _POLICY_ACCEPT:
1147 1.1 hikaru case _POLICY_REJECT:
1148 1.1 hikaru if (naddrs > CN30XXGMX_FILTER_NADDRS_MAX)
1149 1.1 hikaru return E2BIG;
1150 1.1 hikaru SET(rx_adr_ctl, (policy == _POLICY_ACCEPT) ?
1151 1.1 hikaru RXN_ADR_CTL_CAM_MODE : 0);
1152 1.1 hikaru SET(rx_adr_ctl, RXN_ADR_CTL_MCST_AFCAM);
1153 1.1 hikaru /* set GMX0_RXN_ADR_CAM_EN, GMX0_RXN_ADR_CAM[0-5] */
1154 1.1 hikaru octeon_gmx_setfilt_addrs(sc, naddrs, addrs);
1155 1.1 hikaru break;
1156 1.1 hikaru }
1157 1.1 hikaru
1158 1.1 hikaru /* set GMX0_RXN_ADR_CTL[MCST] */
1159 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, rx_adr_ctl);
1160 1.1 hikaru
1161 1.1 hikaru return 0;
1162 1.1 hikaru }
1163 1.1 hikaru
1164 1.1 hikaru static int
1165 1.1 hikaru octeon_gmx_setfilt_addrs(struct octeon_gmx_port_softc *sc, size_t naddrs,
1166 1.1 hikaru uint8_t **addrs)
1167 1.1 hikaru {
1168 1.1 hikaru uint64_t rx_adr_cam_en;
1169 1.1 hikaru uint64_t rx_adr_cam_addrs[CN30XXGMX_FILTER_NADDRS_MAX];
1170 1.1 hikaru int i, j;
1171 1.1 hikaru
1172 1.1 hikaru KASSERT(naddrs <= CN30XXGMX_FILTER_NADDRS_MAX);
1173 1.1 hikaru
1174 1.1 hikaru rx_adr_cam_en = 0;
1175 1.1 hikaru (void)memset(rx_adr_cam_addrs, 0, sizeof(rx_adr_cam_addrs));
1176 1.1 hikaru
1177 1.1 hikaru for (i = 0; i < naddrs; i++) {
1178 1.1 hikaru SET(rx_adr_cam_en, 1ULL << i);
1179 1.1 hikaru for (j = 0; j < 6; j++)
1180 1.1 hikaru SET(rx_adr_cam_addrs[j],
1181 1.1 hikaru (uint64_t)addrs[i][j] << (8 * i));
1182 1.1 hikaru }
1183 1.1 hikaru
1184 1.1 hikaru /* set GMX0_RXN_ADR_CAM_EN, GMX0_RXN_ADR_CAM[0-5] */
1185 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, rx_adr_cam_en);
1186 1.1 hikaru for (j = 0; j < 6; j++)
1187 1.1 hikaru _GMX_PORT_WR8(sc, octeon_gmx_rx_adr_cam_regs[j],
1188 1.1 hikaru rx_adr_cam_addrs[j]);
1189 1.1 hikaru
1190 1.1 hikaru return 0;
1191 1.1 hikaru }
1192 1.1 hikaru #endif
1193 1.1 hikaru
1194 1.1 hikaru /* ---- interrupt */
1195 1.1 hikaru
1196 1.1 hikaru #ifdef OCTEON_ETH_DEBUG
1197 1.1 hikaru void octeon_gmx_intr_rml_gmx0(void);
1198 1.1 hikaru
1199 1.1 hikaru int octeon_gmx_intr_rml_verbose;
1200 1.1 hikaru
1201 1.1 hikaru /* tx - per unit (gmx0, gmx1, ...) */
1202 1.1 hikaru static const struct octeon_evcnt_entry octeon_gmx_intr_evcnt_tx_entries[] = {
1203 1.1 hikaru #define _ENTRY(name, type, parent, descr) \
1204 1.1 hikaru OCTEON_EVCNT_ENTRY(struct octeon_gmx_softc, name, type, parent, descr)
1205 1.1 hikaru _ENTRY(latecol, MISC, NULL, "tx late collision"),
1206 1.1 hikaru _ENTRY(xsdef, MISC, NULL, "tx excessive deferral"),
1207 1.1 hikaru _ENTRY(xscol, MISC, NULL, "tx excessive collision"),
1208 1.1 hikaru _ENTRY(undflw, MISC, NULL, "tx underflow"),
1209 1.1 hikaru _ENTRY(pkonxa, MISC, NULL, "tx port addr out-of-range")
1210 1.1 hikaru #undef _ENTRY
1211 1.1 hikaru };
1212 1.1 hikaru
1213 1.1 hikaru /* rx - per port (gmx0:0, gmx0:1, ...) */
1214 1.1 hikaru static const struct octeon_evcnt_entry octeon_gmx_intr_evcnt_rx_entries[] = {
1215 1.1 hikaru #define _ENTRY(name, type, parent, descr) \
1216 1.1 hikaru OCTEON_EVCNT_ENTRY(struct octeon_gmx_port_softc, name, type, parent, descr)
1217 1.1 hikaru _ENTRY(minerr, MISC, NULL, "rx min error"),
1218 1.1 hikaru _ENTRY(carext, MISC, NULL, "rx carrier error"),
1219 1.1 hikaru _ENTRY(maxerr, MISC, NULL, "rx max error"),
1220 1.1 hikaru _ENTRY(jabber, MISC, NULL, "rx jabber error"),
1221 1.1 hikaru _ENTRY(fcserr, MISC, NULL, "rx fcs error"),
1222 1.1 hikaru _ENTRY(alnerr, MISC, NULL, "rx align error"),
1223 1.1 hikaru _ENTRY(lenerr, MISC, NULL, "rx length error"),
1224 1.1 hikaru _ENTRY(rcverr, MISC, NULL, "rx receive error"),
1225 1.1 hikaru _ENTRY(skperr, MISC, NULL, "rx skip error"),
1226 1.1 hikaru _ENTRY(niberr, MISC, NULL, "rx nibble error"),
1227 1.1 hikaru _ENTRY(ovrerr, MISC, NULL, "rx overflow error"),
1228 1.1 hikaru _ENTRY(pckterr, MISC, NULL, "rx packet error"),
1229 1.1 hikaru _ENTRY(rsverr, MISC, NULL, "rx reserved opcode error"),
1230 1.1 hikaru _ENTRY(falerr, MISC, NULL, "rx false carrier error"),
1231 1.1 hikaru _ENTRY(coldet, MISC, NULL, "rx collision detect"),
1232 1.1 hikaru _ENTRY(ifgerr, MISC, NULL, "rx ifg error")
1233 1.1 hikaru #undef _ENTRY
1234 1.1 hikaru };
1235 1.1 hikaru
1236 1.1 hikaru void
1237 1.1 hikaru octeon_gmx_intr_evcnt_attach(struct octeon_gmx_softc *sc)
1238 1.1 hikaru {
1239 1.1 hikaru struct octeon_gmx_port_softc *port_sc;
1240 1.1 hikaru int i;
1241 1.1 hikaru
1242 1.1 hikaru OCTEON_EVCNT_ATTACH_EVCNTS(sc, octeon_gmx_intr_evcnt_tx_entries,
1243 1.1 hikaru device_xname(sc->sc_dev));
1244 1.1 hikaru for (i = 0; i < sc->sc_nports; i++) {
1245 1.1 hikaru port_sc = &sc->sc_ports[i];
1246 1.1 hikaru OCTEON_EVCNT_ATTACH_EVCNTS(port_sc, octeon_gmx_intr_evcnt_rx_entries,
1247 1.1 hikaru device_xname(sc->sc_dev));
1248 1.1 hikaru }
1249 1.1 hikaru }
1250 1.1 hikaru
1251 1.1 hikaru void
1252 1.1 hikaru octeon_gmx_intr_rml_gmx0(void)
1253 1.1 hikaru {
1254 1.1 hikaru struct octeon_gmx_port_softc *sc = NULL/* XXX gcc */;
1255 1.1 hikaru int i;
1256 1.1 hikaru uint64_t reg = 0/* XXX gcc */;
1257 1.1 hikaru
1258 1.1 hikaru octeon_gmx_intr_evcnt.ev_count++;
1259 1.1 hikaru
1260 1.1 hikaru sc = __octeon_gmx_port_softc[0];
1261 1.1 hikaru if (sc == NULL)
1262 1.1 hikaru return;
1263 1.1 hikaru
1264 1.1 hikaru /* GMX0_RXn_INT_REG or GMX0_TXn_INT_REG */
1265 1.1 hikaru reg = octeon_gmx_get_tx_int_reg(sc);
1266 1.1 hikaru if (octeon_gmx_intr_rml_verbose && reg != 0)
1267 1.1 hikaru printf("%s: GMX_TX_INT_REG=0x%016" PRIx64 "\n", __func__, reg);
1268 1.1 hikaru if (reg & TX_INT_REG_LATE_COL)
1269 1.1 hikaru OCTEON_EVCNT_INC(sc->sc_port_gmx, latecol);
1270 1.1 hikaru if (reg & TX_INT_REG_XSDEF)
1271 1.1 hikaru OCTEON_EVCNT_INC(sc->sc_port_gmx, xsdef);
1272 1.1 hikaru if (reg & TX_INT_REG_XSCOL)
1273 1.1 hikaru OCTEON_EVCNT_INC(sc->sc_port_gmx, xscol);
1274 1.1 hikaru if (reg & TX_INT_REG_UNDFLW)
1275 1.1 hikaru OCTEON_EVCNT_INC(sc->sc_port_gmx, undflw);
1276 1.1 hikaru if (reg & TX_INT_REG_PKO_NXA)
1277 1.1 hikaru OCTEON_EVCNT_INC(sc->sc_port_gmx, pkonxa);
1278 1.1 hikaru
1279 1.1 hikaru for (i = 0; i < GMX_PORT_NUNITS; i++) {
1280 1.1 hikaru sc = __octeon_gmx_port_softc[i];
1281 1.1 hikaru if (sc == NULL)
1282 1.1 hikaru continue;
1283 1.1 hikaru reg = octeon_gmx_get_rx_int_reg(sc);
1284 1.1 hikaru if (octeon_gmx_intr_rml_verbose)
1285 1.1 hikaru printf("%s: GMX_RX_INT_REG=0x%016" PRIx64 "\n", __func__, reg);
1286 1.1 hikaru if (reg & RXN_INT_REG_MINERR)
1287 1.1 hikaru OCTEON_EVCNT_INC(sc, minerr);
1288 1.1 hikaru if (reg & RXN_INT_REG_CAREXT)
1289 1.1 hikaru OCTEON_EVCNT_INC(sc, carext);
1290 1.1 hikaru if (reg & RXN_INT_REG_JABBER)
1291 1.1 hikaru OCTEON_EVCNT_INC(sc, jabber);
1292 1.1 hikaru if (reg & RXN_INT_REG_FCSERR)
1293 1.1 hikaru OCTEON_EVCNT_INC(sc, fcserr);
1294 1.1 hikaru if (reg & RXN_INT_REG_ALNERR)
1295 1.1 hikaru OCTEON_EVCNT_INC(sc, alnerr);
1296 1.1 hikaru if (reg & RXN_INT_REG_LENERR)
1297 1.1 hikaru OCTEON_EVCNT_INC(sc, lenerr);
1298 1.1 hikaru if (reg & RXN_INT_REG_RCVERR)
1299 1.1 hikaru OCTEON_EVCNT_INC(sc, rcverr);
1300 1.1 hikaru if (reg & RXN_INT_REG_SKPERR)
1301 1.1 hikaru OCTEON_EVCNT_INC(sc, skperr);
1302 1.1 hikaru if (reg & RXN_INT_REG_NIBERR)
1303 1.1 hikaru OCTEON_EVCNT_INC(sc, niberr);
1304 1.1 hikaru if (reg & RXN_INT_REG_OVRERR)
1305 1.1 hikaru OCTEON_EVCNT_INC(sc, ovrerr);
1306 1.1 hikaru if (reg & RXN_INT_REG_PCTERR)
1307 1.1 hikaru OCTEON_EVCNT_INC(sc, pckterr);
1308 1.1 hikaru if (reg & RXN_INT_REG_RSVERR)
1309 1.1 hikaru OCTEON_EVCNT_INC(sc, rsverr);
1310 1.1 hikaru if (reg & RXN_INT_REG_FALERR)
1311 1.1 hikaru OCTEON_EVCNT_INC(sc, falerr);
1312 1.1 hikaru if (reg & RXN_INT_REG_COLDET)
1313 1.1 hikaru OCTEON_EVCNT_INC(sc, coldet);
1314 1.1 hikaru if (reg & RXN_INT_REG_IFGERR)
1315 1.1 hikaru OCTEON_EVCNT_INC(sc, ifgerr);
1316 1.1 hikaru }
1317 1.1 hikaru }
1318 1.1 hikaru
1319 1.1 hikaru #ifdef notyet
1320 1.1 hikaru void
1321 1.1 hikaru octeon_gmx_intr_rml_gmx1(void)
1322 1.1 hikaru {
1323 1.1 hikaru uint64_t reg = 0/* XXX gcc */;
1324 1.1 hikaru
1325 1.1 hikaru /* GMX1_RXn_INT_REG or GMX1_TXn_INT_REG */
1326 1.1 hikaru }
1327 1.1 hikaru #endif
1328 1.1 hikaru
1329 1.1 hikaru int
1330 1.1 hikaru octeon_gmx_intr_drop(void *arg)
1331 1.1 hikaru {
1332 1.1 hikaru octeon_write_csr(CIU_INT0_SUM0, CIU_INTX_SUM0_GMX_DRP);
1333 1.1 hikaru octeon_gmx_intr_drop_evcnt.ev_count++;
1334 1.1 hikaru return (1);
1335 1.1 hikaru }
1336 1.1 hikaru
1337 1.1 hikaru uint64_t
1338 1.1 hikaru octeon_gmx_get_rx_int_reg(struct octeon_gmx_port_softc *sc)
1339 1.1 hikaru {
1340 1.1 hikaru uint64_t reg;
1341 1.1 hikaru uint64_t rx_int_reg = 0;
1342 1.1 hikaru
1343 1.1 hikaru reg = _GMX_PORT_RD8(sc, GMX0_RX0_INT_REG);
1344 1.1 hikaru /* clear */
1345 1.1 hikaru SET(rx_int_reg, 0 |
1346 1.1 hikaru RXN_INT_REG_PHY_DUPX |
1347 1.1 hikaru RXN_INT_REG_PHY_SPD |
1348 1.1 hikaru RXN_INT_REG_PHY_LINK |
1349 1.1 hikaru RXN_INT_REG_IFGERR |
1350 1.1 hikaru RXN_INT_REG_COLDET |
1351 1.1 hikaru RXN_INT_REG_FALERR |
1352 1.1 hikaru RXN_INT_REG_RSVERR |
1353 1.1 hikaru RXN_INT_REG_PCTERR |
1354 1.1 hikaru RXN_INT_REG_OVRERR |
1355 1.1 hikaru RXN_INT_REG_NIBERR |
1356 1.1 hikaru RXN_INT_REG_SKPERR |
1357 1.1 hikaru RXN_INT_REG_RCVERR |
1358 1.1 hikaru RXN_INT_REG_LENERR |
1359 1.1 hikaru RXN_INT_REG_ALNERR |
1360 1.1 hikaru RXN_INT_REG_FCSERR |
1361 1.1 hikaru RXN_INT_REG_JABBER |
1362 1.1 hikaru RXN_INT_REG_MAXERR |
1363 1.1 hikaru RXN_INT_REG_CAREXT |
1364 1.1 hikaru RXN_INT_REG_MINERR);
1365 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_INT_REG, rx_int_reg);
1366 1.1 hikaru
1367 1.1 hikaru return reg;
1368 1.1 hikaru }
1369 1.1 hikaru
1370 1.1 hikaru uint64_t
1371 1.1 hikaru octeon_gmx_get_tx_int_reg(struct octeon_gmx_port_softc *sc)
1372 1.1 hikaru {
1373 1.1 hikaru uint64_t reg;
1374 1.1 hikaru uint64_t tx_int_reg = 0;
1375 1.1 hikaru
1376 1.1 hikaru reg = _GMX_PORT_RD8(sc, GMX0_TX_INT_REG);
1377 1.1 hikaru /* clear */
1378 1.1 hikaru SET(tx_int_reg, 0 |
1379 1.1 hikaru TX_INT_REG_LATE_COL |
1380 1.1 hikaru TX_INT_REG_XSDEF |
1381 1.1 hikaru TX_INT_REG_XSCOL |
1382 1.1 hikaru TX_INT_REG_UNDFLW |
1383 1.1 hikaru TX_INT_REG_PKO_NXA);
1384 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX_INT_REG, tx_int_reg);
1385 1.1 hikaru
1386 1.1 hikaru return reg;
1387 1.1 hikaru }
1388 1.1 hikaru #endif /* OCTEON_ETH_DEBUG */
1389 1.1 hikaru
1390 1.1 hikaru /* ---- debug */
1391 1.1 hikaru
1392 1.1 hikaru #ifdef OCTEON_ETH_DEBUG
1393 1.1 hikaru #define _ENTRY(x) { #x, x##_BITS, x }
1394 1.1 hikaru
1395 1.1 hikaru struct octeon_gmx_dump_reg_ {
1396 1.1 hikaru const char *name;
1397 1.1 hikaru const char *format;
1398 1.1 hikaru size_t offset;
1399 1.1 hikaru };
1400 1.1 hikaru
1401 1.1 hikaru static const struct octeon_gmx_dump_reg_ octeon_gmx_dump_regs_[] = {
1402 1.1 hikaru _ENTRY(GMX0_SMAC0),
1403 1.1 hikaru _ENTRY(GMX0_BIST0),
1404 1.1 hikaru _ENTRY(GMX0_RX_PRTS),
1405 1.1 hikaru _ENTRY(GMX0_RX_BP_DROP0),
1406 1.1 hikaru _ENTRY(GMX0_RX_BP_DROP1),
1407 1.1 hikaru _ENTRY(GMX0_RX_BP_DROP2),
1408 1.1 hikaru _ENTRY(GMX0_RX_BP_ON0),
1409 1.1 hikaru _ENTRY(GMX0_RX_BP_ON1),
1410 1.1 hikaru _ENTRY(GMX0_RX_BP_ON2),
1411 1.1 hikaru _ENTRY(GMX0_RX_BP_OFF0),
1412 1.1 hikaru _ENTRY(GMX0_RX_BP_OFF1),
1413 1.1 hikaru _ENTRY(GMX0_RX_BP_OFF2),
1414 1.1 hikaru _ENTRY(GMX0_TX_PRTS),
1415 1.1 hikaru _ENTRY(GMX0_TX_IFG),
1416 1.1 hikaru _ENTRY(GMX0_TX_JAM),
1417 1.1 hikaru _ENTRY(GMX0_TX_COL_ATTEMPT),
1418 1.1 hikaru _ENTRY(GMX0_TX_PAUSE_PKT_DMAC),
1419 1.1 hikaru _ENTRY(GMX0_TX_PAUSE_PKT_TYPE),
1420 1.1 hikaru _ENTRY(GMX0_TX_OVR_BP),
1421 1.1 hikaru _ENTRY(GMX0_TX_BP),
1422 1.1 hikaru _ENTRY(GMX0_TX_CORRUPT),
1423 1.1 hikaru _ENTRY(GMX0_RX_PRT_INFO),
1424 1.1 hikaru _ENTRY(GMX0_TX_LFSR),
1425 1.1 hikaru _ENTRY(GMX0_TX_INT_REG),
1426 1.1 hikaru _ENTRY(GMX0_TX_INT_EN),
1427 1.1 hikaru _ENTRY(GMX0_NXA_ADR),
1428 1.1 hikaru _ENTRY(GMX0_BAD_REG),
1429 1.1 hikaru _ENTRY(GMX0_STAT_BP),
1430 1.1 hikaru _ENTRY(GMX0_TX_CLK_MSK0),
1431 1.1 hikaru _ENTRY(GMX0_TX_CLK_MSK1),
1432 1.1 hikaru _ENTRY(GMX0_RX_TX_STATUS),
1433 1.1 hikaru _ENTRY(GMX0_INF_MODE),
1434 1.1 hikaru };
1435 1.1 hikaru
1436 1.1 hikaru static const struct octeon_gmx_dump_reg_ octeon_gmx_dump_port_regs_[] = {
1437 1.1 hikaru _ENTRY(GMX0_RX0_INT_REG),
1438 1.1 hikaru _ENTRY(GMX0_RX0_INT_EN),
1439 1.1 hikaru _ENTRY(GMX0_PRT0_CFG),
1440 1.1 hikaru _ENTRY(GMX0_RX0_FRM_CTL),
1441 1.1 hikaru _ENTRY(GMX0_RX0_FRM_CHK),
1442 1.1 hikaru _ENTRY(GMX0_RX0_FRM_MIN),
1443 1.1 hikaru _ENTRY(GMX0_RX0_FRM_MAX),
1444 1.1 hikaru _ENTRY(GMX0_RX0_JABBER),
1445 1.1 hikaru _ENTRY(GMX0_RX0_DECISION),
1446 1.1 hikaru _ENTRY(GMX0_RX0_UDD_SKP),
1447 1.1 hikaru _ENTRY(GMX0_RX0_STATS_CTL),
1448 1.1 hikaru _ENTRY(GMX0_RX0_IFG),
1449 1.1 hikaru _ENTRY(GMX0_RX0_RX_INBND),
1450 1.1 hikaru _ENTRY(GMX0_RX0_ADR_CTL),
1451 1.1 hikaru _ENTRY(GMX0_RX0_ADR_CAM_EN),
1452 1.1 hikaru _ENTRY(GMX0_RX0_ADR_CAM0),
1453 1.1 hikaru _ENTRY(GMX0_RX0_ADR_CAM1),
1454 1.1 hikaru _ENTRY(GMX0_RX0_ADR_CAM2),
1455 1.1 hikaru _ENTRY(GMX0_RX0_ADR_CAM3),
1456 1.1 hikaru _ENTRY(GMX0_RX0_ADR_CAM4),
1457 1.1 hikaru _ENTRY(GMX0_RX0_ADR_CAM5),
1458 1.1 hikaru _ENTRY(GMX0_TX0_CLK),
1459 1.1 hikaru _ENTRY(GMX0_TX0_THRESH),
1460 1.1 hikaru _ENTRY(GMX0_TX0_APPEND),
1461 1.1 hikaru _ENTRY(GMX0_TX0_SLOT),
1462 1.1 hikaru _ENTRY(GMX0_TX0_BURST),
1463 1.1 hikaru _ENTRY(GMX0_TX0_PAUSE_PKT_TIME),
1464 1.1 hikaru _ENTRY(GMX0_TX0_MIN_PKT),
1465 1.1 hikaru _ENTRY(GMX0_TX0_PAUSE_PKT_INTERVAL),
1466 1.1 hikaru _ENTRY(GMX0_TX0_SOFT_PAUSE),
1467 1.1 hikaru _ENTRY(GMX0_TX0_PAUSE_TOGO),
1468 1.1 hikaru _ENTRY(GMX0_TX0_PAUSE_ZERO),
1469 1.1 hikaru _ENTRY(GMX0_TX0_STATS_CTL),
1470 1.1 hikaru _ENTRY(GMX0_TX0_CTL),
1471 1.1 hikaru };
1472 1.1 hikaru
1473 1.1 hikaru static const struct octeon_gmx_dump_reg_ octeon_gmx_dump_port_stats_[] = {
1474 1.1 hikaru _ENTRY(GMX0_RX0_STATS_PKTS),
1475 1.1 hikaru _ENTRY(GMX0_RX0_STATS_OCTS),
1476 1.1 hikaru _ENTRY(GMX0_RX0_STATS_PKTS_CTL),
1477 1.1 hikaru _ENTRY(GMX0_RX0_STATS_OCTS_CTL),
1478 1.1 hikaru _ENTRY(GMX0_RX0_STATS_PKTS_DMAC),
1479 1.1 hikaru _ENTRY(GMX0_RX0_STATS_OCTS_DMAC),
1480 1.1 hikaru _ENTRY(GMX0_RX0_STATS_PKTS_DRP),
1481 1.1 hikaru _ENTRY(GMX0_RX0_STATS_OCTS_DRP),
1482 1.1 hikaru _ENTRY(GMX0_RX0_STATS_PKTS_BAD),
1483 1.1 hikaru _ENTRY(GMX0_TX0_STAT0),
1484 1.1 hikaru _ENTRY(GMX0_TX0_STAT1),
1485 1.1 hikaru _ENTRY(GMX0_TX0_STAT2),
1486 1.1 hikaru _ENTRY(GMX0_TX0_STAT3),
1487 1.1 hikaru _ENTRY(GMX0_TX0_STAT4),
1488 1.1 hikaru _ENTRY(GMX0_TX0_STAT5),
1489 1.1 hikaru _ENTRY(GMX0_TX0_STAT6),
1490 1.1 hikaru _ENTRY(GMX0_TX0_STAT7),
1491 1.1 hikaru _ENTRY(GMX0_TX0_STAT8),
1492 1.1 hikaru _ENTRY(GMX0_TX0_STAT9),
1493 1.1 hikaru };
1494 1.1 hikaru
1495 1.1 hikaru void octeon_gmx_dump_common(void);
1496 1.1 hikaru void octeon_gmx_dump_port0(void);
1497 1.1 hikaru void octeon_gmx_dump_port1(void);
1498 1.1 hikaru void octeon_gmx_dump_port2(void);
1499 1.1 hikaru void octeon_gmx_dump_port0_regs(void);
1500 1.1 hikaru void octeon_gmx_dump_port1_regs(void);
1501 1.1 hikaru void octeon_gmx_dump_port2_regs(void);
1502 1.1 hikaru void octeon_gmx_dump_port0_stats(void);
1503 1.1 hikaru void octeon_gmx_dump_port1_stats(void);
1504 1.1 hikaru void octeon_gmx_dump_port2_stats(void);
1505 1.1 hikaru void octeon_gmx_dump_port_regs(int);
1506 1.1 hikaru void octeon_gmx_dump_port_stats(int);
1507 1.1 hikaru void octeon_gmx_dump_common_x(int, const struct octeon_gmx_dump_reg_ *, size_t);
1508 1.1 hikaru void octeon_gmx_dump_port_x(int, const struct octeon_gmx_dump_reg_ *, size_t);
1509 1.1 hikaru void octeon_gmx_dump_x(int, const struct octeon_gmx_dump_reg_ *, size_t, size_t, int);
1510 1.1 hikaru void octeon_gmx_dump_x_index(char *, size_t, int);
1511 1.1 hikaru
1512 1.1 hikaru void
1513 1.1 hikaru octeon_gmx_dump(void)
1514 1.1 hikaru {
1515 1.1 hikaru octeon_gmx_dump_common();
1516 1.1 hikaru octeon_gmx_dump_port0();
1517 1.1 hikaru octeon_gmx_dump_port1();
1518 1.1 hikaru octeon_gmx_dump_port2();
1519 1.1 hikaru }
1520 1.1 hikaru
1521 1.1 hikaru void
1522 1.1 hikaru octeon_gmx_dump_common(void)
1523 1.1 hikaru {
1524 1.1 hikaru octeon_gmx_dump_common_x(0, octeon_gmx_dump_regs_,
1525 1.1 hikaru __arraycount(octeon_gmx_dump_regs_));
1526 1.1 hikaru }
1527 1.1 hikaru
1528 1.1 hikaru void
1529 1.1 hikaru octeon_gmx_dump_port0(void)
1530 1.1 hikaru {
1531 1.1 hikaru octeon_gmx_dump_port_regs(0);
1532 1.1 hikaru octeon_gmx_dump_port_stats(0);
1533 1.1 hikaru }
1534 1.1 hikaru
1535 1.1 hikaru void
1536 1.1 hikaru octeon_gmx_dump_port1(void)
1537 1.1 hikaru {
1538 1.1 hikaru octeon_gmx_dump_port_regs(1);
1539 1.1 hikaru octeon_gmx_dump_port_stats(1);
1540 1.1 hikaru }
1541 1.1 hikaru
1542 1.1 hikaru void
1543 1.1 hikaru octeon_gmx_dump_port2(void)
1544 1.1 hikaru {
1545 1.1 hikaru octeon_gmx_dump_port_regs(2);
1546 1.1 hikaru octeon_gmx_dump_port_stats(2);
1547 1.1 hikaru }
1548 1.1 hikaru
1549 1.1 hikaru void
1550 1.1 hikaru octeon_gmx_dump_port_regs(int portno)
1551 1.1 hikaru {
1552 1.1 hikaru octeon_gmx_dump_port_x(portno, octeon_gmx_dump_port_regs_,
1553 1.1 hikaru __arraycount(octeon_gmx_dump_port_regs_));
1554 1.1 hikaru }
1555 1.1 hikaru
1556 1.1 hikaru void
1557 1.1 hikaru octeon_gmx_dump_port_stats(int portno)
1558 1.1 hikaru {
1559 1.1 hikaru struct octeon_gmx_port_softc *sc = __octeon_gmx_port_softc[0];
1560 1.1 hikaru uint64_t rx_stats_ctl;
1561 1.1 hikaru uint64_t tx_stats_ctl;
1562 1.1 hikaru
1563 1.1 hikaru rx_stats_ctl = _GMX_RD8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_RX0_STATS_CTL);
1564 1.1 hikaru _GMX_WR8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_RX0_STATS_CTL,
1565 1.1 hikaru rx_stats_ctl & ~RXN_STATS_CTL_RD_CLR);
1566 1.1 hikaru tx_stats_ctl = _GMX_RD8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_TX0_STATS_CTL);
1567 1.1 hikaru _GMX_WR8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_TX0_STATS_CTL,
1568 1.1 hikaru tx_stats_ctl & ~TXN_STATS_CTL_RD_CLR);
1569 1.1 hikaru octeon_gmx_dump_port_x(portno, octeon_gmx_dump_port_stats_,
1570 1.1 hikaru __arraycount(octeon_gmx_dump_port_stats_));
1571 1.1 hikaru _GMX_WR8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_RX0_STATS_CTL, rx_stats_ctl);
1572 1.1 hikaru _GMX_WR8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_TX0_STATS_CTL, tx_stats_ctl);
1573 1.1 hikaru }
1574 1.1 hikaru
1575 1.1 hikaru void
1576 1.1 hikaru octeon_gmx_dump_common_x(int portno, const struct octeon_gmx_dump_reg_ *regs, size_t size)
1577 1.1 hikaru {
1578 1.1 hikaru octeon_gmx_dump_x(portno, regs, size, 0, 0);
1579 1.1 hikaru }
1580 1.1 hikaru
1581 1.1 hikaru void
1582 1.1 hikaru octeon_gmx_dump_port_x(int portno, const struct octeon_gmx_dump_reg_ *regs, size_t size)
1583 1.1 hikaru {
1584 1.1 hikaru octeon_gmx_dump_x(portno, regs, size, GMX0_BASE_PORT_SIZE * portno, 1);
1585 1.1 hikaru }
1586 1.1 hikaru
1587 1.1 hikaru void
1588 1.1 hikaru octeon_gmx_dump_x(int portno, const struct octeon_gmx_dump_reg_ *regs, size_t size, size_t base, int index)
1589 1.1 hikaru {
1590 1.1 hikaru struct octeon_gmx_port_softc *sc = __octeon_gmx_port_softc[0];
1591 1.1 hikaru const struct octeon_gmx_dump_reg_ *reg;
1592 1.1 hikaru uint64_t tmp;
1593 1.1 hikaru char name[64];
1594 1.1 hikaru char buf[512];
1595 1.1 hikaru int i;
1596 1.1 hikaru
1597 1.1 hikaru for (i = 0; i < (int)size; i++) {
1598 1.1 hikaru reg = ®s[i];
1599 1.1 hikaru tmp = _GMX_RD8(sc, base + reg->offset);
1600 1.1 hikaru
1601 1.1 hikaru if (reg->format == NULL)
1602 1.1 hikaru snprintf(buf, sizeof(buf), "%016" PRIx64, tmp);
1603 1.1 hikaru else
1604 1.1 hikaru snprintb(buf, sizeof(buf), reg->format, tmp);
1605 1.1 hikaru
1606 1.1 hikaru snprintf(name, sizeof(name), "%s", reg->name);
1607 1.1 hikaru if (index > 0)
1608 1.1 hikaru octeon_gmx_dump_x_index(name, sizeof(name), portno);
1609 1.1 hikaru
1610 1.1 hikaru printf("\t%-24s: %s\n", name, buf);
1611 1.1 hikaru }
1612 1.1 hikaru }
1613 1.1 hikaru
1614 1.1 hikaru void
1615 1.1 hikaru octeon_gmx_dump_x_index(char *buf, size_t len, int index)
1616 1.1 hikaru {
1617 1.1 hikaru static const char *patterns[] = { "_TX0_", "_RX0_", "_PRT0_" };
1618 1.1 hikaru int i;
1619 1.1 hikaru
1620 1.1 hikaru for (i = 0; i < (int)__arraycount(patterns); i++) {
1621 1.1 hikaru char *p;
1622 1.1 hikaru
1623 1.1 hikaru p = strstr(buf, patterns[i]);
1624 1.1 hikaru if (p == NULL)
1625 1.1 hikaru continue;
1626 1.1 hikaru p = strchr(p, '0');
1627 1.1 hikaru KASSERT(p != NULL);
1628 1.1 hikaru *p = '0' + index;
1629 1.1 hikaru return;
1630 1.1 hikaru }
1631 1.1 hikaru }
1632 1.1 hikaru
1633 1.1 hikaru void
1634 1.1 hikaru octeon_gmx_debug_reset(void)
1635 1.1 hikaru {
1636 1.1 hikaru int i;
1637 1.1 hikaru
1638 1.1 hikaru for (i = 0; i < 3; i++)
1639 1.1 hikaru octeon_gmx_link_enable(__octeon_gmx_port_softc[i], 0);
1640 1.1 hikaru for (i = 0; i < 3; i++)
1641 1.1 hikaru octeon_gmx_link_enable(__octeon_gmx_port_softc[i], 1);
1642 1.1 hikaru }
1643 1.1 hikaru #endif
1644