static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad,
int mdio_reg)
{
struct eqos_priv *eqos = bus->priv;
u32 val;
int ret;
ret = eqos_mdio_wait_idle(eqos);
if (ret)
{
pr_err("MDIO not idle at entry");
return ret;
}
val = readl(&eqos->mac_regs->mdio_address);
val &= EQOS_MAC_MDIO_ADDRESS_SKAP | EQOS_MAC_MDIO_ADDRESS_C45E;
val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) |
(mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
(EQOS_MAC_MDIO_ADDRESS_CR <<
EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) |
(EQOS_MAC_MDIO_ADDRESS_GOC_READ <<
EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) |
EQOS_MAC_MDIO_ADDRESS_GB;
writel(val, &eqos->mac_regs->mdio_address);
udelay(10);
ret = eqos_mdio_wait_idle(eqos);
if (ret)
{
pr_err("MDIO read didn't complete");
return ret;
}
val = readl(&eqos->mac_regs->mdio_data);
val &= EQOS_MAC_MDIO_DATA_GD_MASK;
// printf("MDIO:%d 0x%02x=0x%08x\n", mdio_addr, mdio_reg, val);
return val;
}
static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad,
int mdio_reg, u16 mdio_val)
{
struct eqos_priv *eqos = bus->priv;
u32 val;
int ret;
ret = eqos_mdio_wait_idle(eqos);
if (ret)
{
pr_err("MDIO not idle at entry");
return ret;
}
writel(mdio_val, &eqos->mac_regs->mdio_data);
val = readl(&eqos->mac_regs->mdio_address);
val &= EQOS_MAC_MDIO_ADDRESS_SKAP |
EQOS_MAC_MDIO_ADDRESS_C45E;
val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) |
(mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
(EQOS_MAC_MDIO_ADDRESS_CR <<
EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) |
(EQOS_MAC_MDIO_ADDRESS_GOC_WRITE <<
EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) |
EQOS_MAC_MDIO_ADDRESS_GB;
writel(val, &eqos->mac_regs->mdio_address);
udelay(10);
ret = eqos_mdio_wait_idle(eqos);
if (ret)
{
pr_err("MDIO write didn't complete");
return ret;
}
return 0;
}
static int eqos_mdio_c45read(struct mii_dev *bus, int mdio_addr, int mdio_devad,
int mdio_reg)
{
u32 val = 0;
int ret = 0;
ret = eqos_mdio_write(bus, mdio_addr, -1, 0x0d, mdio_devad);
if (ret)
{
pr_err("MDIO write: mdio_devad = %d didn't complete", mdio_devad);
return ret;
}
ret = eqos_mdio_write(bus, mdio_addr, -1, 0x0e, mdio_reg);
if (ret)
{
pr_err("MDIO write: mdio_reg = 0x%02x didn't complete", mdio_reg);
return ret;
}
ret = eqos_mdio_write(bus, mdio_addr, -1, 0x0d, 0x4000+mdio_devad);
if (ret)
{
pr_err("MDIO write: 0x40000+mdio_devad didn't complete");
return ret;
}
val = eqos_mdio_read(bus, mdio_addr, -1, 0x0e);
if (val < 0 )
{
pr_err("MDIO not idle at entry");
return val;
}
return val;
}
static int eqos_mdio_c45write(struct mii_dev *bus, int mdio_addr, int mdio_devad,
int mdio_reg, u16 mdio_val)
{
int ret;
ret = eqos_mdio_write(bus, mdio_addr, -1, 0x0d, mdio_devad);
if (ret)
{
pr_err("MDIO write: mdio_devad = %d didn't complete", mdio_devad);
return ret;
}
ret = eqos_mdio_write(bus, mdio_addr, -1, 0x0e, mdio_reg);
if (ret)
{
pr_err("MDIO write: mdio_reg = 0x%02x didn't complete", mdio_reg);
return ret;
}
ret = eqos_mdio_write(bus, mdio_addr, -1, 0x0d, 0x4000+mdio_devad);
if (ret)
{
pr_err("MDIO write: 0x40000+mdio_devad didn't complete");
return ret;
}
ret = eqos_mdio_write(bus, mdio_addr, -1, 0x0e, mdio_val);
if (ret)
{
pr_err("MDIO write: mdio_val = 0x%02x didn't complete", mdio_val);
return ret;
}
return 0;
}
phy_c45write(phydev, 3, 0x8100, 0x0200);
static inline int phy_c45write(struct phy_device *phydev, int devad, int regnum,
u16 val)
{
struct mii_dev *bus = phydev->bus;
return bus->c45write(bus, phydev->addr, devad, regnum, val);
}
/
phy的uid 是phy的 2寄存器+3寄存器
/
(board_r.c)initr_net-->eth_initialize-->eth_common_init-->phy_init
使用C22模式访问C45标准的器件
为了兼容性,协议定义了一套使用C22模式访问C45标准的设备。C45标准的设备都要预留reg13和reg14能够使用C22模式访问到。
reg13,用于填写C45特有的定义device type和操作码。
reg14,用于传输寄存器或者数据