Example #1
0
/*
 * Initialise other global values for the AR7240.
 */
static int
ar7240_hw_global_setup(struct arswitch_softc *sc)
{

	/* Enable CPU port; disable mirror port */
	arswitch_writereg(sc->sc_dev, AR8X16_REG_CPU_PORT,
	    AR8X16_CPU_PORT_EN | AR8X16_CPU_MIRROR_DIS);

	/* Setup TAG priority mapping */
	arswitch_writereg(sc->sc_dev, AR8X16_REG_TAG_PRIO, 0xfa50);

	/* Enable broadcast frames transmitted to the CPU */
	arswitch_writereg(sc->sc_dev, AR8X16_REG_FLOOD_MASK,
	    AR8X16_FLOOD_MASK_BCAST_TO_CPU | 0x003f003f);

	/* Setup MTU */
	arswitch_modifyreg(sc->sc_dev, AR8X16_REG_GLOBAL_CTRL,
	    AR7240_GLOBAL_CTRL_MTU_MASK,
	    SM(1536, AR7240_GLOBAL_CTRL_MTU_MASK));

	/* Service Tag */
	arswitch_modifyreg(sc->sc_dev, AR8X16_REG_SERVICE_TAG,
	    AR8X16_SERVICE_TAG_MASK, 0);

	return (0);
}
Example #2
0
/*
 * Initialise other global values, for the AR8316.
 */
static int
ar8316_hw_global_setup(struct arswitch_softc *sc)
{

	arswitch_writereg(sc->sc_dev, 0x38, AR8X16_MAGIC);

	/* Enable CPU port and disable mirror port. */
	arswitch_writereg(sc->sc_dev, AR8X16_REG_CPU_PORT,
	    AR8X16_CPU_PORT_EN | AR8X16_CPU_MIRROR_DIS);

	/* Setup TAG priority mapping. */
	arswitch_writereg(sc->sc_dev, AR8X16_REG_TAG_PRIO, 0xfa50);

	/* Enable ARP frame acknowledge. */
	arswitch_modifyreg(sc->sc_dev, AR8X16_REG_AT_CTRL, 0,
	    AR8X16_AT_CTRL_ARP_EN);

	/*
	 * Flood address table misses to all ports, and enable forwarding of
	 * broadcasts to the cpu port.
	 */
	arswitch_writereg(sc->sc_dev, AR8X16_REG_FLOOD_MASK,
	    AR8X16_FLOOD_MASK_BCAST_TO_CPU | 0x003f003f);

	/* Enable jumbo frames. */
	arswitch_modifyreg(sc->sc_dev, AR8X16_REG_GLOBAL_CTRL,
	    AR8316_GLOBAL_CTRL_MTU_MASK, 9018 + 8 + 2);

	/* Setup service TAG. */
	arswitch_modifyreg(sc->sc_dev, AR8X16_REG_SERVICE_TAG,
	    AR8X16_SERVICE_TAG_MASK, 0);

	return (0);
}
Example #3
0
static void
ar8327_reset_vlans(struct arswitch_softc *sc)
{
	int i;
	uint32_t mode, t;

	/*
	 * For now, let's default to one portgroup, just so traffic
	 * flows.  All ports can see other ports.
	 */
	for (i = 0; i < AR8327_NUM_PORTS; i++) {
		/* set pvid = i */
		t = i << AR8327_PORT_VLAN0_DEF_SVID_S;
		t |= i << AR8327_PORT_VLAN0_DEF_CVID_S;
		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(i), t);

		/* set egress == out_keep */
		mode = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH;

		t = AR8327_PORT_VLAN1_PORT_VLAN_PROP;
		t |= mode << AR8327_PORT_VLAN1_OUT_MODE_S;
		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(i), t);

		/* Set ingress = out_keep; members = 0x3f for all ports */

		t = 0x3f;	/* all ports */
		t |= AR8327_PORT_LOOKUP_LEARN;

		/* in_port_only, forward */
		t |= AR8X16_PORT_VLAN_MODE_PORT_ONLY << AR8327_PORT_LOOKUP_IN_MODE_S;
		t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S;
		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(i), t);
	}
}
Example #4
0
/*
 * Initialise other global values, for the AR8327.
 */
