1/*-
2 * Copyright (c) 2016 Stanislav Galabov.
3 * Copyright (c) 2011-2012 Stefan Bethke.
4 * Copyright (c) 2012 Adrian Chadd.
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 AUTHOR 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 AUTHOR 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 * $FreeBSD$
29 */
30
31#include <sys/param.h>
32#include <sys/bus.h>
33#include <sys/errno.h>
34#include <sys/kernel.h>
35#include <sys/lock.h>
36#include <sys/malloc.h>
37#include <sys/module.h>
38#include <sys/mutex.h>
39#include <sys/socket.h>
40#include <sys/sockio.h>
41#include <sys/sysctl.h>
42#include <sys/systm.h>
43
44#include <net/if.h>
45#include <net/if_var.h>
46#include <net/ethernet.h>
47#include <net/if_media.h>
48#include <net/if_types.h>
49
50#include <machine/bus.h>
51#include <dev/mii/mii.h>
52#include <dev/mii/miivar.h>
53#include <dev/mdio/mdio.h>
54
55#include <dev/etherswitch/etherswitch.h>
56#include <dev/etherswitch/mtkswitch/mtkswitchvar.h>
57
58#include <dev/ofw/ofw_bus_subr.h>
59
60#include "mdio_if.h"
61#include "miibus_if.h"
62#include "etherswitch_if.h"
63
64#define DEBUG
65
66#if defined(DEBUG)
67static SYSCTL_NODE(_debug, OID_AUTO, mtkswitch, CTLFLAG_RD, 0, "mtkswitch");
68#endif
69
70static inline int mtkswitch_portforphy(int phy);
71static int mtkswitch_ifmedia_upd(struct ifnet *ifp);
72static void mtkswitch_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr);
73static void mtkswitch_tick(void *arg);
74
75static const struct ofw_compat_data compat_data[] = {
76	{ "ralink,rt3050-esw",		MTK_SWITCH_RT3050 },
77	{ "ralink,rt3352-esw",		MTK_SWITCH_RT3352 },
78	{ "ralink,rt5350-esw",		MTK_SWITCH_RT5350 },
79	{ "mediatek,mt7620-gsw",	MTK_SWITCH_MT7620 },
80	{ "mediatek,mt7621-gsw",	MTK_SWITCH_MT7621 },
81	{ "mediatek,mt7628-esw",	MTK_SWITCH_MT7628 },
82
83	/* Sentinel */
84	{ NULL,				MTK_SWITCH_NONE }
85};
86
87static int
88mtkswitch_probe(device_t dev)
89{
90	struct mtkswitch_softc *sc;
91	mtk_switch_type switch_type;
92
93	if (!ofw_bus_status_okay(dev))
94		return (ENXIO);
95
96	switch_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
97	if (switch_type == MTK_SWITCH_NONE)
98		return (ENXIO);
99
100	sc = device_get_softc(dev);
101	bzero(sc, sizeof(*sc));
102	sc->sc_switchtype = switch_type;
103
104	device_set_desc_copy(dev, "MTK Switch Driver");
105
106	return (0);
107}
108
109static int
110mtkswitch_attach_phys(struct mtkswitch_softc *sc)
111{
112	int phy, err = 0;
113	char name[IFNAMSIZ];
114
115	/* PHYs need an interface, so we generate a dummy one */
116	snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev));
117	for (phy = 0; phy < sc->numphys; phy++) {
118		if ((sc->phymap & (1u << phy)) == 0) {
119			sc->ifp[phy] = NULL;
120			sc->ifname[phy] = NULL;
121			sc->miibus[phy] = NULL;
122			continue;
123		}
124		sc->ifp[phy] = if_alloc(IFT_ETHER);
125		if (sc->ifp[phy] == NULL) {
126			device_printf(sc->sc_dev, "couldn't allocate ifnet structure\n");
127			err = ENOMEM;
128			break;
129		}
130
131		sc->ifp[phy]->if_softc = sc;
132		sc->ifp[phy]->if_flags |= IFF_UP | IFF_BROADCAST |
133		    IFF_DRV_RUNNING | IFF_SIMPLEX;
134		sc->ifname[phy] = malloc(strlen(name) + 1, M_DEVBUF, M_WAITOK);
135		bcopy(name, sc->ifname[phy], strlen(name) + 1);
136		if_initname(sc->ifp[phy], sc->ifname[phy],
137		    mtkswitch_portforphy(phy));
138		err = mii_attach(sc->sc_dev, &sc->miibus[phy], sc->ifp[phy],
139		    mtkswitch_ifmedia_upd, mtkswitch_ifmedia_sts,
140		    BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
141		if (err != 0) {
142			device_printf(sc->sc_dev,
143			    "attaching PHY %d failed\n",
144			    phy);
145		} else {
146			DPRINTF(sc->sc_dev, "%s attached to pseudo interface "
147			    "%s\n", device_get_nameunit(sc->miibus[phy]),
148			    sc->ifp[phy]->if_xname);
149		}
150	}
151	return (err);
152}
153
154static int
155mtkswitch_set_vlan_mode(struct mtkswitch_softc *sc, uint32_t mode)
156{
157
158	/* Check for invalid modes. */
159	if ((mode & sc->info.es_vlan_caps) != mode)
160		return (EINVAL);
161
162	sc->vlan_mode = mode;
163
164	/* Reset VLANs. */
165	sc->hal.mtkswitch_vlan_init_hw(sc);
166
167	return (0);
168}
169
170static int
171mtkswitch_attach(device_t dev)
172{
173	struct mtkswitch_softc *sc;
174	int err = 0;
175	int port, rid;
176
177	sc = device_get_softc(dev);
178
179	/* sc->sc_switchtype is already decided in mtkswitch_probe() */
180	sc->numports = MTKSWITCH_MAX_PORTS;
181	sc->numphys = MTKSWITCH_MAX_PHYS;
182	sc->cpuport = MTKSWITCH_CPU_PORT;
183	sc->sc_dev = dev;
184
185	/* Attach switch related functions */
186	if (sc->sc_switchtype == MTK_SWITCH_NONE) {
187		device_printf(dev, "Unknown switch type\n");
188		return (ENXIO);
189	}
190
191	if (sc->sc_switchtype == MTK_SWITCH_MT7620 ||
192	    sc->sc_switchtype == MTK_SWITCH_MT7621)
193		mtk_attach_switch_mt7620(sc);
194	else
195		mtk_attach_switch_rt3050(sc);
196
197	/* Allocate resources */
198	rid = 0;
199	sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
200	    RF_ACTIVE);
201	if (sc->sc_res == NULL) {
202		device_printf(dev, "could not map memory\n");
203		return (ENXIO);
204	}
205
206	mtx_init(&sc->sc_mtx, "mtkswitch", NULL, MTX_DEF);
207
208	/* Reset the switch */
209	if (sc->hal.mtkswitch_reset(sc)) {
210		DPRINTF(dev, "%s: mtkswitch_reset: failed\n", __func__);
211		return (ENXIO);
212	}
213
214	err = sc->hal.mtkswitch_hw_setup(sc);
215	DPRINTF(dev, "%s: hw_setup: err=%d\n", __func__, err);
216	if (err != 0)
217		return (err);
218
219	err = sc->hal.mtkswitch_hw_global_setup(sc);
220	DPRINTF(dev, "%s: hw_global_setup: err=%d\n", __func__, err);
221	if (err != 0)
222		return (err);
223
224	/* Initialize the switch ports */
225	for (port = 0; port < sc->numports; port++) {
226		sc->hal.mtkswitch_port_init(sc, port);
227	}
228
229	/* Attach the PHYs and complete the bus enumeration */
230	err = mtkswitch_attach_phys(sc);
231	DPRINTF(dev, "%s: attach_phys: err=%d\n", __func__, err);
232	if (err != 0)
233		return (err);
234
235	/* Default to ingress filters off. */
236	err = mtkswitch_set_vlan_mode(sc, ETHERSWITCH_VLAN_DOT1Q);
237	DPRINTF(dev, "%s: set_vlan_mode: err=%d\n", __func__, err);
238	if (err != 0)
239		return (err);
240
241	bus_generic_probe(dev);
242	bus_enumerate_hinted_children(dev);
243	err = bus_generic_attach(dev);
244	DPRINTF(dev, "%s: bus_generic_attach: err=%d\n", __func__, err);
245	if (err != 0)
246		return (err);
247
248	callout_init_mtx(&sc->callout_tick, &sc->sc_mtx, 0);
249
250	MTKSWITCH_LOCK(sc);
251	mtkswitch_tick(sc);
252	MTKSWITCH_UNLOCK(sc);
253
254	return (0);
255}
256
257static int
258mtkswitch_detach(device_t dev)
259{
260	struct mtkswitch_softc *sc = device_get_softc(dev);
261	int phy;
262
263	callout_drain(&sc->callout_tick);
264
265	for (phy = 0; phy < MTKSWITCH_MAX_PHYS; phy++) {
266		if (sc->miibus[phy] != NULL)
267			device_delete_child(dev, sc->miibus[phy]);
268		if (sc->ifp[phy] != NULL)
269			if_free(sc->ifp[phy]);
270		free(sc->ifname[phy], M_DEVBUF);
271	}
272
273	bus_generic_detach(dev);
274	mtx_destroy(&sc->sc_mtx);
275
276	return (0);
277}
278
279/* PHY <-> port mapping is currently 1:1 */
280static inline int
281mtkswitch_portforphy(int phy)
282{
283
284	return (phy);
285}
286
287static inline int
288mtkswitch_phyforport(int port)
289{
290
291	return (port);
292}
293
294static inline struct mii_data *
295mtkswitch_miiforport(struct mtkswitch_softc *sc, int port)
296{
297	int phy = mtkswitch_phyforport(port);
298
299	if (phy < 0 || phy >= MTKSWITCH_MAX_PHYS || sc->miibus[phy] == NULL)
300		return (NULL);
301
302	return (device_get_softc(sc->miibus[phy]));
303}
304
305static inline struct ifnet *
306mtkswitch_ifpforport(struct mtkswitch_softc *sc, int port)
307{
308	int phy = mtkswitch_phyforport(port);
309
310	if (phy < 0 || phy >= MTKSWITCH_MAX_PHYS)
311		return (NULL);
312
313	return (sc->ifp[phy]);
314}
315
316/*
317 * Convert port status to ifmedia.
318 */
319static void
320mtkswitch_update_ifmedia(uint32_t portstatus, u_int *media_status,
321    u_int *media_active)
322{
323	*media_active = IFM_ETHER;
324	*media_status = IFM_AVALID;
325
326	if ((portstatus & MTKSWITCH_LINK_UP) != 0)
327		*media_status |= IFM_ACTIVE;
328	else {
329		*media_active |= IFM_NONE;
330		return;
331	}
332
333	switch (portstatus & MTKSWITCH_SPEED_MASK) {
334	case MTKSWITCH_SPEED_10:
335		*media_active |= IFM_10_T;
336		break;
337	case MTKSWITCH_SPEED_100:
338		*media_active |= IFM_100_TX;
339		break;
340	case MTKSWITCH_SPEED_1000:
341		*media_active |= IFM_1000_T;
342		break;
343	}
344
345	if ((portstatus & MTKSWITCH_DUPLEX) != 0)
346		*media_active |= IFM_FDX;
347	else
348		*media_active |= IFM_HDX;
349
350	if ((portstatus & MTKSWITCH_TXFLOW) != 0)
351		*media_active |= IFM_ETH_TXPAUSE;
352	if ((portstatus & MTKSWITCH_RXFLOW) != 0)
353		*media_active |= IFM_ETH_RXPAUSE;
354}
355
356static void
357mtkswitch_miipollstat(struct mtkswitch_softc *sc)
358{
359	struct mii_data *mii;
360	struct mii_softc *miisc;
361	uint32_t portstatus;
362	int i, port_flap = 0;
363
364	MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
365
366	for (i = 0; i < sc->numphys; i++) {
367		if (sc->miibus[i] == NULL)
368			continue;
369		mii = device_get_softc(sc->miibus[i]);
370		portstatus = sc->hal.mtkswitch_get_port_status(sc,
371		    mtkswitch_portforphy(i));
372
373		/* If a port has flapped - mark it so we can flush the ATU */
374		if (((mii->mii_media_status & IFM_ACTIVE) == 0 &&
375		    (portstatus & MTKSWITCH_LINK_UP) != 0) ||
376		    ((mii->mii_media_status & IFM_ACTIVE) != 0 &&
377		    (portstatus & MTKSWITCH_LINK_UP) == 0)) {
378			port_flap = 1;
379		}
380
381		mtkswitch_update_ifmedia(portstatus, &mii->mii_media_status,
382		    &mii->mii_media_active);
383		LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
384			if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) !=
385			    miisc->mii_inst)
386				continue;
387			mii_phy_update(miisc, MII_POLLSTAT);
388		}
389	}
390
391	if (port_flap)
392		sc->hal.mtkswitch_atu_flush(sc);
393}
394
395static void
396mtkswitch_tick(void *arg)
397{
398	struct mtkswitch_softc *sc = arg;
399
400	mtkswitch_miipollstat(sc);
401	callout_reset(&sc->callout_tick, hz, mtkswitch_tick, sc);
402}
403
404static void
405mtkswitch_lock(device_t dev)
406{
407        struct mtkswitch_softc *sc = device_get_softc(dev);
408
409	MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
410	MTKSWITCH_LOCK(sc);
411}
412
413static void
414mtkswitch_unlock(device_t dev)
415{
416	struct mtkswitch_softc *sc = device_get_softc(dev);
417
418	MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
419	MTKSWITCH_UNLOCK(sc);
420}
421
422static etherswitch_info_t *
423mtkswitch_getinfo(device_t dev)
424{
425	struct mtkswitch_softc *sc = device_get_softc(dev);
426
427	return (&sc->info);
428}
429
430static inline int
431mtkswitch_is_cpuport(struct mtkswitch_softc *sc, int port)
432{
433
434	return (sc->cpuport == port);
435}
436
437static int
438mtkswitch_getport(device_t dev, etherswitch_port_t *p)
439{
440	struct mtkswitch_softc *sc;
441	struct mii_data *mii;
442	struct ifmediareq *ifmr;
443	int err;
444
445	sc = device_get_softc(dev);
446	if (p->es_port < 0 || p->es_port > sc->info.es_nports)
447		return (ENXIO);
448
449	err = sc->hal.mtkswitch_port_vlan_get(sc, p);
450	if (err != 0)
451		return (err);
452
453	mii = mtkswitch_miiforport(sc, p->es_port);
454	if (mtkswitch_is_cpuport(sc, p->es_port)) {
455		/* fill in fixed values for CPU port */
456		/* XXX is this valid in all cases? */
457		p->es_flags |= ETHERSWITCH_PORT_CPU;
458		ifmr = &p->es_ifmr;
459		ifmr->ifm_count = 0;
460		ifmr->ifm_current = ifmr->ifm_active =
461		    IFM_ETHER | IFM_1000_T | IFM_FDX;
462		ifmr->ifm_mask = 0;
463		ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
464	} else if (mii != NULL) {
465		err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr,
466		    &mii->mii_media, SIOCGIFMEDIA);
467		if (err)
468			return (err);
469	} else {
470		ifmr = &p->es_ifmr;
471		ifmr->ifm_count = 0;
472		ifmr->ifm_current = ifmr->ifm_active = IFM_NONE;
473		ifmr->ifm_mask = 0;
474		ifmr->ifm_status = 0;
475	}
476	return (0);
477}
478
479static int
480mtkswitch_setport(device_t dev, etherswitch_port_t *p)
481{
482	int err;
483	struct mtkswitch_softc *sc;
484	struct ifmedia *ifm;
485	struct mii_data *mii;
486	struct ifnet *ifp;
487
488	sc = device_get_softc(dev);
489	if (p->es_port < 0 || p->es_port > sc->info.es_nports)
490		return (ENXIO);
491
492	/* Port flags. */
493	if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
494		err = sc->hal.mtkswitch_port_vlan_setup(sc, p);
495		if (err)
496			return (err);
497	}
498
499	/* Do not allow media changes on CPU port. */
500	if (mtkswitch_is_cpuport(sc, p->es_port))
501		return (0);
502
503	mii = mtkswitch_miiforport(sc, p->es_port);
504	if (mii == NULL)
505		return (ENXIO);
506
507	ifp = mtkswitch_ifpforport(sc, p->es_port);
508
509	ifm = &mii->mii_media;
510	return (ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA));
511}
512
513static void
514mtkswitch_statchg(device_t dev)
515{
516
517	DPRINTF(dev, "%s\n", __func__);
518}
519
520static int
521mtkswitch_ifmedia_upd(struct ifnet *ifp)
522{
523	struct mtkswitch_softc *sc = ifp->if_softc;
524	struct mii_data *mii = mtkswitch_miiforport(sc, ifp->if_dunit);
525
526	if (mii == NULL)
527		return (ENXIO);
528	mii_mediachg(mii);
529	return (0);
530}
531
532static void
533mtkswitch_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
534{
535	struct mtkswitch_softc *sc = ifp->if_softc;
536	struct mii_data *mii = mtkswitch_miiforport(sc, ifp->if_dunit);
537
538	DPRINTF(sc->sc_dev, "%s\n", __func__);
539
540	if (mii == NULL)
541		return;
542	mii_pollstat(mii);
543	ifmr->ifm_active = mii->mii_media_active;
544	ifmr->ifm_status = mii->mii_media_status;
545}
546
547static int
548mtkswitch_getconf(device_t dev, etherswitch_conf_t *conf)
549{
550	struct mtkswitch_softc *sc;
551
552	sc = device_get_softc(dev);
553
554	/* Return the VLAN mode. */
555	conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
556	conf->vlan_mode = sc->vlan_mode;
557
558	return (0);
559}
560
561static int
562mtkswitch_setconf(device_t dev, etherswitch_conf_t *conf)
563{
564	struct mtkswitch_softc *sc;
565	int err;
566
567	sc = device_get_softc(dev);
568
569	/* Set the VLAN mode. */
570	if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) {
571		err = mtkswitch_set_vlan_mode(sc, conf->vlan_mode);
572		if (err != 0)
573			return (err);
574	}
575
576	return (0);
577}
578
579static int
580mtkswitch_getvgroup(device_t dev, etherswitch_vlangroup_t *e)
581{
582        struct mtkswitch_softc *sc = device_get_softc(dev);
583
584        return (sc->hal.mtkswitch_vlan_getvgroup(sc, e));
585}
586
587static int
588mtkswitch_setvgroup(device_t dev, etherswitch_vlangroup_t *e)
589{
590	struct mtkswitch_softc *sc = device_get_softc(dev);
591
592	return (sc->hal.mtkswitch_vlan_setvgroup(sc, e));
593}
594
595static int
596mtkswitch_readphy(device_t dev, int phy, int reg)
597{
598	struct mtkswitch_softc *sc = device_get_softc(dev);
599
600	return (sc->hal.mtkswitch_phy_read(dev, phy, reg));
601}
602
603static int
604mtkswitch_writephy(device_t dev, int phy, int reg, int val)
605{
606	struct mtkswitch_softc *sc = device_get_softc(dev);
607
608	return (sc->hal.mtkswitch_phy_write(dev, phy, reg, val));
609}
610
611static int
612mtkswitch_readreg(device_t dev, int addr)
613{
614	struct mtkswitch_softc *sc = device_get_softc(dev);
615
616	return (sc->hal.mtkswitch_reg_read(dev, addr));
617}
618
619static int
620mtkswitch_writereg(device_t dev, int addr, int value)
621{
622	struct mtkswitch_softc *sc = device_get_softc(dev);
623
624	return (sc->hal.mtkswitch_reg_write(dev, addr, value));
625}
626
627static device_method_t mtkswitch_methods[] = {
628	/* Device interface */
629	DEVMETHOD(device_probe,		mtkswitch_probe),
630	DEVMETHOD(device_attach,	mtkswitch_attach),
631	DEVMETHOD(device_detach,	mtkswitch_detach),
632
633	/* bus interface */
634	DEVMETHOD(bus_add_child,	device_add_child_ordered),
635
636	/* MII interface */
637	DEVMETHOD(miibus_readreg,	mtkswitch_readphy),
638	DEVMETHOD(miibus_writereg,	mtkswitch_writephy),
639	DEVMETHOD(miibus_statchg,	mtkswitch_statchg),
640
641	/* MDIO interface */
642	DEVMETHOD(mdio_readreg,		mtkswitch_readphy),
643	DEVMETHOD(mdio_writereg,	mtkswitch_writephy),
644
645	/* ehterswitch interface */
646	DEVMETHOD(etherswitch_lock,	mtkswitch_lock),
647	DEVMETHOD(etherswitch_unlock,	mtkswitch_unlock),
648	DEVMETHOD(etherswitch_getinfo,	mtkswitch_getinfo),
649	DEVMETHOD(etherswitch_readreg,	mtkswitch_readreg),
650	DEVMETHOD(etherswitch_writereg,	mtkswitch_writereg),
651	DEVMETHOD(etherswitch_readphyreg,	mtkswitch_readphy),
652	DEVMETHOD(etherswitch_writephyreg,	mtkswitch_writephy),
653	DEVMETHOD(etherswitch_getport,	mtkswitch_getport),
654	DEVMETHOD(etherswitch_setport,	mtkswitch_setport),
655	DEVMETHOD(etherswitch_getvgroup,	mtkswitch_getvgroup),
656	DEVMETHOD(etherswitch_setvgroup,	mtkswitch_setvgroup),
657	DEVMETHOD(etherswitch_getconf,	mtkswitch_getconf),
658	DEVMETHOD(etherswitch_setconf,	mtkswitch_setconf),
659
660	DEVMETHOD_END
661};
662
663DEFINE_CLASS_0(mtkswitch, mtkswitch_driver, mtkswitch_methods,
664    sizeof(struct mtkswitch_softc));
665static devclass_t mtkswitch_devclass;
666
667DRIVER_MODULE(mtkswitch, simplebus, mtkswitch_driver, mtkswitch_devclass, 0, 0);
668DRIVER_MODULE(miibus, mtkswitch, miibus_driver, miibus_devclass, 0, 0);
669DRIVER_MODULE(mdio, mtkswitch, mdio_driver, mdio_devclass, 0, 0);
670DRIVER_MODULE(etherswitch, mtkswitch, etherswitch_driver, etherswitch_devclass,
671    0, 0);
672MODULE_VERSION(mtkswitch, 1);
673MODULE_DEPEND(mtkswitch, miibus, 1, 1, 1);
674MODULE_DEPEND(mtkswitch, etherswitch, 1, 1, 1);
675