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 /* 220f9950f9aSAdrian Chadd * Fetch the port data for the given port. 221f9950f9aSAdrian Chadd * 222f9950f9aSAdrian Chadd * This goes and does dirty things with the hints space 223f9950f9aSAdrian Chadd * to determine what the configuration parameters should be. 224f9950f9aSAdrian Chadd * 225f9950f9aSAdrian Chadd * Returns 1 if the structure was successfully parsed and 226f9950f9aSAdrian Chadd * the contents are valid; 0 otherwise. 227f9950f9aSAdrian Chadd */ 228f9950f9aSAdrian Chadd static int 229f9950f9aSAdrian Chadd ar8327_fetch_pdata_port(struct arswitch_softc *sc, 230f9950f9aSAdrian Chadd struct ar8327_port_cfg *pcfg, 231f9950f9aSAdrian Chadd int port) 232f9950f9aSAdrian Chadd { 233f9950f9aSAdrian Chadd int val; 234f9950f9aSAdrian Chadd char sbuf[128]; 235f9950f9aSAdrian Chadd 236f9950f9aSAdrian Chadd /* Check if force_link exists */ 237f9950f9aSAdrian Chadd val = 0; 238f9950f9aSAdrian Chadd snprintf(sbuf, 128, "port.%d.force_link", port); 239f9950f9aSAdrian Chadd (void) resource_int_value(device_get_name(sc->sc_dev), 240f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 241f9950f9aSAdrian Chadd sbuf, &val); 242f9950f9aSAdrian Chadd if (val != 1) 243f9950f9aSAdrian Chadd return (0); 244f9950f9aSAdrian Chadd pcfg->force_link = 1; 245f9950f9aSAdrian Chadd 246f9950f9aSAdrian Chadd /* force_link is set; let's parse the rest of the fields */ 247f9950f9aSAdrian Chadd snprintf(sbuf, 128, "port.%d.speed", port); 248f9950f9aSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 249f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 250f9950f9aSAdrian Chadd sbuf, &val) == 0) { 251f9950f9aSAdrian Chadd switch (val) { 252f9950f9aSAdrian Chadd case 10: 253f9950f9aSAdrian Chadd pcfg->speed = AR8327_PORT_SPEED_10; 254f9950f9aSAdrian Chadd break; 255f9950f9aSAdrian Chadd case 100: 256f9950f9aSAdrian Chadd pcfg->speed = AR8327_PORT_SPEED_100; 257f9950f9aSAdrian Chadd break; 258f9950f9aSAdrian Chadd case 1000: 259f9950f9aSAdrian Chadd pcfg->speed = AR8327_PORT_SPEED_1000; 260f9950f9aSAdrian Chadd break; 261f9950f9aSAdrian Chadd default: 262f9950f9aSAdrian Chadd device_printf(sc->sc_dev, 263f9950f9aSAdrian Chadd "%s: invalid port %d duplex value (%d)\n", 264f9950f9aSAdrian Chadd __func__, 265f9950f9aSAdrian Chadd port, 266f9950f9aSAdrian Chadd val); 267f9950f9aSAdrian Chadd return (0); 268f9950f9aSAdrian Chadd } 269f9950f9aSAdrian Chadd } 270f9950f9aSAdrian Chadd 271f9950f9aSAdrian Chadd snprintf(sbuf, 128, "port.%d.duplex", port); 272f9950f9aSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 273f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 274f9950f9aSAdrian Chadd sbuf, &val) == 0) 275f9950f9aSAdrian Chadd pcfg->duplex = val; 276f9950f9aSAdrian Chadd 277f9950f9aSAdrian Chadd snprintf(sbuf, 128, "port.%d.txpause", port); 278f9950f9aSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 279f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 280f9950f9aSAdrian Chadd sbuf, &val) == 0) 281f9950f9aSAdrian Chadd pcfg->txpause = val; 282f9950f9aSAdrian Chadd 283f9950f9aSAdrian Chadd snprintf(sbuf, 128, "port.%d.rxpause", port); 284f9950f9aSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 285f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 286f9950f9aSAdrian Chadd sbuf, &val) == 0) 287f9950f9aSAdrian Chadd pcfg->rxpause = val; 288f9950f9aSAdrian Chadd 289f9950f9aSAdrian Chadd #if 0 290f9950f9aSAdrian Chadd device_printf(sc->sc_dev, 291f9950f9aSAdrian Chadd "%s: port %d: speed=%d, duplex=%d, txpause=%d, rxpause=%d\n", 292f9950f9aSAdrian Chadd __func__, 293f9950f9aSAdrian Chadd port, 294f9950f9aSAdrian Chadd pcfg->speed, 295f9950f9aSAdrian Chadd pcfg->duplex, 296f9950f9aSAdrian Chadd pcfg->txpause, 297f9950f9aSAdrian Chadd pcfg->rxpause); 298f9950f9aSAdrian Chadd #endif 299f9950f9aSAdrian Chadd 300f9950f9aSAdrian Chadd return (1); 301f9950f9aSAdrian Chadd } 302f9950f9aSAdrian Chadd 303f9950f9aSAdrian Chadd /* 304f9950f9aSAdrian Chadd * Parse the pad configuration from the boot hints. 305f9950f9aSAdrian Chadd * 306f9950f9aSAdrian Chadd * The (mostly optional) fields are: 307f9950f9aSAdrian Chadd * 308f9950f9aSAdrian Chadd * uint32_t mode; 309f9950f9aSAdrian Chadd * uint32_t rxclk_sel; 310f9950f9aSAdrian Chadd * uint32_t txclk_sel; 311f9950f9aSAdrian Chadd * uint32_t txclk_delay_sel; 312f9950f9aSAdrian Chadd * uint32_t rxclk_delay_sel; 313f9950f9aSAdrian Chadd * uint32_t txclk_delay_en; 314f9950f9aSAdrian Chadd * uint32_t rxclk_delay_en; 315f9950f9aSAdrian Chadd * uint32_t sgmii_delay_en; 316f9950f9aSAdrian Chadd * uint32_t pipe_rxclk_sel; 317f9950f9aSAdrian Chadd * 318f9950f9aSAdrian Chadd * If mode isn't in the hints, 0 is returned. 319f9950f9aSAdrian Chadd * Else the structure is fleshed out and 1 is returned. 320f9950f9aSAdrian Chadd */ 321f9950f9aSAdrian Chadd static int 322f9950f9aSAdrian Chadd ar8327_fetch_pdata_pad(struct arswitch_softc *sc, 323f9950f9aSAdrian Chadd struct ar8327_pad_cfg *pc, 324f9950f9aSAdrian Chadd int pad) 325f9950f9aSAdrian Chadd { 326f9950f9aSAdrian Chadd int val; 327f9950f9aSAdrian Chadd char sbuf[128]; 328f9950f9aSAdrian Chadd 329f9950f9aSAdrian Chadd /* Check if mode exists */ 330f9950f9aSAdrian Chadd val = 0; 331f9950f9aSAdrian Chadd snprintf(sbuf, 128, "pad.%d.mode", pad); 332f9950f9aSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 333f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 334f9950f9aSAdrian Chadd sbuf, &val) != 0) 335f9950f9aSAdrian Chadd return (0); 336f9950f9aSAdrian Chadd 337f9950f9aSAdrian Chadd /* assume that 'mode' exists and was found */ 338f9950f9aSAdrian Chadd pc->mode = val; 339f9950f9aSAdrian Chadd 340f9950f9aSAdrian Chadd snprintf(sbuf, 128, "pad.%d.rxclk_sel", pad); 341f9950f9aSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 342f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 343f9950f9aSAdrian Chadd sbuf, &val) == 0) 344f9950f9aSAdrian Chadd pc->rxclk_sel = val; 345f9950f9aSAdrian Chadd 346f9950f9aSAdrian Chadd snprintf(sbuf, 128, "pad.%d.txclk_sel", pad); 347f9950f9aSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 348f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 349f9950f9aSAdrian Chadd sbuf, &val) == 0) 350f9950f9aSAdrian Chadd pc->txclk_sel = val; 351f9950f9aSAdrian Chadd 352f9950f9aSAdrian Chadd snprintf(sbuf, 128, "pad.%d.txclk_delay_sel", pad); 353f9950f9aSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 354f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 355f9950f9aSAdrian Chadd sbuf, &val) == 0) 356f9950f9aSAdrian Chadd pc->txclk_delay_sel = val; 357f9950f9aSAdrian Chadd 358f9950f9aSAdrian Chadd snprintf(sbuf, 128, "pad.%d.rxclk_delay_sel", pad); 359f9950f9aSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 360f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 361f9950f9aSAdrian Chadd sbuf, &val) == 0) 362f9950f9aSAdrian Chadd pc->rxclk_delay_sel = val; 363f9950f9aSAdrian Chadd 364f9950f9aSAdrian Chadd snprintf(sbuf, 128, "pad.%d.txclk_delay_en", pad); 365f9950f9aSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 366f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 367f9950f9aSAdrian Chadd sbuf, &val) == 0) 368f9950f9aSAdrian Chadd pc->txclk_delay_en = val; 369f9950f9aSAdrian Chadd 370f9950f9aSAdrian Chadd snprintf(sbuf, 128, "pad.%d.rxclk_delay_en", pad); 371f9950f9aSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 372f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 373f9950f9aSAdrian Chadd sbuf, &val) == 0) 374f9950f9aSAdrian Chadd pc->rxclk_delay_en = val; 375f9950f9aSAdrian Chadd 376f9950f9aSAdrian Chadd snprintf(sbuf, 128, "pad.%d.sgmii_delay_en", pad); 377f9950f9aSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 378f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 379f9950f9aSAdrian Chadd sbuf, &val) == 0) 380f9950f9aSAdrian Chadd pc->sgmii_delay_en = val; 381f9950f9aSAdrian Chadd 382f9950f9aSAdrian Chadd snprintf(sbuf, 128, "pad.%d.pipe_rxclk_sel", pad); 383f9950f9aSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 384f9950f9aSAdrian Chadd device_get_unit(sc->sc_dev), 385f9950f9aSAdrian Chadd sbuf, &val) == 0) 386f9950f9aSAdrian Chadd pc->pipe_rxclk_sel = val; 387f9950f9aSAdrian Chadd 388f9950f9aSAdrian Chadd #if 0 389f9950f9aSAdrian Chadd device_printf(sc->sc_dev, 390f9950f9aSAdrian Chadd "%s: pad %d: mode=%d, rxclk_sel=%d, txclk_sel=%d, " 391f9950f9aSAdrian Chadd "txclk_delay_sel=%d, rxclk_delay_sel=%d, txclk_delay_en=%d, " 392f9950f9aSAdrian Chadd "rxclk_enable_en=%d, sgmii_delay_en=%d, pipe_rxclk_sel=%d\n", 393f9950f9aSAdrian Chadd __func__, 394f9950f9aSAdrian Chadd pad, 395f9950f9aSAdrian Chadd pc->mode, 396f9950f9aSAdrian Chadd pc->rxclk_sel, 397f9950f9aSAdrian Chadd pc->txclk_sel, 398f9950f9aSAdrian Chadd pc->txclk_delay_sel, 399f9950f9aSAdrian Chadd pc->rxclk_delay_sel, 400f9950f9aSAdrian Chadd pc->txclk_delay_en, 401f9950f9aSAdrian Chadd pc->rxclk_delay_en, 402f9950f9aSAdrian Chadd pc->sgmii_delay_en, 403f9950f9aSAdrian Chadd pc->pipe_rxclk_sel); 404f9950f9aSAdrian Chadd #endif 405f9950f9aSAdrian Chadd 406f9950f9aSAdrian Chadd return (1); 407f9950f9aSAdrian Chadd } 408f9950f9aSAdrian Chadd 409f9950f9aSAdrian Chadd /* 410*810bdeddSAdrian Chadd * Fetch the SGMII configuration block from the boot hints. 411*810bdeddSAdrian Chadd */ 412*810bdeddSAdrian Chadd static int 413*810bdeddSAdrian Chadd ar8327_fetch_pdata_sgmii(struct arswitch_softc *sc, 414*810bdeddSAdrian Chadd struct ar8327_sgmii_cfg *scfg) 415*810bdeddSAdrian Chadd { 416*810bdeddSAdrian Chadd int val; 417*810bdeddSAdrian Chadd 418*810bdeddSAdrian Chadd /* sgmii_ctrl */ 419*810bdeddSAdrian Chadd val = 0; 420*810bdeddSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 421*810bdeddSAdrian Chadd device_get_unit(sc->sc_dev), 422*810bdeddSAdrian Chadd "sgmii.ctrl", &val) != 0) 423*810bdeddSAdrian Chadd return (0); 424*810bdeddSAdrian Chadd scfg->sgmii_ctrl = val; 425*810bdeddSAdrian Chadd 426*810bdeddSAdrian Chadd /* serdes_aen */ 427*810bdeddSAdrian Chadd val = 0; 428*810bdeddSAdrian Chadd if (resource_int_value(device_get_name(sc->sc_dev), 429*810bdeddSAdrian Chadd device_get_unit(sc->sc_dev), 430*810bdeddSAdrian Chadd "sgmii.serdes_aen", &val) != 0) 431*810bdeddSAdrian Chadd return (0); 432*810bdeddSAdrian Chadd scfg->serdes_aen = val; 433*810bdeddSAdrian Chadd 434*810bdeddSAdrian Chadd return (1); 435*810bdeddSAdrian Chadd } 436*810bdeddSAdrian Chadd 437*810bdeddSAdrian Chadd /* 4389ab21e32SAdrian Chadd * Initialise the ar8327 specific hardware features from 4399ab21e32SAdrian Chadd * the hints provided in the boot environment. 4409ab21e32SAdrian Chadd */ 4419ab21e32SAdrian Chadd static int 4429ab21e32SAdrian Chadd ar8327_init_pdata(struct arswitch_softc *sc) 4439ab21e32SAdrian Chadd { 4449ab21e32SAdrian Chadd struct ar8327_pad_cfg pc; 4459ab21e32SAdrian Chadd struct ar8327_port_cfg port_cfg; 446*810bdeddSAdrian Chadd struct ar8327_sgmii_cfg scfg; 447*810bdeddSAdrian Chadd uint32_t t, new_pos, pos; 4489ab21e32SAdrian Chadd 449f9950f9aSAdrian Chadd /* Port 0 */ 4509ab21e32SAdrian Chadd bzero(&port_cfg, sizeof(port_cfg)); 451f9950f9aSAdrian Chadd sc->ar8327.port0_status = 0; 452f9950f9aSAdrian Chadd if (ar8327_fetch_pdata_port(sc, &port_cfg, 0)) 4539ab21e32SAdrian Chadd sc->ar8327.port0_status = ar8327_get_port_init_status(&port_cfg); 4549ab21e32SAdrian Chadd 455f9950f9aSAdrian Chadd /* Port 6 */ 4569ab21e32SAdrian Chadd bzero(&port_cfg, sizeof(port_cfg)); 457f9950f9aSAdrian Chadd sc->ar8327.port6_status = 0; 458f9950f9aSAdrian Chadd if (ar8327_fetch_pdata_port(sc, &port_cfg, 6)) 4599ab21e32SAdrian Chadd sc->ar8327.port6_status = ar8327_get_port_init_status(&port_cfg); 4609ab21e32SAdrian Chadd 4619ab21e32SAdrian Chadd /* Pad 0 */ 4629ab21e32SAdrian Chadd bzero(&pc, sizeof(pc)); 463f9950f9aSAdrian Chadd t = 0; 464f9950f9aSAdrian Chadd if (ar8327_fetch_pdata_pad(sc, &pc, 0)) 4659ab21e32SAdrian Chadd t = ar8327_get_pad_cfg(&pc); 4669ab21e32SAdrian Chadd #if 0 4679ab21e32SAdrian Chadd if (AR8X16_IS_SWITCH(sc, AR8337)) 4689ab21e32SAdrian Chadd t |= AR8337_PAD_MAC06_EXCHANGE_EN; 4697330dd0bSAdrian Chadd #endif 4709ab21e32SAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_PAD0_MODE, t); 4719ab21e32SAdrian Chadd 4729ab21e32SAdrian Chadd /* Pad 5 */ 4739ab21e32SAdrian Chadd bzero(&pc, sizeof(pc)); 474f9950f9aSAdrian Chadd t = 0; 475f9950f9aSAdrian Chadd if (ar8327_fetch_pdata_pad(sc, &pc, 5)) 4769ab21e32SAdrian Chadd t = ar8327_get_pad_cfg(&pc); 4779ab21e32SAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_PAD5_MODE, t); 4789ab21e32SAdrian Chadd 4799ab21e32SAdrian Chadd /* Pad 6 */ 4809ab21e32SAdrian Chadd bzero(&pc, sizeof(pc)); 481f9950f9aSAdrian Chadd t = 0; 482f9950f9aSAdrian Chadd if (ar8327_fetch_pdata_pad(sc, &pc, 6)) 4839ab21e32SAdrian Chadd t = ar8327_get_pad_cfg(&pc); 4849ab21e32SAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_PAD6_MODE, t); 4859ab21e32SAdrian Chadd 486*810bdeddSAdrian Chadd pos = arswitch_readreg(sc->sc_dev, AR8327_REG_POWER_ON_STRIP); 487*810bdeddSAdrian Chadd new_pos = pos; 488*810bdeddSAdrian Chadd 4899ab21e32SAdrian Chadd /* XXX LED config */ 4909ab21e32SAdrian Chadd 491*810bdeddSAdrian Chadd /* SGMII config */ 492*810bdeddSAdrian Chadd bzero(&scfg, sizeof(scfg)); 493*810bdeddSAdrian Chadd if (ar8327_fetch_pdata_sgmii(sc, &scfg)) { 494*810bdeddSAdrian Chadd t = scfg.sgmii_ctrl; 495*810bdeddSAdrian Chadd if (sc->chip_rev == 1) 496*810bdeddSAdrian Chadd t |= AR8327_SGMII_CTRL_EN_PLL | 497*810bdeddSAdrian Chadd AR8327_SGMII_CTRL_EN_RX | 498*810bdeddSAdrian Chadd AR8327_SGMII_CTRL_EN_TX; 499*810bdeddSAdrian Chadd else 500*810bdeddSAdrian Chadd t &= ~(AR8327_SGMII_CTRL_EN_PLL | 501*810bdeddSAdrian Chadd AR8327_SGMII_CTRL_EN_RX | 502*810bdeddSAdrian Chadd AR8327_SGMII_CTRL_EN_TX); 503*810bdeddSAdrian Chadd 504*810bdeddSAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_SGMII_CTRL, t); 505*810bdeddSAdrian Chadd 506*810bdeddSAdrian Chadd if (scfg.serdes_aen) 507*810bdeddSAdrian Chadd new_pos &= ~AR8327_POWER_ON_STRIP_SERDES_AEN; 508*810bdeddSAdrian Chadd else 509*810bdeddSAdrian Chadd new_pos |= AR8327_POWER_ON_STRIP_SERDES_AEN; 510*810bdeddSAdrian Chadd } 511*810bdeddSAdrian Chadd 512*810bdeddSAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_POWER_ON_STRIP, new_pos); 5139ab21e32SAdrian Chadd 5149ab21e32SAdrian Chadd return (0); 5159ab21e32SAdrian Chadd } 5167330dd0bSAdrian Chadd 5177330dd0bSAdrian Chadd static int 5187330dd0bSAdrian Chadd ar8327_hw_setup(struct arswitch_softc *sc) 5197330dd0bSAdrian Chadd { 5207330dd0bSAdrian Chadd int i; 5217330dd0bSAdrian Chadd int err; 5227330dd0bSAdrian Chadd 5237330dd0bSAdrian Chadd /* pdata fetch and setup */ 5247330dd0bSAdrian Chadd err = ar8327_init_pdata(sc); 5257330dd0bSAdrian Chadd if (err != 0) 5267330dd0bSAdrian Chadd return (err); 5277330dd0bSAdrian Chadd 5287330dd0bSAdrian Chadd /* XXX init leds */ 5297330dd0bSAdrian Chadd 5307330dd0bSAdrian Chadd for (i = 0; i < AR8327_NUM_PHYS; i++) { 5317330dd0bSAdrian Chadd /* phy fixup */ 5327330dd0bSAdrian Chadd ar8327_phy_fixup(sc, i); 5337330dd0bSAdrian Chadd 5347330dd0bSAdrian Chadd /* start PHY autonegotiation? */ 5357330dd0bSAdrian Chadd /* XXX is this done as part of the normal PHY setup? */ 5367330dd0bSAdrian Chadd 5377330dd0bSAdrian Chadd }; 5387330dd0bSAdrian Chadd 5397330dd0bSAdrian Chadd /* Let things settle */ 5407330dd0bSAdrian Chadd DELAY(1000); 5417330dd0bSAdrian Chadd 5427330dd0bSAdrian Chadd return (0); 5437330dd0bSAdrian Chadd } 5447330dd0bSAdrian Chadd 5457330dd0bSAdrian Chadd /* 5467330dd0bSAdrian Chadd * Initialise other global values, for the AR8327. 5477330dd0bSAdrian Chadd */ 5487330dd0bSAdrian Chadd static int 5497330dd0bSAdrian Chadd ar8327_hw_global_setup(struct arswitch_softc *sc) 5507330dd0bSAdrian Chadd { 5517330dd0bSAdrian Chadd uint32_t t; 5527330dd0bSAdrian Chadd 5537330dd0bSAdrian Chadd /* enable CPU port and disable mirror port */ 5547330dd0bSAdrian Chadd t = AR8327_FWD_CTRL0_CPU_PORT_EN | 5557330dd0bSAdrian Chadd AR8327_FWD_CTRL0_MIRROR_PORT; 5567330dd0bSAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL0, t); 5577330dd0bSAdrian Chadd 5587330dd0bSAdrian Chadd /* forward multicast and broadcast frames to CPU */ 5597330dd0bSAdrian Chadd t = (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_UC_FLOOD_S) | 5607330dd0bSAdrian Chadd (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_MC_FLOOD_S) | 5617330dd0bSAdrian Chadd (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_BC_FLOOD_S); 5627330dd0bSAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL1, t); 5637330dd0bSAdrian Chadd 5647330dd0bSAdrian Chadd /* enable jumbo frames */ 5657330dd0bSAdrian Chadd /* XXX need to macro-shift the value! */ 5667330dd0bSAdrian Chadd arswitch_modifyreg(sc->sc_dev, AR8327_REG_MAX_FRAME_SIZE, 5677330dd0bSAdrian Chadd AR8327_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2); 5687330dd0bSAdrian Chadd 5697330dd0bSAdrian Chadd /* Enable MIB counters */ 5707330dd0bSAdrian Chadd arswitch_modifyreg(sc->sc_dev, AR8327_REG_MODULE_EN, 5717330dd0bSAdrian Chadd AR8327_MODULE_EN_MIB, AR8327_MODULE_EN_MIB); 5727330dd0bSAdrian Chadd 5737330dd0bSAdrian Chadd return (0); 5747330dd0bSAdrian Chadd } 5757330dd0bSAdrian Chadd 5767330dd0bSAdrian Chadd /* 5777330dd0bSAdrian Chadd * Port setup. 5787330dd0bSAdrian Chadd */ 5797330dd0bSAdrian Chadd static void 5807330dd0bSAdrian Chadd ar8327_port_init(struct arswitch_softc *sc, int port) 5817330dd0bSAdrian Chadd { 5827330dd0bSAdrian Chadd uint32_t t; 5837330dd0bSAdrian Chadd 5849ab21e32SAdrian Chadd if (port == AR8X16_PORT_CPU) 5859ab21e32SAdrian Chadd t = sc->ar8327.port0_status; 5867330dd0bSAdrian Chadd else if (port == 6) 5879ab21e32SAdrian Chadd t = sc->ar8327.port6_status; 5887330dd0bSAdrian Chadd else 5899ab21e32SAdrian Chadd #if 0 5907330dd0bSAdrian Chadd /* XXX DB120 - hard-code port0 to 1000/full */ 5917330dd0bSAdrian Chadd if (port == 0) { 5927330dd0bSAdrian Chadd t = AR8X16_PORT_STS_SPEED_1000; 5937330dd0bSAdrian Chadd t |= AR8X16_PORT_STS_TXMAC | AR8X16_PORT_STS_RXMAC; 5947330dd0bSAdrian Chadd t |= AR8X16_PORT_STS_DUPLEX; 5957330dd0bSAdrian Chadd t |= AR8X16_PORT_STS_RXFLOW; 5967330dd0bSAdrian Chadd t |= AR8X16_PORT_STS_TXFLOW; 5977330dd0bSAdrian Chadd } else 5989ab21e32SAdrian Chadd #endif 5997330dd0bSAdrian Chadd t = AR8X16_PORT_STS_LINK_AUTO; 6007330dd0bSAdrian Chadd 6017330dd0bSAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_STATUS(port), t); 6027330dd0bSAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_HEADER(port), 0); 6037330dd0bSAdrian Chadd 6047330dd0bSAdrian Chadd t = 1 << AR8327_PORT_VLAN0_DEF_SVID_S; 6057330dd0bSAdrian Chadd t |= 1 << AR8327_PORT_VLAN0_DEF_CVID_S; 6067330dd0bSAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(port), t); 6077330dd0bSAdrian Chadd 6087330dd0bSAdrian Chadd t = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH << AR8327_PORT_VLAN1_OUT_MODE_S; 6097330dd0bSAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(port), t); 6107330dd0bSAdrian Chadd 6117330dd0bSAdrian Chadd t = AR8327_PORT_LOOKUP_LEARN; 6127330dd0bSAdrian Chadd t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S; 6137330dd0bSAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(port), t); 6147330dd0bSAdrian Chadd } 6157330dd0bSAdrian Chadd 6167330dd0bSAdrian Chadd static int 6177330dd0bSAdrian Chadd ar8327_port_vlan_setup(struct arswitch_softc *sc, etherswitch_port_t *p) 6187330dd0bSAdrian Chadd { 6197330dd0bSAdrian Chadd 6207330dd0bSAdrian Chadd /* XXX stub for now */ 6217330dd0bSAdrian Chadd device_printf(sc->sc_dev, "%s: called\n", __func__); 6227330dd0bSAdrian Chadd return (0); 6237330dd0bSAdrian Chadd } 6247330dd0bSAdrian Chadd 6257330dd0bSAdrian Chadd static int 6267330dd0bSAdrian Chadd ar8327_port_vlan_get(struct arswitch_softc *sc, etherswitch_port_t *p) 6277330dd0bSAdrian Chadd { 6287330dd0bSAdrian Chadd 6297330dd0bSAdrian Chadd /* XXX stub for now */ 6307330dd0bSAdrian Chadd device_printf(sc->sc_dev, "%s: called\n", __func__); 6317330dd0bSAdrian Chadd return (0); 6327330dd0bSAdrian Chadd } 6337330dd0bSAdrian Chadd 6347330dd0bSAdrian Chadd static void 6357330dd0bSAdrian Chadd ar8327_reset_vlans(struct arswitch_softc *sc) 6367330dd0bSAdrian Chadd { 6377330dd0bSAdrian Chadd int i; 6387330dd0bSAdrian Chadd uint32_t mode, t; 6397330dd0bSAdrian Chadd 6407330dd0bSAdrian Chadd /* 6417330dd0bSAdrian Chadd * For now, let's default to one portgroup, just so traffic 6427330dd0bSAdrian Chadd * flows. All ports can see other ports. 6437330dd0bSAdrian Chadd */ 6447330dd0bSAdrian Chadd for (i = 0; i < AR8327_NUM_PORTS; i++) { 6457330dd0bSAdrian Chadd /* set pvid = i */ 6467330dd0bSAdrian Chadd t = i << AR8327_PORT_VLAN0_DEF_SVID_S; 6477330dd0bSAdrian Chadd t |= i << AR8327_PORT_VLAN0_DEF_CVID_S; 6487330dd0bSAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(i), t); 6497330dd0bSAdrian Chadd 6507330dd0bSAdrian Chadd /* set egress == out_keep */ 6517330dd0bSAdrian Chadd mode = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH; 6527330dd0bSAdrian Chadd 6537330dd0bSAdrian Chadd t = AR8327_PORT_VLAN1_PORT_VLAN_PROP; 6547330dd0bSAdrian Chadd t |= mode << AR8327_PORT_VLAN1_OUT_MODE_S; 6557330dd0bSAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(i), t); 6567330dd0bSAdrian Chadd 6577330dd0bSAdrian Chadd /* Set ingress = out_keep; members = 0x3f for all ports */ 6587330dd0bSAdrian Chadd 6597330dd0bSAdrian Chadd t = 0x3f; /* all ports */ 6607330dd0bSAdrian Chadd t |= AR8327_PORT_LOOKUP_LEARN; 6617330dd0bSAdrian Chadd 6627330dd0bSAdrian Chadd /* in_port_only, forward */ 6637330dd0bSAdrian Chadd t |= AR8X16_PORT_VLAN_MODE_PORT_ONLY << AR8327_PORT_LOOKUP_IN_MODE_S; 6647330dd0bSAdrian Chadd t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S; 6657330dd0bSAdrian Chadd arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(i), t); 6667330dd0bSAdrian Chadd } 6677330dd0bSAdrian Chadd } 6687330dd0bSAdrian Chadd 6697330dd0bSAdrian Chadd static int 6707330dd0bSAdrian Chadd ar8327_vlan_getvgroup(struct arswitch_softc *sc, etherswitch_vlangroup_t *vg) 6717330dd0bSAdrian Chadd { 6727330dd0bSAdrian Chadd device_printf(sc->sc_dev, "%s: called\n", __func__); 6737330dd0bSAdrian Chadd return (0); 6747330dd0bSAdrian Chadd } 6757330dd0bSAdrian Chadd 6767330dd0bSAdrian Chadd static int 6777330dd0bSAdrian Chadd ar8327_vlan_setvgroup(struct arswitch_softc *sc, etherswitch_vlangroup_t *vg) 6787330dd0bSAdrian Chadd { 6797330dd0bSAdrian Chadd 6807330dd0bSAdrian Chadd device_printf(sc->sc_dev, "%s: called\n", __func__); 6817330dd0bSAdrian Chadd return (0); 6827330dd0bSAdrian Chadd } 6837330dd0bSAdrian Chadd 6847330dd0bSAdrian Chadd static int 6857330dd0bSAdrian Chadd ar8327_get_pvid(struct arswitch_softc *sc, int port, int *pvid) 6867330dd0bSAdrian Chadd { 6877330dd0bSAdrian Chadd 6887330dd0bSAdrian Chadd device_printf(sc->sc_dev, "%s: called\n", __func__); 6897330dd0bSAdrian Chadd return (0); 6907330dd0bSAdrian Chadd } 6917330dd0bSAdrian Chadd 6927330dd0bSAdrian Chadd static int 6937330dd0bSAdrian Chadd ar8327_set_pvid(struct arswitch_softc *sc, int port, int pvid) 6947330dd0bSAdrian Chadd { 6957330dd0bSAdrian Chadd 6967330dd0bSAdrian Chadd device_printf(sc->sc_dev, "%s: called\n", __func__); 6977330dd0bSAdrian Chadd return (0); 6987330dd0bSAdrian Chadd } 6997330dd0bSAdrian Chadd 7007330dd0bSAdrian Chadd void 7017330dd0bSAdrian Chadd ar8327_attach(struct arswitch_softc *sc) 7027330dd0bSAdrian Chadd { 7037330dd0bSAdrian Chadd 7047330dd0bSAdrian Chadd sc->hal.arswitch_hw_setup = ar8327_hw_setup; 7057330dd0bSAdrian Chadd sc->hal.arswitch_hw_global_setup = ar8327_hw_global_setup; 7067330dd0bSAdrian Chadd 7077330dd0bSAdrian Chadd sc->hal.arswitch_port_init = ar8327_port_init; 7087330dd0bSAdrian Chadd sc->hal.arswitch_port_vlan_setup = ar8327_port_vlan_setup; 7097330dd0bSAdrian Chadd sc->hal.arswitch_port_vlan_get = ar8327_port_vlan_get; 7107330dd0bSAdrian Chadd 7117330dd0bSAdrian Chadd sc->hal.arswitch_vlan_init_hw = ar8327_reset_vlans; 7127330dd0bSAdrian Chadd sc->hal.arswitch_vlan_getvgroup = ar8327_vlan_getvgroup; 7137330dd0bSAdrian Chadd sc->hal.arswitch_vlan_setvgroup = ar8327_vlan_setvgroup; 7147330dd0bSAdrian Chadd sc->hal.arswitch_vlan_get_pvid = ar8327_get_pvid; 7157330dd0bSAdrian Chadd sc->hal.arswitch_vlan_set_pvid = ar8327_set_pvid; 7167330dd0bSAdrian Chadd 7177330dd0bSAdrian Chadd /* Set the switch vlan capabilities. */ 7187330dd0bSAdrian Chadd sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q | 7197330dd0bSAdrian Chadd ETHERSWITCH_VLAN_PORT | ETHERSWITCH_VLAN_DOUBLE_TAG; 7207330dd0bSAdrian Chadd sc->info.es_nvlangroups = AR8X16_MAX_VLANS; 7217330dd0bSAdrian Chadd } 722