1 /* $OpenBSD: cn30xxgmx.c,v 1.55 2024/07/08 08:07:45 landry 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
81 struct 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
87 int cn30xxgmx_match(struct device *, void *, void *);
88 void cn30xxgmx_attach(struct device *, struct device *, void *);
89 int cn30xxgmx_print(void *, const char *);
90 void cn30xxgmx_init(struct cn30xxgmx_softc *);
91 int cn30xxgmx_rx_frm_ctl_xable(struct cn30xxgmx_port_softc *,
92 uint64_t, int);
93 void cn30xxgmx_agl_init(struct cn30xxgmx_port_softc *);
94 int cn30xxgmx_agl_enable(struct cn30xxgmx_port_softc *, int);
95 int cn30xxgmx_agl_speed(struct cn30xxgmx_port_softc *);
96 int cn30xxgmx_agl_timing(struct cn30xxgmx_port_softc *);
97 int cn30xxgmx_rgmii_enable(struct cn30xxgmx_port_softc *, int);
98 int cn30xxgmx_rgmii_speed(struct cn30xxgmx_port_softc *);
99 int cn30xxgmx_rgmii_speed_newlink(struct cn30xxgmx_port_softc *,
100 uint64_t *);
101 int cn30xxgmx_rgmii_speed_speed(struct cn30xxgmx_port_softc *);
102 int cn30xxgmx_rgmii_timing(struct cn30xxgmx_port_softc *);
103 int cn30xxgmx_sgmii_enable(struct cn30xxgmx_port_softc *, int);
104 int cn30xxgmx_sgmii_speed(struct cn30xxgmx_port_softc *);
105 int cn30xxgmx_sgmii_timing(struct cn30xxgmx_port_softc *);
106 int cn30xxgmx_tx_ovr_bp_enable(struct cn30xxgmx_port_softc *, int);
107 int cn30xxgmx_rx_pause_enable(struct cn30xxgmx_port_softc *, int);
108
109 #ifdef OCTEON_ETH_DEBUG
110 int cn30xxgmx_rgmii_speed_newlink_log(struct cn30xxgmx_port_softc *,
111 uint64_t);
112 #endif
113
114 struct 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
120 struct cn30xxgmx_port_ops cn30xxgmx_port_ops_mii = {
121 /* XXX not implemented */
122 };
123
124 struct 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
130 struct 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
136 struct 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
142 struct cn30xxgmx_port_ops cn30xxgmx_port_ops_spi42 = {
143 /* XXX not implemented */
144 };
145
146 struct 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
155 const struct cfattach octgmx_ca = {sizeof(struct cn30xxgmx_softc),
156 cn30xxgmx_match, cn30xxgmx_attach, NULL, NULL};
157
158 struct cfdriver octgmx_cd = {NULL, "octgmx", DV_DULL};
159
160 int
cn30xxgmx_match(struct device * parent,void * match,void * aux)161 cn30xxgmx_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
171 int
cn30xxgmx_get_phy_phandle(int interface,int port)172 cn30xxgmx_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
187 void
cn30xxgmx_attach(struct device * parent,struct device * self,void * aux)188 cn30xxgmx_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
294 error:
295 bus_space_unmap(sc->sc_regt, sc->sc_regh, GMX_BLOCK_SIZE);
296 }
297
298 int
cn30xxgmx_print(void * aux,const char * pnp)299 cn30xxgmx_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
320 void
cn30xxgmx_init(struct cn30xxgmx_softc * sc)321 cn30xxgmx_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 */
452 int
cn30xxgmx_link_enable(struct cn30xxgmx_port_softc * sc,int enable)453 cn30xxgmx_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
478 void
cn30xxgmx_stats_init(struct cn30xxgmx_port_softc * sc)479 cn30xxgmx_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
502 int
cn30xxgmx_tx_ovr_bp_enable(struct cn30xxgmx_port_softc * sc,int enable)503 cn30xxgmx_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
524 int
cn30xxgmx_rx_pause_enable(struct cn30xxgmx_port_softc * sc,int enable)525 cn30xxgmx_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
536 void
cn30xxgmx_tx_int_enable(struct cn30xxgmx_port_softc * sc,int enable)537 cn30xxgmx_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
551 void
cn30xxgmx_rx_int_enable(struct cn30xxgmx_port_softc * sc,int enable)552 cn30xxgmx_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
580 int
cn30xxgmx_rx_frm_ctl_enable(struct cn30xxgmx_port_softc * sc,uint64_t rx_frm_ctl)581 cn30xxgmx_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
594 int
cn30xxgmx_rx_frm_ctl_disable(struct cn30xxgmx_port_softc * sc,uint64_t rx_frm_ctl)595 cn30xxgmx_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
601 int
cn30xxgmx_rx_frm_ctl_xable(struct cn30xxgmx_port_softc * sc,uint64_t rx_frm_ctl,int enable)602 cn30xxgmx_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
617 int
cn30xxgmx_tx_thresh(struct cn30xxgmx_port_softc * sc,int cnt)618 cn30xxgmx_tx_thresh(struct cn30xxgmx_port_softc *sc, int cnt)
619 {
620 _GMX_PORT_WR8(sc, GMX0_TX0_THRESH, cnt);
621 return 0;
622 }
623
624 int
cn30xxgmx_set_filter(struct cn30xxgmx_port_softc * sc)625 cn30xxgmx_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
696 int
cn30xxgmx_port_enable(struct cn30xxgmx_port_softc * sc,int enable)697 cn30xxgmx_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
703 int
cn30xxgmx_reset_speed(struct cn30xxgmx_port_softc * sc)704 cn30xxgmx_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
717 int
cn30xxgmx_reset_timing(struct cn30xxgmx_port_softc * sc)718 cn30xxgmx_reset_timing(struct cn30xxgmx_port_softc *sc)
719 {
720 (*sc->sc_port_ops->port_ops_timing)(sc);
721 return 0;
722 }
723
724 int
cn30xxgmx_reset_flowctl(struct cn30xxgmx_port_softc * sc)725 cn30xxgmx_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
765 void
cn30xxgmx_agl_init(struct cn30xxgmx_port_softc * sc)766 cn30xxgmx_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
817 void
cn30xxgmx_agl_up(struct cn30xxgmx_port_softc * sc)818 cn30xxgmx_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
833 void
cn30xxgmx_agl_down(struct cn30xxgmx_port_softc * sc)834 cn30xxgmx_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
860 int
cn30xxgmx_agl_enable(struct cn30xxgmx_port_softc * sc,int enable)861 cn30xxgmx_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
870 int
cn30xxgmx_agl_speed(struct cn30xxgmx_port_softc * sc)871 cn30xxgmx_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
944 int
cn30xxgmx_agl_timing(struct cn30xxgmx_port_softc * sc)945 cn30xxgmx_agl_timing(struct cn30xxgmx_port_softc *sc)
946 {
947 return 0;
948 }
949
950 int
cn30xxgmx_rgmii_enable(struct cn30xxgmx_port_softc * sc,int enable)951 cn30xxgmx_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
964 int
cn30xxgmx_rgmii_speed(struct cn30xxgmx_port_softc * sc)965 cn30xxgmx_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 /* Assume 1Gbps for now */
995 baudrate = IF_Gbps(1); /* XXX */
996 break;
997 }
998 ifp->if_baudrate = baudrate;
999
1000 cn30xxgmx_link_enable(sc, 0);
1001
1002 /*
1003 * According to CN30XX-HM-1.0, 13.4.2 Link Status Changes:
1004 * wait a max_packet_time
1005 * max_packet_time(us) = (max_packet_size(bytes) * 8) / link_speed(Mbps)
1006 */
1007 delay((GMX_FRM_MAX_SIZ * 8) / (baudrate / 1000000));
1008
1009 cn30xxgmx_rgmii_speed_speed(sc);
1010
1011 cn30xxgmx_link_enable(sc, 1);
1012 cn30xxasx_enable(sc->sc_port_asx, 1);
1013
1014 return 0;
1015 }
1016
1017 int
cn30xxgmx_rgmii_speed_newlink(struct cn30xxgmx_port_softc * sc,uint64_t * rnewlink)1018 cn30xxgmx_rgmii_speed_newlink(struct cn30xxgmx_port_softc *sc,
1019 uint64_t *rnewlink)
1020 {
1021 uint64_t newlink;
1022
1023 /* Inband status does not seem to work */
1024 newlink = _GMX_PORT_RD8(sc, GMX0_RX0_RX_INBND);
1025
1026 *rnewlink = newlink;
1027 return 0;
1028 }
1029
1030 #ifdef OCTEON_ETH_DEBUG
1031 int
cn30xxgmx_rgmii_speed_newlink_log(struct cn30xxgmx_port_softc * sc,uint64_t newlink)1032 cn30xxgmx_rgmii_speed_newlink_log(struct cn30xxgmx_port_softc *sc,
1033 uint64_t newlink)
1034 {
1035 struct ifnet *ifp = &sc->sc_port_ac->ac_if;
1036 const char *status_str;
1037 const char *speed_str;
1038 const char *duplex_str;
1039 int is_status_changed;
1040 int is_speed_changed;
1041 int is_linked;
1042 char status_buf[80/* XXX */];
1043 char speed_buf[80/* XXX */];
1044
1045 is_status_changed = (newlink & RXN_RX_INBND_STATUS) !=
1046 (sc->sc_link & RXN_RX_INBND_STATUS);
1047 is_speed_changed = (newlink & RXN_RX_INBND_SPEED) !=
1048 (sc->sc_link & RXN_RX_INBND_SPEED);
1049 is_linked = ISSET(newlink, RXN_RX_INBND_STATUS);
1050 if (is_status_changed) {
1051 if (is_linked)
1052 status_str = "link up";
1053 else
1054 status_str = "link down";
1055 } else {
1056 if (is_linked) {
1057 /* any other conditions? */
1058 if (is_speed_changed)
1059 status_str = "link change";
1060 else
1061 status_str = NULL;
1062 } else {
1063 status_str = NULL;
1064 }
1065 }
1066
1067 if (status_str != NULL) {
1068 if ((is_speed_changed && is_linked) || is_linked) {
1069 switch (newlink & RXN_RX_INBND_SPEED) {
1070 case RXN_RX_INBND_SPEED_2_5:
1071 speed_str = "10baseT";
1072 break;
1073 case RXN_RX_INBND_SPEED_25:
1074 speed_str = "100baseTX";
1075 break;
1076 case RXN_RX_INBND_SPEED_125:
1077 speed_str = "1000baseT";
1078 break;
1079 default:
1080 panic("Unknown link speed");
1081 break;
1082 }
1083
1084 if (ISSET(newlink, RXN_RX_INBND_DUPLEX))
1085 duplex_str = "-FDX";
1086 else
1087 duplex_str = "";
1088
1089 (void)snprintf(speed_buf, sizeof(speed_buf), "(%s%s)",
1090 speed_str, duplex_str);
1091 } else {
1092 speed_buf[0] = '\0';
1093 }
1094 (void)snprintf(status_buf, sizeof(status_buf), "%s: %s%s%s\n",
1095 ifp->if_xname, status_str, (is_speed_changed | is_linked) ? " " : "",
1096 speed_buf);
1097 log(LOG_CRIT, status_buf);
1098 }
1099
1100 return 0;
1101 }
1102 #endif
1103
1104 int
cn30xxgmx_rgmii_speed_speed(struct cn30xxgmx_port_softc * sc)1105 cn30xxgmx_rgmii_speed_speed(struct cn30xxgmx_port_softc *sc)
1106 {
1107 uint64_t prt_cfg;
1108 uint64_t tx_clk, tx_slot, tx_burst;
1109
1110 prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
1111
1112 switch (sc->sc_link & RXN_RX_INBND_SPEED) {
1113 case RXN_RX_INBND_SPEED_2_5:
1114 /* 10Mbps */
1115 /*
1116 * "GMX Tx Clock Generation Registers", CN30XX-HM-1.0;
1117 * > 8ns x 50 = 400ns (2.5MHz TXC clock)
1118 */
1119 tx_clk = 50;
1120 /*
1121 * "TX Slottime Counter Registers", CN30XX-HM-1.0;
1122 * > 10/100Mbps: set SLOT to 0x40
1123 */
1124 tx_slot = 0x40;
1125 /*
1126 * "TX Burst-Counter Registers", CN30XX-HM-1.0;
1127 * > 10/100Mbps: set BURST to 0x0
1128 */
1129 tx_burst = 0;
1130 /*
1131 * "GMX Tx Port Configuration Registers", CN30XX-HM-1.0;
1132 * > Slot time for half-duplex operation
1133 * > 0 = 512 bittimes (10/100Mbps operation)
1134 */
1135 CLR(prt_cfg, PRTN_CFG_SLOTTIME);
1136 /*
1137 * "GMX Port Configuration Registers", CN30XX-HM-1.0;
1138 * > Link speed
1139 * > 0 = 10/100Mbps operation
1140 * > in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
1141 */
1142 CLR(prt_cfg, PRTN_CFG_SPEED);
1143 break;
1144 case RXN_RX_INBND_SPEED_25:
1145 /* 100Mbps */
1146 /*
1147 * "GMX Tx Clock Generation Registers", CN30XX-HM-1.0;
1148 * > 8ns x 5 = 40ns (25.0MHz TXC clock)
1149 */
1150 tx_clk = 5;
1151 /*
1152 * "TX Slottime Counter Registers", CN30XX-HM-1.0;
1153 * > 10/100Mbps: set SLOT to 0x40
1154 */
1155 tx_slot = 0x40;
1156 /*
1157 * "TX Burst-Counter Registers", CN30XX-HM-1.0;
1158 * > 10/100Mbps: set BURST to 0x0
1159 */
1160 tx_burst = 0;
1161 /*
1162 * "GMX Tx Port Configuration Registers", CN30XX-HM-1.0;
1163 * > Slot time for half-duplex operation
1164 * > 0 = 512 bittimes (10/100Mbps operation)
1165 */
1166 CLR(prt_cfg, PRTN_CFG_SLOTTIME);
1167 /*
1168 * "GMX Port Configuration Registers", CN30XX-HM-1.0;
1169 * > Link speed
1170 * > 0 = 10/100Mbps operation
1171 * > in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
1172 */
1173 CLR(prt_cfg, PRTN_CFG_SPEED);
1174 break;
1175 case RXN_RX_INBND_SPEED_125:
1176 /* 1000Mbps */
1177 /*
1178 * "GMX Tx Clock Generation Registers", CN30XX-HM-1.0;
1179 * > 8ns x 1 = 8ns (125.0MHz TXC clock)
1180 */
1181 tx_clk = 1;
1182 /*
1183 * "TX Slottime Counter Registers", CN30XX-HM-1.0;
1184 * > 1000Mbps: set SLOT to 0x200
1185 */
1186 tx_slot = 0x200;
1187 /*
1188 * "TX Burst-Counter Registers", CN30XX-HM-1.0;
1189 * > 1000Mbps: set BURST to 0x2000
1190 */
1191 tx_burst = 0x2000;
1192 /*
1193 * "GMX Tx Port Configuration Registers", CN30XX-HM-1.0;
1194 * > Slot time for half-duplex operation
1195 * > 1 = 4096 bittimes (1000Mbps operation)
1196 */
1197 SET(prt_cfg, PRTN_CFG_SLOTTIME);
1198 /*
1199 * "GMX Port Configuration Registers", CN30XX-HM-1.0;
1200 * > Link speed
1201 * > 1 = 1000Mbps operation
1202 */
1203 SET(prt_cfg, PRTN_CFG_SPEED);
1204 break;
1205 default:
1206 /* THEORETICALLY NOT REACHED! */
1207 /* Following configuration is default value of system.
1208 */
1209 tx_clk = 1;
1210 tx_slot = 0x200;
1211 tx_burst = 0x2000;
1212 SET(prt_cfg, PRTN_CFG_SLOTTIME);
1213 SET(prt_cfg, PRTN_CFG_SPEED);
1214 break;
1215 }
1216
1217 /* Setup Duplex mode(negotiated) */
1218 /*
1219 * "GMX Port Configuration Registers", CN30XX-HM-1.0;
1220 * > Duplex mode: 0 = half-duplex mode, 1=full-duplex
1221 */
1222 if (ISSET(sc->sc_link, RXN_RX_INBND_DUPLEX)) {
1223 /* Full-Duplex */
1224 SET(prt_cfg, PRTN_CFG_DUPLEX);
1225 } else {
1226 /* Half-Duplex */
1227 CLR(prt_cfg, PRTN_CFG_DUPLEX);
1228 }
1229
1230 _GMX_PORT_WR8(sc, GMX0_TX0_CLK, tx_clk);
1231 _GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot);
1232 _GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst);
1233 _GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
1234
1235 return 0;
1236 }
1237
1238 int
cn30xxgmx_rgmii_timing(struct cn30xxgmx_port_softc * sc)1239 cn30xxgmx_rgmii_timing(struct cn30xxgmx_port_softc *sc)
1240 {
1241 int clk_tx_setting;
1242 int clk_rx_setting;
1243 uint64_t rx_frm_ctl;
1244
1245 /* RGMII TX Threshold Registers, CN30XX-HM-1.0;
1246 * > Number of 16-byte ticks to accumulate in the TX FIFO before
1247 * > sending on the RGMII interface. This field should be large
1248 * > enough to prevent underflow on the RGMII interface and must
1249 * > never be set to less than 0x4. This register cannot exceed
1250 * > the TX FIFO depth of 0x40 words.
1251 */
1252 /* Default parameter of CN30XX */
1253 cn30xxgmx_tx_thresh(sc, 32);
1254
1255 rx_frm_ctl = 0 |
1256 /* RXN_FRM_CTL_NULL_DIS | (cn5xxx only) */
1257 /* RXN_FRM_CTL_PRE_ALIGN | (cn5xxx only) */
1258 /* RXN_FRM_CTL_PAD_LEN | (cn3xxx only) */
1259 /* RXN_FRM_CTL_VLAN_LEN | (cn3xxx only) */
1260 RXN_FRM_CTL_PRE_FREE |
1261 RXN_FRM_CTL_CTL_SMAC |
1262 RXN_FRM_CTL_CTL_MCST |
1263 RXN_FRM_CTL_CTL_DRP |
1264 RXN_FRM_CTL_PRE_STRP |
1265 RXN_FRM_CTL_PRE_CHK;
1266 cn30xxgmx_rx_frm_ctl_enable(sc, rx_frm_ctl);
1267
1268 /* XXX PHY-dependent parameter */
1269 /* RGMII RX Clock-Delay Registers, CN30XX-HM-1.0;
1270 * > Delay setting to place n RXC (RGMII receive clock) delay line.
1271 * > The intrinsic delay can range from 50ps to 80ps per tap,
1272 * > which corresponds to skews of 1.25ns to 2.00ns at 25 taps(CSR+1).
1273 * > This is the best match for the RGMII specification which wants
1274 * > 1ns - 2.6ns of skew.
1275 */
1276 /* RGMII TX Clock-Delay Registers, CN30XX-HM-1.0;
1277 * > Delay setting to place n TXC (RGMII transmit clock) delay line.
1278 * > ...
1279 */
1280
1281 switch (octeon_board) {
1282 default:
1283 /* Default parameter of CN30XX */
1284 clk_tx_setting = 24;
1285 clk_rx_setting = 24;
1286 break;
1287 case BOARD_NETGEAR_UTM25:
1288 if (sc->sc_port_no == 0) {
1289 clk_tx_setting = 9;
1290 clk_rx_setting = 9;
1291 } else {
1292 clk_tx_setting = 24;
1293 clk_rx_setting = 24;
1294 }
1295 break;
1296 case BOARD_UBIQUITI_E100:
1297 case BOARD_UBIQUITI_E120:
1298 clk_tx_setting = 16;
1299 clk_rx_setting = 0;
1300 break;
1301 }
1302
1303 cn30xxasx_clk_set(sc->sc_port_asx, clk_tx_setting, clk_rx_setting);
1304
1305 return 0;
1306 }
1307
1308 int
cn30xxgmx_sgmii_enable(struct cn30xxgmx_port_softc * sc,int enable)1309 cn30xxgmx_sgmii_enable(struct cn30xxgmx_port_softc *sc, int enable)
1310 {
1311 uint64_t ctl_reg, status, timer_count;
1312 uint64_t cpu_freq = octeon_boot_info->eclock / 1000000;
1313 int done;
1314 int i;
1315
1316 if (!enable)
1317 return 0;
1318
1319 /* Set link timer interval to 1.6ms. */
1320 timer_count = PCS_READ_8(sc, PCS_LINK_TIMER_COUNT);
1321 CLR(timer_count, PCS_LINK_TIMER_COUNT_MASK);
1322 SET(timer_count, ((1600 * cpu_freq) >> 10) & PCS_LINK_TIMER_COUNT_MASK);
1323 PCS_WRITE_8(sc, PCS_LINK_TIMER_COUNT, timer_count);
1324
1325 /* Reset the PCS. */
1326 ctl_reg = PCS_READ_8(sc, PCS_MR_CONTROL);
1327 SET(ctl_reg, PCS_MR_CONTROL_RESET);
1328 PCS_WRITE_8(sc, PCS_MR_CONTROL, ctl_reg);
1329
1330 /* Wait for the reset to complete. */
1331 done = 0;
1332 for (i = 0; i < 1000000; i++) {
1333 ctl_reg = PCS_READ_8(sc, PCS_MR_CONTROL);
1334 if (!ISSET(ctl_reg, PCS_MR_CONTROL_RESET)) {
1335 done = 1;
1336 break;
1337 }
1338 }
1339 if (!done) {
1340 printf("SGMII reset timeout on port %d\n", sc->sc_port_no);
1341 return 1;
1342 }
1343
1344 /* Start a new SGMII autonegotiation. */
1345 SET(ctl_reg, PCS_MR_CONTROL_AN_EN);
1346 SET(ctl_reg, PCS_MR_CONTROL_RST_AN);
1347 CLR(ctl_reg, PCS_MR_CONTROL_PWR_DN);
1348 PCS_WRITE_8(sc, PCS_MR_CONTROL, ctl_reg);
1349
1350 /* Wait for the SGMII autonegotiation to complete. */
1351 done = 0;
1352 for (i = 0; i < 1000000; i++) {
1353 status = PCS_READ_8(sc, PCS_MR_STATUS);
1354 if (ISSET(status, PCS_MR_STATUS_AN_CPT)) {
1355 done = 1;
1356 break;
1357 }
1358 }
1359 if (!done) {
1360 printf("SGMII autonegotiation timeout on port %d\n",
1361 sc->sc_port_no);
1362 return 1;
1363 }
1364
1365 return 0;
1366 }
1367
1368 int
cn30xxgmx_sgmii_speed(struct cn30xxgmx_port_softc * sc)1369 cn30xxgmx_sgmii_speed(struct cn30xxgmx_port_softc *sc)
1370 {
1371 uint64_t misc_ctl, prt_cfg;
1372 int tx_burst, tx_slot;
1373
1374 cn30xxgmx_link_enable(sc, 0);
1375
1376 prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
1377
1378 if (ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX))
1379 SET(prt_cfg, PRTN_CFG_DUPLEX);
1380 else
1381 CLR(prt_cfg, PRTN_CFG_DUPLEX);
1382
1383 misc_ctl = PCS_READ_8(sc, PCS_MISC_CTL);
1384 CLR(misc_ctl, PCS_MISC_CTL_SAMP_PT);
1385
1386 /* Disable the GMX port if the link is down. */
1387 if (cn30xxgmx_link_status(sc))
1388 CLR(misc_ctl, PCS_MISC_CTL_GMXENO);
1389 else
1390 SET(misc_ctl, PCS_MISC_CTL_GMXENO);
1391
1392 switch (sc->sc_port_ac->ac_if.if_baudrate) {
1393 case IF_Mbps(10):
1394 tx_slot = 0x40;
1395 tx_burst = 0;
1396 CLR(prt_cfg, PRTN_CFG_SPEED);
1397 SET(prt_cfg, PRTN_CFG_SPEED_MSB);
1398 CLR(prt_cfg, PRTN_CFG_SLOTTIME);
1399 misc_ctl |= 25 & PCS_MISC_CTL_SAMP_PT;
1400 break;
1401 case IF_Mbps(100):
1402 tx_slot = 0x40;
1403 tx_burst = 0;
1404 CLR(prt_cfg, PRTN_CFG_SPEED);
1405 CLR(prt_cfg, PRTN_CFG_SPEED_MSB);
1406 CLR(prt_cfg, PRTN_CFG_SLOTTIME);
1407 misc_ctl |= 5 & PCS_MISC_CTL_SAMP_PT;
1408 break;
1409 case IF_Gbps(1):
1410 default:
1411 tx_slot = 0x200;
1412 tx_burst = 0x2000;
1413 SET(prt_cfg, PRTN_CFG_SPEED);
1414 CLR(prt_cfg, PRTN_CFG_SPEED_MSB);
1415 SET(prt_cfg, PRTN_CFG_SLOTTIME);
1416 misc_ctl |= 1 & PCS_MISC_CTL_SAMP_PT;
1417 break;
1418 }
1419
1420 PCS_WRITE_8(sc, PCS_MISC_CTL, misc_ctl);
1421
1422 _GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot);
1423 _GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst);
1424 _GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
1425
1426 cn30xxgmx_link_enable(sc, 1);
1427
1428 return 0;
1429 }
1430
1431 int
cn30xxgmx_sgmii_timing(struct cn30xxgmx_port_softc * sc)1432 cn30xxgmx_sgmii_timing(struct cn30xxgmx_port_softc *sc)
1433 {
1434 uint64_t rx_frm_ctl;
1435
1436 cn30xxgmx_tx_thresh(sc, 32);
1437
1438 rx_frm_ctl =
1439 RXN_FRM_CTL_PRE_FREE |
1440 RXN_FRM_CTL_CTL_SMAC |
1441 RXN_FRM_CTL_CTL_MCST |
1442 RXN_FRM_CTL_CTL_DRP |
1443 RXN_FRM_CTL_PRE_STRP |
1444 RXN_FRM_CTL_PRE_CHK;
1445 cn30xxgmx_rx_frm_ctl_enable(sc, rx_frm_ctl);
1446
1447 return 0;
1448 }
1449
1450 #if NKSTAT > 0
1451 void
cn30xxgmx_kstat_read(struct cn30xxgmx_port_softc * sc,struct kstat_kv * kvs)1452 cn30xxgmx_kstat_read(struct cn30xxgmx_port_softc *sc, struct kstat_kv *kvs)
1453 {
1454 uint64_t val;
1455
1456 kstat_kv_u64(&kvs[cnmac_stat_rx_totp_gmx]) +=
1457 (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS);
1458 kstat_kv_u64(&kvs[cnmac_stat_rx_toto_gmx]) +=
1459 (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_OCTS);
1460 kstat_kv_u64(&kvs[cnmac_stat_rx_ctl]) +=
1461 (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_CTL);
1462 kstat_kv_u64(&kvs[cnmac_stat_rx_dmac]) +=
1463 (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_DMAC);
1464 kstat_kv_u64(&kvs[cnmac_stat_rx_drop]) +=
1465 (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_DRP);
1466 kstat_kv_u64(&kvs[cnmac_stat_rx_bad]) +=
1467 (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_BAD);
1468
1469 val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT0);
1470 kstat_kv_u64(&kvs[cnmac_stat_tx_coll]) += (uint32_t)val;
1471 kstat_kv_u64(&kvs[cnmac_stat_tx_defer]) += val >> 32;
1472
1473 val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT1);
1474 kstat_kv_u64(&kvs[cnmac_stat_tx_mcol]) += (uint32_t)val;
1475 kstat_kv_u64(&kvs[cnmac_stat_tx_scol]) += val >> 32;
1476
1477 kstat_kv_u64(&kvs[cnmac_stat_tx_toto]) +=
1478 (uint32_t)_GMX_PORT_RD8(sc, GMX0_TX0_STAT2);
1479 kstat_kv_u64(&kvs[cnmac_stat_tx_totp]) +=
1480 (uint32_t)_GMX_PORT_RD8(sc, GMX0_TX0_STAT3);
1481
1482 val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT4);
1483 kstat_kv_u64(&kvs[cnmac_stat_tx_hmin]) += (uint32_t)val;
1484 kstat_kv_u64(&kvs[cnmac_stat_tx_h64]) += val >> 32;
1485
1486 val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT5);
1487 kstat_kv_u64(&kvs[cnmac_stat_tx_h127]) += (uint32_t)val;
1488 kstat_kv_u64(&kvs[cnmac_stat_tx_h255]) += val >> 32;
1489
1490 val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT6);
1491 kstat_kv_u64(&kvs[cnmac_stat_tx_h511]) += (uint32_t)val;
1492 kstat_kv_u64(&kvs[cnmac_stat_tx_h1023]) += val >> 32;
1493
1494 val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT7);
1495 kstat_kv_u64(&kvs[cnmac_stat_tx_h1518]) += (uint32_t)val;
1496 kstat_kv_u64(&kvs[cnmac_stat_tx_hmax]) += val >> 32;
1497
1498 val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT8);
1499 kstat_kv_u64(&kvs[cnmac_stat_tx_bcast]) += (uint32_t)val;
1500 kstat_kv_u64(&kvs[cnmac_stat_tx_mcast]) += val >> 32;
1501
1502 val = _GMX_PORT_RD8(sc, GMX0_TX0_STAT9);
1503 kstat_kv_u64(&kvs[cnmac_stat_tx_ctl]) += (uint32_t)val;
1504 kstat_kv_u64(&kvs[cnmac_stat_tx_uflow]) += val >> 32;
1505 }
1506 #endif
1507