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); }
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)); }
static int emac_set_intr_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { struct emac_adapter *adpt = netdev_priv(netdev); struct emac_hw *hw = &adpt->hw; u32 val; /* irq moderator timers have resolution of 2us */ val = ((ec->rx_coalesce_usecs / 2) << IRQ_MODERATOR2_INIT_SHFT) & IRQ_MODERATOR2_INIT_BMSK; val |= ((ec->tx_coalesce_usecs / 2) << IRQ_MODERATOR_INIT_SHFT) & IRQ_MODERATOR_INIT_BMSK; emac_reg_w32(hw, EMAC, EMAC_IRQ_MOD_TIM_INIT, val); hw->irq_mod = val; return 0; }