xref: /freebsd/sys/dev/etherswitch/arswitch/arswitch_8327.c (revision f9950f9ac8237059785774973b5cb826c002efab)
17330dd0bSAdrian Chadd /*-
27330dd0bSAdrian Chadd  * Copyright (c) 2011-2012 Stefan Bethke.
37330dd0bSAdrian Chadd  * Copyright (c) 2014 Adrian Chadd.
47330dd0bSAdrian Chadd  * All rights reserved.
57330dd0bSAdrian Chadd  *
67330dd0bSAdrian Chadd  * Redistribution and use in source and binary forms, with or without
77330dd0bSAdrian Chadd  * modification, are permitted provided that the following conditions
87330dd0bSAdrian Chadd  * are met:
97330dd0bSAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
107330dd0bSAdrian Chadd  *    notice, this list of conditions and the following disclaimer.
117330dd0bSAdrian Chadd  * 2. Redistributions in binary form must reproduce the above copyright
127330dd0bSAdrian Chadd  *    notice, this list of conditions and the following disclaimer in the
137330dd0bSAdrian Chadd  *    documentation and/or other materials provided with the distribution.
147330dd0bSAdrian Chadd  *
157330dd0bSAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
167330dd0bSAdrian Chadd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
177330dd0bSAdrian Chadd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
187330dd0bSAdrian Chadd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
197330dd0bSAdrian Chadd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
207330dd0bSAdrian Chadd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
217330dd0bSAdrian Chadd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
227330dd0bSAdrian Chadd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
237330dd0bSAdrian Chadd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
247330dd0bSAdrian Chadd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
257330dd0bSAdrian Chadd  * SUCH DAMAGE.
267330dd0bSAdrian Chadd  *
277330dd0bSAdrian Chadd  * $FreeBSD$
287330dd0bSAdrian Chadd  */
297330dd0bSAdrian Chadd 
307330dd0bSAdrian Chadd #include <sys/param.h>
317330dd0bSAdrian Chadd #include <sys/bus.h>
327330dd0bSAdrian Chadd #include <sys/errno.h>
337330dd0bSAdrian Chadd #include <sys/kernel.h>
347330dd0bSAdrian Chadd #include <sys/module.h>
357330dd0bSAdrian Chadd #include <sys/socket.h>
367330dd0bSAdrian Chadd #include <sys/sockio.h>
377330dd0bSAdrian Chadd #include <sys/sysctl.h>
387330dd0bSAdrian Chadd #include <sys/systm.h>
397330dd0bSAdrian Chadd 
407330dd0bSAdrian Chadd #include <net/if.h>
417330dd0bSAdrian Chadd #include <net/if_arp.h>
427330dd0bSAdrian Chadd #include <net/ethernet.h>
437330dd0bSAdrian Chadd #include <net/if_dl.h>
447330dd0bSAdrian Chadd #include <net/if_media.h>
457330dd0bSAdrian Chadd #include <net/if_types.h>
467330dd0bSAdrian Chadd 
477330dd0bSAdrian Chadd #include <machine/bus.h>
487330dd0bSAdrian Chadd #include <dev/iicbus/iic.h>
497330dd0bSAdrian Chadd #include <dev/iicbus/iiconf.h>
507330dd0bSAdrian Chadd #include <dev/iicbus/iicbus.h>
517330dd0bSAdrian Chadd #include <dev/mii/mii.h>
527330dd0bSAdrian Chadd #include <dev/mii/miivar.h>
537330dd0bSAdrian Chadd #include <dev/etherswitch/mdio.h>
547330dd0bSAdrian Chadd 
557330dd0bSAdrian Chadd #include <dev/etherswitch/etherswitch.h>
567330dd0bSAdrian Chadd 
577330dd0bSAdrian Chadd #include <dev/etherswitch/arswitch/arswitchreg.h>
587330dd0bSAdrian Chadd #include <dev/etherswitch/arswitch/arswitchvar.h>
597330dd0bSAdrian Chadd #include <dev/etherswitch/arswitch/arswitch_reg.h>
607330dd0bSAdrian Chadd #include <dev/etherswitch/arswitch/arswitch_8327.h>
617330dd0bSAdrian Chadd 
627330dd0bSAdrian Chadd #include "mdio_if.h"
637330dd0bSAdrian Chadd #include "miibus_if.h"
647330dd0bSAdrian Chadd #include "etherswitch_if.h"
657330dd0bSAdrian Chadd 
667330dd0bSAdrian Chadd static void
677330dd0bSAdrian Chadd ar8327_phy_fixup(struct arswitch_softc *sc, int phy)
687330dd0bSAdrian Chadd {
697330dd0bSAdrian Chadd 
707330dd0bSAdrian Chadd 	switch (sc->chip_rev) {
717330dd0bSAdrian Chadd 	case 1:
727330dd0bSAdrian Chadd 		/* For 100M waveform */
737330dd0bSAdrian Chadd 		arswitch_writedbg(sc->sc_dev, phy, 0, 0x02ea);
747330dd0bSAdrian Chadd 		/* Turn on Gigabit clock */
757330dd0bSAdrian Chadd 		arswitch_writedbg(sc->sc_dev, phy, 0x3d, 0x68a0);
767330dd0bSAdrian Chadd 		break;
777330dd0bSAdrian Chadd 
787330dd0bSAdrian Chadd 	case 2:
797330dd0bSAdrian Chadd 		arswitch_writemmd(sc->sc_dev, phy, 0x7, 0x3c);
807330dd0bSAdrian Chadd 		arswitch_writemmd(sc->sc_dev, phy, 0x4007, 0x0);
817330dd0bSAdrian Chadd 		/* fallthrough */
827330dd0bSAdrian Chadd 	case 4:
837330dd0bSAdrian Chadd 		arswitch_writemmd(sc->sc_dev, phy, 0x3, 0x800d);
847330dd0bSAdrian Chadd 		arswitch_writemmd(sc->sc_dev, phy, 0x4003, 0x803f);
857330dd0bSAdrian Chadd 
867330dd0bSAdrian Chadd 		arswitch_writedbg(sc->sc_dev, phy, 0x3d, 0x6860);
877330dd0bSAdrian Chadd 		arswitch_writedbg(sc->sc_dev, phy, 0x5, 0x2c46);
887330dd0bSAdrian Chadd 		arswitch_writedbg(sc->sc_dev, phy, 0x3c, 0x6000);
897330dd0bSAdrian Chadd 		break;
907330dd0bSAdrian Chadd 	}
917330dd0bSAdrian Chadd }
927330dd0bSAdrian Chadd 
937330dd0bSAdrian Chadd static uint32_t
947330dd0bSAdrian Chadd ar8327_get_pad_cfg(struct ar8327_pad_cfg *cfg)
957330dd0bSAdrian Chadd {
967330dd0bSAdrian Chadd 	uint32_t t;
977330dd0bSAdrian Chadd 
987330dd0bSAdrian Chadd 	if (!cfg)
997330dd0bSAdrian Chadd 		return (0);
1007330dd0bSAdrian Chadd 
1017330dd0bSAdrian Chadd 	t = 0;
1027330dd0bSAdrian Chadd 	switch (cfg->mode) {
1037330dd0bSAdrian Chadd 	case AR8327_PAD_NC:
1047330dd0bSAdrian Chadd 		break;
1057330dd0bSAdrian Chadd 
1067330dd0bSAdrian Chadd 	case AR8327_PAD_MAC2MAC_MII:
1077330dd0bSAdrian Chadd 		t = AR8327_PAD_MAC_MII_EN;
1087330dd0bSAdrian Chadd 		if (cfg->rxclk_sel)
1097330dd0bSAdrian Chadd 			t |= AR8327_PAD_MAC_MII_RXCLK_SEL;
1107330dd0bSAdrian Chadd 		if (cfg->txclk_sel)
1117330dd0bSAdrian Chadd 			t |= AR8327_PAD_MAC_MII_TXCLK_SEL;
1127330dd0bSAdrian Chadd 		break;
1137330dd0bSAdrian Chadd 
1147330dd0bSAdrian Chadd 	case AR8327_PAD_MAC2MAC_GMII:
1157330dd0bSAdrian Chadd 		t = AR8327_PAD_MAC_GMII_EN;
1167330dd0bSAdrian Chadd 		if (cfg->rxclk_sel)
1177330dd0bSAdrian Chadd 			t |= AR8327_PAD_MAC_GMII_RXCLK_SEL;
1187330dd0bSAdrian Chadd 		if (cfg->txclk_sel)
1197330dd0bSAdrian Chadd 			t |= AR8327_PAD_MAC_GMII_TXCLK_SEL;
1207330dd0bSAdrian Chadd 		break;
1217330dd0bSAdrian Chadd 
1227330dd0bSAdrian Chadd 	case AR8327_PAD_MAC_SGMII:
1237330dd0bSAdrian Chadd 		t = AR8327_PAD_SGMII_EN;
1247330dd0bSAdrian Chadd 
1257330dd0bSAdrian Chadd 		/*
1269ab21e32SAdrian Chadd 		 * WAR for the Qualcomm Atheros AP136 board.
1277330dd0bSAdrian Chadd 		 * It seems that RGMII TX/RX delay settings needs to be
1287330dd0bSAdrian Chadd 		 * applied for SGMII mode as well, The ethernet is not
1297330dd0bSAdrian Chadd 		 * reliable without this.
1307330dd0bSAdrian Chadd 		 */
1317330dd0bSAdrian Chadd 		t |= cfg->txclk_delay_sel << AR8327_PAD_RGMII_TXCLK_DELAY_SEL_S;
1327330dd0bSAdrian Chadd 		t |= cfg->rxclk_delay_sel << AR8327_PAD_RGMII_RXCLK_DELAY_SEL_S;
1337330dd0bSAdrian Chadd 		if (cfg->rxclk_delay_en)
1347330dd0bSAdrian Chadd 			t |= AR8327_PAD_RGMII_RXCLK_DELAY_EN;
1357330dd0bSAdrian Chadd 		if (cfg->txclk_delay_en)
1367330dd0bSAdrian Chadd 			t |= AR8327_PAD_RGMII_TXCLK_DELAY_EN;
1377330dd0bSAdrian Chadd 
1387330dd0bSAdrian Chadd 		if (cfg->sgmii_delay_en)
1397330dd0bSAdrian Chadd 			t |= AR8327_PAD_SGMII_DELAY_EN;
1407330dd0bSAdrian Chadd 
1417330dd0bSAdrian Chadd 		break;
1427330dd0bSAdrian Chadd 
1437330dd0bSAdrian Chadd 	case AR8327_PAD_MAC2PHY_MII:
1447330dd0bSAdrian Chadd 		t = AR8327_PAD_PHY_MII_EN;
1457330dd0bSAdrian Chadd 		if (cfg->rxclk_sel)
1467330dd0bSAdrian Chadd 			t |= AR8327_PAD_PHY_MII_RXCLK_SEL;
1477330dd0bSAdrian Chadd 		if (cfg->txclk_sel)
1487330dd0bSAdrian Chadd 			t |= AR8327_PAD_PHY_MII_TXCLK_SEL;
1497330dd0bSAdrian Chadd 		break;
1507330dd0bSAdrian Chadd 
1517330dd0bSAdrian Chadd 	case AR8327_PAD_MAC2PHY_GMII:
1527330dd0bSAdrian Chadd 		t = AR8327_PAD_PHY_GMII_EN;
1537330dd0bSAdrian Chadd 		if (cfg->pipe_rxclk_sel)
1547330dd0bSAdrian Chadd 			t |= AR8327_PAD_PHY_GMII_PIPE_RXCLK_SEL;
1557330dd0bSAdrian Chadd 		if (cfg->rxclk_sel)
1567330dd0bSAdrian Chadd 			t |= AR8327_PAD_PHY_GMII_RXCLK_SEL;
1577330dd0bSAdrian Chadd 		if (cfg->txclk_sel)
1587330dd0bSAdrian Chadd 			t |= AR8327_PAD_PHY_GMII_TXCLK_SEL;
1597330dd0bSAdrian Chadd 		break;
1607330dd0bSAdrian Chadd 
1617330dd0bSAdrian Chadd 	case AR8327_PAD_MAC_RGMII:
1627330dd0bSAdrian Chadd 		t = AR8327_PAD_RGMII_EN;
1637330dd0bSAdrian Chadd 		t |= cfg->txclk_delay_sel << AR8327_PAD_RGMII_TXCLK_DELAY_SEL_S;
1647330dd0bSAdrian Chadd 		t |= cfg->rxclk_delay_sel << AR8327_PAD_RGMII_RXCLK_DELAY_SEL_S;
1657330dd0bSAdrian Chadd 		if (cfg->rxclk_delay_en)
1667330dd0bSAdrian Chadd 			t |= AR8327_PAD_RGMII_RXCLK_DELAY_EN;
1677330dd0bSAdrian Chadd 		if (cfg->txclk_delay_en)
1687330dd0bSAdrian Chadd 			t |= AR8327_PAD_RGMII_TXCLK_DELAY_EN;
1697330dd0bSAdrian Chadd 		break;
1707330dd0bSAdrian Chadd 
1717330dd0bSAdrian Chadd 	case AR8327_PAD_PHY_GMII:
1727330dd0bSAdrian Chadd 		t = AR8327_PAD_PHYX_GMII_EN;
1737330dd0bSAdrian Chadd 		break;
1747330dd0bSAdrian Chadd 
1757330dd0bSAdrian Chadd 	case AR8327_PAD_PHY_RGMII:
1767330dd0bSAdrian Chadd 		t = AR8327_PAD_PHYX_RGMII_EN;
1777330dd0bSAdrian Chadd 		break;
1787330dd0bSAdrian Chadd 
1797330dd0bSAdrian Chadd 	case AR8327_PAD_PHY_MII:
1807330dd0bSAdrian Chadd 		t = AR8327_PAD_PHYX_MII_EN;
1817330dd0bSAdrian Chadd 		break;
1827330dd0bSAdrian Chadd 	}
1837330dd0bSAdrian Chadd 
1847330dd0bSAdrian Chadd 	return (t);
1857330dd0bSAdrian Chadd }
1867330dd0bSAdrian Chadd 
1877330dd0bSAdrian Chadd /*
1887330dd0bSAdrian Chadd  * Map the hard-coded port config from the switch setup to
1897330dd0bSAdrian Chadd  * the chipset port config (status, duplex, flow, etc.)
1907330dd0bSAdrian Chadd  */
1917330dd0bSAdrian Chadd static uint32_t
1927330dd0bSAdrian Chadd ar8327_get_port_init_status(struct ar8327_port_cfg *cfg)
1937330dd0bSAdrian Chadd {
1947330dd0bSAdrian Chadd 	uint32_t t;
1957330dd0bSAdrian Chadd 
1967330dd0bSAdrian Chadd 	if (!cfg->force_link)
1977330dd0bSAdrian Chadd 		return (AR8X16_PORT_STS_LINK_AUTO);
1987330dd0bSAdrian Chadd 
1997330dd0bSAdrian Chadd 	t = AR8X16_PORT_STS_TXMAC | AR8X16_PORT_STS_RXMAC;
2007330dd0bSAdrian Chadd 	t |= cfg->duplex ? AR8X16_PORT_STS_DUPLEX : 0;
2017330dd0bSAdrian Chadd 	t |= cfg->rxpause ? AR8X16_PORT_STS_RXFLOW : 0;
2027330dd0bSAdrian Chadd 	t |= cfg->txpause ? AR8X16_PORT_STS_TXFLOW : 0;
2037330dd0bSAdrian Chadd 
2047330dd0bSAdrian Chadd 	switch (cfg->speed) {
2057330dd0bSAdrian Chadd 	case AR8327_PORT_SPEED_10:
2067330dd0bSAdrian Chadd 		t |= AR8X16_PORT_STS_SPEED_10;
2077330dd0bSAdrian Chadd 		break;
2087330dd0bSAdrian Chadd 	case AR8327_PORT_SPEED_100:
2097330dd0bSAdrian Chadd 		t |= AR8X16_PORT_STS_SPEED_100;
2107330dd0bSAdrian Chadd 		break;
2117330dd0bSAdrian Chadd 	case AR8327_PORT_SPEED_1000:
2127330dd0bSAdrian Chadd 		t |= AR8X16_PORT_STS_SPEED_1000;
2137330dd0bSAdrian Chadd 		break;
2147330dd0bSAdrian Chadd 	}
2157330dd0bSAdrian Chadd 
2167330dd0bSAdrian Chadd 	return (t);
2177330dd0bSAdrian Chadd }
2189ab21e32SAdrian Chadd 
2199ab21e32SAdrian Chadd /*
220*f9950f9aSAdrian Chadd  * Fetch the port data for the given port.
221*f9950f9aSAdrian Chadd  *
222*f9950f9aSAdrian Chadd  * This goes and does dirty things with the hints space
223*f9950f9aSAdrian Chadd  * to determine what the configuration parameters should be.
224*f9950f9aSAdrian Chadd  *
225*f9950f9aSAdrian Chadd  * Returns 1 if the structure was successfully parsed and
226*f9950f9aSAdrian Chadd  * the contents are valid; 0 otherwise.
227*f9950f9aSAdrian Chadd  */
228*f9950f9aSAdrian Chadd static int
229*f9950f9aSAdrian Chadd ar8327_fetch_pdata_port(struct arswitch_softc *sc,
230*f9950f9aSAdrian Chadd     struct ar8327_port_cfg *pcfg,
231*f9950f9aSAdrian Chadd     int port)
232*f9950f9aSAdrian Chadd {
233*f9950f9aSAdrian Chadd 	int val;
234*f9950f9aSAdrian Chadd 	char sbuf[128];
235*f9950f9aSAdrian Chadd 
236*f9950f9aSAdrian Chadd 	/* Check if force_link exists */
237*f9950f9aSAdrian Chadd 	val = 0;
238*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "port.%d.force_link", port);
239*f9950f9aSAdrian Chadd 	(void) resource_int_value(device_get_name(sc->sc_dev),
240*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
241*f9950f9aSAdrian Chadd 	    sbuf, &val);
242*f9950f9aSAdrian Chadd 	if (val != 1)
243*f9950f9aSAdrian Chadd 		return (0);
244*f9950f9aSAdrian Chadd 	pcfg->force_link = 1;
245*f9950f9aSAdrian Chadd 
246*f9950f9aSAdrian Chadd 	/* force_link is set; let's parse the rest of the fields */
247*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "port.%d.speed", port);
248*f9950f9aSAdrian Chadd 	if (resource_int_value(device_get_name(sc->sc_dev),
249*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
250*f9950f9aSAdrian Chadd 	    sbuf, &val) == 0) {
251*f9950f9aSAdrian Chadd 		switch (val) {
252*f9950f9aSAdrian Chadd 		case 10:
253*f9950f9aSAdrian Chadd 			pcfg->speed = AR8327_PORT_SPEED_10;
254*f9950f9aSAdrian Chadd 			break;
255*f9950f9aSAdrian Chadd 		case 100:
256*f9950f9aSAdrian Chadd 			pcfg->speed = AR8327_PORT_SPEED_100;
257*f9950f9aSAdrian Chadd 			break;
258*f9950f9aSAdrian Chadd 		case 1000:
259*f9950f9aSAdrian Chadd 			pcfg->speed = AR8327_PORT_SPEED_1000;
260*f9950f9aSAdrian Chadd 			break;
261*f9950f9aSAdrian Chadd 		default:
262*f9950f9aSAdrian Chadd 			device_printf(sc->sc_dev,
263*f9950f9aSAdrian Chadd 			    "%s: invalid port %d duplex value (%d)\n",
264*f9950f9aSAdrian Chadd 			    __func__,
265*f9950f9aSAdrian Chadd 			    port,
266*f9950f9aSAdrian Chadd 			    val);
267*f9950f9aSAdrian Chadd 			return (0);
268*f9950f9aSAdrian Chadd 		}
269*f9950f9aSAdrian Chadd 	}
270*f9950f9aSAdrian Chadd 
271*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "port.%d.duplex", port);
272*f9950f9aSAdrian Chadd 	if (resource_int_value(device_get_name(sc->sc_dev),
273*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
274*f9950f9aSAdrian Chadd 	    sbuf, &val) == 0)
275*f9950f9aSAdrian Chadd 		pcfg->duplex = val;
276*f9950f9aSAdrian Chadd 
277*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "port.%d.txpause", port);
278*f9950f9aSAdrian Chadd 	if (resource_int_value(device_get_name(sc->sc_dev),
279*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
280*f9950f9aSAdrian Chadd 	    sbuf, &val) == 0)
281*f9950f9aSAdrian Chadd 		pcfg->txpause = val;
282*f9950f9aSAdrian Chadd 
283*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "port.%d.rxpause", port);
284*f9950f9aSAdrian Chadd 	if (resource_int_value(device_get_name(sc->sc_dev),
285*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
286*f9950f9aSAdrian Chadd 	    sbuf, &val) == 0)
287*f9950f9aSAdrian Chadd 		pcfg->rxpause = val;
288*f9950f9aSAdrian Chadd 
289*f9950f9aSAdrian Chadd #if 0
290*f9950f9aSAdrian Chadd 	device_printf(sc->sc_dev,
291*f9950f9aSAdrian Chadd 	    "%s: port %d: speed=%d, duplex=%d, txpause=%d, rxpause=%d\n",
292*f9950f9aSAdrian Chadd 	    __func__,
293*f9950f9aSAdrian Chadd 	    port,
294*f9950f9aSAdrian Chadd 	    pcfg->speed,
295*f9950f9aSAdrian Chadd 	    pcfg->duplex,
296*f9950f9aSAdrian Chadd 	    pcfg->txpause,
297*f9950f9aSAdrian Chadd 	    pcfg->rxpause);
298*f9950f9aSAdrian Chadd #endif
299*f9950f9aSAdrian Chadd 
300*f9950f9aSAdrian Chadd 	return (1);
301*f9950f9aSAdrian Chadd }
302*f9950f9aSAdrian Chadd 
303*f9950f9aSAdrian Chadd /*
304*f9950f9aSAdrian Chadd  * Parse the pad configuration from the boot hints.
305*f9950f9aSAdrian Chadd  *
306*f9950f9aSAdrian Chadd  * The (mostly optional) fields are:
307*f9950f9aSAdrian Chadd  *
308*f9950f9aSAdrian Chadd  * uint32_t mode;
309*f9950f9aSAdrian Chadd  * uint32_t rxclk_sel;
310*f9950f9aSAdrian Chadd  * uint32_t txclk_sel;
311*f9950f9aSAdrian Chadd  * uint32_t txclk_delay_sel;
312*f9950f9aSAdrian Chadd  * uint32_t rxclk_delay_sel;
313*f9950f9aSAdrian Chadd  * uint32_t txclk_delay_en;
314*f9950f9aSAdrian Chadd  * uint32_t rxclk_delay_en;
315*f9950f9aSAdrian Chadd  * uint32_t sgmii_delay_en;
316*f9950f9aSAdrian Chadd  * uint32_t pipe_rxclk_sel;
317*f9950f9aSAdrian Chadd  *
318*f9950f9aSAdrian Chadd  * If mode isn't in the hints, 0 is returned.
319*f9950f9aSAdrian Chadd  * Else the structure is fleshed out and 1 is returned.
320*f9950f9aSAdrian Chadd  */
321*f9950f9aSAdrian Chadd static int
322*f9950f9aSAdrian Chadd ar8327_fetch_pdata_pad(struct arswitch_softc *sc,
323*f9950f9aSAdrian Chadd     struct ar8327_pad_cfg *pc,
324*f9950f9aSAdrian Chadd     int pad)
325*f9950f9aSAdrian Chadd {
326*f9950f9aSAdrian Chadd 	int val;
327*f9950f9aSAdrian Chadd 	char sbuf[128];
328*f9950f9aSAdrian Chadd 
329*f9950f9aSAdrian Chadd 	/* Check if mode exists */
330*f9950f9aSAdrian Chadd 	val = 0;
331*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "pad.%d.mode", pad);
332*f9950f9aSAdrian Chadd 	if (resource_int_value(device_get_name(sc->sc_dev),
333*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
334*f9950f9aSAdrian Chadd 	    sbuf, &val) != 0)
335*f9950f9aSAdrian Chadd 		return (0);
336*f9950f9aSAdrian Chadd 
337*f9950f9aSAdrian Chadd 	/* assume that 'mode' exists and was found */
338*f9950f9aSAdrian Chadd 	pc->mode = val;
339*f9950f9aSAdrian Chadd 
340*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "pad.%d.rxclk_sel", pad);
341*f9950f9aSAdrian Chadd 	if (resource_int_value(device_get_name(sc->sc_dev),
342*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
343*f9950f9aSAdrian Chadd 	    sbuf, &val) == 0)
344*f9950f9aSAdrian Chadd 		pc->rxclk_sel = val;
345*f9950f9aSAdrian Chadd 
346*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "pad.%d.txclk_sel", pad);
347*f9950f9aSAdrian Chadd 	if (resource_int_value(device_get_name(sc->sc_dev),
348*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
349*f9950f9aSAdrian Chadd 	    sbuf, &val) == 0)
350*f9950f9aSAdrian Chadd 		pc->txclk_sel = val;
351*f9950f9aSAdrian Chadd 
352*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "pad.%d.txclk_delay_sel", pad);
353*f9950f9aSAdrian Chadd 	if (resource_int_value(device_get_name(sc->sc_dev),
354*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
355*f9950f9aSAdrian Chadd 	    sbuf, &val) == 0)
356*f9950f9aSAdrian Chadd 		pc->txclk_delay_sel = val;
357*f9950f9aSAdrian Chadd 
358*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "pad.%d.rxclk_delay_sel", pad);
359*f9950f9aSAdrian Chadd 	if (resource_int_value(device_get_name(sc->sc_dev),
360*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
361*f9950f9aSAdrian Chadd 	    sbuf, &val) == 0)
362*f9950f9aSAdrian Chadd 		pc->rxclk_delay_sel = val;
363*f9950f9aSAdrian Chadd 
364*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "pad.%d.txclk_delay_en", pad);
365*f9950f9aSAdrian Chadd 	if (resource_int_value(device_get_name(sc->sc_dev),
366*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
367*f9950f9aSAdrian Chadd 	    sbuf, &val) == 0)
368*f9950f9aSAdrian Chadd 		pc->txclk_delay_en = val;
369*f9950f9aSAdrian Chadd 
370*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "pad.%d.rxclk_delay_en", pad);
371*f9950f9aSAdrian Chadd 	if (resource_int_value(device_get_name(sc->sc_dev),
372*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
373*f9950f9aSAdrian Chadd 	    sbuf, &val) == 0)
374*f9950f9aSAdrian Chadd 		pc->rxclk_delay_en = val;
375*f9950f9aSAdrian Chadd 
376*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "pad.%d.sgmii_delay_en", pad);
377*f9950f9aSAdrian Chadd 	if (resource_int_value(device_get_name(sc->sc_dev),
378*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
379*f9950f9aSAdrian Chadd 	    sbuf, &val) == 0)
380*f9950f9aSAdrian Chadd 		pc->sgmii_delay_en = val;
381*f9950f9aSAdrian Chadd 
382*f9950f9aSAdrian Chadd 	snprintf(sbuf, 128, "pad.%d.pipe_rxclk_sel", pad);
383*f9950f9aSAdrian Chadd 	if (resource_int_value(device_get_name(sc->sc_dev),
384*f9950f9aSAdrian Chadd 	    device_get_unit(sc->sc_dev),
385*f9950f9aSAdrian Chadd 	    sbuf, &val) == 0)
386*f9950f9aSAdrian Chadd 		pc->pipe_rxclk_sel = val;
387*f9950f9aSAdrian Chadd 
388*f9950f9aSAdrian Chadd #if 0
389*f9950f9aSAdrian Chadd 	device_printf(sc->sc_dev,
390*f9950f9aSAdrian Chadd 	    "%s: pad %d: mode=%d, rxclk_sel=%d, txclk_sel=%d, "
391*f9950f9aSAdrian Chadd 	    "txclk_delay_sel=%d, rxclk_delay_sel=%d, txclk_delay_en=%d, "
392*f9950f9aSAdrian Chadd 	    "rxclk_enable_en=%d, sgmii_delay_en=%d, pipe_rxclk_sel=%d\n",
393*f9950f9aSAdrian Chadd 	    __func__,
394*f9950f9aSAdrian Chadd 	    pad,
395*f9950f9aSAdrian Chadd 	    pc->mode,
396*f9950f9aSAdrian Chadd 	    pc->rxclk_sel,
397*f9950f9aSAdrian Chadd 	    pc->txclk_sel,
398*f9950f9aSAdrian Chadd 	    pc->txclk_delay_sel,
399*f9950f9aSAdrian Chadd 	    pc->rxclk_delay_sel,
400*f9950f9aSAdrian Chadd 	    pc->txclk_delay_en,
401*f9950f9aSAdrian Chadd 	    pc->rxclk_delay_en,
402*f9950f9aSAdrian Chadd 	    pc->sgmii_delay_en,
403*f9950f9aSAdrian Chadd 	    pc->pipe_rxclk_sel);
404*f9950f9aSAdrian Chadd #endif
405*f9950f9aSAdrian Chadd 
406*f9950f9aSAdrian Chadd 	return (1);
407*f9950f9aSAdrian Chadd }
408*f9950f9aSAdrian Chadd 
409*f9950f9aSAdrian Chadd /*
4109ab21e32SAdrian Chadd  * Initialise the ar8327 specific hardware features from
4119ab21e32SAdrian Chadd  * the hints provided in the boot environment.
4129ab21e32SAdrian Chadd  */
4139ab21e32SAdrian Chadd static int
4149ab21e32SAdrian Chadd ar8327_init_pdata(struct arswitch_softc *sc)
4159ab21e32SAdrian Chadd {
4169ab21e32SAdrian Chadd 	struct ar8327_pad_cfg pc;
4179ab21e32SAdrian Chadd 	struct ar8327_port_cfg port_cfg;
4189ab21e32SAdrian Chadd 	uint32_t t;
4199ab21e32SAdrian Chadd 
420*f9950f9aSAdrian Chadd 	/* Port 0 */
4219ab21e32SAdrian Chadd 	bzero(&port_cfg, sizeof(port_cfg));
422*f9950f9aSAdrian Chadd 	sc->ar8327.port0_status = 0;
423*f9950f9aSAdrian Chadd 	if (ar8327_fetch_pdata_port(sc, &port_cfg, 0))
4249ab21e32SAdrian Chadd 		sc->ar8327.port0_status = ar8327_get_port_init_status(&port_cfg);
4259ab21e32SAdrian Chadd 
426*f9950f9aSAdrian Chadd 	/* Port 6 */
4279ab21e32SAdrian Chadd 	bzero(&port_cfg, sizeof(port_cfg));
428*f9950f9aSAdrian Chadd 	sc->ar8327.port6_status = 0;
429*f9950f9aSAdrian Chadd 	if (ar8327_fetch_pdata_port(sc, &port_cfg, 6))
4309ab21e32SAdrian Chadd 		sc->ar8327.port6_status = ar8327_get_port_init_status(&port_cfg);
4319ab21e32SAdrian Chadd 
4329ab21e32SAdrian Chadd 	/* Pad 0 */
4339ab21e32SAdrian Chadd 	bzero(&pc, sizeof(pc));
434*f9950f9aSAdrian Chadd 	t = 0;
435*f9950f9aSAdrian Chadd 	if (ar8327_fetch_pdata_pad(sc, &pc, 0))
4369ab21e32SAdrian Chadd 		t = ar8327_get_pad_cfg(&pc);
4379ab21e32SAdrian Chadd #if 0
4389ab21e32SAdrian Chadd 		if (AR8X16_IS_SWITCH(sc, AR8337))
4399ab21e32SAdrian Chadd 			t |= AR8337_PAD_MAC06_EXCHANGE_EN;
4407330dd0bSAdrian Chadd #endif
4419ab21e32SAdrian Chadd 	arswitch_writereg(sc->sc_dev, AR8327_REG_PAD0_MODE, t);
4429ab21e32SAdrian Chadd 
4439ab21e32SAdrian Chadd 	/* Pad 5 */
4449ab21e32SAdrian Chadd 	bzero(&pc, sizeof(pc));
445*f9950f9aSAdrian Chadd 	t = 0;
446*f9950f9aSAdrian Chadd 	if (ar8327_fetch_pdata_pad(sc, &pc, 5))
4479ab21e32SAdrian Chadd 		t = ar8327_get_pad_cfg(&pc);
4489ab21e32SAdrian Chadd 	arswitch_writereg(sc->sc_dev, AR8327_REG_PAD5_MODE, t);
4499ab21e32SAdrian Chadd 
4509ab21e32SAdrian Chadd 	/* Pad 6 */
4519ab21e32SAdrian Chadd 	bzero(&pc, sizeof(pc));
452*f9950f9aSAdrian Chadd 	t = 0;
453*f9950f9aSAdrian Chadd 	if (ar8327_fetch_pdata_pad(sc, &pc, 6))
4549ab21e32SAdrian Chadd 		t = ar8327_get_pad_cfg(&pc);
4559ab21e32SAdrian Chadd 	arswitch_writereg(sc->sc_dev, AR8327_REG_PAD6_MODE, t);
4569ab21e32SAdrian Chadd 
4579ab21e32SAdrian Chadd 	/* XXX LED config */
4589ab21e32SAdrian Chadd 
4599ab21e32SAdrian Chadd 	/* XXX SGMII config */
4609ab21e32SAdrian Chadd 
4619ab21e32SAdrian Chadd 	return (0);
4629ab21e32SAdrian Chadd }
4637330dd0bSAdrian Chadd 
4647330dd0bSAdrian Chadd static int
4657330dd0bSAdrian Chadd ar8327_hw_setup(struct arswitch_softc *sc)
4667330dd0bSAdrian Chadd {
4677330dd0bSAdrian Chadd 	int i;
4687330dd0bSAdrian Chadd 	int err;
4697330dd0bSAdrian Chadd 
4707330dd0bSAdrian Chadd 	/* pdata fetch and setup */
4717330dd0bSAdrian Chadd 	err = ar8327_init_pdata(sc);
4727330dd0bSAdrian Chadd 	if (err != 0)
4737330dd0bSAdrian Chadd 		return (err);
4747330dd0bSAdrian Chadd 
4757330dd0bSAdrian Chadd 	/* XXX init leds */
4767330dd0bSAdrian Chadd 
4777330dd0bSAdrian Chadd 	for (i = 0; i < AR8327_NUM_PHYS; i++) {
4787330dd0bSAdrian Chadd 		/* phy fixup */
4797330dd0bSAdrian Chadd 		ar8327_phy_fixup(sc, i);
4807330dd0bSAdrian Chadd 
4817330dd0bSAdrian Chadd 		/* start PHY autonegotiation? */
4827330dd0bSAdrian Chadd 		/* XXX is this done as part of the normal PHY setup? */
4837330dd0bSAdrian Chadd 
4847330dd0bSAdrian Chadd 	};
4857330dd0bSAdrian Chadd 
4867330dd0bSAdrian Chadd 	/* Let things settle */
4877330dd0bSAdrian Chadd 	DELAY(1000);
4887330dd0bSAdrian Chadd 
4897330dd0bSAdrian Chadd 	return (0);
4907330dd0bSAdrian Chadd }
4917330dd0bSAdrian Chadd 
4927330dd0bSAdrian Chadd /*
4937330dd0bSAdrian Chadd  * Initialise other global values, for the AR8327.
4947330dd0bSAdrian Chadd  */
4957330dd0bSAdrian Chadd static int
4967330dd0bSAdrian Chadd ar8327_hw_global_setup(struct arswitch_softc *sc)
4977330dd0bSAdrian Chadd {
4987330dd0bSAdrian Chadd 	uint32_t t;
4997330dd0bSAdrian Chadd 
5007330dd0bSAdrian Chadd 	/* enable CPU port and disable mirror port */
5017330dd0bSAdrian Chadd 	t = AR8327_FWD_CTRL0_CPU_PORT_EN |
5027330dd0bSAdrian Chadd 	    AR8327_FWD_CTRL0_MIRROR_PORT;
5037330dd0bSAdrian Chadd 	arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL0, t);
5047330dd0bSAdrian Chadd 
5057330dd0bSAdrian Chadd 	/* forward multicast and broadcast frames to CPU */
5067330dd0bSAdrian Chadd 	t = (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_UC_FLOOD_S) |
5077330dd0bSAdrian Chadd 	    (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_MC_FLOOD_S) |
5087330dd0bSAdrian Chadd 	    (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_BC_FLOOD_S);
5097330dd0bSAdrian Chadd 	arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL1, t);
5107330dd0bSAdrian Chadd 
5117330dd0bSAdrian Chadd 	/* enable jumbo frames */
5127330dd0bSAdrian Chadd 	/* XXX need to macro-shift the value! */
5137330dd0bSAdrian Chadd 	arswitch_modifyreg(sc->sc_dev, AR8327_REG_MAX_FRAME_SIZE,
5147330dd0bSAdrian Chadd 	    AR8327_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2);
5157330dd0bSAdrian Chadd 
5167330dd0bSAdrian Chadd 	/* Enable MIB counters */
5177330dd0bSAdrian Chadd 	arswitch_modifyreg(sc->sc_dev, AR8327_REG_MODULE_EN,
5187330dd0bSAdrian Chadd 	    AR8327_MODULE_EN_MIB, AR8327_MODULE_EN_MIB);
5197330dd0bSAdrian Chadd 
5207330dd0bSAdrian Chadd 	return (0);
5217330dd0bSAdrian Chadd }
5227330dd0bSAdrian Chadd 
5237330dd0bSAdrian Chadd /*
5247330dd0bSAdrian Chadd  * Port setup.
5257330dd0bSAdrian Chadd  */
5267330dd0bSAdrian Chadd static void
5277330dd0bSAdrian Chadd ar8327_port_init(struct arswitch_softc *sc, int port)
5287330dd0bSAdrian Chadd {
5297330dd0bSAdrian Chadd 	uint32_t t;
5307330dd0bSAdrian Chadd 
5319ab21e32SAdrian Chadd 	if (port == AR8X16_PORT_CPU)
5329ab21e32SAdrian Chadd 		t = sc->ar8327.port0_status;
5337330dd0bSAdrian Chadd 	else if (port == 6)
5349ab21e32SAdrian Chadd 		t = sc->ar8327.port6_status;
5357330dd0bSAdrian Chadd         else
5369ab21e32SAdrian Chadd #if 0
5377330dd0bSAdrian Chadd 	/* XXX DB120 - hard-code port0 to 1000/full */
5387330dd0bSAdrian Chadd 	if (port == 0) {
5397330dd0bSAdrian Chadd 		t = AR8X16_PORT_STS_SPEED_1000;
5407330dd0bSAdrian Chadd 		t |= AR8X16_PORT_STS_TXMAC | AR8X16_PORT_STS_RXMAC;
5417330dd0bSAdrian Chadd 		t |= AR8X16_PORT_STS_DUPLEX;
5427330dd0bSAdrian Chadd 		t |= AR8X16_PORT_STS_RXFLOW;
5437330dd0bSAdrian Chadd 		t |= AR8X16_PORT_STS_TXFLOW;
5447330dd0bSAdrian Chadd 	} else
5459ab21e32SAdrian Chadd #endif
5467330dd0bSAdrian Chadd 		t = AR8X16_PORT_STS_LINK_AUTO;
5477330dd0bSAdrian Chadd 
5487330dd0bSAdrian Chadd 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_STATUS(port), t);
5497330dd0bSAdrian Chadd 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_HEADER(port), 0);
5507330dd0bSAdrian Chadd 
5517330dd0bSAdrian Chadd 	t = 1 << AR8327_PORT_VLAN0_DEF_SVID_S;
5527330dd0bSAdrian Chadd 	t |= 1 << AR8327_PORT_VLAN0_DEF_CVID_S;
5537330dd0bSAdrian Chadd 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(port), t);
5547330dd0bSAdrian Chadd 
5557330dd0bSAdrian Chadd 	t = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH << AR8327_PORT_VLAN1_OUT_MODE_S;
5567330dd0bSAdrian Chadd 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(port), t);
5577330dd0bSAdrian Chadd 
5587330dd0bSAdrian Chadd 	t = AR8327_PORT_LOOKUP_LEARN;
5597330dd0bSAdrian Chadd 	t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S;
5607330dd0bSAdrian Chadd 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(port), t);
5617330dd0bSAdrian Chadd }
5627330dd0bSAdrian Chadd 
5637330dd0bSAdrian Chadd static int
5647330dd0bSAdrian Chadd ar8327_port_vlan_setup(struct arswitch_softc *sc, etherswitch_port_t *p)
5657330dd0bSAdrian Chadd {
5667330dd0bSAdrian Chadd 
5677330dd0bSAdrian Chadd 	/* XXX stub for now */
5687330dd0bSAdrian Chadd 	device_printf(sc->sc_dev, "%s: called\n", __func__);
5697330dd0bSAdrian Chadd 	return (0);
5707330dd0bSAdrian Chadd }
5717330dd0bSAdrian Chadd 
5727330dd0bSAdrian Chadd static int
5737330dd0bSAdrian Chadd ar8327_port_vlan_get(struct arswitch_softc *sc, etherswitch_port_t *p)
5747330dd0bSAdrian Chadd {
5757330dd0bSAdrian Chadd 
5767330dd0bSAdrian Chadd 	/* XXX stub for now */
5777330dd0bSAdrian Chadd 	device_printf(sc->sc_dev, "%s: called\n", __func__);
5787330dd0bSAdrian Chadd 	return (0);
5797330dd0bSAdrian Chadd }
5807330dd0bSAdrian Chadd 
5817330dd0bSAdrian Chadd static void
5827330dd0bSAdrian Chadd ar8327_reset_vlans(struct arswitch_softc *sc)
5837330dd0bSAdrian Chadd {
5847330dd0bSAdrian Chadd 	int i;
5857330dd0bSAdrian Chadd 	uint32_t mode, t;
5867330dd0bSAdrian Chadd 
5877330dd0bSAdrian Chadd 	/*
5887330dd0bSAdrian Chadd 	 * For now, let's default to one portgroup, just so traffic
5897330dd0bSAdrian Chadd 	 * flows.  All ports can see other ports.
5907330dd0bSAdrian Chadd 	 */
5917330dd0bSAdrian Chadd 	for (i = 0; i < AR8327_NUM_PORTS; i++) {
5927330dd0bSAdrian Chadd 		/* set pvid = i */
5937330dd0bSAdrian Chadd 		t = i << AR8327_PORT_VLAN0_DEF_SVID_S;
5947330dd0bSAdrian Chadd 		t |= i << AR8327_PORT_VLAN0_DEF_CVID_S;
5957330dd0bSAdrian Chadd 		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(i), t);
5967330dd0bSAdrian Chadd 
5977330dd0bSAdrian Chadd 		/* set egress == out_keep */
5987330dd0bSAdrian Chadd 		mode = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH;
5997330dd0bSAdrian Chadd 
6007330dd0bSAdrian Chadd 		t = AR8327_PORT_VLAN1_PORT_VLAN_PROP;
6017330dd0bSAdrian Chadd 		t |= mode << AR8327_PORT_VLAN1_OUT_MODE_S;
6027330dd0bSAdrian Chadd 		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(i), t);
6037330dd0bSAdrian Chadd 
6047330dd0bSAdrian Chadd 		/* Set ingress = out_keep; members = 0x3f for all ports */
6057330dd0bSAdrian Chadd 
6067330dd0bSAdrian Chadd 		t = 0x3f;	/* all ports */
6077330dd0bSAdrian Chadd 		t |= AR8327_PORT_LOOKUP_LEARN;
6087330dd0bSAdrian Chadd 
6097330dd0bSAdrian Chadd 		/* in_port_only, forward */
6107330dd0bSAdrian Chadd 		t |= AR8X16_PORT_VLAN_MODE_PORT_ONLY << AR8327_PORT_LOOKUP_IN_MODE_S;
6117330dd0bSAdrian Chadd 		t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S;
6127330dd0bSAdrian Chadd 		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(i), t);
6137330dd0bSAdrian Chadd 	}
6147330dd0bSAdrian Chadd }
6157330dd0bSAdrian Chadd 
6167330dd0bSAdrian Chadd static int
6177330dd0bSAdrian Chadd ar8327_vlan_getvgroup(struct arswitch_softc *sc, etherswitch_vlangroup_t *vg)
6187330dd0bSAdrian Chadd {
6197330dd0bSAdrian Chadd 	device_printf(sc->sc_dev, "%s: called\n", __func__);
6207330dd0bSAdrian Chadd 	return (0);
6217330dd0bSAdrian Chadd }
6227330dd0bSAdrian Chadd 
6237330dd0bSAdrian Chadd static int
6247330dd0bSAdrian Chadd ar8327_vlan_setvgroup(struct arswitch_softc *sc, etherswitch_vlangroup_t *vg)
6257330dd0bSAdrian Chadd {
6267330dd0bSAdrian Chadd 
6277330dd0bSAdrian Chadd 	device_printf(sc->sc_dev, "%s: called\n", __func__);
6287330dd0bSAdrian Chadd 	return (0);
6297330dd0bSAdrian Chadd }
6307330dd0bSAdrian Chadd 
6317330dd0bSAdrian Chadd static int
6327330dd0bSAdrian Chadd ar8327_get_pvid(struct arswitch_softc *sc, int port, int *pvid)
6337330dd0bSAdrian Chadd {
6347330dd0bSAdrian Chadd 
6357330dd0bSAdrian Chadd 	device_printf(sc->sc_dev, "%s: called\n", __func__);
6367330dd0bSAdrian Chadd 	return (0);
6377330dd0bSAdrian Chadd }
6387330dd0bSAdrian Chadd 
6397330dd0bSAdrian Chadd static int
6407330dd0bSAdrian Chadd ar8327_set_pvid(struct arswitch_softc *sc, int port, int pvid)
6417330dd0bSAdrian Chadd {
6427330dd0bSAdrian Chadd 
6437330dd0bSAdrian Chadd 	device_printf(sc->sc_dev, "%s: called\n", __func__);
6447330dd0bSAdrian Chadd 	return (0);
6457330dd0bSAdrian Chadd }
6467330dd0bSAdrian Chadd 
6477330dd0bSAdrian Chadd void
6487330dd0bSAdrian Chadd ar8327_attach(struct arswitch_softc *sc)
6497330dd0bSAdrian Chadd {
6507330dd0bSAdrian Chadd 
6517330dd0bSAdrian Chadd 	sc->hal.arswitch_hw_setup = ar8327_hw_setup;
6527330dd0bSAdrian Chadd 	sc->hal.arswitch_hw_global_setup = ar8327_hw_global_setup;
6537330dd0bSAdrian Chadd 
6547330dd0bSAdrian Chadd 	sc->hal.arswitch_port_init = ar8327_port_init;
6557330dd0bSAdrian Chadd 	sc->hal.arswitch_port_vlan_setup = ar8327_port_vlan_setup;
6567330dd0bSAdrian Chadd 	sc->hal.arswitch_port_vlan_get = ar8327_port_vlan_get;
6577330dd0bSAdrian Chadd 
6587330dd0bSAdrian Chadd 	sc->hal.arswitch_vlan_init_hw = ar8327_reset_vlans;
6597330dd0bSAdrian Chadd 	sc->hal.arswitch_vlan_getvgroup = ar8327_vlan_getvgroup;
6607330dd0bSAdrian Chadd 	sc->hal.arswitch_vlan_setvgroup = ar8327_vlan_setvgroup;
6617330dd0bSAdrian Chadd 	sc->hal.arswitch_vlan_get_pvid = ar8327_get_pvid;
6627330dd0bSAdrian Chadd 	sc->hal.arswitch_vlan_set_pvid = ar8327_set_pvid;
6637330dd0bSAdrian Chadd 
6647330dd0bSAdrian Chadd 	/* Set the switch vlan capabilities. */
6657330dd0bSAdrian Chadd 	sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q |
6667330dd0bSAdrian Chadd 	    ETHERSWITCH_VLAN_PORT | ETHERSWITCH_VLAN_DOUBLE_TAG;
6677330dd0bSAdrian Chadd 	sc->info.es_nvlangroups = AR8X16_MAX_VLANS;
6687330dd0bSAdrian Chadd }
669