xref: /openbsd/sys/arch/octeon/dev/cn30xxgmx.c (revision 3cab2bb3)
1 /*	$OpenBSD: cn30xxgmx.c,v 1.44 2020/07/04 09:00:09 visa Exp $	*/
2 
3 /*
4  * Copyright (c) 2007 Internet Initiative Japan, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/device.h>
32 #include <sys/malloc.h>
33 #include <sys/syslog.h>
34 
35 #include <dev/ofw/openfirm.h>
36 
37 #include <machine/bus.h>
38 #include <machine/octeon_model.h>
39 #include <machine/octeonvar.h>
40 
41 #include <octeon/dev/iobusvar.h>
42 #include <octeon/dev/cn30xxasxvar.h>
43 #include <octeon/dev/cn30xxciureg.h>
44 #include <octeon/dev/cn30xxgmxreg.h>
45 #include <octeon/dev/cn30xxgmxvar.h>
46 #include <octeon/dev/cn30xxipdvar.h>
47 #include <octeon/dev/cn30xxpipvar.h>
48 #include <octeon/dev/cn30xxsmivar.h>
49 
50 #define	dprintf(...)
51 #define	OCTEON_ETH_KASSERT	KASSERT
52 
53 #define	ADDR2UINT64(u, a) \
54 	do { \
55 		u = \
56 		    (((uint64_t)a[0] << 40) | ((uint64_t)a[1] << 32) | \
57 		     ((uint64_t)a[2] << 24) | ((uint64_t)a[3] << 16) | \
58 		     ((uint64_t)a[4] <<  8) | ((uint64_t)a[5] <<  0)); \
59 	} while (0)
60 #define	UINT642ADDR(a, u) \
61 	do { \
62 		a[0] = (uint8_t)((u) >> 40); a[1] = (uint8_t)((u) >> 32); \
63 		a[2] = (uint8_t)((u) >> 24); a[3] = (uint8_t)((u) >> 16); \
64 		a[4] = (uint8_t)((u) >>  8); a[5] = (uint8_t)((u) >>  0); \
65 	} while (0)
66 
67 #define	_GMX_RD8(sc, off) \
68 	bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off))
69 #define	_GMX_WR8(sc, off, v) \
70 	bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off), (v))
71 #define	_GMX_PORT_RD8(sc, off) \
72 	bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off))
73 #define	_GMX_PORT_WR8(sc, off, v) \
74 	bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off), (v))
75 
76 #define PCS_READ_8(sc, reg) \
77 	bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_pcs_regh, \
78 	    (reg))
79 #define PCS_WRITE_8(sc, reg, val) \
80 	bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_pcs_regh, \
81 	    (reg), (val))
82 
83 struct cn30xxgmx_port_ops {
84 	int	(*port_ops_enable)(struct cn30xxgmx_port_softc *, int);
85 	int	(*port_ops_speed)(struct cn30xxgmx_port_softc *);
86 	int	(*port_ops_timing)(struct cn30xxgmx_port_softc *);
87 };
88 
89 int	cn30xxgmx_match(struct device *, void *, void *);
90 void	cn30xxgmx_attach(struct device *, struct device *, void *);
91 int	cn30xxgmx_print(void *, const char *);
92 int	cn30xxgmx_port_phy_addr(int);
93 int	cn30xxgmx_init(struct cn30xxgmx_softc *);
94 int	cn30xxgmx_rx_frm_ctl_xable(struct cn30xxgmx_port_softc *,
95 	    uint64_t, int);
96 int	cn30xxgmx_rgmii_enable(struct cn30xxgmx_port_softc *, int);
97 int	cn30xxgmx_rgmii_speed(struct cn30xxgmx_port_softc *);
98 int	cn30xxgmx_rgmii_speed_newlink(struct cn30xxgmx_port_softc *,
99 	    uint64_t *);
100 int	cn30xxgmx_rgmii_speed_speed(struct cn30xxgmx_port_softc *);
101 int	cn30xxgmx_rgmii_timing(struct cn30xxgmx_port_softc *);
102 int	cn30xxgmx_sgmii_enable(struct cn30xxgmx_port_softc *, int);
103 int	cn30xxgmx_sgmii_speed(struct cn30xxgmx_port_softc *);
104 int	cn30xxgmx_sgmii_timing(struct cn30xxgmx_port_softc *);
105 int	cn30xxgmx_tx_ovr_bp_enable(struct cn30xxgmx_port_softc *, int);
106 int	cn30xxgmx_rx_pause_enable(struct cn30xxgmx_port_softc *, int);
107 
108 #ifdef OCTEON_ETH_DEBUG
109 int	cn30xxgmx_rgmii_speed_newlink_log(struct cn30xxgmx_port_softc *,
110 	    uint64_t);
111 #endif
112 
113 static const int	cn30xxgmx_rx_adr_cam_regs[] = {
114 	GMX0_RX0_ADR_CAM0, GMX0_RX0_ADR_CAM1, GMX0_RX0_ADR_CAM2,
115 	GMX0_RX0_ADR_CAM3, GMX0_RX0_ADR_CAM4, GMX0_RX0_ADR_CAM5
116 };
117 
118 struct cn30xxgmx_port_ops cn30xxgmx_port_ops_mii = {
119 	/* XXX not implemented */
120 };
121 
122 struct cn30xxgmx_port_ops cn30xxgmx_port_ops_gmii = {
123 	.port_ops_enable = cn30xxgmx_rgmii_enable,
124 	.port_ops_speed = cn30xxgmx_rgmii_speed,
125 	.port_ops_timing = cn30xxgmx_rgmii_timing,
126 };
127 
128 struct cn30xxgmx_port_ops cn30xxgmx_port_ops_rgmii = {
129 	.port_ops_enable = cn30xxgmx_rgmii_enable,
130 	.port_ops_speed = cn30xxgmx_rgmii_speed,
131 	.port_ops_timing = cn30xxgmx_rgmii_timing,
132 };
133 
134 struct cn30xxgmx_port_ops cn30xxgmx_port_ops_sgmii = {
135 	.port_ops_enable = cn30xxgmx_sgmii_enable,
136 	.port_ops_speed = cn30xxgmx_sgmii_speed,
137 	.port_ops_timing = cn30xxgmx_sgmii_timing,
138 };
139 
140 struct cn30xxgmx_port_ops cn30xxgmx_port_ops_spi42 = {
141 	/* XXX not implemented */
142 };
143 
144 struct cn30xxgmx_port_ops *cn30xxgmx_port_ops[] = {
145 	[GMX_MII_PORT] = &cn30xxgmx_port_ops_mii,
146 	[GMX_GMII_PORT] = &cn30xxgmx_port_ops_gmii,
147 	[GMX_RGMII_PORT] = &cn30xxgmx_port_ops_rgmii,
148 	[GMX_SGMII_PORT] = &cn30xxgmx_port_ops_sgmii,
149 	[GMX_SPI42_PORT] = &cn30xxgmx_port_ops_spi42
150 };
151 
152 struct cfattach octgmx_ca = {sizeof(struct cn30xxgmx_softc),
153     cn30xxgmx_match, cn30xxgmx_attach, NULL, NULL};
154 
155 struct cfdriver octgmx_cd = {NULL, "octgmx", DV_DULL};
156 
157 int
158 cn30xxgmx_match(struct device *parent, void *match, void *aux)
159 {
160 	struct cfdata *cf = (struct cfdata *)match;
161 	struct iobus_attach_args *aa = aux;
162 
163 	if (strcmp(cf->cf_driver->cd_name, aa->aa_name) != 0)
164 		return 0;
165 	return 1;
166 }
167 
168 int
169 cn30xxgmx_get_phy_phandle(int interface, int port)
170 {
171 	char name[64];
172 	int node;
173 	int phandle = 0;
174 
175 	snprintf(name, sizeof(name),
176 	    "/soc/pip@11800a0000000/interface@%x/ethernet@%x",
177 	    interface, port);
178 	node = OF_finddevice(name);
179 	if (node != - 1)
180 		phandle = OF_getpropint(node, "phy-handle", 0);
181 	return phandle;
182 }
183 
184 void
185 cn30xxgmx_attach(struct device *parent, struct device *self, void *aux)
186 {
187 	struct cn30xxgmx_attach_args gmx_aa;
188 	struct iobus_attach_args *aa = aux;
189 	struct cn30xxgmx_port_softc *port_sc;
190 	struct cn30xxgmx_softc *sc = (void *)self;
191 	struct cn30xxsmi_softc *smi;
192 	int i;
193 	int phy_addr;
194 	int port;
195 	int status;
196 
197 	printf("\n");
198 
199 	sc->sc_regt = aa->aa_bust; /* XXX why there are iot? */
200 	sc->sc_unitno = aa->aa_unitno;
201 
202 	status = bus_space_map(sc->sc_regt, aa->aa_addr,
203 	    GMX0_BASE_IF_SIZE(sc->sc_nports), 0, &sc->sc_regh);
204 	if (status != 0)
205 		panic(": can't map register");
206 
207 	cn30xxgmx_init(sc);
208 
209 	sc->sc_ports = mallocarray(sc->sc_nports, sizeof(*sc->sc_ports),
210 	    M_DEVBUF, M_NOWAIT | M_ZERO);
211 	if (sc->sc_ports == NULL) {
212 		printf("%s: out of memory\n", sc->sc_dev.dv_xname);
213 		return;
214 	}
215 
216 	for (i = 0; i < sc->sc_nports; i++) {
217 		port = GMX_PORT_NUM(sc->sc_unitno, i);
218 		if (cn30xxsmi_get_phy(cn30xxgmx_get_phy_phandle(sc->sc_unitno,
219 		    i), port, &smi, &phy_addr))
220 			continue;
221 
222 		port_sc = &sc->sc_ports[i];
223 		port_sc->sc_port_gmx = sc;
224 		port_sc->sc_port_no = port;
225 		port_sc->sc_port_type = sc->sc_port_types[i];
226 		port_sc->sc_port_ops = cn30xxgmx_port_ops[port_sc->sc_port_type];
227 		status = bus_space_map(sc->sc_regt,
228 		    aa->aa_addr + GMX0_BASE_PORT_SIZE * i,
229 		    GMX0_BASE_PORT_SIZE, 0, &port_sc->sc_port_regh);
230 		if (status != 0)
231 			panic(": can't map port register");
232 
233 		switch (port_sc->sc_port_type) {
234 		case GMX_MII_PORT:
235 		case GMX_GMII_PORT:
236 		case GMX_RGMII_PORT: {
237 			struct cn30xxasx_attach_args asx_aa;
238 
239 			asx_aa.aa_port = i;
240 			asx_aa.aa_regt = aa->aa_bust;
241 			cn30xxasx_init(&asx_aa, &port_sc->sc_port_asx);
242 			break;
243 		}
244 		case GMX_SGMII_PORT:
245 			if (bus_space_map(sc->sc_regt,
246 			    PCS_BASE(sc->sc_unitno, i), PCS_SIZE, 0,
247 			    &port_sc->sc_port_pcs_regh))
248 				panic("could not map PCS registers");
249 			break;
250 		default:
251 			/* nothing */
252 			break;
253 		}
254 
255 		(void)memset(&gmx_aa, 0, sizeof(gmx_aa));
256 		gmx_aa.ga_regt = aa->aa_bust;
257 		gmx_aa.ga_dmat = aa->aa_dmat;
258 		gmx_aa.ga_addr = aa->aa_addr;
259 		gmx_aa.ga_name = "cnmac";
260 		gmx_aa.ga_portno = port_sc->sc_port_no;
261 		gmx_aa.ga_port_type = sc->sc_port_types[i];
262 		gmx_aa.ga_gmx = sc;
263 		gmx_aa.ga_gmx_port = port_sc;
264 		gmx_aa.ga_phy_addr = phy_addr;
265 		gmx_aa.ga_smi = smi;
266 
267 		config_found(self, &gmx_aa, cn30xxgmx_print);
268 	}
269 }
270 
271 int
272 cn30xxgmx_print(void *aux, const char *pnp)
273 {
274 	struct cn30xxgmx_attach_args *ga = aux;
275 	static const char *types[] = {
276 		[GMX_MII_PORT] = "MII",
277 		[GMX_GMII_PORT] = "GMII",
278 		[GMX_RGMII_PORT] = "RGMII",
279 		[GMX_SGMII_PORT] = "SGMII"
280 	};
281 
282 #if DEBUG
283 	if (pnp)
284 		printf("%s at %s", ga->ga_name, pnp);
285 #endif
286 
287 	printf(": %s", types[ga->ga_port_type]);
288 
289 	return UNCONF;
290 }
291 
292 int
293 cn30xxgmx_init(struct cn30xxgmx_softc *sc)
294 {
295 	int result = 0;
296 	uint64_t inf_mode;
297 	int i, id;
298 
299 	inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh, GMX0_INF_MODE);
300 	if ((inf_mode & INF_MODE_EN) == 0) {
301 		printf("ports are disabled\n");
302 		sc->sc_nports = 0;
303 		return 1;
304 	}
305 
306 	id = octeon_get_chipid();
307 
308 	switch (octeon_model_family(id)) {
309 	case OCTEON_MODEL_FAMILY_CN31XX:
310 		/*
311 		 * CN31XX-HM-1.01
312 		 * 14.1 Packet Interface Introduction
313 		 * Table 14-1 Packet Interface Configuration
314 		 * 14.8 GMX Registers, Interface Mode Register, GMX0_INF_MODE
315 		 */
316 		if ((inf_mode & INF_MODE_TYPE) == 0) {
317 			/* all three ports configured as RGMII */
318 			sc->sc_nports = 3;
319 			sc->sc_port_types[0] = GMX_RGMII_PORT;
320 			sc->sc_port_types[1] = GMX_RGMII_PORT;
321 			sc->sc_port_types[2] = GMX_RGMII_PORT;
322 		} else {
323 			/* port 0: RGMII, port 1: GMII, port 2: disabled */
324 			/* XXX CN31XX-HM-1.01 says "Port 3: disabled"; typo? */
325 			sc->sc_nports = 2;
326 			sc->sc_port_types[0] = GMX_RGMII_PORT;
327 			sc->sc_port_types[1] = GMX_GMII_PORT;
328 		}
329 		break;
330 	case OCTEON_MODEL_FAMILY_CN30XX:
331 	case OCTEON_MODEL_FAMILY_CN50XX:
332 		/*
333 		 * CN30XX-HM-1.0
334 		 * 13.1 Packet Interface Introduction
335 		 * Table 13-1 Packet Interface Configuration
336 		 * 13.8 GMX Registers, Interface Mode Register, GMX0_INF_MODE
337 		 */
338 		if ((inf_mode & INF_MODE_P0MII) == 0)
339 			sc->sc_port_types[0] = GMX_RGMII_PORT;
340 		else
341 			sc->sc_port_types[0] = GMX_MII_PORT;
342 		if ((inf_mode & INF_MODE_TYPE) == 0) {
343 			/* port 1 and 2 are configred as RGMII ports */
344 			sc->sc_nports = 3;
345 			sc->sc_port_types[1] = GMX_RGMII_PORT;
346 			sc->sc_port_types[2] = GMX_RGMII_PORT;
347 		} else {
348 			/* port 1: GMII/MII, port 2: disabled */
349 			/* GMII or MII port is slected by GMX_PRT1_CFG[SPEED] */
350 			sc->sc_nports = 2;
351 			sc->sc_port_types[1] = GMX_GMII_PORT;
352 		}
353 		/* port 2 is in CN3010/CN5010 only */
354 		if ((octeon_model(id) != OCTEON_MODEL_CN3010) &&
355 		    (octeon_model(id) != OCTEON_MODEL_CN5010))
356 			if (sc->sc_nports == 3)
357 				sc->sc_nports = 2;
358 		break;
359 	case OCTEON_MODEL_FAMILY_CN61XX: {
360 		uint64_t qlm_cfg;
361 
362 		if (sc->sc_unitno == 0)
363 			qlm_cfg = octeon_xkphys_read_8(MIO_QLM_CFG(2));
364 		else
365 			qlm_cfg = octeon_xkphys_read_8(MIO_QLM_CFG(0));
366 		if ((qlm_cfg & MIO_QLM_CFG_CFG) == 2) {
367 			sc->sc_nports = 4;
368 			for (i = 0; i < sc->sc_nports; i++)
369 				sc->sc_port_types[i] = GMX_SGMII_PORT;
370 		} else if ((qlm_cfg & MIO_QLM_CFG_CFG) == 3) {
371 			printf("XAUI interface is not supported\n");
372 			sc->sc_nports = 0;
373 			result = 1;
374 		} else {
375 			/* The interface is disabled. */
376 			sc->sc_nports = 0;
377 			result = 1;
378 		}
379 		break;
380 	}
381 	case OCTEON_MODEL_FAMILY_CN71XX:
382 		switch (inf_mode & INF_MODE_MODE) {
383 		case INF_MODE_MODE_SGMII:
384 			sc->sc_nports = 4;
385 			for (i = 0; i < sc->sc_nports; i++)
386 				sc->sc_port_types[i] = GMX_SGMII_PORT;
387 			break;
388 #ifdef notyet
389 		case INF_MODE_MODE_XAUI:
390 #endif
391 		default:
392 			sc->sc_nports = 0;
393 			result = 1;
394 		}
395 		break;
396 	case OCTEON_MODEL_FAMILY_CN38XX:
397 	case OCTEON_MODEL_FAMILY_CN56XX:
398 	case OCTEON_MODEL_FAMILY_CN58XX:
399 	default:
400 		printf("unsupported octeon model: 0x%x\n", octeon_get_chipid());
401 		sc->sc_nports = 0;
402 		result = 1;
403 		break;
404 	}
405 
406 	return result;
407 }
408 
409 /* XXX RGMII specific */
410 int
411 cn30xxgmx_link_enable(struct cn30xxgmx_port_softc *sc, int enable)
412 {
413 	uint64_t prt_cfg;
414 
415 	cn30xxgmx_tx_int_enable(sc, enable);
416 	cn30xxgmx_rx_int_enable(sc, enable);
417 
418 	prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
419 	if (enable) {
420 		if (cn30xxgmx_link_status(sc)) {
421 			SET(prt_cfg, PRTN_CFG_EN);
422 		}
423 	} else {
424 		CLR(prt_cfg, PRTN_CFG_EN);
425 	}
426 	_GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
427 	/*
428 	 * According to CN30XX-HM-1.0, 13.4.2 Link Status Changes:
429 	 * > software should read back to flush the write operation.
430 	 */
431 	(void)_GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
432 
433 	return 0;
434 }
435 
436 /* XXX RGMII specific */
437 int
438 cn30xxgmx_stats_init(struct cn30xxgmx_port_softc *sc)
439 {
440         _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS, 0x0ULL);
441         _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_DRP, 0x0ULL);
442         _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_BAD, 0x0ULL);
443         _GMX_PORT_WR8(sc, GMX0_TX0_STAT0, 0x0ULL);
444         _GMX_PORT_WR8(sc, GMX0_TX0_STAT1, 0x0ULL);
445         _GMX_PORT_WR8(sc, GMX0_TX0_STAT3, 0x0ULL);
446         _GMX_PORT_WR8(sc, GMX0_TX0_STAT9, 0x0ULL);
447 	return 0;
448 }
449 
450 int
451 cn30xxgmx_tx_stats_rd_clr(struct cn30xxgmx_port_softc *sc, int enable)
452 {
453 	_GMX_PORT_WR8(sc, GMX0_TX0_STATS_CTL, enable ? 0x1ULL : 0x0ULL);
454 	return 0;
455 }
456 
457 int
458 cn30xxgmx_rx_stats_rd_clr(struct cn30xxgmx_port_softc *sc, int enable)
459 {
460 	_GMX_PORT_WR8(sc, GMX0_RX0_STATS_CTL, enable ? 0x1ULL : 0x0ULL);
461 	return 0;
462 }
463 
464 void
465 cn30xxgmx_rx_stats_dec_bad(struct cn30xxgmx_port_softc *sc)
466 {
467 	uint64_t tmp;
468 
469         tmp = _GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_BAD);
470 	_GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_BAD, tmp - 1);
471 }
472 
473 int
474 cn30xxgmx_tx_ovr_bp_enable(struct cn30xxgmx_port_softc *sc, int enable)
475 {
476 	uint64_t ovr_bp;
477 	int index = GMX_PORT_INDEX(sc->sc_port_no);
478 
479 	ovr_bp = _GMX_RD8(sc, GMX0_TX_OVR_BP);
480 	if (enable) {
481 		CLR(ovr_bp, (1 << index) << TX_OVR_BP_EN_SHIFT);
482 		SET(ovr_bp, (1 << index) << TX_OVR_BP_BP_SHIFT);
483 		/* XXX really??? */
484 		SET(ovr_bp, (1 << index) << TX_OVR_BP_IGN_FULL_SHIFT);
485 	} else {
486 		SET(ovr_bp, (1 << index) << TX_OVR_BP_EN_SHIFT);
487 		CLR(ovr_bp, (1 << index) << TX_OVR_BP_BP_SHIFT);
488 		/* XXX really??? */
489 		SET(ovr_bp, (1 << index) << TX_OVR_BP_IGN_FULL_SHIFT);
490 	}
491 	_GMX_WR8(sc, GMX0_TX_OVR_BP, ovr_bp);
492 	return 0;
493 }
494 
495 int
496 cn30xxgmx_rx_pause_enable(struct cn30xxgmx_port_softc *sc, int enable)
497 {
498 	if (enable) {
499 		cn30xxgmx_rx_frm_ctl_enable(sc, RXN_FRM_CTL_CTL_BCK);
500 	} else {
501 		cn30xxgmx_rx_frm_ctl_disable(sc, RXN_FRM_CTL_CTL_BCK);
502 	}
503 
504 	return 0;
505 }
506 
507 void
508 cn30xxgmx_tx_int_enable(struct cn30xxgmx_port_softc *sc, int enable)
509 {
510 	uint64_t tx_int_xxx = 0;
511 
512 	SET(tx_int_xxx,
513 	    TX_INT_REG_LATE_COL |
514 	    TX_INT_REG_XSDEF |
515 	    TX_INT_REG_XSCOL |
516 	    TX_INT_REG_UNDFLW |
517 	    TX_INT_REG_PKO_NXA);
518 	_GMX_WR8(sc, GMX0_TX_INT_REG, tx_int_xxx);
519 	_GMX_WR8(sc, GMX0_TX_INT_EN, enable ? tx_int_xxx : 0);
520 }
521 
522 void
523 cn30xxgmx_rx_int_enable(struct cn30xxgmx_port_softc *sc, int enable)
524 {
525 	uint64_t rx_int_xxx = 0;
526 
527 	SET(rx_int_xxx, 0 |
528 	    RXN_INT_REG_PHY_DUPX |
529 	    RXN_INT_REG_PHY_SPD |
530 	    RXN_INT_REG_PHY_LINK |
531 	    RXN_INT_REG_IFGERR |
532 	    RXN_INT_REG_COLDET |
533 	    RXN_INT_REG_FALERR |
534 	    RXN_INT_REG_RSVERR |
535 	    RXN_INT_REG_PCTERR |
536 	    RXN_INT_REG_OVRERR |
537 	    RXN_INT_REG_NIBERR |
538 	    RXN_INT_REG_SKPERR |
539 	    RXN_INT_REG_RCVERR |
540 	    RXN_INT_REG_LENERR |
541 	    RXN_INT_REG_ALNERR |
542 	    RXN_INT_REG_FCSERR |
543 	    RXN_INT_REG_JABBER |
544 	    RXN_INT_REG_MAXERR |
545 	    RXN_INT_REG_CAREXT |
546 	    RXN_INT_REG_MINERR);
547 	_GMX_PORT_WR8(sc, GMX0_RX0_INT_REG, rx_int_xxx);
548 	_GMX_PORT_WR8(sc, GMX0_RX0_INT_EN, enable ? rx_int_xxx : 0);
549 }
550 
551 int
552 cn30xxgmx_rx_frm_ctl_enable(struct cn30xxgmx_port_softc *sc,
553     uint64_t rx_frm_ctl)
554 {
555 	struct ifnet *ifp = &sc->sc_port_ac->ac_if;
556 	unsigned int maxlen;
557 
558 	maxlen = roundup(ifp->if_hardmtu + ETHER_HDR_LEN + ETHER_CRC_LEN +
559 	    ETHER_VLAN_ENCAP_LEN, 8);
560 	_GMX_PORT_WR8(sc, GMX0_RX0_JABBER, maxlen);
561 
562 	return cn30xxgmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 1);
563 }
564 
565 int
566 cn30xxgmx_rx_frm_ctl_disable(struct cn30xxgmx_port_softc *sc,
567     uint64_t rx_frm_ctl)
568 {
569 	return cn30xxgmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 0);
570 }
571 
572 int
573 cn30xxgmx_rx_frm_ctl_xable(struct cn30xxgmx_port_softc *sc,
574     uint64_t rx_frm_ctl, int enable)
575 {
576 	uint64_t tmp;
577 
578 	tmp = _GMX_PORT_RD8(sc, GMX0_RX0_FRM_CTL);
579 	if (enable)
580 		SET(tmp, rx_frm_ctl);
581 	else
582 		CLR(tmp, rx_frm_ctl);
583 	_GMX_PORT_WR8(sc, GMX0_RX0_FRM_CTL, tmp);
584 
585 	return 0;
586 }
587 
588 int
589 cn30xxgmx_tx_thresh(struct cn30xxgmx_port_softc *sc, int cnt)
590 {
591 	_GMX_PORT_WR8(sc, GMX0_TX0_THRESH, cnt);
592 	return 0;
593 }
594 
595 int
596 cn30xxgmx_set_mac_addr(struct cn30xxgmx_port_softc *sc, uint8_t *addr)
597 {
598 	uint64_t mac;
599 	int i;
600 
601 	ADDR2UINT64(mac, addr);
602 
603 	cn30xxgmx_link_enable(sc, 0);
604 
605 	sc->sc_mac = mac;
606 	_GMX_PORT_WR8(sc, GMX0_SMAC0, mac);
607 	for (i = 0; i < 6; i++)
608 		_GMX_PORT_WR8(sc, cn30xxgmx_rx_adr_cam_regs[i], addr[i]);
609 
610 	cn30xxgmx_link_enable(sc, 1);
611 
612 	return 0;
613 }
614 
615 int
616 cn30xxgmx_set_filter(struct cn30xxgmx_port_softc *sc)
617 {
618 	struct ifnet *ifp = &sc->sc_port_ac->ac_if;
619 	struct arpcom *ac = sc->sc_port_ac;
620 	struct ether_multi *enm;
621 	struct ether_multistep step;
622 	uint64_t cam_en = 0x01ULL;
623 	uint64_t ctl = 0;
624 	int multi = 0;
625 
626 	cn30xxgmx_link_enable(sc, 0);
627 
628 	SET(ctl, RXN_ADR_CTL_CAM_MODE);
629 	CLR(ctl, RXN_ADR_CTL_MCST_ACCEPT | RXN_ADR_CTL_MCST_AFCAM |
630 	    RXN_ADR_CTL_MCST_REJECT);
631 	CLR(ifp->if_flags, IFF_ALLMULTI);
632 
633 	/*
634 	 * Always accept broadcast frames.
635 	 */
636 	SET(ctl, RXN_ADR_CTL_BCST);
637 
638 	if (ISSET(ifp->if_flags, IFF_PROMISC)) {
639 		SET(ifp->if_flags, IFF_ALLMULTI);
640 		CLR(ctl, RXN_ADR_CTL_CAM_MODE);
641 		SET(ctl, RXN_ADR_CTL_MCST_ACCEPT);
642 		cam_en = 0x00ULL;
643 	} else if (ac->ac_multirangecnt > 0 || ac->ac_multicnt > 7) {
644 		SET(ifp->if_flags, IFF_ALLMULTI);
645 		SET(ctl, RXN_ADR_CTL_MCST_ACCEPT);
646 	} else {
647 		/*
648 		 * Note first entry is self MAC address; other 7 entires are
649 		 * available for multicast addresses.
650 		 */
651 		ETHER_FIRST_MULTI(step, sc->sc_port_ac, enm);
652 		while (enm != NULL) {
653 			int i;
654 
655 			dprintf("%d: %02x:%02x:%02x:%02x:%02x:%02x\n"
656 			    multi + 1,
657 			    enm->enm_addrlo[0], enm->enm_addrlo[1],
658 			    enm->enm_addrlo[2], enm->enm_addrlo[3],
659 			    enm->enm_addrlo[4], enm->enm_addrlo[5]);
660 			multi++;
661 
662 			SET(cam_en, 1ULL << multi); /* XXX */
663 
664 			for (i = 0; i < 6; i++) {
665 				uint64_t tmp;
666 
667 				/* XXX */
668 				tmp = _GMX_PORT_RD8(sc,
669 				    cn30xxgmx_rx_adr_cam_regs[i]);
670 				CLR(tmp, 0xffULL << (8 * multi));
671 				SET(tmp, (uint64_t)enm->enm_addrlo[i] <<
672 				    (8 * multi));
673 				_GMX_PORT_WR8(sc, cn30xxgmx_rx_adr_cam_regs[i],
674 				    tmp);
675 			}
676 
677 			for (i = 0; i < 6; i++)
678 				dprintf("cam%d = %016llx\n", i,
679 				    _GMX_PORT_RD8(sc,
680 				    cn30xxgmx_rx_adr_cam_regs[i]));
681 
682 			ETHER_NEXT_MULTI(step, enm);
683 		}
684 
685 		if (multi)
686 			SET(ctl, RXN_ADR_CTL_MCST_AFCAM);
687 		else
688 			SET(ctl, RXN_ADR_CTL_MCST_REJECT);
689 
690 		OCTEON_ETH_KASSERT(enm == NULL);
691 	}
692 
693 	dprintf("ctl = %llx, cam_en = %llx\n", ctl, cam_en);
694 	_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, ctl);
695 	_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, cam_en);
696 
697 	cn30xxgmx_link_enable(sc, 1);
698 
699 	return 0;
700 }
701 
702 int
703 cn30xxgmx_port_enable(struct cn30xxgmx_port_softc *sc, int enable)
704 {
705 	(*sc->sc_port_ops->port_ops_enable)(sc, enable);
706 	return 0;
707 }
708 
709 int
710 cn30xxgmx_reset_speed(struct cn30xxgmx_port_softc *sc)
711 {
712 	struct ifnet *ifp = &sc->sc_port_ac->ac_if;
713 	if (ISSET(sc->sc_port_mii->mii_flags, MIIF_DOINGAUTO)) {
714 		log(LOG_WARNING,
715 		    "%s: autonegotiation has not been completed yet\n",
716 		    ifp->if_xname);
717 		return 1;
718 	}
719 	(*sc->sc_port_ops->port_ops_speed)(sc);
720 	return 0;
721 }
722 
723 int
724 cn30xxgmx_reset_timing(struct cn30xxgmx_port_softc *sc)
725 {
726 	(*sc->sc_port_ops->port_ops_timing)(sc);
727 	return 0;
728 }
729 
730 int
731 cn30xxgmx_reset_flowctl(struct cn30xxgmx_port_softc *sc)
732 {
733 	struct ifmedia_entry *ife = sc->sc_port_mii->mii_media.ifm_cur;
734 
735 	/*
736 	 * Get flow control negotiation result.
737 	 */
738 #ifdef GMX_802_3X_DISABLE_AUTONEG
739 	/* Tentative support for SEIL-compat.. */
740 	if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
741 		sc->sc_port_flowflags &= ~IFM_ETH_FMASK;
742 	}
743 #else
744 	/* Default configuration of NetBSD */
745 	if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO &&
746 	    (sc->sc_port_mii->mii_media_active & IFM_ETH_FMASK) !=
747 			sc->sc_port_flowflags) {
748 		sc->sc_port_flowflags =
749 			sc->sc_port_mii->mii_media_active & IFM_ETH_FMASK;
750 		sc->sc_port_mii->mii_media_active &= ~IFM_ETH_FMASK;
751 	}
752 #endif /* GMX_802_3X_DISABLE_AUTONEG */
753 
754 	/*
755 	 * 802.3x Flow Control Capabilities
756 	 */
757 	if (sc->sc_port_flowflags & IFM_ETH_TXPAUSE) {
758 		cn30xxgmx_tx_ovr_bp_enable(sc, 1);
759 	} else {
760 		cn30xxgmx_tx_ovr_bp_enable(sc, 0);
761 	}
762 	if (sc->sc_port_flowflags & IFM_ETH_RXPAUSE) {
763 		cn30xxgmx_rx_pause_enable(sc, 1);
764 	} else {
765 		cn30xxgmx_rx_pause_enable(sc, 0);
766 	}
767 
768 	return 0;
769 }
770 
771 int
772 cn30xxgmx_rgmii_enable(struct cn30xxgmx_port_softc *sc, int enable)
773 {
774 	uint64_t mode;
775 
776 	/* XXX */
777 	mode = _GMX_RD8(sc, GMX0_INF_MODE);
778 	if (ISSET(mode, INF_MODE_EN)) {
779 		cn30xxasx_enable(sc->sc_port_asx, 1);
780 	}
781 
782 	return 0;
783 }
784 
785 int
786 cn30xxgmx_rgmii_speed(struct cn30xxgmx_port_softc *sc)
787 {
788 	struct ifnet *ifp = &sc->sc_port_ac->ac_if;
789 	uint64_t newlink;
790 	int baudrate;
791 
792 	/* XXX */
793 	cn30xxgmx_link_enable(sc, 1);
794 
795 	cn30xxgmx_rgmii_speed_newlink(sc, &newlink);
796 	if (sc->sc_link == newlink) {
797 		return 0;
798 	}
799 #ifdef OCTEON_ETH_DEBUG
800 	cn30xxgmx_rgmii_speed_newlink_log(sc, newlink);
801 #endif
802 	sc->sc_link = newlink;
803 
804 	switch (sc->sc_link & RXN_RX_INBND_SPEED) {
805 	case RXN_RX_INBND_SPEED_2_5:
806 		baudrate = IF_Mbps(10);
807 		break;
808 	case RXN_RX_INBND_SPEED_25:
809 		baudrate = IF_Mbps(100);
810 		break;
811 	case RXN_RX_INBND_SPEED_125:
812 		baudrate = IF_Gbps(1);
813 		break;
814 	default:
815 		baudrate = 0/* XXX */;
816 		break;
817 	}
818 	ifp->if_baudrate = baudrate;
819 
820 	cn30xxgmx_link_enable(sc, 0);
821 
822 	/*
823 	 * According to CN30XX-HM-1.0, 13.4.2 Link Status Changes:
824 	 * wait a max_packet_time
825 	 * max_packet_time(us) = (max_packet_size(bytes) * 8) / link_speed(Mbps)
826 	 */
827 	delay((GMX_FRM_MAX_SIZ * 8) / (baudrate / 1000000));
828 
829 	cn30xxgmx_rgmii_speed_speed(sc);
830 
831 	cn30xxgmx_link_enable(sc, 1);
832 	cn30xxasx_enable(sc->sc_port_asx, 1);
833 
834 	return 0;
835 }
836 
837 int
838 cn30xxgmx_rgmii_speed_newlink(struct cn30xxgmx_port_softc *sc,
839     uint64_t *rnewlink)
840 {
841 	uint64_t newlink;
842 
843 	/* Inband status does not seem to work */
844 	newlink = _GMX_PORT_RD8(sc, GMX0_RX0_RX_INBND);
845 
846 	*rnewlink = newlink;
847 	return 0;
848 }
849 
850 #ifdef OCTEON_ETH_DEBUG
851 int
852 cn30xxgmx_rgmii_speed_newlink_log(struct cn30xxgmx_port_softc *sc,
853     uint64_t newlink)
854 {
855 	struct ifnet *ifp = &sc->sc_port_ac->ac_if;
856 	const char *status_str;
857 	const char *speed_str;
858 	const char *duplex_str;
859 	int is_status_changed;
860 	int is_speed_changed;
861 	int is_linked;
862 	char status_buf[80/* XXX */];
863 	char speed_buf[80/* XXX */];
864 
865 	is_status_changed = (newlink & RXN_RX_INBND_STATUS) !=
866 	    (sc->sc_link & RXN_RX_INBND_STATUS);
867 	is_speed_changed = (newlink & RXN_RX_INBND_SPEED) !=
868 	    (sc->sc_link & RXN_RX_INBND_SPEED);
869 	is_linked = ISSET(newlink, RXN_RX_INBND_STATUS);
870 	if (is_status_changed) {
871 		if (is_linked)
872 			status_str = "link up";
873 		else
874 			status_str = "link down";
875 	} else {
876 		if (is_linked) {
877 			/* any other conditions? */
878 			if (is_speed_changed)
879 				status_str = "link change";
880 			else
881 				status_str = NULL;
882 		} else {
883 			status_str = NULL;
884 		}
885 	}
886 
887 	if (status_str != NULL) {
888 		if ((is_speed_changed && is_linked) || is_linked) {
889 			switch (newlink & RXN_RX_INBND_SPEED) {
890 			case RXN_RX_INBND_SPEED_2_5:
891 				speed_str = "10baseT";
892 				break;
893 			case RXN_RX_INBND_SPEED_25:
894 				speed_str = "100baseTX";
895 				break;
896 			case RXN_RX_INBND_SPEED_125:
897 				speed_str = "1000baseT";
898 				break;
899 			default:
900 				panic("Unknown link speed");
901 				break;
902 			}
903 
904 			if (ISSET(newlink, RXN_RX_INBND_DUPLEX))
905 				duplex_str = "-FDX";
906 			else
907 				duplex_str = "";
908 
909 			(void)snprintf(speed_buf, sizeof(speed_buf), "(%s%s)",
910 			    speed_str, duplex_str);
911 		} else {
912 			speed_buf[0] = '\0';
913 		}
914 		(void)snprintf(status_buf, sizeof(status_buf), "%s: %s%s%s\n",
915 		    ifp->if_xname, status_str, (is_speed_changed | is_linked) ? " " : "",
916 		    speed_buf);
917 		log(LOG_CRIT, status_buf);
918 	}
919 
920 	return 0;
921 }
922 #endif
923 
924 int
925 cn30xxgmx_rgmii_speed_speed(struct cn30xxgmx_port_softc *sc)
926 {
927 	uint64_t prt_cfg;
928 	uint64_t tx_clk, tx_slot, tx_burst;
929 
930 	prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
931 
932 	switch (sc->sc_link & RXN_RX_INBND_SPEED) {
933 	case RXN_RX_INBND_SPEED_2_5:
934 		/* 10Mbps */
935 		/*
936 		 * "GMX Tx Clock Generation Registers", CN30XX-HM-1.0;
937 		 * > 8ns x 50 = 400ns (2.5MHz TXC clock)
938 		 */
939 		tx_clk = 50;
940 		/*
941 		 * "TX Slottime Counter Registers", CN30XX-HM-1.0;
942 		 * > 10/100Mbps: set SLOT to 0x40
943 		 */
944 		tx_slot = 0x40;
945 		/*
946 		 * "TX Burst-Counter Registers", CN30XX-HM-1.0;
947 		 * > 10/100Mbps: set BURST to 0x0
948 		 */
949 		tx_burst = 0;
950 		/*
951 		 * "GMX Tx Port Configuration Registers", CN30XX-HM-1.0;
952 		 * > Slot time for half-duplex operation
953 		 * >   0 = 512 bittimes (10/100Mbps operation)
954 		 */
955 		CLR(prt_cfg, PRTN_CFG_SLOTTIME);
956 		/*
957 		 * "GMX Port Configuration Registers", CN30XX-HM-1.0;
958 		 * > Link speed
959 		 * >   0 = 10/100Mbps operation
960 		 * >     in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
961 		 */
962 		CLR(prt_cfg, PRTN_CFG_SPEED);
963 		break;
964 	case RXN_RX_INBND_SPEED_25:
965 		/* 100Mbps */
966 		/*
967 		 * "GMX Tx Clock Generation Registers", CN30XX-HM-1.0;
968 		 * > 8ns x 5 = 40ns (25.0MHz TXC clock)
969 		 */
970 		tx_clk = 5;
971 		/*
972 		 * "TX Slottime Counter Registers", CN30XX-HM-1.0;
973 		 * > 10/100Mbps: set SLOT to 0x40
974 		 */
975 		tx_slot = 0x40;
976 		/*
977 		 * "TX Burst-Counter Registers", CN30XX-HM-1.0;
978 		 * > 10/100Mbps: set BURST to 0x0
979 		 */
980 		tx_burst = 0;
981 		/*
982 		 * "GMX Tx Port Configuration Registers", CN30XX-HM-1.0;
983 		 * > Slot time for half-duplex operation
984 		 * >   0 = 512 bittimes (10/100Mbps operation)
985 		 */
986 		CLR(prt_cfg, PRTN_CFG_SLOTTIME);
987 		/*
988 		 * "GMX Port Configuration Registers", CN30XX-HM-1.0;
989 		 * > Link speed
990 		 * >   0 = 10/100Mbps operation
991 		 * >     in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
992 		 */
993 		CLR(prt_cfg, PRTN_CFG_SPEED);
994 		break;
995 	case RXN_RX_INBND_SPEED_125:
996 		/* 1000Mbps */
997 		/*
998 		 * "GMX Tx Clock Generation Registers", CN30XX-HM-1.0;
999 		 * > 8ns x 1 = 8ns (125.0MHz TXC clock)
1000 		 */
1001 		tx_clk = 1;
1002 		/*
1003 		 * "TX Slottime Counter Registers", CN30XX-HM-1.0;
1004 		 * > 1000Mbps: set SLOT to 0x200
1005 		 */
1006 		tx_slot = 0x200;
1007 		/*
1008 		 * "TX Burst-Counter Registers", CN30XX-HM-1.0;
1009 		 * > 1000Mbps: set BURST to 0x2000
1010 		 */
1011 		tx_burst = 0x2000;
1012 		/*
1013 		 * "GMX Tx Port Configuration Registers", CN30XX-HM-1.0;
1014 		 * > Slot time for half-duplex operation
1015 		 * >   1 = 4096 bittimes (1000Mbps operation)
1016 		 */
1017 		SET(prt_cfg, PRTN_CFG_SLOTTIME);
1018 		/*
1019 		 * "GMX Port Configuration Registers", CN30XX-HM-1.0;
1020 		 * > Link speed
1021 		 * >   1 = 1000Mbps operation
1022 		 */
1023 		SET(prt_cfg, PRTN_CFG_SPEED);
1024 		break;
1025 	default:
1026 		/* NOT REACHED! */
1027 		/* Following configuration is default value of system.
1028 		*/
1029 		tx_clk = 1;
1030 		tx_slot = 0x200;
1031 		tx_burst = 0x2000;
1032 		SET(prt_cfg, PRTN_CFG_SLOTTIME);
1033 		SET(prt_cfg, PRTN_CFG_SPEED);
1034 		break;
1035 	}
1036 
1037 	/* Setup Duplex mode(negotiated) */
1038 	/*
1039 	 * "GMX Port Configuration Registers", CN30XX-HM-1.0;
1040 	 * > Duplex mode: 0 = half-duplex mode, 1=full-duplex
1041 	 */
1042 	if (ISSET(sc->sc_link, RXN_RX_INBND_DUPLEX)) {
1043 		/* Full-Duplex */
1044 		SET(prt_cfg, PRTN_CFG_DUPLEX);
1045 	} else {
1046 		/* Half-Duplex */
1047 		CLR(prt_cfg, PRTN_CFG_DUPLEX);
1048 	}
1049 
1050 	_GMX_PORT_WR8(sc, GMX0_TX0_CLK, tx_clk);
1051 	_GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot);
1052 	_GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst);
1053 	_GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
1054 
1055 	return 0;
1056 }
1057 
1058 int
1059 cn30xxgmx_rgmii_timing(struct cn30xxgmx_port_softc *sc)
1060 {
1061 	int clk_tx_setting;
1062 	int clk_rx_setting;
1063 	uint64_t rx_frm_ctl;
1064 
1065 	/* RGMII TX Threshold Registers, CN30XX-HM-1.0;
1066 	 * > Number of 16-byte ticks to accumulate in the TX FIFO before
1067 	 * > sending on the RGMII interface. This field should be large
1068 	 * > enough to prevent underflow on the RGMII interface and must
1069 	 * > never be set to less than 0x4. This register cannot exceed
1070 	 * > the TX FIFO depth of 0x40 words.
1071 	 */
1072 	/* Default parameter of CN30XX */
1073 	cn30xxgmx_tx_thresh(sc, 32);
1074 
1075 	rx_frm_ctl = 0 |
1076 	    /* RXN_FRM_CTL_NULL_DIS |	(cn5xxx only) */
1077 	    /* RXN_FRM_CTL_PRE_ALIGN |	(cn5xxx only) */
1078 	    /* RXN_FRM_CTL_PAD_LEN |	(cn3xxx only) */
1079 	    /* RXN_FRM_CTL_VLAN_LEN |	(cn3xxx only) */
1080 	    RXN_FRM_CTL_PRE_FREE |
1081 	    RXN_FRM_CTL_CTL_SMAC |
1082 	    RXN_FRM_CTL_CTL_MCST |
1083 	    RXN_FRM_CTL_CTL_DRP |
1084 	    RXN_FRM_CTL_PRE_STRP |
1085 	    RXN_FRM_CTL_PRE_CHK;
1086 	cn30xxgmx_rx_frm_ctl_enable(sc, rx_frm_ctl);
1087 
1088 	/* XXX PHY-dependent parameter */
1089 	/* RGMII RX Clock-Delay Registers, CN30XX-HM-1.0;
1090 	 * > Delay setting to place n RXC (RGMII receive clock) delay line.
1091 	 * > The intrinsic delay can range from 50ps to 80ps per tap,
1092 	 * > which corresponds to skews of 1.25ns to 2.00ns at 25 taps(CSR+1).
1093 	 * > This is the best match for the RGMII specification which wants
1094 	 * > 1ns - 2.6ns of skew.
1095 	 */
1096 	/* RGMII TX Clock-Delay Registers, CN30XX-HM-1.0;
1097 	 * > Delay setting to place n TXC (RGMII transmit clock) delay line.
1098 	 * > ...
1099 	 */
1100 
1101 	switch (octeon_boot_info->board_type) {
1102 	default:
1103 		/* Default parameter of CN30XX */
1104 		clk_tx_setting = 24;
1105 		clk_rx_setting = 24;
1106 		break;
1107 	case BOARD_TYPE_UBIQUITI_E100:
1108 	case BOARD_TYPE_UBIQUITI_E120:
1109 		clk_tx_setting = 16;
1110 		clk_rx_setting = 0;
1111 		break;
1112 	}
1113 
1114 	cn30xxasx_clk_set(sc->sc_port_asx, clk_tx_setting, clk_rx_setting);
1115 
1116 	return 0;
1117 }
1118 
1119 int
1120 cn30xxgmx_sgmii_enable(struct cn30xxgmx_port_softc *sc, int enable)
1121 {
1122 	uint64_t ctl_reg, status, timer_count;
1123 	uint64_t cpu_freq = octeon_boot_info->eclock / 1000000;
1124 	int done;
1125 	int i;
1126 
1127 	if (!enable)
1128 		return 0;
1129 
1130 	/* Set link timer interval to 1.6ms. */
1131 	timer_count = PCS_READ_8(sc, PCS_LINK_TIMER_COUNT);
1132 	CLR(timer_count, PCS_LINK_TIMER_COUNT_MASK);
1133 	SET(timer_count, ((1600 * cpu_freq) >> 10) & PCS_LINK_TIMER_COUNT_MASK);
1134 	PCS_WRITE_8(sc, PCS_LINK_TIMER_COUNT, timer_count);
1135 
1136 	/* Reset the PCS. */
1137 	ctl_reg = PCS_READ_8(sc, PCS_MR_CONTROL);
1138 	SET(ctl_reg, PCS_MR_CONTROL_RESET);
1139 	PCS_WRITE_8(sc, PCS_MR_CONTROL, ctl_reg);
1140 
1141 	/* Wait for the reset to complete. */
1142 	done = 0;
1143 	for (i = 0; i < 1000000; i++) {
1144 		ctl_reg = PCS_READ_8(sc, PCS_MR_CONTROL);
1145 		if (!ISSET(ctl_reg, PCS_MR_CONTROL_RESET)) {
1146 			done = 1;
1147 			break;
1148 		}
1149 	}
1150 	if (!done) {
1151 		printf("SGMII reset timeout on port %d\n", sc->sc_port_no);
1152 		return 1;
1153 	}
1154 
1155 	/* Start a new SGMII autonegotiation. */
1156 	SET(ctl_reg, PCS_MR_CONTROL_AN_EN);
1157 	SET(ctl_reg, PCS_MR_CONTROL_RST_AN);
1158 	CLR(ctl_reg, PCS_MR_CONTROL_PWR_DN);
1159 	PCS_WRITE_8(sc, PCS_MR_CONTROL, ctl_reg);
1160 
1161 	/* Wait for the SGMII autonegotiation to complete. */
1162 	done = 0;
1163 	for (i = 0; i < 1000000; i++) {
1164 		status = PCS_READ_8(sc, PCS_MR_STATUS);
1165 		if (ISSET(status, PCS_MR_STATUS_AN_CPT)) {
1166 			done = 1;
1167 			break;
1168 		}
1169 	}
1170 	if (!done) {
1171 		printf("SGMII autonegotiation timeout on port %d\n",
1172 		    sc->sc_port_no);
1173 		return 1;
1174 	}
1175 
1176 	return 0;
1177 }
1178 
1179 int
1180 cn30xxgmx_sgmii_speed(struct cn30xxgmx_port_softc *sc)
1181 {
1182 	uint64_t misc_ctl, prt_cfg;
1183 	int tx_burst, tx_slot;
1184 
1185 	cn30xxgmx_link_enable(sc, 0);
1186 
1187 	prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
1188 
1189 	if (ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX))
1190 		SET(prt_cfg, PRTN_CFG_DUPLEX);
1191 	else
1192 		CLR(prt_cfg, PRTN_CFG_DUPLEX);
1193 
1194 	misc_ctl = PCS_READ_8(sc, PCS_MISC_CTL);
1195 	CLR(misc_ctl, PCS_MISC_CTL_SAMP_PT);
1196 
1197 	/* Disable the GMX port if the link is down. */
1198 	if (cn30xxgmx_link_status(sc))
1199 		CLR(misc_ctl, PCS_MISC_CTL_GMXENO);
1200 	else
1201 		SET(misc_ctl, PCS_MISC_CTL_GMXENO);
1202 
1203 	switch (sc->sc_port_ac->ac_if.if_baudrate) {
1204 	case IF_Mbps(10):
1205 		tx_slot = 0x40;
1206 		tx_burst = 0;
1207 		CLR(prt_cfg, PRTN_CFG_SPEED);
1208 		SET(prt_cfg, PRTN_CFG_SPEED_MSB);
1209 		CLR(prt_cfg, PRTN_CFG_SLOTTIME);
1210 		misc_ctl |= 25 & PCS_MISC_CTL_SAMP_PT;
1211 		break;
1212 	case IF_Mbps(100):
1213 		tx_slot = 0x40;
1214 		tx_burst = 0;
1215 		CLR(prt_cfg, PRTN_CFG_SPEED);
1216 		CLR(prt_cfg, PRTN_CFG_SPEED_MSB);
1217 		CLR(prt_cfg, PRTN_CFG_SLOTTIME);
1218 		misc_ctl |= 5 & PCS_MISC_CTL_SAMP_PT;
1219 		break;
1220 	case IF_Gbps(1):
1221 	default:
1222 		tx_slot = 0x200;
1223 		tx_burst = 0x2000;
1224 		SET(prt_cfg, PRTN_CFG_SPEED);
1225 		CLR(prt_cfg, PRTN_CFG_SPEED_MSB);
1226 		SET(prt_cfg, PRTN_CFG_SLOTTIME);
1227 		misc_ctl |= 1 & PCS_MISC_CTL_SAMP_PT;
1228 		break;
1229 	}
1230 
1231 	PCS_WRITE_8(sc, PCS_MISC_CTL, misc_ctl);
1232 
1233 	_GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot);
1234 	_GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst);
1235 	_GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
1236 
1237 	cn30xxgmx_link_enable(sc, 1);
1238 
1239 	return 0;
1240 }
1241 
1242 int
1243 cn30xxgmx_sgmii_timing(struct cn30xxgmx_port_softc *sc)
1244 {
1245 	uint64_t rx_frm_ctl;
1246 
1247 	cn30xxgmx_tx_thresh(sc, 32);
1248 
1249 	rx_frm_ctl =
1250 	    RXN_FRM_CTL_PRE_FREE |
1251 	    RXN_FRM_CTL_CTL_SMAC |
1252 	    RXN_FRM_CTL_CTL_MCST |
1253 	    RXN_FRM_CTL_CTL_DRP |
1254 	    RXN_FRM_CTL_PRE_STRP |
1255 	    RXN_FRM_CTL_PRE_CHK;
1256 	cn30xxgmx_rx_frm_ctl_enable(sc, rx_frm_ctl);
1257 
1258 	return 0;
1259 }
1260 
1261 void
1262 cn30xxgmx_stats(struct cn30xxgmx_port_softc *sc)
1263 {
1264 	struct ifnet *ifp = &sc->sc_port_ac->ac_if;
1265 	uint64_t tmp;
1266 
1267 	ifp->if_ierrors +=
1268 	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_BAD);
1269 	ifp->if_iqdrops +=
1270 	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_DRP);
1271 	tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT0);
1272 	ifp->if_oerrors +=
1273 	    (uint32_t)tmp + ((uint32_t)(tmp >> 32) * 16);
1274 	ifp->if_collisions += ((uint32_t)tmp) * 16;
1275 	tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT1);
1276 	ifp->if_collisions +=
1277 	    ((uint32_t)tmp * 2) + (uint32_t)(tmp >> 32);
1278 	tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT9);
1279 	ifp->if_oerrors += (uint32_t)(tmp >> 32);
1280 }
1281