/* * Reads a register from the MII Management serial interface via the GMAC registers */ static inline int phy_read_via_mac_unit( int unit, gmac_priv_t *priv, int phyaddr, int phyreg) { unsigned long mask; int data = 0; unsigned long end; u32 addr = (phyaddr << MAC_GMII_ADR_PA_BIT) | (phyreg << MAC_GMII_ADR_GR_BIT) | (priv->gmii_csr_clk_range << MAC_GMII_ADR_CR_BIT) | (1UL << MAC_GMII_ADR_GB_BIT); spin_lock_irqsave(&phy_access_spinlock[priv->unit], mask); unit_mac_reg_write(unit, MAC_GMII_ADR_REG, addr); end = jiffies + MS_TO_JIFFIES(PHY_TRANSFER_TIMEOUT_MS); while (time_before(jiffies, end)) { if (!(unit_mac_reg_read(unit, MAC_GMII_ADR_REG) & (1UL << MAC_GMII_ADR_GB_BIT))) { // Successfully read from PHY data = unit_mac_reg_read(unit, MAC_GMII_DATA_REG) & 0xFFFF; break; } } spin_unlock_irqrestore(&phy_access_spinlock[priv->unit], mask); return data; }
/* * Writes a register to the MII Management serial interface */ void phy_write(struct net_device *dev, int phyaddr, int phyreg, int phydata) { #ifndef ARMULATING gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev); unsigned long end; u32 addr = (phyaddr << MAC_GMII_ADR_PA_BIT) | (phyreg << MAC_GMII_ADR_GR_BIT) | (priv->gmii_csr_clk_range << MAC_GMII_ADR_CR_BIT) | (1UL << MAC_GMII_ADR_GW_BIT) | (1UL << MAC_GMII_ADR_GB_BIT); mac_reg_write(priv, MAC_GMII_DATA_REG, phydata); mac_reg_write(priv, MAC_GMII_ADR_REG, addr); end = jiffies + MS_TO_JIFFIES(PHY_TRANSFER_TIMEOUT_MS); while (time_before(jiffies, end)) { if (!(mac_reg_read(priv, MAC_GMII_ADR_REG) & (1UL << MAC_GMII_ADR_GB_BIT))) { break; } } DBG(1, KERN_INFO "phy_write() %s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", dev->name, phyaddr, phyreg, phydata); #endif // ARMULATING }
int phy_reset(struct net_device *dev) { #ifdef ARMULATING return 0; #else // ARMULATING gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev); int complete = 0; unsigned long end; // Start the reset operation start_phy_reset(priv); // Total time to wait for reset to complete end = jiffies + MS_TO_JIFFIES(PHY_TRANSFER_TIMEOUT_MS); // Should apparently wait at least 50mS before reading back from PHY; this // could just be a nasty feature of the SMC91x MAC/PHY and not apply to us msleep(50); // Read back the status until it indicates reset, or we timeout while (!(complete = is_phy_reset_complete(priv)) && time_before(jiffies, end)) { msleep(1); } return !complete; #endif // ARMULATING }
/* * Reads a register from the MII Management serial interface via the GMAC registers */ static inline int phy_read_via_mac_unit( int unit, gmac_priv_t *priv, int phyaddr, int phyreg) { unsigned long mask; int data = 0; unsigned long end; u32 addr = (phyaddr << MAC_GMII_ADR_PA_BIT) | (phyreg << MAC_GMII_ADR_GR_BIT) | (priv->gmii_csr_clk_range << MAC_GMII_ADR_CR_BIT) | (1UL << MAC_GMII_ADR_GB_BIT); spin_lock_irqsave(&phy_access_spinlock[priv->unit], mask); // Wait for GB bit to be low before writing GMII adr and data regs end = jiffies + MS_TO_JIFFIES(PHY_TRANSFER_TIMEOUT_MS); while (unit_mac_reg_read(unit, MAC_GMII_ADR_REG) & (1UL << MAC_GMII_ADR_GB_BIT)) { if (time_after(jiffies, end)) { printk(KERN_ERR "phy_read_via_mac_unit() Timed out of initial wait for GB bit low\n"); break; } } // Write the GMII address register, with GB low unit_mac_reg_write(unit, MAC_GMII_ADR_REG, addr); wmb(); end = jiffies + MS_TO_JIFFIES(PHY_TRANSFER_TIMEOUT_MS); while (unit_mac_reg_read(unit, MAC_GMII_ADR_REG) & (1UL << MAC_GMII_ADR_GB_BIT)) { if (time_after(jiffies, end)) { printk(KERN_ERR "phy_read_via_mac_unit() Timed out of wait for read to complete\n"); break; } } // Read the data read back from the PHY data = unit_mac_reg_read(unit, MAC_GMII_DATA_REG) & 0xFFFF; spin_unlock_irqrestore(&phy_access_spinlock[priv->unit], mask); return data; }
int phy_reset(struct net_device *dev) { gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev); int complete = 0; unsigned long end; // Start the reset operation start_phy_reset(priv); // Total time to wait for reset to complete end = jiffies + MS_TO_JIFFIES(PHY_TRANSFER_TIMEOUT_MS); // Read back the status until it indicates reset, or we timeout while (!(complete = is_phy_reset_complete(priv)) && time_before(jiffies, end)) { msleep(1); } /* if (complete) { */ /* post_phy_reset_action(dev); */ /* } */ return !complete; }