static int
ar8327_hw_global_setup(struct arswitch_softc *sc)
{
	uint32_t t;

	/* enable CPU port and disable mirror port */
	t = AR8327_FWD_CTRL0_CPU_PORT_EN |
	    AR8327_FWD_CTRL0_MIRROR_PORT;
	arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL0, t);

	/* forward multicast and broadcast frames to CPU */
	t = (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_UC_FLOOD_S) |
	    (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_MC_FLOOD_S) |
	    (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_BC_FLOOD_S);
	arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL1, t);

	/* enable jumbo frames */
	/* XXX need to macro-shift the value! */
	arswitch_modifyreg(sc->sc_dev, AR8327_REG_MAX_FRAME_SIZE,
	    AR8327_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2);

	/* Enable MIB counters */
	arswitch_modifyreg(sc->sc_dev, AR8327_REG_MODULE_EN,
	    AR8327_MODULE_EN_MIB, AR8327_MODULE_EN_MIB);

	return (0);
}
Example #5
0
static void
ar8327_reset_vlans(struct arswitch_softc *sc)
{
	int i;
	uint32_t mode, t;

	/*
	 * Disable mirroring.
	 */
	arswitch_modifyreg(sc->sc_dev, AR8327_REG_FWD_CTRL0,
	    AR8327_FWD_CTRL0_MIRROR_PORT,
	    (0xF << AR8327_FWD_CTRL0_MIRROR_PORT_S));

	/*
	 * For now, let's default to one portgroup, just so traffic
	 * flows.  All ports can see other ports.
	 */
	for (i = 0; i < AR8327_NUM_PORTS; i++) {
		/* set pvid = i */
		t = i << AR8327_PORT_VLAN0_DEF_SVID_S;
		t |= i << AR8327_PORT_VLAN0_DEF_CVID_S;
		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(i), t);

		/* set egress == out_keep */
		mode = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH;

		t = AR8327_PORT_VLAN1_PORT_VLAN_PROP;
		t |= mode << AR8327_PORT_VLAN1_OUT_MODE_S;
		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(i), t);

		/* Set ingress = out_keep; members = 0x3f for all ports */

		t = (0x3f & ~(1 << i));	/* all ports besides us */
		t |= AR8327_PORT_LOOKUP_LEARN;

		/* in_port_only, forward */
		t |= AR8X16_PORT_VLAN_MODE_PORT_ONLY << AR8327_PORT_LOOKUP_IN_MODE_S;
		t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S;
		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(i), t);

		/*
		 * Disable port mirroring entirely.
		 */
		arswitch_modifyreg(sc->sc_dev,
		    AR8327_REG_PORT_LOOKUP(i),
		    AR8327_PORT_LOOKUP_ING_MIRROR_EN,
		    0);
		arswitch_modifyreg(sc->sc_dev,
		    AR8327_REG_PORT_HOL_CTRL1(i),
		    AR8327_PORT_HOL_CTRL1_EG_MIRROR_EN,
		    0);
	}
}
Example #6
0
/*
 * AR8316 specific functions
 */
