Beispiel #1
0
int ag71xx_mdio_mii_read(struct ag71xx_mdio *am, int addr, int reg)
{
	int ret;
	int i;

	ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_WRITE);
	ag71xx_mdio_wr(am, AG71XX_REG_MII_ADDR,
			((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff));
	ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_READ);

	i = AG71XX_MDIO_RETRY;
	while (ag71xx_mdio_rr(am, AG71XX_REG_MII_IND) & MII_IND_BUSY) {
		if (i-- == 0) {
			printk(KERN_ERR "%s: mii_read timed out\n",
				am->mii_bus->name);
			ret = 0xffff;
			goto out;
		}
		udelay(AG71XX_MDIO_DELAY);
	}

	ret = ag71xx_mdio_rr(am, AG71XX_REG_MII_STATUS) & 0xffff;
	ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_WRITE);

	DBG("mii_read: addr=%04x, reg=%04x, value=%04x\n", addr, reg, ret);

out:
	return ret;
}
Beispiel #2
0
int ag71xx_mdio_mii_read(struct ag71xx_mdio *am, int addr, int reg)
{
	int err;
	int ret;

	err = ag71xx_mdio_wait_busy(am);
	if (err)
		return 0xffff;

	ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_WRITE);
	ag71xx_mdio_wr(am, AG71XX_REG_MII_ADDR,
			((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff));
	ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_READ);

	err = ag71xx_mdio_wait_busy(am);
	if (err)
		return 0xffff;

	ret = ag71xx_mdio_rr(am, AG71XX_REG_MII_STATUS) & 0xffff;
	ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_WRITE);

	DBG("mii_read: addr=%04x, reg=%04x, value=%04x\n", addr, reg, ret);

	return ret;
}
Beispiel #3
0
static int ag71xx_mdio_reset(struct mii_bus *bus)
{
	struct ag71xx_mdio *am = bus->priv;
	u32 t;
	int err;

	err = ag71xx_mdio_get_divider(am, &t);
	if (err) {
		/* fallback */
		if (am->pdata->is_ar7240)
			t = MII_CFG_CLK_DIV_6;
		else if (am->pdata->builtin_switch && !am->pdata->is_ar934x)
			t = MII_CFG_CLK_DIV_10;
		else if (!am->pdata->builtin_switch && am->pdata->is_ar934x)
			t = MII_CFG_CLK_DIV_58;
		else
			t = MII_CFG_CLK_DIV_28;
	}

	ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, t | MII_CFG_RESET);
	udelay(100);

	ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, t);
	udelay(100);

	return 0;
}
Beispiel #4
0
void ag71xx_mdio_mii_write(struct ag71xx_mdio *am, int addr, int reg, u16 val)
{
	DBG("mii_write: addr=%04x, reg=%04x, value=%04x\n", addr, reg, val);

	ag71xx_mdio_wr(am, AG71XX_REG_MII_ADDR,
			((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff));
	ag71xx_mdio_wr(am, AG71XX_REG_MII_CTRL, val);

	ag71xx_mdio_wait_busy(am);
}
static int ag71xx_mdio_reset(struct mii_bus *bus)
{
	struct ag71xx_mdio *am = bus->priv;

	ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, MII_CFG_RESET);
	udelay(100);

	ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, MII_CFG_CLK_DIV_28);
	udelay(100);

	return 0;
}
Beispiel #6
0
static int ag71xx_mdio_reset(struct mii_bus *bus)
{
	struct ag71xx_mdio *am = bus->priv;
	u32 t;

	if (am->pdata->is_ar7240)
		t = MII_CFG_CLK_DIV_6;
	else
		t = MII_CFG_CLK_DIV_28;

	ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, t | MII_CFG_RESET);
	udelay(100);

	ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, t);
	udelay(100);

	return 0;
}
Beispiel #7
0
void ag71xx_mdio_mii_write(struct ag71xx_mdio *am, int addr, int reg, u16 val)
{
	int i;

	DBG("mii_write: addr=%04x, reg=%04x, value=%04x\n", addr, reg, val);

	ag71xx_mdio_wr(am, AG71XX_REG_MII_ADDR,
			((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff));
	ag71xx_mdio_wr(am, AG71XX_REG_MII_CTRL, val);

	i = AG71XX_MDIO_RETRY;
	while (ag71xx_mdio_rr(am, AG71XX_REG_MII_IND) & MII_IND_BUSY) {
		if (i-- == 0) {
			pr_err("%s: mii_write timed out\n", am->mii_bus->name);
			break;
		}
		udelay(AG71XX_MDIO_DELAY);
	}
}
Beispiel #8
0
static int __devinit ag71xx_mdio_probe(struct platform_device *pdev)
{
	struct ag71xx_mdio_platform_data *pdata;
	struct ag71xx_mdio *am;
	struct resource *res;
	int i;
	int err;

	pdata = pdev->dev.platform_data;
	if (!pdata) {
		dev_err(&pdev->dev, "no platform data specified\n");
		return -EINVAL;
	}

	am = kzalloc(sizeof(*am), GFP_KERNEL);
	if (!am) {
		err = -ENOMEM;
		goto err_out;
	}

	am->pdata = pdata;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "no iomem resource found\n");
		err = -ENXIO;
		goto err_out;
	}

	am->mdio_base = ioremap_nocache(res->start, res->end - res->start + 1);
	if (!am->mdio_base) {
		dev_err(&pdev->dev, "unable to ioremap registers\n");
		err = -ENOMEM;
		goto err_free_mdio;
	}

	am->mii_bus = mdiobus_alloc();
	if (am->mii_bus == NULL) {
		err = -ENOMEM;
		goto err_iounmap;
	}

	am->mii_bus->name = "ag71xx_mdio";
	am->mii_bus->read = ag71xx_mdio_read;
	am->mii_bus->write = ag71xx_mdio_write;
	am->mii_bus->reset = ag71xx_mdio_reset;
	am->mii_bus->irq = am->mii_irq;
	am->mii_bus->priv = am;
	am->mii_bus->parent = &pdev->dev;
	snprintf(am->mii_bus->id, MII_BUS_ID_SIZE, "%s", dev_name(&pdev->dev));
	am->mii_bus->phy_mask = pdata->phy_mask;

	for (i = 0; i < PHY_MAX_ADDR; i++)
		am->mii_irq[i] = PHY_POLL;

	ag71xx_mdio_wr(am, AG71XX_REG_MAC_CFG1, 0);

	err = mdiobus_register(am->mii_bus);
	if (err)
		goto err_free_bus;

	ag71xx_mdio_dump_regs(am);

	platform_set_drvdata(pdev, am);
	return 0;

err_free_bus:
	mdiobus_free(am->mii_bus);
err_iounmap:
	iounmap(am->mdio_base);
err_free_mdio:
	kfree(am);
err_out:
	return err;
}