xref: /freebsd/sys/dev/dwc/if_dwc.c (revision 5d88a52be44a98e2b49db7ead317b2d0b2ef9eaa)
1 /*-
2  * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
3  *
4  * This software was developed by SRI International and the University of
5  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
6  * ("CTSRD"), as part of the DARPA CRASH research programme.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /*
31  * Ethernet media access controller (EMAC)
32  * Chapter 17, Altera Cyclone V Device Handbook (CV-5V2 2014.07.22)
33  *
34  * EMAC is an instance of the Synopsys DesignWare 3504-0
35  * Universal 10/100/1000 Ethernet MAC (DWC_gmac).
36  */
37 
38 #include <sys/cdefs.h>
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/bus.h>
42 #include <sys/gpio.h>
43 #include <sys/kernel.h>
44 #include <sys/lock.h>
45 #include <sys/malloc.h>
46 #include <sys/mbuf.h>
47 #include <sys/module.h>
48 #include <sys/mutex.h>
49 #include <sys/rman.h>
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
52 
53 #include <net/bpf.h>
54 #include <net/if.h>
55 #include <net/ethernet.h>
56 #include <net/if_dl.h>
57 #include <net/if_media.h>
58 #include <net/if_types.h>
59 #include <net/if_var.h>
60 
61 #include <machine/bus.h>
62 
63 #include <dev/extres/clk/clk.h>
64 #include <dev/extres/hwreset/hwreset.h>
65 
66 #include <dev/mii/mii.h>
67 #include <dev/mii/miivar.h>
68 #include <dev/ofw/ofw_bus.h>
69 #include <dev/ofw/ofw_bus_subr.h>
70 #include <dev/mii/mii_fdt.h>
71 
72 #include <dev/dwc/if_dwcvar.h>
73 #include <dev/dwc/dwc1000_reg.h>
74 #include <dev/dwc/dwc1000_core.h>
75 #include <dev/dwc/dwc1000_dma.h>
76 
77 #include "if_dwc_if.h"
78 #include "gpio_if.h"
79 #include "miibus_if.h"
80 
81 static struct resource_spec dwc_spec[] = {
82 	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
83 	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
84 	{ -1, 0 }
85 };
86 
87 static void dwc_stop_locked(struct dwc_softc *sc);
88 
89 static void dwc_tick(void *arg);
90 
91 /*
92  * Media functions
93  */
94 
95 static void
96 dwc_media_status(if_t ifp, struct ifmediareq *ifmr)
97 {
98 	struct dwc_softc *sc;
99 	struct mii_data *mii;
100 
101 	sc = if_getsoftc(ifp);
102 	mii = sc->mii_softc;
103 	DWC_LOCK(sc);
104 	mii_pollstat(mii);
105 	ifmr->ifm_active = mii->mii_media_active;
106 	ifmr->ifm_status = mii->mii_media_status;
107 	DWC_UNLOCK(sc);
108 }
109 
110 static int
111 dwc_media_change_locked(struct dwc_softc *sc)
112 {
113 
114 	return (mii_mediachg(sc->mii_softc));
115 }
116 
117 static int
118 dwc_media_change(if_t ifp)
119 {
120 	struct dwc_softc *sc;
121 	int error;
122 
123 	sc = if_getsoftc(ifp);
124 
125 	DWC_LOCK(sc);
126 	error = dwc_media_change_locked(sc);
127 	DWC_UNLOCK(sc);
128 	return (error);
129 }
130 
131 /*
132  * if_ functions
133  */
134 
135 static void
136 dwc_txstart_locked(struct dwc_softc *sc)
137 {
138 	if_t ifp;
139 
140 	DWC_ASSERT_LOCKED(sc);
141 
142 	if (!sc->link_is_up)
143 		return;
144 
145 	ifp = sc->ifp;
146 
147 	if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
148 	    IFF_DRV_RUNNING)
149 		return;
150 	dma1000_txstart(sc);
151 }
152 
153 static void
154 dwc_txstart(if_t ifp)
155 {
156 	struct dwc_softc *sc = if_getsoftc(ifp);
157 
158 	DWC_LOCK(sc);
159 	dwc_txstart_locked(sc);
160 	DWC_UNLOCK(sc);
161 }
162 
163 static void
164 dwc_init_locked(struct dwc_softc *sc)
165 {
166 	if_t ifp = sc->ifp;
167 
168 	DWC_ASSERT_LOCKED(sc);
169 
170 	if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
171 		return;
172 
173 	/*
174 	 * Call mii_mediachg() which will call back into dwc1000_miibus_statchg()
175 	 * to set up the remaining config registers based on current media.
176 	 */
177 	mii_mediachg(sc->mii_softc);
178 
179 	dwc1000_setup_rxfilter(sc);
180 	dwc1000_core_setup(sc);
181 	dwc1000_enable_mac(sc, true);
182 	dwc1000_enable_csum_offload(sc);
183 	dma1000_start(sc);
184 
185 	if_setdrvflagbits(ifp, IFF_DRV_RUNNING, IFF_DRV_OACTIVE);
186 
187 	callout_reset(&sc->dwc_callout, hz, dwc_tick, sc);
188 }
189 
190 static void
191 dwc_init(void *if_softc)
192 {
193 	struct dwc_softc *sc = if_softc;
194 
195 	DWC_LOCK(sc);
196 	dwc_init_locked(sc);
197 	DWC_UNLOCK(sc);
198 }
199 
200 static void
201 dwc_stop_locked(struct dwc_softc *sc)
202 {
203 	if_t ifp;
204 
205 	DWC_ASSERT_LOCKED(sc);
206 
207 	ifp = sc->ifp;
208 	if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
209 	sc->tx_watchdog_count = 0;
210 	sc->stats_harvest_count = 0;
211 
212 	callout_stop(&sc->dwc_callout);
213 
214 	dma1000_stop(sc);
215 	dwc1000_enable_mac(sc, false);
216 }
217 
218 static int
219 dwc_ioctl(if_t ifp, u_long cmd, caddr_t data)
220 {
221 	struct dwc_softc *sc;
222 	struct mii_data *mii;
223 	struct ifreq *ifr;
224 	int flags, mask, error;
225 
226 	sc = if_getsoftc(ifp);
227 	ifr = (struct ifreq *)data;
228 
229 	error = 0;
230 	switch (cmd) {
231 	case SIOCSIFFLAGS:
232 		DWC_LOCK(sc);
233 		if (if_getflags(ifp) & IFF_UP) {
234 			if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
235 				flags = if_getflags(ifp) ^ sc->if_flags;
236 				if ((flags & (IFF_PROMISC|IFF_ALLMULTI)) != 0)
237 					dwc1000_setup_rxfilter(sc);
238 			} else {
239 				if (!sc->is_detaching)
240 					dwc_init_locked(sc);
241 			}
242 		} else {
243 			if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
244 				dwc_stop_locked(sc);
245 		}
246 		sc->if_flags = if_getflags(ifp);
247 		DWC_UNLOCK(sc);
248 		break;
249 	case SIOCADDMULTI:
250 	case SIOCDELMULTI:
251 		if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
252 			DWC_LOCK(sc);
253 			dwc1000_setup_rxfilter(sc);
254 			DWC_UNLOCK(sc);
255 		}
256 		break;
257 	case SIOCSIFMEDIA:
258 	case SIOCGIFMEDIA:
259 		mii = sc->mii_softc;
260 		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
261 		break;
262 	case SIOCSIFCAP:
263 		mask = ifr->ifr_reqcap ^ if_getcapenable(ifp);
264 		if (mask & IFCAP_VLAN_MTU) {
265 			/* No work to do except acknowledge the change took */
266 			if_togglecapenable(ifp, IFCAP_VLAN_MTU);
267 		}
268 		if (mask & IFCAP_RXCSUM)
269 			if_togglecapenable(ifp, IFCAP_RXCSUM);
270 		if (mask & IFCAP_TXCSUM)
271 			if_togglecapenable(ifp, IFCAP_TXCSUM);
272 		if ((if_getcapenable(ifp) & IFCAP_TXCSUM) != 0)
273 			if_sethwassistbits(ifp, CSUM_IP | CSUM_UDP | CSUM_TCP, 0);
274 		else
275 			if_sethwassistbits(ifp, 0, CSUM_IP | CSUM_UDP | CSUM_TCP);
276 
277 		if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
278 			DWC_LOCK(sc);
279 			dwc1000_enable_csum_offload(sc);
280 			DWC_UNLOCK(sc);
281 		}
282 		break;
283 
284 	default:
285 		error = ether_ioctl(ifp, cmd, data);
286 		break;
287 	}
288 
289 	return (error);
290 }
291 
292 /*
293  * Interrupts functions
294  */
295 
296 
297 static void
298 dwc_intr(void *arg)
299 {
300 	struct dwc_softc *sc;
301 	int rv;
302 
303 	sc = arg;
304 	DWC_LOCK(sc);
305 	dwc1000_intr(sc);
306 	rv = dma1000_intr(sc);
307 	if (rv == EIO) {
308 		device_printf(sc->dev,
309 		  "Ethernet DMA error, restarting controller.\n");
310 		dwc_stop_locked(sc);
311 		dwc_init_locked(sc);
312 	}
313 	DWC_UNLOCK(sc);
314 }
315 
316 static void
317 dwc_tick(void *arg)
318 {
319 	struct dwc_softc *sc;
320 	if_t ifp;
321 	int link_was_up;
322 
323 	sc = arg;
324 
325 	DWC_ASSERT_LOCKED(sc);
326 
327 	ifp = sc->ifp;
328 
329 	if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0)
330 	    return;
331 
332 	/*
333 	 * Typical tx watchdog.  If this fires it indicates that we enqueued
334 	 * packets for output and never got a txdone interrupt for them.  Maybe
335 	 * it's a missed interrupt somehow, just pretend we got one.
336 	 */
337 	if (sc->tx_watchdog_count > 0) {
338 		if (--sc->tx_watchdog_count == 0) {
339 			dma1000_txfinish_locked(sc);
340 		}
341 	}
342 
343 	/* Gather stats from hardware counters. */
344 	dwc1000_harvest_stats(sc);
345 
346 	/* Check the media status. */
347 	link_was_up = sc->link_is_up;
348 	mii_tick(sc->mii_softc);
349 	if (sc->link_is_up && !link_was_up)
350 		dwc_txstart_locked(sc);
351 
352 	/* Schedule another check one second from now. */
353 	callout_reset(&sc->dwc_callout, hz, dwc_tick, sc);
354 }
355 
356 static int
357 dwc_reset_phy(struct dwc_softc *sc)
358 {
359 	pcell_t gpio_prop[4];
360 	pcell_t delay_prop[3];
361 	phandle_t gpio_node;
362 	device_t gpio;
363 	uint32_t pin, flags;
364 	uint32_t pin_value;
365 
366 	/*
367 	 * All those properties are deprecated but still used in some DTS.
368 	 * The new way to deal with this is to use the generic bindings
369 	 * present in the ethernet-phy node.
370 	 */
371 	if (OF_getencprop(sc->node, "snps,reset-gpio",
372 	    gpio_prop, sizeof(gpio_prop)) <= 0)
373 		return (0);
374 
375 	if (OF_getencprop(sc->node, "snps,reset-delays-us",
376 	    delay_prop, sizeof(delay_prop)) <= 0) {
377 		device_printf(sc->dev,
378 		    "Wrong property for snps,reset-delays-us");
379 		return (ENXIO);
380 	}
381 
382 	gpio_node = OF_node_from_xref(gpio_prop[0]);
383 	if ((gpio = OF_device_from_xref(gpio_prop[0])) == NULL) {
384 		device_printf(sc->dev,
385 		    "Can't find gpio controller for phy reset\n");
386 		return (ENXIO);
387 	}
388 
389 	if (GPIO_MAP_GPIOS(gpio, sc->node, gpio_node,
390 	    nitems(gpio_prop) - 1,
391 	    gpio_prop + 1, &pin, &flags) != 0) {
392 		device_printf(sc->dev, "Can't map gpio for phy reset\n");
393 		return (ENXIO);
394 	}
395 
396 	pin_value = GPIO_PIN_LOW;
397 	if (OF_hasprop(sc->node, "snps,reset-active-low"))
398 		pin_value = GPIO_PIN_HIGH;
399 
400 	GPIO_PIN_SETFLAGS(gpio, pin, GPIO_PIN_OUTPUT);
401 	GPIO_PIN_SET(gpio, pin, pin_value);
402 	DELAY(delay_prop[0] * 5);
403 	GPIO_PIN_SET(gpio, pin, !pin_value);
404 	DELAY(delay_prop[1] * 5);
405 	GPIO_PIN_SET(gpio, pin, pin_value);
406 	DELAY(delay_prop[2] * 5);
407 
408 	return (0);
409 }
410 
411 static int
412 dwc_clock_init(struct dwc_softc *sc)
413 {
414 	int rv;
415 	int64_t freq;
416 
417 	/* Required clock */
418 	rv = clk_get_by_ofw_name(sc->dev, 0, "stmmaceth", &sc->clk_stmmaceth);
419 	if (rv != 0) {
420 		device_printf(sc->dev, "Cannot get GMAC main clock\n");
421 		return (ENXIO);
422 	}
423 	if ((rv = clk_enable(sc->clk_stmmaceth)) != 0) {
424 		device_printf(sc->dev, "could not enable main clock\n");
425 		return (rv);
426 	}
427 
428 	/* Optional clock */
429 	rv = clk_get_by_ofw_name(sc->dev, 0, "pclk", &sc->clk_pclk);
430 	if (rv != 0)
431 		return (0);
432 	if ((rv = clk_enable(sc->clk_pclk)) != 0) {
433 		device_printf(sc->dev, "could not enable peripheral clock\n");
434 		return (rv);
435 	}
436 
437 	if (bootverbose) {
438 		clk_get_freq(sc->clk_stmmaceth, &freq);
439 		device_printf(sc->dev, "MAC clock(%s) freq: %jd\n",
440 		    clk_get_name(sc->clk_stmmaceth), (intmax_t)freq);
441 	}
442 
443 	return (0);
444 }
445 
446 static int
447 dwc_reset_deassert(struct dwc_softc *sc)
448 {
449 	int rv;
450 
451 	/* Required reset */
452 	rv = hwreset_get_by_ofw_name(sc->dev, 0, "stmmaceth", &sc->rst_stmmaceth);
453 	if (rv != 0) {
454 		device_printf(sc->dev, "Cannot get GMAC reset\n");
455 		return (ENXIO);
456 	}
457 	rv = hwreset_deassert(sc->rst_stmmaceth);
458 	if (rv != 0) {
459 		device_printf(sc->dev, "could not de-assert GMAC reset\n");
460 		return (rv);
461 	}
462 
463 	/* Optional reset */
464 	rv = hwreset_get_by_ofw_name(sc->dev, 0, "ahb", &sc->rst_ahb);
465 	if (rv != 0)
466 		return (0);
467 	rv = hwreset_deassert(sc->rst_ahb);
468 	if (rv != 0) {
469 		device_printf(sc->dev, "could not de-assert AHB reset\n");
470 		return (rv);
471 	}
472 
473 	return (0);
474 }
475 
476 /*
477  * Probe/Attach functions
478  */
479 
480 static int
481 dwc_probe(device_t dev)
482 {
483 
484 	if (!ofw_bus_status_okay(dev))
485 		return (ENXIO);
486 
487 	if (!ofw_bus_is_compatible(dev, "snps,dwmac"))
488 		return (ENXIO);
489 
490 	device_set_desc(dev, "Gigabit Ethernet Controller");
491 	return (BUS_PROBE_DEFAULT);
492 }
493 
494 static int
495 dwc_attach(device_t dev)
496 {
497 	uint8_t macaddr[ETHER_ADDR_LEN];
498 	struct dwc_softc *sc;
499 	if_t ifp;
500 	int error;
501 	uint32_t pbl;
502 
503 	sc = device_get_softc(dev);
504 	sc->dev = dev;
505 	sc->rx_idx = 0;
506 	sc->tx_desccount = TX_DESC_COUNT;
507 	sc->tx_mapcount = 0;
508 	sc->mii_clk = IF_DWC_MII_CLK(dev);
509 	sc->mactype = IF_DWC_MAC_TYPE(dev);
510 
511 	sc->node = ofw_bus_get_node(dev);
512 	switch (mii_fdt_get_contype(sc->node)) {
513 	case MII_CONTYPE_RGMII:
514 	case MII_CONTYPE_RGMII_ID:
515 	case MII_CONTYPE_RGMII_RXID:
516 	case MII_CONTYPE_RGMII_TXID:
517 		sc->phy_mode = PHY_MODE_RGMII;
518 		break;
519 	case MII_CONTYPE_RMII:
520 		sc->phy_mode = PHY_MODE_RMII;
521 		break;
522 	case MII_CONTYPE_MII:
523 		sc->phy_mode = PHY_MODE_MII;
524 		break;
525 	default:
526 		device_printf(dev, "Unsupported MII type\n");
527 		return (ENXIO);
528 	}
529 
530 	if (OF_getencprop(sc->node, "snps,pbl", &pbl, sizeof(uint32_t)) <= 0)
531 		pbl = BUS_MODE_DEFAULT_PBL;
532 	if (OF_getencprop(sc->node, "snps,txpbl", &sc->txpbl, sizeof(uint32_t)) <= 0)
533 		sc->txpbl = pbl;
534 	if (OF_getencprop(sc->node, "snps,rxpbl", &sc->rxpbl, sizeof(uint32_t)) <= 0)
535 		sc->rxpbl = pbl;
536 	if (OF_hasprop(sc->node, "snps,no-pbl-x8") == 1)
537 		sc->nopblx8 = true;
538 	if (OF_hasprop(sc->node, "snps,fixed-burst") == 1)
539 		sc->fixed_burst = true;
540 	if (OF_hasprop(sc->node, "snps,mixed-burst") == 1)
541 		sc->mixed_burst = true;
542 	if (OF_hasprop(sc->node, "snps,aal") == 1)
543 		sc->aal = true;
544 
545 	error = clk_set_assigned(dev, ofw_bus_get_node(dev));
546 	if (error != 0) {
547 		device_printf(dev, "clk_set_assigned failed\n");
548 		return (error);
549 	}
550 
551 	/* Enable main clock */
552 	if ((error = dwc_clock_init(sc)) != 0)
553 		return (error);
554 	/* De-assert main reset */
555 	if ((error = dwc_reset_deassert(sc)) != 0)
556 		return (error);
557 
558 	if (IF_DWC_INIT(dev) != 0)
559 		return (ENXIO);
560 
561 	if (bus_alloc_resources(dev, dwc_spec, sc->res)) {
562 		device_printf(dev, "could not allocate resources\n");
563 		return (ENXIO);
564 	}
565 
566 	/* Read MAC before reset */
567 	dwc1000_get_hwaddr(sc, macaddr);
568 
569 	/* Reset the PHY if needed */
570 	if (dwc_reset_phy(sc) != 0) {
571 		device_printf(dev, "Can't reset the PHY\n");
572 		bus_release_resources(dev, dwc_spec, sc->res);
573 		return (ENXIO);
574 	}
575 
576 	/* Reset */
577 	if ((error = dma1000_reset(sc)) != 0) {
578 		device_printf(sc->dev, "Can't reset DMA controller.\n");
579 		bus_release_resources(sc->dev, dwc_spec, sc->res);
580 		return (error);
581 	}
582 
583 	if (dma1000_init(sc)) {
584 		bus_release_resources(dev, dwc_spec, sc->res);
585 		return (ENXIO);
586 	}
587 
588 	mtx_init(&sc->mtx, device_get_nameunit(sc->dev),
589 	    MTX_NETWORK_LOCK, MTX_DEF);
590 
591 	callout_init_mtx(&sc->dwc_callout, &sc->mtx, 0);
592 
593 	/* Setup interrupt handler. */
594 	error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_NET | INTR_MPSAFE,
595 	    NULL, dwc_intr, sc, &sc->intr_cookie);
596 	if (error != 0) {
597 		device_printf(dev, "could not setup interrupt handler.\n");
598 		bus_release_resources(dev, dwc_spec, sc->res);
599 		return (ENXIO);
600 	}
601 
602 	/* Set up the ethernet interface. */
603 	sc->ifp = ifp = if_alloc(IFT_ETHER);
604 
605 	if_setsoftc(ifp, sc);
606 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
607 	if_setflags(sc->ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
608 	if_setstartfn(ifp, dwc_txstart);
609 	if_setioctlfn(ifp, dwc_ioctl);
610 	if_setinitfn(ifp, dwc_init);
611 	if_setsendqlen(ifp, TX_MAP_COUNT - 1);
612 	if_setsendqready(sc->ifp);
613 	if_sethwassist(sc->ifp, CSUM_IP | CSUM_UDP | CSUM_TCP);
614 	if_setcapabilities(sc->ifp, IFCAP_VLAN_MTU | IFCAP_HWCSUM);
615 	if_setcapenable(sc->ifp, if_getcapabilities(sc->ifp));
616 
617 	/* Attach the mii driver. */
618 	error = mii_attach(dev, &sc->miibus, ifp, dwc_media_change,
619 	    dwc_media_status, BMSR_DEFCAPMASK, MII_PHY_ANY,
620 	    MII_OFFSET_ANY, 0);
621 
622 	if (error != 0) {
623 		device_printf(dev, "PHY attach failed\n");
624 		bus_teardown_intr(dev, sc->res[1], sc->intr_cookie);
625 		bus_release_resources(dev, dwc_spec, sc->res);
626 		return (ENXIO);
627 	}
628 	sc->mii_softc = device_get_softc(sc->miibus);
629 
630 	/* All ready to run, attach the ethernet interface. */
631 	ether_ifattach(ifp, macaddr);
632 	sc->is_attached = true;
633 
634 	return (0);
635 }
636 
637 static int
638 dwc_detach(device_t dev)
639 {
640 	struct dwc_softc *sc;
641 
642 	sc = device_get_softc(dev);
643 
644 	/*
645 	 * Disable and tear down interrupts before anything else, so we don't
646 	 * race with the handler.
647 	 */
648 	dwc1000_intr_disable(sc);
649 	if (sc->intr_cookie != NULL) {
650 		bus_teardown_intr(dev, sc->res[1], sc->intr_cookie);
651 	}
652 
653 	if (sc->is_attached) {
654 		DWC_LOCK(sc);
655 		sc->is_detaching = true;
656 		dwc_stop_locked(sc);
657 		DWC_UNLOCK(sc);
658 		callout_drain(&sc->dwc_callout);
659 		ether_ifdetach(sc->ifp);
660 	}
661 
662 	if (sc->miibus != NULL) {
663 		device_delete_child(dev, sc->miibus);
664 		sc->miibus = NULL;
665 	}
666 	bus_generic_detach(dev);
667 
668 	/* Free DMA descriptors */
669 	dma1000_free(sc);
670 
671 	if (sc->ifp != NULL) {
672 		if_free(sc->ifp);
673 		sc->ifp = NULL;
674 	}
675 
676 	bus_release_resources(dev, dwc_spec, sc->res);
677 
678 	mtx_destroy(&sc->mtx);
679 	return (0);
680 }
681 
682 static device_method_t dwc_methods[] = {
683 	DEVMETHOD(device_probe,		dwc_probe),
684 	DEVMETHOD(device_attach,	dwc_attach),
685 	DEVMETHOD(device_detach,	dwc_detach),
686 
687 	/* MII Interface */
688 	DEVMETHOD(miibus_readreg,	dwc1000_miibus_read_reg),
689 	DEVMETHOD(miibus_writereg,	dwc1000_miibus_write_reg),
690 	DEVMETHOD(miibus_statchg,	dwc1000_miibus_statchg),
691 
692 	{ 0, 0 }
693 };
694 
695 driver_t dwc_driver = {
696 	"dwc",
697 	dwc_methods,
698 	sizeof(struct dwc_softc),
699 };
700 
701 DRIVER_MODULE(dwc, simplebus, dwc_driver, 0, 0);
702 DRIVER_MODULE(miibus, dwc, miibus_driver, 0, 0);
703 
704 MODULE_DEPEND(dwc, ether, 1, 1, 1);
705 MODULE_DEPEND(dwc, miibus, 1, 1, 1);
706