static int
ar8316_hw_setup(struct arswitch_softc *sc)
{

	/*
	 * Configure the switch mode based on whether:
	 *
	 * + The switch port is GMII/RGMII;
	 * + Port 4 is either connected to the CPU or to the internal switch.
	 */
	if (sc->is_rgmii && sc->phy4cpu) {
		arswitch_writereg(sc->sc_dev, AR8X16_REG_MODE,
		    AR8X16_MODE_RGMII_PORT4_ISO);
		device_printf(sc->sc_dev,
		    "%s: MAC port == RGMII, port 4 = dedicated PHY\n",
		    __func__);
	} else if (sc->is_rgmii) {
		arswitch_writereg(sc->sc_dev, AR8X16_REG_MODE,
		    AR8X16_MODE_RGMII_PORT4_SWITCH);
		device_printf(sc->sc_dev,
		    "%s: MAC port == RGMII, port 4 = switch port\n",
		    __func__);
	} else if (sc->is_gmii) {
		arswitch_writereg(sc->sc_dev, AR8X16_REG_MODE,
		    AR8X16_MODE_GMII);
		device_printf(sc->sc_dev, "%s: MAC port == GMII\n", __func__);
	} else {
		device_printf(sc->sc_dev, "%s: unknown switch PHY config\n",
		    __func__);
		return (ENXIO);
	}

	DELAY(1000);	/* 1ms wait for things to settle */

	/*
	 * If port 4 is RGMII, force workaround
	 */
	if (sc->is_rgmii && sc->phy4cpu) {
		device_printf(sc->sc_dev,
		    "%s: port 4 RGMII workaround\n",
		    __func__);

		/* work around for phy4 rgmii mode */
		arswitch_writedbg(sc->sc_dev, 4, 0x12, 0x480c);
		/* rx delay */
		arswitch_writedbg(sc->sc_dev, 4, 0x0, 0x824e);
		/* tx delay */
		arswitch_writedbg(sc->sc_dev, 4, 0x5, 0x3d47);
		DELAY(1000);	/* 1ms, again to let things settle */
	}

	return (0);
}
Example #7
0
int
arswitch_writephy(device_t dev, int phy, int reg, int data)
{
	struct arswitch_softc *sc;
	uint32_t ctrl;
	int err, timeout;

	sc = device_get_softc(dev);
	ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);

	if (reg < 0 || reg >= 32)
		return (ENXIO);

	ARSWITCH_LOCK(sc);
	err = arswitch_writereg(dev, AR8X16_REG_MDIO_CTRL,
	    AR8X16_MDIO_CTRL_BUSY |
	    AR8X16_MDIO_CTRL_MASTER_EN |
	    AR8X16_MDIO_CTRL_CMD_WRITE |
	    (phy << AR8X16_MDIO_CTRL_PHY_ADDR_SHIFT) |
	    (reg << AR8X16_MDIO_CTRL_REG_ADDR_SHIFT) |
	    (data & AR8X16_MDIO_CTRL_DATA_MASK));
	if (err != 0)
		goto out;
	for (timeout = 100; timeout--; ) {
		ctrl = arswitch_readreg(dev, AR8X16_REG_MDIO_CTRL);
		if ((ctrl & AR8X16_MDIO_CTRL_BUSY) == 0)
			break;
	}
	if (timeout < 0)
		err = EIO;
out:
	DEVERR(dev, err, "arswitch_writephy()=%d: phy=%d.%02x\n", phy, reg);
	ARSWITCH_UNLOCK(sc);
	return (err);
}
Example #8
0
/*
 * Initialise other global values, for the AR8316.
 */
static int
ar8316_hw_global_setup(struct arswitch_softc *sc)
{

	arswitch_writereg(sc->sc_dev, 0x38, 0xc000050e);

	/*
	 * Flood address table misses to all ports, and enable forwarding of
	 * broadcasts to the cpu port.
	 */
	arswitch_writereg(sc->sc_dev, AR8X16_REG_FLOOD_MASK,
	    AR8X16_FLOOD_MASK_BCAST_TO_CPU | 0x003f003f);

	arswitch_modifyreg(sc->sc_dev, AR8X16_REG_GLOBAL_CTRL,
	    AR8316_GLOBAL_CTRL_MTU_MASK, 9018 + 8 + 2);

	return (0);
}
Example #9
0
/*
 * Port setup.  Called at attach time.
 */
