示例#1
0
/*
 * Access PHYs integrated into the switch chip through the switch's MDIO
 * control register.
 */
int
arswitch_readphy_internal(device_t dev, int phy, int reg)
{
	struct arswitch_softc *sc;
	uint32_t data = 0, ctrl;
	int err, timeout;
	uint32_t a;

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

	if (phy < 0 || phy >= 32)
		return (ENXIO);
	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_msb(dev, a,
	    AR8X16_MDIO_CTRL_BUSY | AR8X16_MDIO_CTRL_MASTER_EN |
	    AR8X16_MDIO_CTRL_CMD_READ |
	    (phy << AR8X16_MDIO_CTRL_PHY_ADDR_SHIFT) |
	    (reg << AR8X16_MDIO_CTRL_REG_ADDR_SHIFT));
	DEVERR(dev, err, "arswitch_readphy()=%d: phy=%d.%02x\n", phy, reg);
	if (err != 0)
		goto fail;
	for (timeout = 100; timeout--; ) {
		ctrl = arswitch_readreg_msb(dev, a);
		if ((ctrl & AR8X16_MDIO_CTRL_BUSY) == 0)
			break;
	}
	if (timeout < 0) {
		DPRINTF(sc, ARSWITCH_DBG_ANY,
		    "arswitch_readphy(): phy=%d.%02x; timeout=%d\n",
		    phy, reg, timeout);
		goto fail;
	}
	data = arswitch_readreg_lsb(dev, a) &
	    AR8X16_MDIO_CTRL_DATA_MASK;
	ARSWITCH_UNLOCK(sc);

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

	return (data);

fail:
	ARSWITCH_UNLOCK(sc);

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

	return (-1);
}
示例#2
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);
}
示例#3
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);
}