void emac_reg_update32(struct emac_hw *hw, u8 base, u32 reg, u32 mask, u32 val) { u32 data; data = emac_reg_r32(hw, base, reg); emac_reg_w32(hw, base, reg, ((data & ~mask) | val)); }
u32 emac_reg_field_r32(struct emac_hw *hw, u8 base, u32 reg, u32 mask, u32 shift) { u32 data; data = emac_reg_r32(hw, base, reg); return (data & mask) >> shift; }
int emac_hw_read_phy_reg(struct emac_hw *hw, bool ext, u8 dev, bool fast, u16 reg_addr, u16 *phy_data) { u32 i, clk_sel, val = 0; int retval = 0; *phy_data = 0; clk_sel = fast ? MDIO_CLK_25_4 : MDIO_CLK_25_28; if (hw->adpt->no_ephy == false) { retval = emac_disable_mdio_autopoll(hw); if (retval) return retval; } emac_reg_update32(hw, EMAC, EMAC_PHY_STS, PHY_ADDR_BMSK, (dev << PHY_ADDR_SHFT)); wmb(); /* ensure PHY address is set before we proceed */ if (ext) { val = ((dev << DEVAD_SHFT) & DEVAD_BMSK) | ((reg_addr << EX_REG_ADDR_SHFT) & EX_REG_ADDR_BMSK); emac_reg_w32(hw, EMAC, EMAC_MDIO_EX_CTRL, val); wmb(); /* ensure proper address is set before proceeding */ val = SUP_PREAMBLE | ((clk_sel << MDIO_CLK_SEL_SHFT) & MDIO_CLK_SEL_BMSK) | MDIO_START | MDIO_MODE | MDIO_RD_NWR; } else { val = val & ~(MDIO_REG_ADDR_BMSK | MDIO_CLK_SEL_BMSK | MDIO_MODE | MDIO_PR); val = SUP_PREAMBLE | ((clk_sel << MDIO_CLK_SEL_SHFT) & MDIO_CLK_SEL_BMSK) | ((reg_addr << MDIO_REG_ADDR_SHFT) & MDIO_REG_ADDR_BMSK) | MDIO_START | MDIO_RD_NWR; } emac_reg_w32(hw, EMAC, EMAC_MDIO_CTRL, val); mb(); /* ensure hw starts the operation before we check for result */ for (i = 0; i < MDIO_WAIT_TIMES; i++) { val = emac_reg_r32(hw, EMAC, EMAC_MDIO_CTRL); if (!(val & (MDIO_START | MDIO_BUSY))) { *phy_data = (u16)((val >> MDIO_DATA_SHFT) & MDIO_DATA_BMSK); break; } udelay(100); }
/* PHY */ static int emac_disable_mdio_autopoll(struct emac_hw *hw) { u32 i, val; emac_reg_update32(hw, EMAC, EMAC_MDIO_CTRL, MDIO_AP_EN, 0); wmb(); /* ensure mdio autopoll disable is requested */ /* wait for any mdio polling to complete */ for (i = 0; i < MDIO_WAIT_TIMES; i++) { val = emac_reg_r32(hw, EMAC, EMAC_MDIO_CTRL); if (!(val & MDIO_BUSY)) return 0; udelay(100); } /* failed to disable; ensure it is enabled before returning */ emac_reg_update32(hw, EMAC, EMAC_MDIO_CTRL, 0, MDIO_AP_EN); wmb(); /* ensure mdio autopoll is enabled */ return -EBUSY; }
static void emac_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buff) { struct emac_adapter *adpt = netdev_priv(netdev); struct emac_hw *hw = &adpt->hw; u16 i; u32 *val = buff; static const u32 reg[EMAC_MAX_REG_SIZE] = { EMAC_DMA_MAS_CTRL, EMAC_MAC_CTRL, EMAC_WOL_CTRL0, EMAC_TXQ_CTRL_0, EMAC_RXQ_CTRL_0, EMAC_DMA_CTRL, EMAC_INT_MASK, EMAC_AXI_MAST_CTRL, EMAC_CORE_HW_VERSION, EMAC_MISC_CTRL, }; regs->version = 0; regs->len = EMAC_MAX_REG_SIZE * sizeof(u32); memset(val, 0, EMAC_MAX_REG_SIZE * sizeof(u32)); for (i = 0; i < ARRAY_SIZE(reg); i++) val[i] = emac_reg_r32(hw, EMAC, reg[i]); return; }