static void
ar8327_port_init(struct arswitch_softc *sc, int port)
{
	uint32_t t;
	int ports;

	/* For now, port can see all other ports */
	ports = 0x7f;

	if (port == AR8X16_PORT_CPU)
		t = sc->ar8327.port0_status;
	else if (port == 6)
		t = sc->ar8327.port6_status;
        else
		t = AR8X16_PORT_STS_LINK_AUTO;

	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_STATUS(port), t);
	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_HEADER(port), 0);

	/*
	 * Default to 1 port group.
	 */
	t = 1 << AR8327_PORT_VLAN0_DEF_SVID_S;
	t |= 1 << AR8327_PORT_VLAN0_DEF_CVID_S;
	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(port), t);

	t = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH << AR8327_PORT_VLAN1_OUT_MODE_S;
	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(port), t);

	/*
	 * This doesn't configure any ports which this port can "see".
	 * bits 0-6 control which ports a frame coming into this port
	 * can be sent out to.
	 *
	 * So by doing this, we're making it impossible to send frames out
	 * to that port.
	 */
	t = AR8327_PORT_LOOKUP_LEARN;
	t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S;

	/* So this allows traffic to any port except ourselves */
	t |= (ports & ~(1 << port));
	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(port), t);
}
Example #10
0
static int
ar8327_vlan_op(struct arswitch_softc *sc, uint32_t op, uint32_t vid,
    uint32_t data)
{
	int err;

	/*
	 * Wait for the "done" bit to finish.
	 */
	if (arswitch_waitreg(sc->sc_dev, AR8327_REG_VTU_FUNC1,
	    AR8327_VTU_FUNC1_BUSY, 0, 5))
		return (EBUSY);

	/*
	 * If it's a "load" operation, then ensure 'data' is loaded
	 * in first.
	 */
	if ((op & AR8327_VTU_FUNC1_OP) == AR8327_VTU_FUNC1_OP_LOAD) {
		err = arswitch_writereg(sc->sc_dev, AR8327_REG_VTU_FUNC0, data);
		if (err)
			return (err);
	}

	/*
	 * Set the VID.
	 */
	op |= ((vid & 0xfff) << AR8327_VTU_FUNC1_VID_S);

	/*
	 * Set busy bit to start loading in the command.
	 */
	op |= AR8327_VTU_FUNC1_BUSY;
	arswitch_writereg(sc->sc_dev, AR8327_REG_VTU_FUNC1, op);

	/*
	 * Finally - wait for it to load.
	 */
	if (arswitch_waitreg(sc->sc_dev, AR8327_REG_VTU_FUNC1,
	    AR8327_VTU_FUNC1_BUSY, 0, 5))
		return (EBUSY);

	return (0);
}
Example #11
0
/*
 * Initialise other global values, for the AR8327.
 */
static int
ar8327_hw_global_setup(struct arswitch_softc *sc)
{
	uint32_t t;

	/* enable CPU port and disable mirror port */
	t = AR8327_FWD_CTRL0_CPU_PORT_EN |
	    AR8327_FWD_CTRL0_MIRROR_PORT;
	arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL0, t);

	/* forward multicast and broadcast frames to CPU */
	t = (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_UC_FLOOD_S) |
	    (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_MC_FLOOD_S) |
	    (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_BC_FLOOD_S);
	arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL1, t);

	/* enable jumbo frames */
	/* XXX need to macro-shift the value! */
	arswitch_modifyreg(sc->sc_dev, AR8327_REG_MAX_FRAME_SIZE,
	    AR8327_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2);

	/* Enable MIB counters */
	arswitch_modifyreg(sc->sc_dev, AR8327_REG_MODULE_EN,
	    AR8327_MODULE_EN_MIB, AR8327_MODULE_EN_MIB);

	/* Disable EEE on all ports due to stability issues */
	t = arswitch_readreg(sc->sc_dev, AR8327_REG_EEE_CTRL);
	t |= AR8327_EEE_CTRL_DISABLE_PHY(0) |
	    AR8327_EEE_CTRL_DISABLE_PHY(1) |
	    AR8327_EEE_CTRL_DISABLE_PHY(2) |
	    AR8327_EEE_CTRL_DISABLE_PHY(3) |
	    AR8327_EEE_CTRL_DISABLE_PHY(4);
	arswitch_writereg(sc->sc_dev, AR8327_REG_EEE_CTRL, t);

	/* Set the right number of ports */
	/* GMAC0 (CPU), GMAC1..5 (PHYs), GMAC6 (CPU) */
	sc->info.es_nports = 7;

	return (0);
}
Example #12
0
static int
ar8327_set_pvid(struct arswitch_softc *sc, int port, int pvid)
{
	uint32_t t;

	/* Limit pvid to valid values */
	pvid &= 0x7f;

	t = pvid << AR8327_PORT_VLAN0_DEF_SVID_S;
	t |= pvid << AR8327_PORT_VLAN0_DEF_CVID_S;
	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(port), t);

	return (0);
}
Example #13
0
/*
 * Port setup.
 */
