static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; unsigned int phydata; SMC_SELECT_BANK(lp, 3); smc_mii_out(dev, 0xffffffff, 32); smc_mii_out(dev, 6 << 10 | phyaddr << 5 | phyreg, 14); phydata = smc_mii_in(dev, 18); SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO)); DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", __func__, phyaddr, phyreg, phydata); SMC_SELECT_BANK(lp, 2); return phydata; }
/* * Reads a register from the MII Management serial interface */ static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; unsigned int phydata; SMC_SELECT_BANK(lp, 3); /* Idle - 32 ones */ smc_mii_out(dev, 0xffffffff, 32); /* Start code (01) + read (10) + phyaddr + phyreg */ smc_mii_out(dev, 6 << 10 | phyaddr << 5 | phyreg, 14); /* Turnaround (2bits) + phydata */ phydata = smc_mii_in(dev, 18); /* Return to idle state */ SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO)); DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", __func__, phyaddr, phyreg, phydata); SMC_SELECT_BANK(lp, 2); return phydata; }
static unsigned int smc_mii_in(struct net_device *dev, int bits) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; unsigned int mii_reg, mask, val; mii_reg = SMC_GET_MII(lp) & ~(MII_MCLK | MII_MDOE | MII_MDO); SMC_SET_MII(lp, mii_reg); for (mask = 1 << (bits - 1), val = 0; mask; mask >>= 1) { if (SMC_GET_MII(lp) & MII_MDI) val |= mask; SMC_SET_MII(lp, mii_reg); udelay(MII_DELAY); SMC_SET_MII(lp, mii_reg | MII_MCLK); udelay(MII_DELAY); } return val; }
static void smc_mii_out(struct net_device *dev, unsigned int val, int bits) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; unsigned int mii_reg, mask; mii_reg = SMC_GET_MII(lp) & ~(MII_MCLK | MII_MDOE | MII_MDO); mii_reg |= MII_MDOE; for (mask = 1 << (bits - 1); mask; mask >>= 1) { if (val & mask) mii_reg |= MII_MDO; else mii_reg &= ~MII_MDO; SMC_SET_MII(lp, mii_reg); udelay(MII_DELAY); SMC_SET_MII(lp, mii_reg | MII_MCLK); udelay(MII_DELAY); } }
static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg, int phydata) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; SMC_SELECT_BANK(lp, 3); smc_mii_out(dev, 0xffffffff, 32); smc_mii_out(dev, 5 << 28 | phyaddr << 23 | phyreg << 18 | 2 << 16 | phydata, 32); SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO)); DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", __func__, phyaddr, phyreg, phydata); SMC_SELECT_BANK(lp, 2); }
/* * Writes a register to the MII Management serial interface */ static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg, int phydata) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; SMC_SELECT_BANK(lp, 3); /* Idle - 32 ones */ smc_mii_out(dev, 0xffffffff, 32); /* Start code (01) + write (01) + phyaddr + phyreg + turnaround + phydata */ smc_mii_out(dev, 5 << 28 | phyaddr << 23 | phyreg << 18 | 2 << 16 | phydata, 32); /* Return to idle state */ SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO)); DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", __func__, phyaddr, phyreg, phydata); SMC_SELECT_BANK(lp, 2); }