xref: /freebsd/sys/dev/axgbe/if_axgbe.c (revision 22cf89c938886d14f5796fc49f9f020c23ea8eaf)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2016,2017 SoftIron Inc.
5  * Copyright (c) 2020 Advanced Micro Devices, Inc.
6  *
7  * This software was developed by Andrew Turner under
8  * the sponsorship of SoftIron Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36 #include <sys/kernel.h>
37 #include <sys/lock.h>
38 #include <sys/malloc.h>
39 #include <sys/module.h>
40 #include <sys/mutex.h>
41 #include <sys/queue.h>
42 #include <sys/rman.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <sys/sx.h>
46 #include <sys/taskqueue.h>
47 
48 #include <net/ethernet.h>
49 #include <net/if.h>
50 #include <net/if_var.h>
51 #include <net/if_media.h>
52 #include <net/if_types.h>
53 
54 #include <dev/ofw/openfirm.h>
55 #include <dev/ofw/ofw_bus.h>
56 #include <dev/ofw/ofw_bus_subr.h>
57 
58 #include <machine/bus.h>
59 
60 #include "miibus_if.h"
61 
62 #include "xgbe.h"
63 #include "xgbe-common.h"
64 
65 static device_probe_t	axgbe_probe;
66 static device_attach_t	axgbe_attach;
67 
68 struct axgbe_softc {
69 	/* Must be first */
70 	struct xgbe_prv_data	prv;
71 
72 	uint8_t			mac_addr[ETHER_ADDR_LEN];
73 	struct ifmedia		media;
74 };
75 
76 static struct ofw_compat_data compat_data[] = {
77 	{ "amd,xgbe-seattle-v1a",	true },
78 	{ NULL,				false }
79 };
80 
81 static struct resource_spec old_phy_spec[] = {
82 	{ SYS_RES_MEMORY,	0,	RF_ACTIVE }, /* Rx/Tx regs */
83 	{ SYS_RES_MEMORY,	1,	RF_ACTIVE }, /* Integration regs */
84 	{ SYS_RES_MEMORY,	2,	RF_ACTIVE }, /* Integration regs */
85 	{ SYS_RES_IRQ,		0,	RF_ACTIVE }, /* Interrupt */
86 	{ -1, 0 }
87 };
88 
89 static struct resource_spec old_mac_spec[] = {
90 	{ SYS_RES_MEMORY,	0,	RF_ACTIVE }, /* MAC regs */
91 	{ SYS_RES_MEMORY,	1,	RF_ACTIVE }, /* PCS regs */
92 	{ SYS_RES_IRQ,		0,	RF_ACTIVE }, /* Device interrupt */
93 	/* Per-channel interrupts */
94 	{ SYS_RES_IRQ,		1,	RF_ACTIVE | RF_OPTIONAL },
95 	{ SYS_RES_IRQ,		2,	RF_ACTIVE | RF_OPTIONAL },
96 	{ SYS_RES_IRQ,		3,	RF_ACTIVE | RF_OPTIONAL },
97 	{ SYS_RES_IRQ,		4,	RF_ACTIVE | RF_OPTIONAL },
98 	{ -1, 0 }
99 };
100 
101 static struct resource_spec mac_spec[] = {
102 	{ SYS_RES_MEMORY,	0,	RF_ACTIVE }, /* MAC regs */
103 	{ SYS_RES_MEMORY,	1,	RF_ACTIVE }, /* PCS regs */
104 	{ SYS_RES_MEMORY,	2,	RF_ACTIVE }, /* Rx/Tx regs */
105 	{ SYS_RES_MEMORY,	3,	RF_ACTIVE }, /* Integration regs */
106 	{ SYS_RES_MEMORY,	4,	RF_ACTIVE }, /* Integration regs */
107 	{ SYS_RES_IRQ,		0,	RF_ACTIVE }, /* Device interrupt */
108 	/* Per-channel and auto-negotiation interrupts */
109 	{ SYS_RES_IRQ,		1,	RF_ACTIVE },
110 	{ SYS_RES_IRQ,		2,	RF_ACTIVE | RF_OPTIONAL },
111 	{ SYS_RES_IRQ,		3,	RF_ACTIVE | RF_OPTIONAL },
112 	{ SYS_RES_IRQ,		4,	RF_ACTIVE | RF_OPTIONAL },
113 	{ SYS_RES_IRQ,		5,	RF_ACTIVE | RF_OPTIONAL },
114 	{ -1, 0 }
115 };
116 
117 static struct xgbe_version_data xgbe_v1 = {
118 	.init_function_ptrs_phy_impl    = xgbe_init_function_ptrs_phy_v1,
119 	.xpcs_access                    = XGBE_XPCS_ACCESS_V1,
120 	.tx_max_fifo_size               = 81920,
121 	.rx_max_fifo_size               = 81920,
122 	.tx_tstamp_workaround           = 1,
123 };
124 
125 MALLOC_DEFINE(M_AXGBE, "axgbe", "axgbe data");
126 
127 static void
128 axgbe_init(void *p)
129 {
130 	struct axgbe_softc *sc;
131 	if_t ifp;
132 
133 	sc = p;
134 	ifp = sc->prv.netdev;
135 	if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
136 		return;
137 
138 	if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0);
139 }
140 
141 static int
142 axgbe_ioctl(if_t ifp, unsigned long command, caddr_t data)
143 {
144 	struct axgbe_softc *sc = if_getsoftc(ifp);
145 	struct ifreq *ifr = (struct ifreq *)data;
146 	int error = 0;
147 
148 	switch(command) {
149 	case SIOCSIFMTU:
150 		if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU_JUMBO)
151 			error = EINVAL;
152 		/* TODO - change it to iflib way */
153 		break;
154 	case SIOCSIFFLAGS:
155 		error = 0;
156 		break;
157 	case SIOCSIFMEDIA:
158 	case SIOCGIFMEDIA:
159 		error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
160 		break;
161 	default:
162 		error = ether_ioctl(ifp, command, data);
163 		break;
164 	}
165 
166 	return (error);
167 }
168 
169 static void
170 axgbe_qflush(if_t ifp)
171 {
172 
173 	if_qflush(ifp);
174 }
175 
176 static int
177 axgbe_media_change(if_t ifp)
178 {
179 	struct axgbe_softc *sc;
180 	int cur_media;
181 
182 	sc = if_getsoftc(ifp);
183 
184 	sx_xlock(&sc->prv.an_mutex);
185 	cur_media = sc->media.ifm_cur->ifm_media;
186 
187 	switch (IFM_SUBTYPE(cur_media)) {
188 	case IFM_10G_KR:
189 		sc->prv.phy.speed = SPEED_10000;
190 		sc->prv.phy.autoneg = AUTONEG_DISABLE;
191 		break;
192 	case IFM_2500_KX:
193 		sc->prv.phy.speed = SPEED_2500;
194 		sc->prv.phy.autoneg = AUTONEG_DISABLE;
195 		break;
196 	case IFM_1000_KX:
197 		sc->prv.phy.speed = SPEED_1000;
198 		sc->prv.phy.autoneg = AUTONEG_DISABLE;
199 		break;
200 	case IFM_AUTO:
201 		sc->prv.phy.autoneg = AUTONEG_ENABLE;
202 		break;
203 	}
204 	sx_xunlock(&sc->prv.an_mutex);
205 
206 	return (-sc->prv.phy_if.phy_config_aneg(&sc->prv));
207 }
208 
209 static void
210 axgbe_media_status(if_t ifp, struct ifmediareq *ifmr)
211 {
212 	struct axgbe_softc *sc;
213 
214 	sc = if_getsoftc(ifp);
215 
216 	ifmr->ifm_status = IFM_AVALID;
217 	if (!sc->prv.phy.link)
218 		return;
219 
220 	ifmr->ifm_status |= IFM_ACTIVE;
221 	ifmr->ifm_active = IFM_ETHER;
222 
223 	if (sc->prv.phy.duplex == DUPLEX_FULL)
224 		ifmr->ifm_active |= IFM_FDX;
225 	else
226 		ifmr->ifm_active |= IFM_HDX;
227 
228 	switch (sc->prv.phy.speed) {
229 	case SPEED_10000:
230 		ifmr->ifm_active |= IFM_10G_KR;
231 		break;
232 	case SPEED_2500:
233 		ifmr->ifm_active |= IFM_2500_KX;
234 		break;
235 	case SPEED_1000:
236 		ifmr->ifm_active |= IFM_1000_KX;
237 		break;
238 	}
239 }
240 
241 static uint64_t
242 axgbe_get_counter(if_t ifp, ift_counter c)
243 {
244 	struct xgbe_prv_data *pdata = if_getsoftc(ifp);
245 	struct xgbe_mmc_stats *pstats = &pdata->mmc_stats;
246 
247 	DBGPR("-->%s\n", __func__);
248 
249 	pdata->hw_if.read_mmc_stats(pdata);
250 
251 	switch(c) {
252 	case IFCOUNTER_IPACKETS:
253 		return (pstats->rxframecount_gb);
254 	case IFCOUNTER_IERRORS:
255 		return (pstats->rxframecount_gb -
256 		    pstats->rxbroadcastframes_g -
257 		    pstats->rxmulticastframes_g -
258 		    pstats->rxunicastframes_g);
259 	case IFCOUNTER_OPACKETS:
260 		return (pstats->txframecount_gb);
261 	case IFCOUNTER_OERRORS:
262 		return (pstats->txframecount_gb - pstats->txframecount_g);
263 	case IFCOUNTER_IBYTES:
264 		return (pstats->rxoctetcount_gb);
265 	case IFCOUNTER_OBYTES:
266 		return (pstats->txoctetcount_gb);
267 	default:
268 		return (if_get_counter_default(ifp, c));
269 	}
270 }
271 
272 static int
273 axgbe_probe(device_t dev)
274 {
275 
276 	if (!ofw_bus_status_okay(dev))
277 		return (ENXIO);
278 
279 	if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
280 		return (ENXIO);
281 
282 	device_set_desc(dev, "AMD 10 Gigabit Ethernet");
283 	return (BUS_PROBE_DEFAULT);
284 }
285 
286 static int
287 axgbe_get_optional_prop(device_t dev, phandle_t node, const char *name,
288     int *data, size_t len)
289 {
290 
291 	if (!OF_hasprop(node, name))
292 		return (-1);
293 
294 	if (OF_getencprop(node, name, data, len) <= 0) {
295 		device_printf(dev,"%s property is invalid\n", name);
296 		return (ENXIO);
297 	}
298 
299 	return (0);
300 }
301 
302 static int
303 axgbe_attach(device_t dev)
304 {
305 	struct axgbe_softc *sc;
306 	if_t ifp;
307 	pcell_t phy_handle;
308 	device_t phydev;
309 	phandle_t node, phy_node;
310 	struct resource *mac_res[11];
311 	struct resource *phy_res[4];
312 	ssize_t len;
313 	int error, i, j;
314 
315 	sc = device_get_softc(dev);
316 
317 	sc->prv.vdata = &xgbe_v1;
318 	node = ofw_bus_get_node(dev);
319 	if (OF_getencprop(node, "phy-handle", &phy_handle,
320 	    sizeof(phy_handle)) <= 0) {
321 		phy_node = node;
322 
323 		if (bus_alloc_resources(dev, mac_spec, mac_res)) {
324 			device_printf(dev,
325 			    "could not allocate phy resources\n");
326 			return (ENXIO);
327 		}
328 
329 		sc->prv.xgmac_res = mac_res[0];
330 		sc->prv.xpcs_res = mac_res[1];
331 		sc->prv.rxtx_res = mac_res[2];
332 		sc->prv.sir0_res = mac_res[3];
333 		sc->prv.sir1_res = mac_res[4];
334 
335 		sc->prv.dev_irq_res = mac_res[5];
336 		sc->prv.per_channel_irq = OF_hasprop(node,
337 		    XGBE_DMA_IRQS_PROPERTY);
338 		for (i = 0, j = 6; j < nitems(mac_res) - 1 &&
339 		    mac_res[j + 1] != NULL; i++, j++) {
340 			if (sc->prv.per_channel_irq) {
341 				sc->prv.chan_irq_res[i] = mac_res[j];
342 			}
343 		}
344 
345 		/* The last entry is the auto-negotiation interrupt */
346 		sc->prv.an_irq_res = mac_res[j];
347 	} else {
348 		phydev = OF_device_from_xref(phy_handle);
349 		phy_node = ofw_bus_get_node(phydev);
350 
351 		if (bus_alloc_resources(phydev, old_phy_spec, phy_res)) {
352 			device_printf(dev,
353 			    "could not allocate phy resources\n");
354 			return (ENXIO);
355 		}
356 
357 		if (bus_alloc_resources(dev, old_mac_spec, mac_res)) {
358 			device_printf(dev,
359 			    "could not allocate mac resources\n");
360 			return (ENXIO);
361 		}
362 
363 		sc->prv.rxtx_res = phy_res[0];
364 		sc->prv.sir0_res = phy_res[1];
365 		sc->prv.sir1_res = phy_res[2];
366 		sc->prv.an_irq_res = phy_res[3];
367 
368 		sc->prv.xgmac_res = mac_res[0];
369 		sc->prv.xpcs_res = mac_res[1];
370 		sc->prv.dev_irq_res = mac_res[2];
371 		sc->prv.per_channel_irq = OF_hasprop(node,
372 		    XGBE_DMA_IRQS_PROPERTY);
373 		if (sc->prv.per_channel_irq) {
374 			for (i = 0, j = 3; i < nitems(sc->prv.chan_irq_res) &&
375 			    mac_res[j] != NULL; i++, j++) {
376 				sc->prv.chan_irq_res[i] = mac_res[j];
377 			}
378 		}
379 	}
380 
381 	if ((len = OF_getproplen(node, "mac-address")) < 0) {
382 		device_printf(dev, "No mac-address property\n");
383 		return (EINVAL);
384 	}
385 
386 	if (len != ETHER_ADDR_LEN)
387 		return (EINVAL);
388 
389 	OF_getprop(node, "mac-address", sc->mac_addr, ETHER_ADDR_LEN);
390 
391 	sc->prv.netdev = ifp = if_alloc(IFT_ETHER);
392 	if (ifp == NULL) {
393 		device_printf(dev, "Cannot alloc ifnet\n");
394 		return (ENXIO);
395 	}
396 
397 	sc->prv.dev = dev;
398 	sc->prv.dmat = bus_get_dma_tag(dev);
399 	sc->prv.phy.advertising = ADVERTISED_10000baseKR_Full |
400 	    ADVERTISED_1000baseKX_Full;
401 
402 
403 	/*
404 	 * Read the needed properties from the phy node.
405 	 */
406 
407 	/* This is documented as optional, but Linux requires it */
408 	if (OF_getencprop(phy_node, XGBE_SPEEDSET_PROPERTY, &sc->prv.speed_set,
409 	    sizeof(sc->prv.speed_set)) <= 0) {
410 		device_printf(dev, "%s property is missing\n",
411 		    XGBE_SPEEDSET_PROPERTY);
412 		return (EINVAL);
413 	}
414 
415 	error = axgbe_get_optional_prop(dev, phy_node, XGBE_BLWC_PROPERTY,
416 	    sc->prv.serdes_blwc, sizeof(sc->prv.serdes_blwc));
417 	if (error > 0) {
418 		return (error);
419 	} else if (error < 0) {
420 		sc->prv.serdes_blwc[0] = XGBE_SPEED_1000_BLWC;
421 		sc->prv.serdes_blwc[1] = XGBE_SPEED_2500_BLWC;
422 		sc->prv.serdes_blwc[2] = XGBE_SPEED_10000_BLWC;
423 	}
424 
425 	error = axgbe_get_optional_prop(dev, phy_node, XGBE_CDR_RATE_PROPERTY,
426 	    sc->prv.serdes_cdr_rate, sizeof(sc->prv.serdes_cdr_rate));
427 	if (error > 0) {
428 		return (error);
429 	} else if (error < 0) {
430 		sc->prv.serdes_cdr_rate[0] = XGBE_SPEED_1000_CDR;
431 		sc->prv.serdes_cdr_rate[1] = XGBE_SPEED_2500_CDR;
432 		sc->prv.serdes_cdr_rate[2] = XGBE_SPEED_10000_CDR;
433 	}
434 
435 	error = axgbe_get_optional_prop(dev, phy_node, XGBE_PQ_SKEW_PROPERTY,
436 	    sc->prv.serdes_pq_skew, sizeof(sc->prv.serdes_pq_skew));
437 	if (error > 0) {
438 		return (error);
439 	} else if (error < 0) {
440 		sc->prv.serdes_pq_skew[0] = XGBE_SPEED_1000_PQ;
441 		sc->prv.serdes_pq_skew[1] = XGBE_SPEED_2500_PQ;
442 		sc->prv.serdes_pq_skew[2] = XGBE_SPEED_10000_PQ;
443 	}
444 
445 	error = axgbe_get_optional_prop(dev, phy_node, XGBE_TX_AMP_PROPERTY,
446 	    sc->prv.serdes_tx_amp, sizeof(sc->prv.serdes_tx_amp));
447 	if (error > 0) {
448 		return (error);
449 	} else if (error < 0) {
450 		sc->prv.serdes_tx_amp[0] = XGBE_SPEED_1000_TXAMP;
451 		sc->prv.serdes_tx_amp[1] = XGBE_SPEED_2500_TXAMP;
452 		sc->prv.serdes_tx_amp[2] = XGBE_SPEED_10000_TXAMP;
453 	}
454 
455 	error = axgbe_get_optional_prop(dev, phy_node, XGBE_DFE_CFG_PROPERTY,
456 	    sc->prv.serdes_dfe_tap_cfg, sizeof(sc->prv.serdes_dfe_tap_cfg));
457 	if (error > 0) {
458 		return (error);
459 	} else if (error < 0) {
460 		sc->prv.serdes_dfe_tap_cfg[0] = XGBE_SPEED_1000_DFE_TAP_CONFIG;
461 		sc->prv.serdes_dfe_tap_cfg[1] = XGBE_SPEED_2500_DFE_TAP_CONFIG;
462 		sc->prv.serdes_dfe_tap_cfg[2] = XGBE_SPEED_10000_DFE_TAP_CONFIG;
463 	}
464 
465 	error = axgbe_get_optional_prop(dev, phy_node, XGBE_DFE_ENA_PROPERTY,
466 	    sc->prv.serdes_dfe_tap_ena, sizeof(sc->prv.serdes_dfe_tap_ena));
467 	if (error > 0) {
468 		return (error);
469 	} else if (error < 0) {
470 		sc->prv.serdes_dfe_tap_ena[0] = XGBE_SPEED_1000_DFE_TAP_ENABLE;
471 		sc->prv.serdes_dfe_tap_ena[1] = XGBE_SPEED_2500_DFE_TAP_ENABLE;
472 		sc->prv.serdes_dfe_tap_ena[2] = XGBE_SPEED_10000_DFE_TAP_ENABLE;
473 	}
474 
475 	/* Check if the NIC is DMA coherent */
476 	sc->prv.coherent = OF_hasprop(node, "dma-coherent");
477 	if (sc->prv.coherent) {
478 		sc->prv.arcr = XGBE_DMA_OS_ARCR;
479 		sc->prv.awcr = XGBE_DMA_OS_AWCR;
480 	} else {
481 		sc->prv.arcr = XGBE_DMA_SYS_ARCR;
482 		sc->prv.awcr = XGBE_DMA_SYS_AWCR;
483 	}
484 
485 	/* Create the lock & workqueues */
486 	spin_lock_init(&sc->prv.xpcs_lock);
487 	sc->prv.dev_workqueue = taskqueue_create("axgbe", M_WAITOK,
488 	    taskqueue_thread_enqueue, &sc->prv.dev_workqueue);
489 	taskqueue_start_threads(&sc->prv.dev_workqueue, 1, PI_NET,
490 	    "axgbe taskq");
491 
492 	/* Set the needed pointers */
493 	xgbe_init_function_ptrs_phy(&sc->prv.phy_if);
494 	xgbe_init_function_ptrs_dev(&sc->prv.hw_if);
495 	xgbe_init_function_ptrs_desc(&sc->prv.desc_if);
496 	sc->prv.vdata->init_function_ptrs_phy_impl(&sc->prv.phy_if);
497 
498 	/* Reset the hardware */
499 	sc->prv.hw_if.exit(&sc->prv);
500 
501 	/* Read the hardware features */
502 	xgbe_get_all_hw_features(&sc->prv);
503 
504 	/* Set default values */
505 	sc->prv.tx_desc_count = XGBE_TX_DESC_CNT;
506 	sc->prv.tx_sf_mode = MTL_TSF_ENABLE;
507 	sc->prv.tx_threshold = MTL_TX_THRESHOLD_64;
508 	sc->prv.tx_osp_mode = DMA_OSP_ENABLE;
509 	sc->prv.rx_desc_count = XGBE_RX_DESC_CNT;
510 	sc->prv.rx_sf_mode = MTL_RSF_DISABLE;
511 	sc->prv.rx_threshold = MTL_RX_THRESHOLD_64;
512 	sc->prv.pbl = DMA_PBL_128;
513 	sc->prv.pause_autoneg = 1;
514 	sc->prv.tx_pause = 1;
515 	sc->prv.rx_pause = 1;
516 	sc->prv.phy_speed = SPEED_UNKNOWN;
517 	sc->prv.power_down = 0;
518 
519 	/* TODO: Limit to min(ncpus, hw rings) */
520 	sc->prv.tx_ring_count = 1;
521 	sc->prv.tx_q_count = 1;
522 	sc->prv.rx_ring_count = 1;
523 	sc->prv.rx_q_count = sc->prv.hw_feat.rx_q_cnt;
524 
525 	/* Init the PHY */
526 	sc->prv.phy_if.phy_init(&sc->prv);
527 
528 	/* Set the coalescing */
529 	xgbe_init_rx_coalesce(&sc->prv);
530 	xgbe_init_tx_coalesce(&sc->prv);
531 
532 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
533 	if_setinitfn(ifp, axgbe_init);
534         if_setsoftc(ifp, sc);
535 	if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
536 	if_setioctlfn(ifp, axgbe_ioctl);
537 	/* TODO - change it to iflib way */
538 	if_setqflushfn(ifp, axgbe_qflush);
539 	if_setgetcounterfn(ifp, axgbe_get_counter);
540 
541 	/* TODO: Support HW offload */
542 	if_setcapabilities(ifp, 0);
543 	if_setcapenable(ifp, 0);
544 	if_sethwassist(ifp, 0);
545 
546 	ether_ifattach(ifp, sc->mac_addr);
547 
548 	ifmedia_init(&sc->media, IFM_IMASK, axgbe_media_change,
549 	    axgbe_media_status);
550 #ifdef notyet
551 	ifmedia_add(&sc->media, IFM_ETHER | IFM_10G_KR, 0, NULL);
552 #endif
553 	ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_KX, 0, NULL);
554 	ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
555 	ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO);
556 
557 	set_bit(XGBE_DOWN, &sc->prv.dev_state);
558 
559 	/* TODO - change it to iflib way */
560 	return (0);
561 }
562 
563 static device_method_t axgbe_methods[] = {
564 	/* Device interface */
565 	DEVMETHOD(device_probe,		axgbe_probe),
566 	DEVMETHOD(device_attach,	axgbe_attach),
567 
568 	{ 0, 0 }
569 };
570 
571 DEFINE_CLASS_0(axgbe, axgbe_driver, axgbe_methods,
572     sizeof(struct axgbe_softc));
573 DRIVER_MODULE(axa, simplebus, axgbe_driver, 0, 0);
574 
575 
576 static struct ofw_compat_data phy_compat_data[] = {
577 	{ "amd,xgbe-phy-seattle-v1a",	true },
578 	{ NULL,				false }
579 };
580 
581 static int
582 axgbephy_probe(device_t dev)
583 {
584 
585 	if (!ofw_bus_status_okay(dev))
586 		return (ENXIO);
587 
588 	if (!ofw_bus_search_compatible(dev, phy_compat_data)->ocd_data)
589 		return (ENXIO);
590 
591 	device_set_desc(dev, "AMD 10 Gigabit Ethernet");
592 	return (BUS_PROBE_DEFAULT);
593 }
594 
595 static int
596 axgbephy_attach(device_t dev)
597 {
598 	phandle_t node;
599 
600 	node = ofw_bus_get_node(dev);
601 	OF_device_register_xref(OF_xref_from_node(node), dev);
602 
603 	return (0);
604 }
605 
606 static device_method_t axgbephy_methods[] = {
607 	/* Device interface */
608 	DEVMETHOD(device_probe,		axgbephy_probe),
609 	DEVMETHOD(device_attach,	axgbephy_attach),
610 
611 	{ 0, 0 }
612 };
613 
614 DEFINE_CLASS_0(axgbephy, axgbephy_driver, axgbephy_methods, 0);
615 EARLY_DRIVER_MODULE(axgbephy, simplebus, axgbephy_driver,
616     0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
617