static void
ar8327_port_init(struct arswitch_softc *sc, int port)
{
	uint32_t t;

	if (port == AR8X16_PORT_CPU)
		t = sc->ar8327.port0_status;
	else if (port == 6)
		t = sc->ar8327.port6_status;
        else
#if 0
	/* XXX DB120 - hard-code port0 to 1000/full */
	if (port == 0) {
		t = AR8X16_PORT_STS_SPEED_1000;
		t |= AR8X16_PORT_STS_TXMAC | AR8X16_PORT_STS_RXMAC;
		t |= AR8X16_PORT_STS_DUPLEX;
		t |= AR8X16_PORT_STS_RXFLOW;
		t |= AR8X16_PORT_STS_TXFLOW;
	} else
#endif
		t = AR8X16_PORT_STS_LINK_AUTO;

	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_STATUS(port), t);
	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_HEADER(port), 0);

	t = 1 << AR8327_PORT_VLAN0_DEF_SVID_S;
	t |= 1 << AR8327_PORT_VLAN0_DEF_CVID_S;
	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(port), t);

	t = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH << AR8327_PORT_VLAN1_OUT_MODE_S;
	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(port), t);

	t = AR8327_PORT_LOOKUP_LEARN;
	t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S;
	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(port), t);
}
Example #14
0
int
arswitch_writephy_internal(device_t dev, int phy, int reg, int data)
{
	struct arswitch_softc *sc;
	uint32_t ctrl;
	int err, timeout;
	uint32_t a;

	sc = device_get_softc(dev);
	ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);

	if (reg < 0 || reg >= 32)
		return (ENXIO);

	if (AR8X16_IS_SWITCH(sc, AR8327))
		a = AR8327_REG_MDIO_CTRL;
	else
		a = AR8X16_REG_MDIO_CTRL;

	ARSWITCH_LOCK(sc);
	err = arswitch_writereg(dev, a,
	    AR8X16_MDIO_CTRL_BUSY |
	    AR8X16_MDIO_CTRL_MASTER_EN |
	    AR8X16_MDIO_CTRL_CMD_WRITE |
	    (phy << AR8X16_MDIO_CTRL_PHY_ADDR_SHIFT) |
	    (reg << AR8X16_MDIO_CTRL_REG_ADDR_SHIFT) |
	    (data & AR8X16_MDIO_CTRL_DATA_MASK));
	if (err != 0)
		goto out;
	for (timeout = 100; timeout--; ) {
		ctrl = arswitch_readreg(dev, a);
		if ((ctrl & AR8X16_MDIO_CTRL_BUSY) == 0)
			break;
	}
	if (timeout < 0)
		err = EIO;

	DPRINTF(sc, ARSWITCH_DBG_PHYIO,
	    "%s: phy=0x%08x, reg=0x%08x, data=0x%08x, err=%d\n",
	    __func__, phy, reg, data, err);

