1/*	$OpenBSD: cn30xxgmx.c,v 1.54 2024/05/20 23:13:33 jsg 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 AUTHORS 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 AUTHORS 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 GMX_NCAM	8
51
52#define	_GMX_RD8(sc, off) \
53	bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off))
54#define	_GMX_WR8(sc, off, v) \
55	bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off), (v))
56#define	_GMX_PORT_RD8(sc, off) \
57	bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off))
58#define	_GMX_PORT_WR8(sc, off, v) \
59	bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off), (v))
60
61#define AGL_GMX_RD8(sc, reg) \
62	bus_space_read_8((sc)->sc_port_gmx->sc_regt, \
63	    (sc)->sc_port_gmx->sc_regh, (reg))
64#define AGL_GMX_WR8(sc, reg, val) \
65	bus_space_write_8((sc)->sc_port_gmx->sc_regt, \
66	    (sc)->sc_port_gmx->sc_regh, (reg), (val))
67#define AGL_GMX_PORT_RD8(sc, reg) \
68	bus_space_read_8((sc)->sc_port_gmx->sc_regt, \
69	    (sc)->sc_port_regh, (reg))
70#define AGL_GMX_PORT_WR8(sc, reg, val) \
71	bus_space_write_8((sc)->sc_port_gmx->sc_regt, \
72	    (sc)->sc_port_regh, (reg), (val))
73
74#define PCS_READ_8(sc, reg) \
75	bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_pcs_regh, \
76	    (reg))
77#define PCS_WRITE_8(sc, reg, val) \
78	bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_pcs_regh, \
79	    (reg), (val))
80
81struct cn30xxgmx_port_ops {
82	int	(*port_ops_enable)(struct cn30xxgmx_port_softc *, int);
83	int	(*port_ops_speed)(struct cn30xxgmx_port_softc *);
84	int	(*port_ops_timing)(struct cn30xxgmx_port_softc *);
85};
86
87int	cn30xxgmx_match(struct device *, void *, void *);
88void	cn30xxgmx_attach(struct device *, struct device *, void *);
89int	cn30xxgmx_print(void *, const char *);
90void	cn30xxgmx_init(struct cn30xxgmx_softc *);
91int	cn30xxgmx_rx_frm_ctl_xable(struct cn30xxgmx_port_softc *,
92	    uint64_t, int);
93void	cn30xxgmx_agl_init(struct cn30xxgmx_port_softc *);
94int	cn30xxgmx_agl_enable(struct cn30xxgmx_port_softc *, int);
95int	cn30xxgmx_agl_speed(struct cn30xxgmx_port_softc *);
96int	cn30xxgmx_agl_timing(struct cn30xxgmx_port_softc *);
97int	cn30xxgmx_rgmii_enable(struct cn30xxgmx_port_softc *, int);
98int	cn30xxgmx_rgmii_speed(struct cn30xxgmx_port_softc *);
99int	cn30xxgmx_rgmii_speed_newlink(struct cn30xxgmx_port_softc *,
100	    uint64_t *);
101int	cn30xxgmx_rgmii_speed_speed(struct cn30xxgmx_port_softc *);
102int	cn30xxgmx_rgmii_timing(struct cn30xxgmx_port_softc *);
103int	cn30xxgmx_sgmii_enable(struct cn30xxgmx_port_softc *, int);
104int	cn30xxgmx_sgmii_speed(struct cn30xxgmx_port_softc *);
105int	cn30xxgmx_sgmii_timing(struct cn30xxgmx_port_softc *);
106int	cn30xxgmx_tx_ovr_bp_enable(struct cn30xxgmx_port_softc *, int);
107int	cn30xxgmx_rx_pause_enable(struct cn30xxgmx_port_softc *, int);
108
109#ifdef OCTEON_ETH_DEBUG
110int	cn30xxgmx_rgmii_speed_newlink_log(struct cn30xxgmx_port_softc *,
111	    uint64_t);
112#endif
113
114struct cn30xxgmx_port_ops cn30xxgmx_port_ops_agl = {
115	.port_ops_enable = cn30xxgmx_agl_enable,
116	.port_ops_speed = cn30xxgmx_agl_speed,
117	.port_ops_timing = cn30xxgmx_agl_timing,
118};
119
120struct cn30xxgmx_port_ops cn30xxgmx_port_ops_mii = {
121	/* XXX not implemented */
122};
123
124struct cn30xxgmx_port_ops cn30xxgmx_port_ops_gmii = {
125	.port_ops_enable = cn30xxgmx_rgmii_enable,
126	.port_ops_speed = cn30xxgmx_rgmii_speed,
127	.port_ops_timing = cn30xxgmx_rgmii_timing,
128};
129
130struct cn30xxgmx_port_ops cn30xxgmx_port_ops_rgmii = {
131	.port_ops_enable = cn30xxgmx_rgmii_enable,
132	.port_ops_speed = cn30xxgmx_rgmii_speed,
133	.port_ops_timing = cn30xxgmx_rgmii_timing,
134};
135
136struct cn30xxgmx_port_ops cn30xxgmx_port_ops_sgmii = {
137	.port_ops_enable = cn30xxgmx_sgmii_enable,
138	.port_ops_speed = cn30xxgmx_sgmii_speed,
139	.port_ops_timing = cn30xxgmx_sgmii_timing,
140};
141
142struct cn30xxgmx_port_ops cn30xxgmx_port_ops_spi42 = {
143	/* XXX not implemented */
144};
145
146struct cn30xxgmx_port_ops *cn30xxgmx_port_ops[] = {
147	[GMX_MII_PORT] = &cn30xxgmx_port_ops_mii,
148	[GMX_GMII_PORT] = &cn30xxgmx_port_ops_gmii,
149	[GMX_RGMII_PORT] = &cn30xxgmx_port_ops_rgmii,
150	[GMX_SGMII_PORT] = &cn30xxgmx_port_ops_sgmii,
151	[GMX_SPI42_PORT] = &cn30xxgmx_port_ops_spi42,
152	[GMX_AGL_PORT] = &cn30xxgmx_port_ops_agl,
153};
154
155const struct cfattach octgmx_ca = {sizeof(struct cn30xxgmx_softc),
156    cn30xxgmx_match, cn30xxgmx_attach, NULL, NULL};
157
158struct cfdriver octgmx_cd = {NULL, "octgmx", DV_DULL};
159
160int
161cn30xxgmx_match(struct device *parent, void *match, void *aux)
162{
163	struct cfdata *cf = (struct cfdata *)match;
164	struct iobus_attach_args *aa = aux;
165
166	if (strcmp(cf->cf_driver->cd_name, aa->aa_name) != 0)
167		return 0;
168	return 1;
169}
170
171int
172cn30xxgmx_get_phy_phandle(int interface, int port)
173{
174	char name[64];
175	int node;
176	int phandle = 0;
177
178	snprintf(name, sizeof(name),
179	    "/soc/pip@11800a0000000/interface@%x/ethernet@%x",
180	    interface, port);
181	node = OF_finddevice(name);
182	if (node != - 1)
183		phandle = OF_getpropint(node, "phy-handle", 0);
184	return phandle;
185}
186
187void
188cn30xxgmx_attach(struct device *parent, struct device *self, void *aux)
189{
190	struct cn30xxgmx_attach_args gmx_aa;
191	struct iobus_attach_args *aa = aux;
192	struct cn30xxgmx_port_softc *port_sc;
193	struct cn30xxgmx_softc *sc = (void *)self;
194	struct cn30xxsmi_softc *smi;
195	int i;
196	int phy_addr;
197	int port;
198	int status;
199
200	sc->sc_regt = aa->aa_bust; /* XXX why there are iot? */
201	sc->sc_unitno = aa->aa_unitno;
202
203	status = bus_space_map(sc->sc_regt, aa->aa_addr, GMX_BLOCK_SIZE,
204	    0, &sc->sc_regh);
205	if (status != 0) {
206		printf(": can't map registers\n");
207		return;
208	}
209
210	cn30xxgmx_init(sc);
211
212	if (sc->sc_nports == 0) {
213		printf(": no active ports found\n");
214		goto error;
215	}
216
217	sc->sc_ports = mallocarray(sc->sc_nports, sizeof(*sc->sc_ports),
218	    M_DEVBUF, M_NOWAIT | M_ZERO);
219	if (sc->sc_ports == NULL) {
220		printf(": out of memory\n");
221		goto error;
222	}
223
224	printf("\n");
225
226	for (i = 0; i < sc->sc_nports; i++) {
227		if (sc->sc_port_types[i] == GMX_AGL_PORT)
228			port = 24;
229		else
230			port = GMX_PORT_NUM(sc->sc_unitno, i);
231		if (cn30xxsmi_get_phy(cn30xxgmx_get_phy_phandle(sc->sc_unitno,
232		    i), port, &smi, &phy_addr))
233			continue;
234
235		port_sc = &sc->sc_ports[i];
236		port_sc->sc_port_gmx = sc;
237		port_sc->sc_port_no = port;
238		port_sc->sc_port_type = sc->sc_port_types[i];
239		port_sc->sc_port_ops = cn30xxgmx_port_ops[port_sc->sc_port_type];
240		status = bus_space_map(sc->sc_regt,
241		    aa->aa_addr + GMX0_BASE_PORT_SIZE * i,
242		    GMX0_BASE_PORT_SIZE, 0, &port_sc->sc_port_regh);
243		if (status != 0) {
244			printf("%s port %d: can't map registers\n",
245			    sc->sc_dev.dv_xname, port);
246			continue;
247		}
248
249		switch (port_sc->sc_port_type) {
250		case GMX_AGL_PORT:
251			cn30xxgmx_agl_init(port_sc);
252			break;
253
254		case GMX_MII_PORT:
255		case GMX_GMII_PORT:
256		case GMX_RGMII_PORT: {
257			struct cn30xxasx_attach_args asx_aa;
258
259			asx_aa.aa_port = i;
260			asx_aa.aa_regt = aa->aa_bust;
261			cn30xxasx_init(&asx_aa, &port_sc->sc_port_asx);
262			break;
263		}
264		case GMX_SGMII_PORT:
265			if (bus_space_map(sc->sc_regt,
266			    PCS_BASE(sc->sc_unitno, i), PCS_SIZE, 0,
267			    &port_sc->sc_port_pcs_regh)) {
268				printf("%s port %d: can't map PCS registers\n",
269				    sc->sc_dev.dv_xname, port);
270				continue;
271			}
272			break;
273		default:
274			/* nothing */
275			break;
276		}
277
278		(void)memset(&gmx_aa, 0, sizeof(gmx_aa));
279		gmx_aa.ga_regt = aa->aa_bust;
280		gmx_aa.ga_dmat = aa->aa_dmat;
281		gmx_aa.ga_addr = aa->aa_addr;
282		gmx_aa.ga_name = "cnmac";
283		gmx_aa.ga_portno = port_sc->sc_port_no;
284		gmx_aa.ga_port_type = sc->sc_port_types[i];
285		gmx_aa.ga_gmx = sc;
286		gmx_aa.ga_gmx_port = port_sc;
287		gmx_aa.ga_phy_addr = phy_addr;
288		gmx_aa.ga_smi = smi;
289
290		config_found(self, &gmx_aa, cn30xxgmx_print);
291	}
292	return;
293
294error:
295	bus_space_unmap(sc->sc_regt, sc->sc_regh, GMX_BLOCK_SIZE);
296}
297
298int
299cn30xxgmx_print(void *aux, const char *pnp)
300{
301	struct cn30xxgmx_attach_args *ga = aux;
302	static const char *types[] = {
303		[GMX_AGL_PORT] = "AGL",
304		[GMX_MII_PORT] = "MII",
305		[GMX_GMII_PORT] = "GMII",
306		[GMX_RGMII_PORT] = "RGMII",
307		[GMX_SGMII_PORT] = "SGMII"
308	};
309
310#if DEBUG
311	if (pnp)
312		printf("%s at %s", ga->ga_name, pnp);
313#endif
314
315	printf(": port %d %s", ga->ga_portno, types[ga->ga_port_type]);
316
317	return UNCONF;
318}
319
320void
321cn30xxgmx_init(struct cn30xxgmx_softc *sc)
322{
323	uint64_t inf_mode;
324	int i, id;
325
326	id = octeon_get_chipid();
327
328	switch (octeon_model_family(id)) {
329	case OCTEON_MODEL_FAMILY_CN31XX:
330		inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh,
331		    GMX0_INF_MODE);
332		if ((inf_mode & INF_MODE_EN) == 0)
333			break;
334		/*
335		 * CN31XX-HM-1.01
336		 * 14.1 Packet Interface Introduction
337		 * Table 14-1 Packet Interface Configuration
338		 * 14.8 GMX Registers, Interface Mode Register, GMX0_INF_MODE
339		 */
340		if ((inf_mode & INF_MODE_TYPE) == 0) {
341			/* all three ports configured as RGMII */
342			sc->sc_nports = 3;
343			sc->sc_port_types[0] = GMX_RGMII_PORT;
344			sc->sc_port_types[1] = GMX_RGMII_PORT;
345			sc->sc_port_types[2] = GMX_RGMII_PORT;
346		} else {
347			/* port 0: RGMII, port 1: GMII, port 2: disabled */
348			/* XXX CN31XX-HM-1.01 says "Port 3: disabled"; typo? */
349			sc->sc_nports = 2;
350			sc->sc_port_types[0] = GMX_RGMII_PORT;
351			sc->sc_port_types[1] = GMX_GMII_PORT;
352		}
353		break;
354	case OCTEON_MODEL_FAMILY_CN30XX:
355	case OCTEON_MODEL_FAMILY_CN50XX:
356		inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh,
357		    GMX0_INF_MODE);
358		if ((inf_mode & INF_MODE_EN) == 0)
359			break;
360		/*
361		 * CN30XX-HM-1.0
362		 * 13.1 Packet Interface Introduction
363		 * Table 13-1 Packet Interface Configuration
364		 * 13.8 GMX Registers, Interface Mode Register, GMX0_INF_MODE
365		 */
366		if ((inf_mode & INF_MODE_P0MII) == 0)
367			sc->sc_port_types[0] = GMX_RGMII_PORT;
368		else
369			sc->sc_port_types[0] = GMX_MII_PORT;
370		if ((inf_mode & INF_MODE_TYPE) == 0) {
371			/* port 1 and 2 are configured as RGMII ports */
372			sc->sc_nports = 3;
373			sc->sc_port_types[1] = GMX_RGMII_PORT;
374			sc->sc_port_types[2] = GMX_RGMII_PORT;
375		} else {
376			/* port 1: GMII/MII, port 2: disabled */
377			/* GMII or MII port is selected by GMX_PRT1_CFG[SPEED] */
378			sc->sc_nports = 2;
379			sc->sc_port_types[1] = GMX_GMII_PORT;
380		}
381		/* port 2 is in CN3010/CN5010 only */
382		if ((octeon_model(id) != OCTEON_MODEL_CN3010) &&
383		    (octeon_model(id) != OCTEON_MODEL_CN5010))
384			if (sc->sc_nports == 3)
385				sc->sc_nports = 2;
386		break;
387	case OCTEON_MODEL_FAMILY_CN61XX: {
388		uint64_t qlm_cfg;
389
390		inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh,
391		    GMX0_INF_MODE);
392		if ((inf_mode & INF_MODE_EN) == 0)
393			break;
394
395		if (sc->sc_unitno == 0)
396			qlm_cfg = octeon_xkphys_read_8(MIO_QLM_CFG(2));
397		else
398			qlm_cfg = octeon_xkphys_read_8(MIO_QLM_CFG(0));
399		if ((qlm_cfg & MIO_QLM_CFG_CFG) == 2) {
400			sc->sc_nports = 4;
401			for (i = 0; i < sc->sc_nports; i++)
402				sc->sc_port_types[i] = GMX_SGMII_PORT;
403		} else if ((qlm_cfg & MIO_QLM_CFG_CFG) == 3) {
404			printf(": XAUI interface is not supported");
405		} else {
406			/* The interface is disabled. */
407		}
408		break;
409	}
410	case OCTEON_MODEL_FAMILY_CN71XX:
411		if (sc->sc_unitno == 4) {
412			uint64_t val;
413
414			val = bus_space_read_8(sc->sc_regt, sc->sc_regh,
415			    AGL_PRT_CTL(0));
416			if ((val & AGL_PRT_CTL_MODE_M) ==
417			    AGL_PRT_CTL_MODE_RGMII) {
418				sc->sc_nports = 1;
419				sc->sc_port_types[0] = GMX_AGL_PORT;
420			}
421			break;
422		}
423
424		inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh,
425		    GMX0_INF_MODE);
426		if ((inf_mode & INF_MODE_EN) == 0)
427			break;
428
429		switch (inf_mode & INF_MODE_MODE) {
430		case INF_MODE_MODE_SGMII:
431			sc->sc_nports = 4;
432			for (i = 0; i < sc->sc_nports; i++)
433				sc->sc_port_types[i] = GMX_SGMII_PORT;
434			break;
435#ifdef notyet
436		case INF_MODE_MODE_XAUI:
437#endif
438		default:
439			break;
440		}
441		break;
442	case OCTEON_MODEL_FAMILY_CN38XX:
443	case OCTEON_MODEL_FAMILY_CN56XX:
444	case OCTEON_MODEL_FAMILY_CN58XX:
445	default:
446		printf(": unsupported octeon model: 0x%x", id);
447		break;
448	}
449}
450
451/* XXX RGMII specific */
452int
453cn30xxgmx_link_enable(struct cn30xxgmx_port_softc *sc, int enable)
454{
455	uint64_t prt_cfg;
456
457	cn30xxgmx_tx_int_enable(sc, enable);
458	cn30xxgmx_rx_int_enable(sc, enable);
459
460	prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
461	if (enable) {
462		if (cn30xxgmx_link_status(sc)) {
463			SET(prt_cfg, PRTN_CFG_EN);
464		}
465	} else {
466		CLR(prt_cfg, PRTN_CFG_EN);
467	}
468	_GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
469	/*
470	 * According to CN30XX-HM-1.0, 13.4.2 Link Status Changes:
471	 * > software should read back to flush the write operation.
472	 */
473	(void)_GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
474
475	return 0;
476}
477
478void
479cn30xxgmx_stats_init(struct cn30xxgmx_port_softc *sc)
480{
481	_GMX_PORT_WR8(sc, GMX0_RX0_STATS_CTL, 1);
482	_GMX_PORT_WR8(sc, GMX0_TX0_STATS_CTL, 1);
483
484	_GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS, 0);
485	_GMX_PORT_WR8(sc, GMX0_RX0_STATS_OCTS, 0);
486	_GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_CTL, 0);
487	_GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_DMAC, 0);
488	_GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_DRP, 0);
489	_GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_BAD, 0);
490	_GMX_PORT_WR8(sc, GMX0_TX0_STAT0, 0);
491	_GMX_PORT_WR8(sc, GMX0_TX0_STAT1, 0);
492	_GMX_PORT_WR8(sc, GMX0_TX0_STAT2, 0);
493	_GMX_PORT_WR8(sc, GMX0_TX0_STAT3, 0);
494	_GMX_PORT_WR8(sc, GMX0_TX0_STAT4, 0);
495	_GMX_PORT_WR8(sc, GMX0_TX0_STAT5, 0);
496	_GMX_PORT_WR8(sc, GMX0_TX0_STAT6, 0);
497	_GMX_PORT_WR8(sc, GMX0_TX0_STAT7, 0);
498	_GMX_PORT_WR8(sc, GMX0_TX0_STAT8, 0);
499	_GMX_PORT_WR8(sc, GMX0_TX0_STAT9, 0);
500}
501
502int
503cn30xxgmx_tx_ovr_bp_enable(struct cn30xxgmx_port_softc *sc, int enable)
504{
505	uint64_t ovr_bp;
506	int index = GMX_PORT_INDEX(sc->sc_port_no);
507
508	ovr_bp = _GMX_RD8(sc, GMX0_TX_OVR_BP);
509	if (enable) {
510		CLR(ovr_bp, (1 << index) << TX_OVR_BP_EN_SHIFT);
511		SET(ovr_bp, (1 << index) << TX_OVR_BP_BP_SHIFT);
512		/* XXX really??? */
513		SET(ovr_bp, (1 << index) << TX_OVR_BP_IGN_FULL_SHIFT);
514	} else {
515		SET(ovr_bp, (1 << index) << TX_OVR_BP_EN_SHIFT);
516		CLR(ovr_bp, (1 << index) << TX_OVR_BP_BP_SHIFT);
517		/* XXX really??? */
518		SET(ovr_bp, (1 << index) << TX_OVR_BP_IGN_FULL_SHIFT);
519	}
520	_GMX_WR8(sc, GMX0_TX_OVR_BP, ovr_bp);
521	return 0;
522}
523
524int
525cn30xxgmx_rx_pause_enable(struct cn30xxgmx_port_softc *sc, int enable)
526{
527	if (enable) {
528		cn30xxgmx_rx_frm_ctl_enable(sc, RXN_FRM_CTL_CTL_BCK);
529	} else {
530		cn30xxgmx_rx_frm_ctl_disable(sc, RXN_FRM_CTL_CTL_BCK);
531	}
532
533	return 0;
534}
535
536void
537cn30xxgmx_tx_int_enable(struct cn30xxgmx_port_softc *sc, int enable)
538{
539	uint64_t tx_int_xxx = 0;
540
541	SET(tx_int_xxx,
542	    TX_INT_REG_LATE_COL |
543	    TX_INT_REG_XSDEF |
544	    TX_INT_REG_XSCOL |
545	    TX_INT_REG_UNDFLW |
546	    TX_INT_REG_PKO_NXA);
547	_GMX_WR8(sc, GMX0_TX_INT_REG, tx_int_xxx);
548	_GMX_WR8(sc, GMX0_TX_INT_EN, enable ? tx_int_xxx : 0);
549}
550
551void
552cn30xxgmx_rx_int_enable(struct cn30xxgmx_port_softc *sc, int enable)
553{
554	uint64_t rx_int_xxx = 0;
555
556	SET(rx_int_xxx, 0 |
557	    RXN_INT_REG_PHY_DUPX |
558	    RXN_INT_REG_PHY_SPD |
559	    RXN_INT_REG_PHY_LINK |
560	    RXN_INT_REG_IFGERR |
561	    RXN_INT_REG_COLDET |
562	    RXN_INT_REG_FALERR |
563	    RXN_INT_REG_RSVERR |
564	    RXN_INT_REG_PCTERR |
565	    RXN_INT_REG_OVRERR |
566	    RXN_INT_REG_NIBERR |
567	    RXN_INT_REG_SKPERR |
568	    RXN_INT_REG_RCVERR |
569	    RXN_INT_REG_LENERR |
570	    RXN_INT_REG_ALNERR |
571	    RXN_INT_REG_FCSERR |
572	    RXN_INT_REG_JABBER |
573	    RXN_INT_REG_MAXERR |
574	    RXN_INT_REG_CAREXT |
575	    RXN_INT_REG_MINERR);
576	_GMX_PORT_WR8(sc, GMX0_RX0_INT_REG, rx_int_xxx);
577	_GMX_PORT_WR8(sc, GMX0_RX0_INT_EN, enable ? rx_int_xxx : 0);
578}
579
580int
581cn30xxgmx_rx_frm_ctl_enable(struct cn30xxgmx_port_softc *sc,
582    uint64_t rx_frm_ctl)
583{
584	struct ifnet *ifp = &sc->sc_port_ac->ac_if;
585	unsigned int maxlen;
586
587	maxlen = roundup(ifp->if_hardmtu + ETHER_HDR_LEN + ETHER_CRC_LEN +
588	    ETHER_VLAN_ENCAP_LEN, 8);
589	_GMX_PORT_WR8(sc, GMX0_RX0_JABBER, maxlen);
590
591	return cn30xxgmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 1);
592}
593
594int
595cn30xxgmx_rx_frm_ctl_disable(struct cn30xxgmx_port_softc *sc,
596    uint64_t rx_frm_ctl)
597{
598	return cn30xxgmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 0);
599}
600
601int
602cn30xxgmx_rx_frm_ctl_xable(struct cn30xxgmx_port_softc *sc,
603    uint64_t rx_frm_ctl, int enable)
604{
605	uint64_t tmp;
606
607	tmp = _GMX_PORT_RD8(sc, GMX0_RX0_FRM_CTL);
608	if (enable)
609		SET(tmp, rx_frm_ctl);
610	else
611		CLR(tmp, rx_frm_ctl);
612	_GMX_PORT_WR8(sc, GMX0_RX0_FRM_CTL, tmp);
613
614	return 0;
615}
616
617int
618cn30xxgmx_tx_thresh(struct cn30xxgmx_port_softc *sc, int cnt)
619{
620	_GMX_PORT_WR8(sc, GMX0_TX0_THRESH, cnt);
621	return 0;
622}
623
624int
625cn30xxgmx_set_filter(struct cn30xxgmx_port_softc *sc)
626{
627	struct ifnet *ifp = &sc->sc_port_ac->ac_if;
628	struct arpcom *ac = sc->sc_port_ac;
629	struct ether_multi *enm;
630	struct ether_multistep step;
631	uint64_t cam[ETHER_ADDR_LEN];
632	uint64_t cam_en = 0;
633	uint64_t ctl = 0;
634	uint64_t mac;
635	int i, cidx;
636
637	/*
638	 * Always accept broadcast frames.
639	 */
640	SET(ctl, RXN_ADR_CTL_BCST);
641
642	if (ISSET(ifp->if_flags, IFF_PROMISC)) {
643		SET(ifp->if_flags, IFF_ALLMULTI);
644		SET(ctl, RXN_ADR_CTL_MCST_ACCEPT);
645	} else if (ac->ac_multirangecnt > 0 || ac->ac_multicnt >= GMX_NCAM) {
646		SET(ifp->if_flags, IFF_ALLMULTI);
647		SET(ctl, RXN_ADR_CTL_CAM_MODE);
648		SET(ctl, RXN_ADR_CTL_MCST_ACCEPT);
649	} else {
650		CLR(ifp->if_flags, IFF_ALLMULTI);
651		SET(ctl, RXN_ADR_CTL_CAM_MODE);
652		SET(ctl, RXN_ADR_CTL_MCST_AFCAM);
653	}
654
655	mac = 0;
656	for (i = 0; i < ETHER_ADDR_LEN; i++)
657		mac |= (uint64_t)ac->ac_enaddr[i] <<
658		    ((ETHER_ADDR_LEN - 1 - i) * 8);
659
660	/*
661	 * The first CAM entry is used for the local unicast MAC.
662	 * The remaining entries are used for multicast MACs.
663	 */
664	memset(cam, 0, sizeof(cam));
665	cidx = 0;
666	if (!ISSET(ifp->if_flags, IFF_PROMISC)) {
667		for (i = 0; i < ETHER_ADDR_LEN; i++)
668			cam[i] |= (uint64_t)ac->ac_enaddr[i] << (cidx * 8);
669		cam_en |= 1U << cidx;
670		cidx++;
671	}
672	if (!ISSET(ifp->if_flags, IFF_ALLMULTI)) {
673		ETHER_FIRST_MULTI(step, ac, enm);
674		while (enm != NULL && cidx < GMX_NCAM) {
675			for (i = 0; i < ETHER_ADDR_LEN; i++)
676				cam[i] |= (uint64_t)enm->enm_addrlo[i] <<
677				    (cidx * 8);
678			cam_en |= 1U << cidx;
679			cidx++;
680			ETHER_NEXT_MULTI(step, enm);
681		}
682	}
683
684	cn30xxgmx_link_enable(sc, 0);
685	_GMX_PORT_WR8(sc, GMX0_SMAC0, mac);
686	_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, ctl);
687	for (i = 0; i < ETHER_ADDR_LEN; i++)
688		_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM(i), cam[i]);
689	_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, cam_en);
690	(void)_GMX_PORT_RD8(sc, GMX0_RX0_ADR_CAM_EN);
691	cn30xxgmx_link_enable(sc, 1);
692
693	return 0;
694}
695
696int
697cn30xxgmx_port_enable(struct cn30xxgmx_port_softc *sc, int enable)
698{
699	(*sc->sc_port_ops->port_ops_enable)(sc, enable);
700	return 0;
701}
702
703int
704cn30xxgmx_reset_speed(struct cn30xxgmx_port_softc *sc)
705{
706	struct ifnet *ifp = &sc->sc_port_ac->ac_if;
707	if (ISSET(sc->sc_port_mii->mii_flags, MIIF_DOINGAUTO)) {
708		log(LOG_WARNING,
709		    "%s: autonegotiation has not been completed yet\n",
710		    ifp->if_xname);
711		return 1;
712	}
713	(*sc->sc_port_ops->port_ops_speed)(sc);
714	return 0;
715}
716
717int
718cn30xxgmx_reset_timing(struct cn30xxgmx_port_softc *sc)
719{
720	(*sc->sc_port_ops->port_ops_timing)(sc);
721	return 0;
722}
723
724int
725cn30xxgmx_reset_flowctl(struct cn30xxgmx_port_softc *sc)
726{
727	struct ifmedia_entry *ife = sc->sc_port_mii->mii_media.ifm_cur;
728
729	/*
730	 * Get flow control negotiation result.
731	 */
732#ifdef GMX_802_3X_DISABLE_AUTONEG
733	/* Tentative support for SEIL-compat.. */
734	if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
735		sc->sc_port_flowflags &= ~IFM_ETH_FMASK;
736	}
737#else
738	/* Default configuration of NetBSD */
739	if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO &&
740	    (sc->sc_port_mii->mii_media_active & IFM_ETH_FMASK) !=
741			sc->sc_port_flowflags) {
742		sc->sc_port_flowflags =
743			sc->sc_port_mii->mii_media_active & IFM_ETH_FMASK;
744		sc->sc_port_mii->mii_media_active &= ~IFM_ETH_FMASK;
745	}
746#endif /* GMX_802_3X_DISABLE_AUTONEG */
747
748	/*
749	 * 802.3x Flow Control Capabilities
750	 */
751	if (sc->sc_port_flowflags & IFM_ETH_TXPAUSE) {
752		cn30xxgmx_tx_ovr_bp_enable(sc, 1);
753	} else {
754		cn30xxgmx_tx_ovr_bp_enable(sc, 0);
755	}
756	if (sc->sc_port_flowflags & IFM_ETH_RXPAUSE) {
757		cn30xxgmx_rx_pause_enable(sc, 1);
758	} else {
759		cn30xxgmx_rx_pause_enable(sc, 0);
760	}
761
762	return 0;
763}
764
765void
766cn30xxgmx_agl_init(struct cn30xxgmx_port_softc *sc)
767{
768	uint64_t val;
769	int port = 0;
770
771	/* Disable link for initialization. */
772	val = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
773	CLR(val, AGL_GMX_PRT_CFG_EN);
774	AGL_GMX_PORT_WR8(sc, AGL_GMX_PRT_CFG, val);
775	(void)AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
776
777	val = AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
778	CLR(val, AGL_PRT_CTL_CLKRST);
779	CLR(val, AGL_PRT_CTL_DLLRST);
780	CLR(val, AGL_PRT_CTL_CLKTX_BYP);
781	CLR(val, AGL_PRT_CTL_CLKTX_SET_M);
782	CLR(val, AGL_PRT_CTL_CLKRX_BYP);
783	CLR(val, AGL_PRT_CTL_CLKRX_SET_M);
784	CLR(val, AGL_PRT_CTL_REFCLK_SEL_M);
785	AGL_GMX_WR8(sc, AGL_PRT_CTL(port), val);
786	(void)AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
787
788	/* Let the DLL settle. */
789	delay(5);
790
791	val = AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
792	CLR(val, AGL_PRT_CTL_DRV_BYP);
793	AGL_GMX_WR8(sc, AGL_PRT_CTL(port), val);
794	(void)AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
795
796	val = AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
797	SET(val, AGL_PRT_CTL_COMP);
798	AGL_GMX_WR8(sc, AGL_PRT_CTL(port), val);
799	(void)AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
800
801	/* Let the compensation controller settle. */
802	delay(20);
803
804	val = AGL_GMX_RX_FRM_CTL_PRE_ALIGN
805	    | AGL_GMX_RX_FRM_CTL_PAD_LEN
806	    | AGL_GMX_RX_FRM_CTL_VLAN_LEN
807	    | AGL_GMX_RX_FRM_CTL_PRE_FREE
808	    | AGL_GMX_RX_FRM_CTL_MCST
809	    | AGL_GMX_RX_FRM_CTL_BCK
810	    | AGL_GMX_RX_FRM_CTL_DRP
811	    | AGL_GMX_RX_FRM_CTL_PRE_STRP
812	    | AGL_GMX_RX_FRM_CTL_PRE_CHK;
813	AGL_GMX_PORT_WR8(sc, AGL_GMX_RX_FRM_CTL, val);
814	(void)AGL_GMX_PORT_RD8(sc, AGL_GMX_RX_FRM_CTL);
815}
816
817void
818cn30xxgmx_agl_up(struct cn30xxgmx_port_softc *sc)
819{
820	uint64_t val;
821
822	val = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
823	SET(val, AGL_GMX_PRT_CFG_RX_EN);
824	SET(val, AGL_GMX_PRT_CFG_TX_EN);
825	AGL_GMX_PORT_WR8(sc, AGL_GMX_PRT_CFG, val);
826
827	val = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
828	SET(val, AGL_GMX_PRT_CFG_EN);
829	AGL_GMX_PORT_WR8(sc, AGL_GMX_PRT_CFG, val);
830	(void)AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
831}
832
833void
834cn30xxgmx_agl_down(struct cn30xxgmx_port_softc *sc)
835{
836	uint64_t val;
837	int timeout;
838
839	val = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
840	CLR(val, AGL_GMX_PRT_CFG_EN);
841	AGL_GMX_PORT_WR8(sc, AGL_GMX_PRT_CFG, val);
842
843	val = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
844	CLR(val, AGL_GMX_PRT_CFG_RX_EN);
845	CLR(val, AGL_GMX_PRT_CFG_TX_EN);
846	AGL_GMX_PORT_WR8(sc, AGL_GMX_PRT_CFG, val);
847	(void)AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
848
849	/* Wait until the port is idle. */
850	for (timeout = 1000; timeout > 0; timeout--) {
851		const uint64_t idlemask = AGL_GMX_PRT_CFG_RX_IDLE |
852		    AGL_GMX_PRT_CFG_TX_IDLE;
853		val = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
854		if ((val & idlemask) == idlemask)
855			break;
856		delay(1000);
857	}
858}
859
860int
861cn30xxgmx_agl_enable(struct cn30xxgmx_port_softc *sc, int enable)
862{
863	if (enable)
864		cn30xxgmx_agl_up(sc);
865	else
866		cn30xxgmx_agl_down(sc);
867	return 0;
868}
869
870int
871cn30xxgmx_agl_speed(struct cn30xxgmx_port_softc *sc)
872{
873	struct ifnet *ifp = &sc->sc_port_ac->ac_if;
874	uint64_t clk_cnt, prt_cfg, val;
875	unsigned int maxlen;
876	int port = 0;
877
878	cn30xxgmx_agl_down(sc);
879
880	prt_cfg = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
881
882	if (ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX))
883		SET(prt_cfg, AGL_GMX_PRT_CFG_DUPLEX);
884	else
885		CLR(prt_cfg, AGL_GMX_PRT_CFG_DUPLEX);
886
887	switch (ifp->if_baudrate) {
888	case IF_Mbps(10):
889		CLR(prt_cfg, AGL_GMX_PRT_CFG_SPEED);
890		SET(prt_cfg, AGL_GMX_PRT_CFG_SPEED_MSB);
891		CLR(prt_cfg, AGL_GMX_PRT_CFG_SLOTTIME);
892		SET(prt_cfg, AGL_GMX_PRT_CFG_BURST);
893		clk_cnt = 50;
894		break;
895	case IF_Mbps(100):
896		CLR(prt_cfg, AGL_GMX_PRT_CFG_SPEED);
897		CLR(prt_cfg, AGL_GMX_PRT_CFG_SPEED_MSB);
898		CLR(prt_cfg, AGL_GMX_PRT_CFG_SLOTTIME);
899		SET(prt_cfg, AGL_GMX_PRT_CFG_BURST);
900		clk_cnt = 5;
901		break;
902	case IF_Gbps(1):
903	default:
904		SET(prt_cfg, AGL_GMX_PRT_CFG_SPEED);
905		CLR(prt_cfg, AGL_GMX_PRT_CFG_SPEED_MSB);
906		SET(prt_cfg, AGL_GMX_PRT_CFG_SLOTTIME);
907		if (ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX))
908			SET(prt_cfg, AGL_GMX_PRT_CFG_BURST);
909		else
910			CLR(prt_cfg, AGL_GMX_PRT_CFG_BURST);
911		clk_cnt = 1;
912		break;
913	}
914
915	AGL_GMX_PORT_WR8(sc, AGL_GMX_PRT_CFG, prt_cfg);
916	(void)AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
917
918	val = AGL_GMX_PORT_RD8(sc, AGL_GMX_TX_CLK);
919	CLR(val, AGL_GMX_TX_CLK_CLK_CNT_M);
920	SET(val, clk_cnt << AGL_GMX_TX_CLK_CLK_CNT_S);
921	AGL_GMX_PORT_WR8(sc, AGL_GMX_TX_CLK, val);
922	(void)AGL_GMX_PORT_RD8(sc, AGL_GMX_TX_CLK);
923
924	maxlen = roundup(ifp->if_hardmtu + ETHER_HDR_LEN + ETHER_CRC_LEN +
925	    ETHER_VLAN_ENCAP_LEN, 8);
926	AGL_GMX_PORT_WR8(sc, AGL_GMX_RX_JABBER, maxlen);
927	AGL_GMX_PORT_WR8(sc, AGL_GMX_RX_FRM_MAX, maxlen);
928	(void)AGL_GMX_PORT_RD8(sc, AGL_GMX_RX_FRM_MAX);
929
930	cn30xxgmx_agl_up(sc);
931
932	val = AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
933	SET(val, AGL_PRT_CTL_CLKRST);
934	AGL_GMX_WR8(sc, AGL_PRT_CTL(port), val);
935
936	val = AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
937	SET(val, AGL_PRT_CTL_ENABLE);
938	AGL_GMX_WR8(sc, AGL_PRT_CTL(port), val);
939	(void)AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
940
941	return 0;
942}
943
944int
945cn30xxgmx_agl_timing(struct cn30xxgmx_port_softc *sc)
946{
947	return 0;
948}
949
950int
951cn30xxgmx_rgmii_enable(struct cn30xxgmx_port_softc *sc, int enable)
952{
953	uint64_t mode;
954
955	/* XXX */
956	mode = _GMX_RD8(sc, GMX0_INF_MODE);
957	if (ISSET(mode, INF_MODE_EN)) {
958		cn30xxasx_enable(sc->sc_port_asx, 1);
959	}
960
961	return 0;
962}
963
964int
965cn30xxgmx_rgmii_speed(struct cn30xxgmx_port_softc *sc)
966{
967	struct ifnet *ifp = &sc->sc_port_ac->ac_if;
968	uint64_t newlink;
969	int baudrate;
970
971	/* XXX */
972	cn30xxgmx_link_enable(sc, 1);
973
974	cn30xxgmx_rgmii_speed_newlink(sc, &newlink);
975	if (sc->sc_link == newlink) {
976		return 0;
977	}
978#ifdef OCTEON_ETH_DEBUG
979	cn30xxgmx_rgmii_speed_newlink_log(sc, newlink);
980#endif
981	sc->sc_link = newlink;
982
983	switch (sc->sc_link & RXN_RX_INBND_SPEED) {
984	case RXN_RX_INBND_SPEED_2_5:
985		baudrate = IF_Mbps(10);
986		break;
987	case RXN_RX_INBND_SPEED_25:
988		baudrate = IF_Mbps(100);
989		break;
990	case RXN_RX_INBND_SPEED_125:
991		baudrate = IF_Gbps(1);
992		break;
993	default:
994		baudrate = 0/* XXX */;
995		break;
996	}
997	ifp->if_baudrate = baudrate;
998
999	cn30xxgmx_link_enable(sc, 0);
1000
1001	/*
1002	 * According to CN30XX-HM-1.0, 13.4.2 Link Status Changes:
1003	 * wait a max_packet_time
1004	 * max_packet_time(us) = (max_packet_size(bytes) * 8) / link_speed(Mbps)
1005	 */
1006	delay((GMX_FRM_MAX_SIZ * 8) / (baudrate / 1000000));
1007
1008	cn30xxgmx_rgmii_speed_speed(sc);
1009
1010	cn30xxgmx_link_enable(sc, 1);
1011	cn30xxasx_enable(sc->sc_port_asx, 1);
1012
1013	return 0;
1014}
1015
1016int
1017cn30xxgmx_rgmii_speed_newlink(struct cn30xxgmx_port_softc *sc,
1018    uint64_t *rnewlink)
1019{
1020	uint64_t newlink;
1021
1022	/* Inband status does not seem to work */
1023	newlink = _GMX_PORT_RD8(sc, GMX0_RX0_RX_INBND);
1024
1025	*rnewlink = newlink;
1026	return 0;
1027}
1028
1029#ifdef OCTEON_ETH_DEBUG
1030int
1031cn30xxgmx_rgmii_speed_newlink_log(struct cn30xxgmx_port_softc *sc,
1032    uint64_t newlink)
1033{
1034	struct ifnet *ifp = &sc->sc_port_ac->ac_if;
1035	const char *status_str;
1036	const char *speed_str;
1037	const char *duplex_str;
1038	int is_status_changed;
1039	int is_speed_changed;
1040	int is_linked;
1041	char status_buf[80/* XXX */];
1042	char speed_buf[80/* XXX */];
1043
1044	is_status_changed = (newlink & RXN_RX_INBND_STATUS) !=
1045	    (sc->sc_link & RXN_RX_INBND_STATUS);
1046	is_speed_changed = (newlink & RXN_RX_INBND_SPEED) !=
1047	    (sc->sc_link & RXN_RX_INBND_SPEED);
1048	is_linked = ISSET(newlink, RXN_RX_INBND_STATUS);
1049	if (is_status_changed) {
1050		if (is_linked)
1051			status_str = "link up";
1052		else
1053			status_str = "link down";
1054	} else {
1055		if (is_linked) {
1056			/* any other conditions? */
1057			if (is_speed_changed)
1058				status_str = "link change";
1059			else
1060				status_str = NULL;
1061		} else {
1062			status_str = NULL;
1063		}
1064	}
1065
1066	if (status_str != NULL) {
1067		if ((is_speed_changed && is_linked) || is_linked) {
1068			switch (newlink & RXN_RX_INBND_SPEED) {
1069			case RXN_RX_INBND_SPEED_2_5:
1070				speed_str = "10baseT";
1071				break;
1072			case RXN_RX_INBND_SPEED_25:
1073				speed_str = "100baseTX";
1074				break;
1075			case RXN_RX_INBND_SPEED_125:
1076				speed_str = "1000baseT";
1077				break;
1078			default:
1079				panic("Unknown link speed");
1080				break;
1081			}
1082
1083			if (ISSET(newlink, RXN_RX_INBND_DUPLEX))
1084				duplex_str = "-FDX";
1085			else
1086				duplex_str = "";
1087
1088			(void)snprintf(speed_buf, sizeof(speed_buf), "(%s%s)",
1089			    speed_str, duplex_str);
1090		} else {
1091			speed_buf[0] = '\0';
1092		}
1093		(void)snprintf(status_buf, sizeof(status_buf), "%s: %s%s%s\n",
1094		    ifp->if_xname, status_str, (is_speed_changed | is_linked) ? " " : "",
1095		    speed_buf);
1096		log(LOG_CRIT, status_buf);
1097	}
1098
1099	return 0;
1100}
1101#endif
1102
1103int
1104cn30xxgmx_rgmii_speed_speed(struct cn30xxgmx_port_softc *sc)
1105{
1106	uint64_t prt_cfg;
1107	uint64_t tx_clk, tx_slot, tx_burst;
1108
1109	prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
1110
1111	switch (sc->sc_link & RXN_RX_INBND_SPEED) {
1112	case RXN_RX_INBND_SPEED_2_5:
1113		/* 10Mbps */
1114		/*
1115		 * "GMX Tx Clock Generation Registers", CN30XX-HM-1.0;
1116		 * > 8ns x 50 = 400ns (2.5MHz TXC clock)
1117		 */
1118		tx_clk = 50;
1119		/*
1120		 * "TX Slottime Counter Registers", CN30XX-HM-1.0;
1121		 * > 10/100Mbps: set SLOT to 0x40
1122		 */
1123		tx_slot = 0x40;
1124		/*
1125		 * "TX Burst-Counter Registers", CN30XX-HM-1.0;
1126		 * > 10/100Mbps: set BURST to 0x0
1127		 */
1128		tx_burst = 0;
1129		/*
1130		 * "GMX Tx Port Configuration Registers", CN30XX-HM-1.0;
1131		 * > Slot time for half-duplex operation
1132		 * >   0 = 512 bittimes (10/100Mbps operation)
1133		 */
1134		CLR(prt_cfg, PRTN_CFG_SLOTTIME);
1135		/*
1136		 * "GMX Port Configuration Registers", CN30XX-HM-1.0;
1137		 * > Link speed
1138		 * >   0 = 10/100Mbps operation
1139		 * >     in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
1140		 */
1141		CLR(prt_cfg, PRTN_CFG_SPEED);
1142		break;
1143	case RXN_RX_INBND_SPEED_25:
1144		/* 100Mbps */
1145		/*
1146		 * "GMX Tx Clock Generation Registers", CN30XX-HM-1.0;
1147		 * > 8ns x 5 = 40ns (25.0MHz TXC clock)
1148		 */
1149		tx_clk = 5;
1150		/*
1151		 * "TX Slottime Counter Registers", CN30XX-HM-1.0;
1152		 * > 10/100Mbps: set SLOT to 0x40
1153		 */
1154		tx_slot = 0x40;
1155		/*
1156		 * "TX Burst-Counter Registers", CN30XX-HM-1.0;
1157		 * > 10/100Mbps: set BURST to 0x0
1158		 */
1159		tx_burst = 0;
1160		/*
1161		 * "GMX Tx Port Configuration Registers", CN30XX-HM-1.0;
1162		 * > Slot time for half-duplex operation
1163		 * >   0 = 512 bittimes (10/100Mbps operation)
1164		 */
1165		CLR(prt_cfg, PRTN_CFG_SLOTTIME);
1166		/*
1167		 * "GMX Port Configuration Registers", CN30XX-HM-1.0;
1168		 * > Link speed
1169		 * >   0 = 10/100Mbps operation
1170		 * >     in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
1171		 */
1172		CLR(prt_cfg, PRTN_CFG_SPEED);
1173		break;
1174	case RXN_RX_INBND_SPEED_125:
1175		/* 1000Mbps */
1176		/*
1177		 * "GMX Tx Clock Generation Registers", CN30XX-HM-1.0;
1178		 * > 8ns x 1 = 8ns (125.0MHz TXC clock)
1179		 */
1180		tx_clk = 1;
1181		/*
1182		 * "TX Slottime Counter Registers", CN30XX-HM-1.0;
1183		 * > 1000Mbps: set SLOT to 0x200
1184		 */
1185		tx_slot = 0x200;
1186		/*
1187		 * "TX Burst-Counter Registers", CN30XX-HM-1.0;
1188		 * > 1000Mbps: set BURST to 0x2000
1189		 */
1190		tx_burst = 0x2000;
1191		/*
1192		 * "GMX Tx Port Configuration Registers", CN30XX-HM-1.0;
1193		 * > Slot time for half-duplex operation
1194		 * >   1 = 4096 bittimes (1000Mbps operation)
1195		 */
1196		SET(prt_cfg, PRTN_CFG_SLOTTIME);
1197		/*
1198		 * "GMX Port Configuration Registers", CN30XX-HM-1.0;
1199		 * > Link speed
1200		 * >   1 = 1000Mbps operation
1201		 */
1202		SET(prt_cfg, PRTN_CFG_SPEED);
1203		break;
1204	default:
1205		/* NOT REACHED! */
1206		/* Following configuration is default value of system.
1207		*/
1208		tx_clk = 1;
1209		tx_slot = 0x200;
1210		tx_burst = 0x2000;
1211		SET(prt_cfg, PRTN_CFG_SLOTTIME);
1212		SET(prt_cfg, PRTN_CFG_SPEED);
1213		break;
1214	}
1215
1216	/* Setup Duplex mode(negotiated) */
1217	/*
1218	 * "GMX Port Configuration Registers", CN30XX-HM-1.0;
1219	 * > Duplex mode: 0 = half-duplex mode, 1=full-duplex
1220	 */
1221	if (ISSET(sc->sc_link, RXN_RX_INBND_DUPLEX)) {
1222		/* Full-Duplex */
1223		SET(prt_cfg, PRTN_CFG_DUPLEX);
1224	} else {
1225		/* Half-Duplex */
1226		CLR(prt_cfg, PRTN_CFG_DUPLEX);
1227	}
1228
1229	_GMX_PORT_WR8(sc, GMX0_TX0_CLK, tx_clk);
1230	_GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot);
1231	_GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst);
1232	_GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
1233
1234	return 0;
1235}
1236
1237int
1238cn30xxgmx_rgmii_timing(struct cn30xxgmx_port_softc *sc)
1239{
1240	int clk_tx_setting;
1241	int clk_rx_setting;
1242	uint64_t rx_frm_ctl;
1243
1244	/* RGMII TX Threshold Registers, CN30XX-HM-1.0;
1245	 * > Number of 16-byte ticks to accumulate in the TX FIFO before
1246	 * > sending on the RGMII interface. This field should be large
1247	 * > enough to prevent underflow on the RGMII interface and must
1248	 * > never be set to less than 0x4. This register cannot exceed
1249	 * > the TX FIFO depth of 0x40 words.
1250	 */
1251	/* Default parameter of CN30XX */
1252	cn30xxgmx_tx_thresh(sc, 32);
1253
1254	rx_frm_ctl = 0 |
1255	    /* RXN_FRM_CTL_NULL_DIS |	(cn5xxx only) */
1256	    /* RXN_FRM_CTL_PRE_ALIGN |	(cn5xxx only) */
1257	    /* RXN_FRM_CTL_PAD_LEN |	(cn3xxx only) */
1258	    /* RXN_FRM_CTL_VLAN_LEN |	(cn3xxx only) */
1259	    RXN_FRM_CTL_PRE_FREE |
1260	    RXN_FRM_CTL_CTL_SMAC |
1261	    RXN_FRM_CTL_CTL_MCST |
1262	    RXN_FRM_CTL_CTL_DRP |
1263	    RXN_FRM_CTL_PRE_STRP |
1264	    RXN_FRM_CTL_PRE_CHK;
1265	cn30xxgmx_rx_frm_ctl_enable(sc, rx_frm_ctl);
1266
1267	/* XXX PHY-dependent parameter */
1268	/* RGMII RX Clock-Delay Registers, CN30XX-HM-1.0;
1269	 * > Delay setting to place n RXC (RGMII receive clock) delay line.
1270	 * > The intrinsic delay can range from 50ps to 80ps per tap,
1271	 * > which corresponds to skews of 1.25ns to 2.00ns at 25 taps(CSR+1).
1272	 * > This is the best match for the RGMII specification which wants
1273	 * > 1ns - 2.6ns of skew.
1274	 */
1275	/* RGMII TX Clock-Delay Registers, CN30XX-HM-1.0;
1276	 * > Delay setting to place n TXC (RGMII transmit clock) delay line.
1277	 * > ...
1278	 */
1279
1280	switch (octeon_board) {
1281	default:
1282		/* Default parameter of CN30XX */
1283		clk_tx_setting = 24;
1284		clk_rx_setting = 24;
1285		break;
1286	case BOARD_NETGEAR_UTM25:
1287		if (sc->sc_port_no == 0) {
1288			clk_tx_setting = 9;
1289			clk_rx_setting = 9;
1290		} else {
1291			clk_tx_setting = 24;
1292			clk_rx_setting = 24;
1293		}
1294		break;
1295	case BOARD_UBIQUITI_E100:
1296	case BOARD_UBIQUITI_E120:
1297		clk_tx_setting = 16;
1298		clk_rx_setting = 0;
1299		break;
1300	}
1301
1302	cn30xxasx_clk_set(sc->sc_port_asx, clk_tx_setting, clk_rx_setting);
1303
1304	return 0;
1305}
1306
1307int
1308cn30xxgmx_sgmii_enable(struct cn30xxgmx_port_softc *sc, int enable)
1309{
1310	uint64_t ctl_reg, status, timer_count;
1311	uint64_t cpu_freq = octeon_boot_info->eclock / 1000000;
1312	int done;
1313	int i;
1314
1315	if (!enable)
1316		return 0;
1317
1318	/* Set link timer interval to 1.6ms. */
1319	timer_count = PCS_READ_8(sc, PCS_LINK_TIMER_COUNT);
1320	CLR(timer_count, PCS_LINK_TIMER_COUNT_MASK);
1321	SET(timer_count, ((1600 * cpu_freq) >> 10) & PCS_LINK_TIMER_COUNT_MASK);
1322	PCS_WRITE_8(sc, PCS_LINK_TIMER_COUNT, timer_count);
1323
1324	/* Reset the PCS. */
1325	ctl_reg = PCS_READ_8(sc, PCS_MR_CONTROL);
1326	SET(ctl_reg, PCS_MR_CONTROL_RESET);
1327	PCS_WRITE_8(sc, PCS_MR_CONTROL, ctl_reg);
1328
1329	/* Wait for the reset to complete. */
1330	done = 0;
1331	for (i = 0; i < 1000000; i++) {
1332		ctl_reg = PCS_READ_8(sc, PCS_MR_CONTROL);
1333		if (!ISSET(ctl_reg, PCS_MR_CONTROL_RESET)) {
1334			done = 1;
1335			break;
1336		}
1337	}
1338	if (!done) {
1339		printf("SGMII reset timeout on port %d\n", sc->sc_port_no);
1340		return 1;
1341	}
1342
1343	/* Start a new SGMII autonegotiation. */
1344	SET(ctl_reg, PCS_MR_CONTROL_AN_EN);
1345	SET(ctl_reg, PCS_MR_CONTROL_RST_AN);
1346	CLR(ctl_reg, PCS_MR_CONTROL_PWR_DN);
1347	PCS_WRITE_8(sc, PCS_MR_CONTROL, ctl_reg);
1348
1349	/* Wait for the SGMII autonegotiation to complete. */
1350	done = 0;
1351	for (i = 0; i < 1000000; i++) {
1352		status = PCS_READ_8(sc, PCS_MR_STATUS);
1353		if (ISSET(status, PCS_MR_STATUS_AN_CPT)) {
1354			done = 1;
1355			break;
1356		}
1357	}
1358	if (!done) {
1359		printf("SGMII autonegotiation timeout on port %d\n",
1360		    sc->sc_port_no);
1361		return 1;
1362	}
1363
1364	return 0;
1365}
1366
1367int
1368cn30xxgmx_sgmii_speed(struct cn30xxgmx_port_softc *sc)
1369{
1370	uint64_t misc_ctl, prt_cfg;
1371	int tx_burst, tx_slot;
1372
1373	cn30xxgmx_link_enable(sc, 0);
1374
1375	prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
1376
1377	if (ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX))
1378		SET(prt_cfg, PRTN_CFG_DUPLEX);
1379	else
1380		CLR(prt_cfg, PRTN_CFG_DUPLEX);
1381
1382	misc_ctl = PCS_READ_8(sc, PCS_MISC_CTL);
1383	CLR(misc_ctl, PCS_MISC_CTL_SAMP_PT);
1384
1385	/* Disable the GMX port if the link is down. */
1386	if (cn30xxgmx_link_status(sc))
1387		CLR(misc_ctl, PCS_MISC_CTL_GMXENO);
1388	else
1389		SET(misc_ctl, PCS_MISC_CTL_GMXENO);
1390
1391	switch (sc->sc_port_ac->ac_if.if_baudrate) {
1392	case IF_Mbps(10):
1393		tx_slot = 0x40;
1394		tx_burst = 0;
1395		CLR(prt_cfg, PRTN_CFG_SPEED);
1396		SET(prt_cfg, PRTN_CFG_SPEED_MSB);
1397		CLR(prt_cfg, PRTN_CFG_SLOTTIME);
1398		misc_ctl |= 25 & PCS_MISC_CTL_SAMP_PT;
1399		break;
1400	case IF_Mbps(100):
1401		tx_slot = 0x40;
1402		tx_burst = 0;
1403		CLR(prt_cfg, PRTN_CFG_SPEED);
1404		CLR(prt_cfg, PRTN_CFG_SPEED_MSB);
1405		CLR(prt_cfg, PRTN_CFG_SLOTTIME);
1406		misc_ctl |= 5 & PCS_MISC_CTL_SAMP_PT;
1407		break;
1408	case IF_Gbps(1):
1409	default:
1410		tx_slot = 0x200;
1411		tx_burst = 0x2000;
1412		SET(prt_cfg, PRTN_CFG_SPEED);
1413		CLR(prt_cfg, PRTN_CFG_SPEED_MSB);
1414		SET(prt_cfg, PRTN_CFG_SLOTTIME);
1415		misc_ctl |= 1 & PCS_MISC_CTL_SAMP_PT;
1416		break;
1417	}
1418
1419	PCS_WRITE_8(sc, PCS_MISC_CTL, misc_ctl);
1420
1421	_GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot);
1422	_GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst);
1423	_GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
1424
1425	cn30xxgmx_link_enable(sc, 1);
1426
1427	return 0;
1428}
1429
1430int
1431cn30xxgmx_sgmii_timing(struct cn30xxgmx_port_softc *sc)
1432{
1433	uint64_t rx_frm_ctl;
1434
1435	cn30xxgmx_tx_thresh(sc, 32);
1436
1437	rx_frm_ctl =
1438	    RXN_FRM_CTL_PRE_FREE |
1439	    RXN_FRM_CTL_CTL_SMAC |
1440	    RXN_FRM_CTL_CTL_MCST |
1441	    RXN_FRM_CTL_CTL_DRP |
1442	    RXN_FRM_CTL_PRE_STRP |
1443	    RXN_FRM_CTL_PRE_CHK;
1444	cn30xxgmx_rx_frm_ctl_enable(sc, rx_frm_ctl);
1445
1446	return 0;
1447}
1448
1449#if NKSTAT > 0
1450void
1451cn30xxgmx_kstat_read(struct cn30xxgmx_port_softc *sc, struct kstat_kv *kvs)
1452{
1453	uint64_t val;
1454
1455	kstat_kv_u64(&kvs[cnmac_stat_rx_totp_gmx]) +=
1456	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS);
1457	kstat_kv_u64(&kvs[cnmac_stat_rx_toto_gmx]) +=
1458	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_OCTS);
1459	kstat_kv_u64(&kvs[cnmac_stat_rx_ctl]) +=
1460	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_CTL);
1461	kstat_kv_u64(&kvs[cnmac_stat_rx_dmac]) +=
1462	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_DMAC);
1463	kstat_kv_u64(&kvs[cnmac_stat_rx_drop]) +=
1464	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_DRP);
1465	kstat_kv_u64(&kvs[cnmac_stat_rx_bad]) +=
1466	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_BAD);
1467
1468	val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT0);
1469	kstat_kv_u64(&kvs[cnmac_stat_tx_coll]) += (uint32_t)val;
1470	kstat_kv_u64(&kvs[cnmac_stat_tx_defer]) += val >> 32;
1471
1472	val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT1);
1473	kstat_kv_u64(&kvs[cnmac_stat_tx_mcol]) += (uint32_t)val;
1474	kstat_kv_u64(&kvs[cnmac_stat_tx_scol]) += val >> 32;
1475
1476	kstat_kv_u64(&kvs[cnmac_stat_tx_toto]) +=
1477	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_TX0_STAT2);
1478	kstat_kv_u64(&kvs[cnmac_stat_tx_totp]) +=
1479	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_TX0_STAT3);
1480
1481	val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT4);
1482	kstat_kv_u64(&kvs[cnmac_stat_tx_hmin]) += (uint32_t)val;
1483	kstat_kv_u64(&kvs[cnmac_stat_tx_h64]) += val >> 32;
1484
1485	val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT5);
1486	kstat_kv_u64(&kvs[cnmac_stat_tx_h127]) += (uint32_t)val;
1487	kstat_kv_u64(&kvs[cnmac_stat_tx_h255]) += val >> 32;
1488
1489	val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT6);
1490	kstat_kv_u64(&kvs[cnmac_stat_tx_h511]) += (uint32_t)val;
1491	kstat_kv_u64(&kvs[cnmac_stat_tx_h1023]) += val >> 32;
1492
1493	val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT7);
1494	kstat_kv_u64(&kvs[cnmac_stat_tx_h1518]) += (uint32_t)val;
1495	kstat_kv_u64(&kvs[cnmac_stat_tx_hmax]) += val >> 32;
1496
1497	val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT8);
1498	kstat_kv_u64(&kvs[cnmac_stat_tx_bcast]) += (uint32_t)val;
1499	kstat_kv_u64(&kvs[cnmac_stat_tx_mcast]) += val >> 32;
1500
1501	val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT9);
1502	kstat_kv_u64(&kvs[cnmac_stat_tx_ctl]) += (uint32_t)val;
1503	kstat_kv_u64(&kvs[cnmac_stat_tx_uflow]) += val >> 32;
1504}
1505#endif
1506