out:
	DEVERR(dev, err, "arswitch_writephy()=%d: phy=%d.%02x\n", phy, reg);
	ARSWITCH_UNLOCK(sc);
	return (err);
}
Example #15
0
static int
ar8327_atu_flush(struct arswitch_softc *sc)
{

	int ret;

	ret = arswitch_waitreg(sc->sc_dev,
	    AR8327_REG_ATU_FUNC,
	    AR8327_ATU_FUNC_BUSY,
	    0,
	    1000);

	if (ret)
		device_printf(sc->sc_dev, "%s: waitreg failed\n", __func__);

	if (!ret)
		arswitch_writereg(sc->sc_dev,
		    AR8327_REG_ATU_FUNC,
		    AR8327_ATU_FUNC_OP_FLUSH);
	return (ret);
}
Example #16
0
static void
ar8327_reset_vlans(struct arswitch_softc *sc)
{
	int i;
	uint32_t t;
	int ports;

	ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
	ARSWITCH_LOCK(sc);

	/* Clear the existing VLAN configuration */
	memset(sc->vid, 0, sizeof(sc->vid));

	/*
	 * Disable mirroring.
	 */
	arswitch_modifyreg(sc->sc_dev, AR8327_REG_FWD_CTRL0,
	    AR8327_FWD_CTRL0_MIRROR_PORT,
	    (0xF << AR8327_FWD_CTRL0_MIRROR_PORT_S));

	/*
	 * XXX TODO: disable any Q-in-Q port configuration,
	 * tagging, egress filters, etc.
	 */

	/*
	 * For now, let's default to one portgroup, just so traffic
	 * flows.  All ports can see other ports. There are two CPU GMACs
	 * (GMAC0, GMAC6), GMAC1..GMAC5 are external PHYs.
	 *
	 * (ETHERSWITCH_VLAN_PORT)
	 */
	ports = 0x7f;

	/*
	 * XXX TODO: set things up correctly for vlans!
	 */
	for (i = 0; i < AR8327_NUM_PORTS; i++) {
		int egress, ingress;

		if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) {
			sc->vid[i] = i | ETHERSWITCH_VID_VALID;
			/* set egress == out_keep */
			ingress = AR8X16_PORT_VLAN_MODE_PORT_ONLY;
			/* in_port_only, forward */
			egress = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH;
		} else if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
			ingress = AR8X16_PORT_VLAN_MODE_SECURE;
			egress = AR8327_PORT_VLAN1_OUT_MODE_UNMOD;
		} else {
			/* set egress == out_keep */
			ingress = AR8X16_PORT_VLAN_MODE_PORT_ONLY;
			/* in_port_only, forward */
			egress = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH;
		}

		/* set pvid = 1; there's only one vlangroup to start with */
		t = 1 << AR8327_PORT_VLAN0_DEF_SVID_S;
		t |= 1 << AR8327_PORT_VLAN0_DEF_CVID_S;
		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(i), t);

		t = AR8327_PORT_VLAN1_PORT_VLAN_PROP;
		t |= egress << AR8327_PORT_VLAN1_OUT_MODE_S;
		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(i), t);

		/* Ports can see other ports */
		/* XXX not entirely true for dot1q? */
		t = (ports & ~(1 << i));	/* all ports besides us */
		t |= AR8327_PORT_LOOKUP_LEARN;

		t |= ingress << AR8327_PORT_LOOKUP_IN_MODE_S;
		t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S;
		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(i), t);
	}

	/*
	 * Disable port mirroring entirely.
	 */
	for (i = 0; i < AR8327_NUM_PORTS; i++) {
		ar8327_port_disable_mirror(sc, i);
	}

	/*
	 * If dot1q - set pvid; dot1q, etc.
	 */
	if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
		sc->vid[0] = 1;
		for (i = 0; i < AR8327_NUM_PORTS; i++) {
			/* Each port - pvid 1 */
			sc->hal.arswitch_vlan_set_pvid(sc, i, sc->vid[0]);
		}
		/* Initialise vlan1 - all ports, untagged */
		sc->hal.arswitch_set_dot1q_vlan(sc, ports, ports, sc->vid[0]);
		sc->vid[0] |= ETHERSWITCH_VID_VALID;
	}

	ARSWITCH_UNLOCK(sc);
}
Example #17
0
/*
 * Initialise the ar8327 specific hardware features from
 * the hints provided in the boot environment.
 */
static int
ar8327_init_pdata(struct arswitch_softc *sc)
{
	struct ar8327_pad_cfg pc;
	struct ar8327_port_cfg port_cfg;
	struct ar8327_sgmii_cfg scfg;
	struct ar8327_led_cfg lcfg;
	uint32_t t, new_pos, pos;

	/* Port 0 */
	bzero(&port_cfg, sizeof(port_cfg));
	sc->ar8327.port0_status = 0;
	if (ar8327_fetch_pdata_port(sc, &port_cfg, 0))
		sc->ar8327.port0_status = ar8327_get_port_init_status(&port_cfg);

	/* Port 6 */
	bzero(&port_cfg, sizeof(port_cfg));
	sc->ar8327.port6_status = 0;
	if (ar8327_fetch_pdata_port(sc, &port_cfg, 6))
		sc->ar8327.port6_status = ar8327_get_port_init_status(&port_cfg);

	/* Pad 0 */
	bzero(&pc, sizeof(pc));
	t = 0;
	if (ar8327_fetch_pdata_pad(sc, &pc, 0))
		t = ar8327_get_pad_cfg(&pc);
#if 0
		if (AR8X16_IS_SWITCH(sc, AR8337))
			t |= AR8337_PAD_MAC06_EXCHANGE_EN;
#endif
	arswitch_writereg(sc->sc_dev, AR8327_REG_PAD0_MODE, t);

	/* Pad 5 */
	bzero(&pc, sizeof(pc));
	t = 0;
	if (ar8327_fetch_pdata_pad(sc, &pc, 5))
		t = ar8327_get_pad_cfg(&pc);
	arswitch_writereg(sc->sc_dev, AR8327_REG_PAD5_MODE, t);

	/* Pad 6 */
	bzero(&pc, sizeof(pc));
	t = 0;
	if (ar8327_fetch_pdata_pad(sc, &pc, 6))
		t = ar8327_get_pad_cfg(&pc);
	arswitch_writereg(sc->sc_dev, AR8327_REG_PAD6_MODE, t);

	pos = arswitch_readreg(sc->sc_dev, AR8327_REG_POWER_ON_STRIP);
	new_pos = pos;

	/* XXX LED config */
	bzero(&lcfg, sizeof(lcfg));
	if (ar8327_fetch_pdata_led(sc, &lcfg)) {
		if (lcfg.open_drain)
			new_pos |= AR8327_POWER_ON_STRIP_LED_OPEN_EN;
		else
			new_pos &= ~AR8327_POWER_ON_STRIP_LED_OPEN_EN;

		arswitch_writereg(sc->sc_dev, AR8327_REG_LED_CTRL0,
		    lcfg.led_ctrl0);
		arswitch_writereg(sc->sc_dev, AR8327_REG_LED_CTRL1,
		    lcfg.led_ctrl1);
		arswitch_writereg(sc->sc_dev, AR8327_REG_LED_CTRL2,
		    lcfg.led_ctrl2);
		arswitch_writereg(sc->sc_dev, AR8327_REG_LED_CTRL3,
		    lcfg.led_ctrl3);

		if (new_pos != pos)
			new_pos |= AR8327_POWER_ON_STRIP_POWER_ON_SEL;
	}

	/* SGMII config */
	bzero(&scfg, sizeof(scfg));
	if (ar8327_fetch_pdata_sgmii(sc, &scfg)) {
		t = scfg.sgmii_ctrl;
		if (sc->chip_rev == 1)
			t |= AR8327_SGMII_CTRL_EN_PLL |
			    AR8327_SGMII_CTRL_EN_RX |
			    AR8327_SGMII_CTRL_EN_TX;
		else
			t &= ~(AR8327_SGMII_CTRL_EN_PLL |
			    AR8327_SGMII_CTRL_EN_RX |
			    AR8327_SGMII_CTRL_EN_TX);

		arswitch_writereg(sc->sc_dev, AR8327_REG_SGMII_CTRL, t);

		if (scfg.serdes_aen)
			new_pos &= ~AR8327_POWER_ON_STRIP_SERDES_AEN;
		else
			new_pos |= AR8327_POWER_ON_STRIP_SERDES_AEN;
	}

	arswitch_writereg(sc->sc_dev, AR8327_REG_POWER_ON_STRIP, new_pos);

	return (0);
}