Merge branch 'net-mdio-continue-separating-c22-and-c45'
Michael Walle says: ==================== net: mdio: Continue separating C22 and C45 I've picked this older series from Andrew up and rebased it onto the latest net-next. This is the second patch set in the series which separates the C22 and C45 MDIO bus transactions at the API level to the MDIO bus drivers. ==================== Link: https://lore.kernel.org/r/20230112-net-next-c45-seperation-part-2-v1-0-5eeaae931526@walle.cc Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
da1b0b5c1b
|
@ -954,8 +954,10 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
|
|||
return -ENOMEM;
|
||||
|
||||
bus->name = "VSC9959 internal MDIO bus";
|
||||
bus->read = enetc_mdio_read;
|
||||
bus->write = enetc_mdio_write;
|
||||
bus->read = enetc_mdio_read_c22;
|
||||
bus->write = enetc_mdio_write_c22;
|
||||
bus->read_c45 = enetc_mdio_read_c45;
|
||||
bus->write_c45 = enetc_mdio_write_c45;
|
||||
bus->parent = dev;
|
||||
mdio_priv = bus->priv;
|
||||
mdio_priv->hw = hw;
|
||||
|
|
|
@ -55,7 +55,8 @@ static int enetc_mdio_wait_complete(struct enetc_mdio_priv *mdio_priv)
|
|||
is_busy, !is_busy, 10, 10 * 1000);
|
||||
}
|
||||
|
||||
int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
|
||||
int enetc_mdio_write_c22(struct mii_bus *bus, int phy_id, int regnum,
|
||||
u16 value)
|
||||
{
|
||||
struct enetc_mdio_priv *mdio_priv = bus->priv;
|
||||
u32 mdio_ctl, mdio_cfg;
|
||||
|
@ -63,14 +64,39 @@ int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
|
|||
int ret;
|
||||
|
||||
mdio_cfg = ENETC_EMDIO_CFG;
|
||||
if (regnum & MII_ADDR_C45) {
|
||||
dev_addr = (regnum >> 16) & 0x1f;
|
||||
mdio_cfg |= MDIO_CFG_ENC45;
|
||||
} else {
|
||||
/* clause 22 (ie 1G) */
|
||||
dev_addr = regnum & 0x1f;
|
||||
mdio_cfg &= ~MDIO_CFG_ENC45;
|
||||
}
|
||||
dev_addr = regnum & 0x1f;
|
||||
mdio_cfg &= ~MDIO_CFG_ENC45;
|
||||
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
|
||||
|
||||
ret = enetc_mdio_wait_complete(mdio_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* set port and dev addr */
|
||||
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
|
||||
|
||||
/* write the value */
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_DATA, value);
|
||||
|
||||
ret = enetc_mdio_wait_complete(mdio_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(enetc_mdio_write_c22);
|
||||
|
||||
int enetc_mdio_write_c45(struct mii_bus *bus, int phy_id, int dev_addr,
|
||||
int regnum, u16 value)
|
||||
{
|
||||
struct enetc_mdio_priv *mdio_priv = bus->priv;
|
||||
u32 mdio_ctl, mdio_cfg;
|
||||
int ret;
|
||||
|
||||
mdio_cfg = ENETC_EMDIO_CFG;
|
||||
mdio_cfg |= MDIO_CFG_ENC45;
|
||||
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
|
||||
|
||||
|
@ -83,13 +109,11 @@ int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
|
|||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
|
||||
|
||||
/* set the register address */
|
||||
if (regnum & MII_ADDR_C45) {
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_ADDR, regnum & 0xffff);
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_ADDR, regnum & 0xffff);
|
||||
|
||||
ret = enetc_mdio_wait_complete(mdio_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = enetc_mdio_wait_complete(mdio_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* write the value */
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_DATA, value);
|
||||
|
@ -100,9 +124,9 @@ int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(enetc_mdio_write);
|
||||
EXPORT_SYMBOL_GPL(enetc_mdio_write_c45);
|
||||
|
||||
int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
|
||||
int enetc_mdio_read_c22(struct mii_bus *bus, int phy_id, int regnum)
|
||||
{
|
||||
struct enetc_mdio_priv *mdio_priv = bus->priv;
|
||||
u32 mdio_ctl, mdio_cfg;
|
||||
|
@ -110,13 +134,8 @@ int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
|
|||
int ret;
|
||||
|
||||
mdio_cfg = ENETC_EMDIO_CFG;
|
||||
if (regnum & MII_ADDR_C45) {
|
||||
dev_addr = (regnum >> 16) & 0x1f;
|
||||
mdio_cfg |= MDIO_CFG_ENC45;
|
||||
} else {
|
||||
dev_addr = regnum & 0x1f;
|
||||
mdio_cfg &= ~MDIO_CFG_ENC45;
|
||||
}
|
||||
dev_addr = regnum & 0x1f;
|
||||
mdio_cfg &= ~MDIO_CFG_ENC45;
|
||||
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
|
||||
|
||||
|
@ -128,15 +147,6 @@ int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
|
|||
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
|
||||
|
||||
/* set the register address */
|
||||
if (regnum & MII_ADDR_C45) {
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_ADDR, regnum & 0xffff);
|
||||
|
||||
ret = enetc_mdio_wait_complete(mdio_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* initiate the read */
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
|
||||
|
||||
|
@ -156,7 +166,56 @@ int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
|
|||
|
||||
return value;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(enetc_mdio_read);
|
||||
EXPORT_SYMBOL_GPL(enetc_mdio_read_c22);
|
||||
|
||||
int enetc_mdio_read_c45(struct mii_bus *bus, int phy_id, int dev_addr,
|
||||
int regnum)
|
||||
{
|
||||
struct enetc_mdio_priv *mdio_priv = bus->priv;
|
||||
u32 mdio_ctl, mdio_cfg;
|
||||
u16 value;
|
||||
int ret;
|
||||
|
||||
mdio_cfg = ENETC_EMDIO_CFG;
|
||||
mdio_cfg |= MDIO_CFG_ENC45;
|
||||
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
|
||||
|
||||
ret = enetc_mdio_wait_complete(mdio_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* set port and device addr */
|
||||
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
|
||||
|
||||
/* set the register address */
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_ADDR, regnum & 0xffff);
|
||||
|
||||
ret = enetc_mdio_wait_complete(mdio_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* initiate the read */
|
||||
enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
|
||||
|
||||
ret = enetc_mdio_wait_complete(mdio_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* return all Fs if nothing was there */
|
||||
if (enetc_mdio_rd(mdio_priv, ENETC_MDIO_CFG) & MDIO_CFG_RD_ER) {
|
||||
dev_dbg(&bus->dev,
|
||||
"Error while reading PHY%d reg at %d.%d\n",
|
||||
phy_id, dev_addr, regnum);
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
value = enetc_mdio_rd(mdio_priv, ENETC_MDIO_DATA) & 0xffff;
|
||||
|
||||
return value;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(enetc_mdio_read_c45);
|
||||
|
||||
struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs)
|
||||
{
|
||||
|
|
|
@ -39,8 +39,10 @@ static int enetc_pci_mdio_probe(struct pci_dev *pdev,
|
|||
}
|
||||
|
||||
bus->name = ENETC_MDIO_BUS_NAME;
|
||||
bus->read = enetc_mdio_read;
|
||||
bus->write = enetc_mdio_write;
|
||||
bus->read = enetc_mdio_read_c22;
|
||||
bus->write = enetc_mdio_write_c22;
|
||||
bus->read_c45 = enetc_mdio_read_c45;
|
||||
bus->write_c45 = enetc_mdio_write_c45;
|
||||
bus->parent = dev;
|
||||
mdio_priv = bus->priv;
|
||||
mdio_priv->hw = hw;
|
||||
|
|
|
@ -848,8 +848,10 @@ static int enetc_mdio_probe(struct enetc_pf *pf, struct device_node *np)
|
|||
return -ENOMEM;
|
||||
|
||||
bus->name = "Freescale ENETC MDIO Bus";
|
||||
bus->read = enetc_mdio_read;
|
||||
bus->write = enetc_mdio_write;
|
||||
bus->read = enetc_mdio_read_c22;
|
||||
bus->write = enetc_mdio_write_c22;
|
||||
bus->read_c45 = enetc_mdio_read_c45;
|
||||
bus->write_c45 = enetc_mdio_write_c45;
|
||||
bus->parent = dev;
|
||||
mdio_priv = bus->priv;
|
||||
mdio_priv->hw = &pf->si->hw;
|
||||
|
@ -885,8 +887,10 @@ static int enetc_imdio_create(struct enetc_pf *pf)
|
|||
return -ENOMEM;
|
||||
|
||||
bus->name = "Freescale ENETC internal MDIO Bus";
|
||||
bus->read = enetc_mdio_read;
|
||||
bus->write = enetc_mdio_write;
|
||||
bus->read = enetc_mdio_read_c22;
|
||||
bus->write = enetc_mdio_write_c22;
|
||||
bus->read_c45 = enetc_mdio_read_c45;
|
||||
bus->write_c45 = enetc_mdio_write_c45;
|
||||
bus->parent = dev;
|
||||
bus->phy_mask = ~0;
|
||||
mdio_priv = bus->priv;
|
||||
|
|
|
@ -215,8 +215,8 @@ static int mtk_mdio_busy_wait(struct mtk_eth *eth)
|
|||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int _mtk_mdio_write(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg,
|
||||
u32 write_data)
|
||||
static int _mtk_mdio_write_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg,
|
||||
u32 write_data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -224,35 +224,13 @@ static int _mtk_mdio_write(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (phy_reg & MII_ADDR_C45) {
|
||||
mtk_w32(eth, PHY_IAC_ACCESS |
|
||||
PHY_IAC_START_C45 |
|
||||
PHY_IAC_CMD_C45_ADDR |
|
||||
PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
|
||||
PHY_IAC_ADDR(phy_addr) |
|
||||
PHY_IAC_DATA(mdiobus_c45_regad(phy_reg)),
|
||||
MTK_PHY_IAC);
|
||||
|
||||
ret = mtk_mdio_busy_wait(eth);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mtk_w32(eth, PHY_IAC_ACCESS |
|
||||
PHY_IAC_START_C45 |
|
||||
PHY_IAC_CMD_WRITE |
|
||||
PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
|
||||
PHY_IAC_ADDR(phy_addr) |
|
||||
PHY_IAC_DATA(write_data),
|
||||
MTK_PHY_IAC);
|
||||
} else {
|
||||
mtk_w32(eth, PHY_IAC_ACCESS |
|
||||
PHY_IAC_START_C22 |
|
||||
PHY_IAC_CMD_WRITE |
|
||||
PHY_IAC_REG(phy_reg) |
|
||||
PHY_IAC_ADDR(phy_addr) |
|
||||
PHY_IAC_DATA(write_data),
|
||||
MTK_PHY_IAC);
|
||||
}
|
||||
mtk_w32(eth, PHY_IAC_ACCESS |
|
||||
PHY_IAC_START_C22 |
|
||||
PHY_IAC_CMD_WRITE |
|
||||
PHY_IAC_REG(phy_reg) |
|
||||
PHY_IAC_ADDR(phy_addr) |
|
||||
PHY_IAC_DATA(write_data),
|
||||
MTK_PHY_IAC);
|
||||
|
||||
ret = mtk_mdio_busy_wait(eth);
|
||||
if (ret < 0)
|
||||
|
@ -261,7 +239,8 @@ static int _mtk_mdio_write(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int _mtk_mdio_read(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg)
|
||||
static int _mtk_mdio_write_c45(struct mtk_eth *eth, u32 phy_addr,
|
||||
u32 devad, u32 phy_reg, u32 write_data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -269,33 +248,47 @@ static int _mtk_mdio_read(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (phy_reg & MII_ADDR_C45) {
|
||||
mtk_w32(eth, PHY_IAC_ACCESS |
|
||||
PHY_IAC_START_C45 |
|
||||
PHY_IAC_CMD_C45_ADDR |
|
||||
PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
|
||||
PHY_IAC_ADDR(phy_addr) |
|
||||
PHY_IAC_DATA(mdiobus_c45_regad(phy_reg)),
|
||||
MTK_PHY_IAC);
|
||||
mtk_w32(eth, PHY_IAC_ACCESS |
|
||||
PHY_IAC_START_C45 |
|
||||
PHY_IAC_CMD_C45_ADDR |
|
||||
PHY_IAC_REG(devad) |
|
||||
PHY_IAC_ADDR(phy_addr) |
|
||||
PHY_IAC_DATA(phy_reg),
|
||||
MTK_PHY_IAC);
|
||||
|
||||
ret = mtk_mdio_busy_wait(eth);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = mtk_mdio_busy_wait(eth);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mtk_w32(eth, PHY_IAC_ACCESS |
|
||||
PHY_IAC_START_C45 |
|
||||
PHY_IAC_CMD_C45_READ |
|
||||
PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
|
||||
PHY_IAC_ADDR(phy_addr),
|
||||
MTK_PHY_IAC);
|
||||
} else {
|
||||
mtk_w32(eth, PHY_IAC_ACCESS |
|
||||
PHY_IAC_START_C22 |
|
||||
PHY_IAC_CMD_C22_READ |
|
||||
PHY_IAC_REG(phy_reg) |
|
||||
PHY_IAC_ADDR(phy_addr),
|
||||
MTK_PHY_IAC);
|
||||
}
|
||||
mtk_w32(eth, PHY_IAC_ACCESS |
|
||||
PHY_IAC_START_C45 |
|
||||
PHY_IAC_CMD_WRITE |
|
||||
PHY_IAC_REG(devad) |
|
||||
PHY_IAC_ADDR(phy_addr) |
|
||||
PHY_IAC_DATA(write_data),
|
||||
MTK_PHY_IAC);
|
||||
|
||||
ret = mtk_mdio_busy_wait(eth);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _mtk_mdio_read_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mtk_mdio_busy_wait(eth);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mtk_w32(eth, PHY_IAC_ACCESS |
|
||||
PHY_IAC_START_C22 |
|
||||
PHY_IAC_CMD_C22_READ |
|
||||
PHY_IAC_REG(phy_reg) |
|
||||
PHY_IAC_ADDR(phy_addr),
|
||||
MTK_PHY_IAC);
|
||||
|
||||
ret = mtk_mdio_busy_wait(eth);
|
||||
if (ret < 0)
|
||||
|
@ -304,19 +297,70 @@ static int _mtk_mdio_read(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg)
|
|||
return mtk_r32(eth, MTK_PHY_IAC) & PHY_IAC_DATA_MASK;
|
||||
}
|
||||
|
||||
static int mtk_mdio_write(struct mii_bus *bus, int phy_addr,
|
||||
int phy_reg, u16 val)
|
||||
static int _mtk_mdio_read_c45(struct mtk_eth *eth, u32 phy_addr,
|
||||
u32 devad, u32 phy_reg)
|
||||
{
|
||||
struct mtk_eth *eth = bus->priv;
|
||||
int ret;
|
||||
|
||||
return _mtk_mdio_write(eth, phy_addr, phy_reg, val);
|
||||
ret = mtk_mdio_busy_wait(eth);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mtk_w32(eth, PHY_IAC_ACCESS |
|
||||
PHY_IAC_START_C45 |
|
||||
PHY_IAC_CMD_C45_ADDR |
|
||||
PHY_IAC_REG(devad) |
|
||||
PHY_IAC_ADDR(phy_addr) |
|
||||
PHY_IAC_DATA(phy_reg),
|
||||
MTK_PHY_IAC);
|
||||
|
||||
ret = mtk_mdio_busy_wait(eth);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mtk_w32(eth, PHY_IAC_ACCESS |
|
||||
PHY_IAC_START_C45 |
|
||||
PHY_IAC_CMD_C45_READ |
|
||||
PHY_IAC_REG(devad) |
|
||||
PHY_IAC_ADDR(phy_addr),
|
||||
MTK_PHY_IAC);
|
||||
|
||||
ret = mtk_mdio_busy_wait(eth);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return mtk_r32(eth, MTK_PHY_IAC) & PHY_IAC_DATA_MASK;
|
||||
}
|
||||
|
||||
static int mtk_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
|
||||
static int mtk_mdio_write_c22(struct mii_bus *bus, int phy_addr,
|
||||
int phy_reg, u16 val)
|
||||
{
|
||||
struct mtk_eth *eth = bus->priv;
|
||||
|
||||
return _mtk_mdio_read(eth, phy_addr, phy_reg);
|
||||
return _mtk_mdio_write_c22(eth, phy_addr, phy_reg, val);
|
||||
}
|
||||
|
||||
static int mtk_mdio_write_c45(struct mii_bus *bus, int phy_addr,
|
||||
int devad, int phy_reg, u16 val)
|
||||
{
|
||||
struct mtk_eth *eth = bus->priv;
|
||||
|
||||
return _mtk_mdio_write_c45(eth, phy_addr, devad, phy_reg, val);
|
||||
}
|
||||
|
||||
static int mtk_mdio_read_c22(struct mii_bus *bus, int phy_addr, int phy_reg)
|
||||
{
|
||||
struct mtk_eth *eth = bus->priv;
|
||||
|
||||
return _mtk_mdio_read_c22(eth, phy_addr, phy_reg);
|
||||
}
|
||||
|
||||
static int mtk_mdio_read_c45(struct mii_bus *bus, int phy_addr, int devad,
|
||||
int phy_reg)
|
||||
{
|
||||
struct mtk_eth *eth = bus->priv;
|
||||
|
||||
return _mtk_mdio_read_c45(eth, phy_addr, devad, phy_reg);
|
||||
}
|
||||
|
||||
static int mt7621_gmac0_rgmii_adjust(struct mtk_eth *eth,
|
||||
|
@ -760,8 +804,10 @@ static int mtk_mdio_init(struct mtk_eth *eth)
|
|||
}
|
||||
|
||||
eth->mii_bus->name = "mdio";
|
||||
eth->mii_bus->read = mtk_mdio_read;
|
||||
eth->mii_bus->write = mtk_mdio_write;
|
||||
eth->mii_bus->read = mtk_mdio_read_c22;
|
||||
eth->mii_bus->write = mtk_mdio_write_c22;
|
||||
eth->mii_bus->read_c45 = mtk_mdio_read_c45;
|
||||
eth->mii_bus->write_c45 = mtk_mdio_write_c45;
|
||||
eth->mii_bus->probe_capabilities = MDIOBUS_C22_C45;
|
||||
eth->mii_bus->priv = eth;
|
||||
eth->mii_bus->parent = eth->dev;
|
||||
|
|
|
@ -792,7 +792,7 @@ static int lan743x_mac_mii_wait_till_not_busy(struct lan743x_adapter *adapter)
|
|||
!(data & MAC_MII_ACC_MII_BUSY_), 0, 1000000);
|
||||
}
|
||||
|
||||
static int lan743x_mdiobus_read(struct mii_bus *bus, int phy_id, int index)
|
||||
static int lan743x_mdiobus_read_c22(struct mii_bus *bus, int phy_id, int index)
|
||||
{
|
||||
struct lan743x_adapter *adapter = bus->priv;
|
||||
u32 val, mii_access;
|
||||
|
@ -814,8 +814,8 @@ static int lan743x_mdiobus_read(struct mii_bus *bus, int phy_id, int index)
|
|||
return (int)(val & 0xFFFF);
|
||||
}
|
||||
|
||||
static int lan743x_mdiobus_write(struct mii_bus *bus,
|
||||
int phy_id, int index, u16 regval)
|
||||
static int lan743x_mdiobus_write_c22(struct mii_bus *bus,
|
||||
int phy_id, int index, u16 regval)
|
||||
{
|
||||
struct lan743x_adapter *adapter = bus->priv;
|
||||
u32 val, mii_access;
|
||||
|
@ -835,12 +835,10 @@ static int lan743x_mdiobus_write(struct mii_bus *bus,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static u32 lan743x_mac_mmd_access(int id, int index, int op)
|
||||
static u32 lan743x_mac_mmd_access(int id, int dev_addr, int op)
|
||||
{
|
||||
u16 dev_addr;
|
||||
u32 ret;
|
||||
|
||||
dev_addr = (index >> 16) & 0x1f;
|
||||
ret = (id << MAC_MII_ACC_PHY_ADDR_SHIFT_) &
|
||||
MAC_MII_ACC_PHY_ADDR_MASK_;
|
||||
ret |= (dev_addr << MAC_MII_ACC_MIIMMD_SHIFT_) &
|
||||
|
@ -858,7 +856,8 @@ static u32 lan743x_mac_mmd_access(int id, int index, int op)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int lan743x_mdiobus_c45_read(struct mii_bus *bus, int phy_id, int index)
|
||||
static int lan743x_mdiobus_read_c45(struct mii_bus *bus, int phy_id,
|
||||
int dev_addr, int index)
|
||||
{
|
||||
struct lan743x_adapter *adapter = bus->priv;
|
||||
u32 mmd_access;
|
||||
|
@ -868,32 +867,30 @@ static int lan743x_mdiobus_c45_read(struct mii_bus *bus, int phy_id, int index)
|
|||
ret = lan743x_mac_mii_wait_till_not_busy(adapter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (index & MII_ADDR_C45) {
|
||||
/* Load Register Address */
|
||||
lan743x_csr_write(adapter, MAC_MII_DATA, (u32)(index & 0xffff));
|
||||
mmd_access = lan743x_mac_mmd_access(phy_id, index,
|
||||
MMD_ACCESS_ADDRESS);
|
||||
lan743x_csr_write(adapter, MAC_MII_ACC, mmd_access);
|
||||
ret = lan743x_mac_mii_wait_till_not_busy(adapter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Read Data */
|
||||
mmd_access = lan743x_mac_mmd_access(phy_id, index,
|
||||
MMD_ACCESS_READ);
|
||||
lan743x_csr_write(adapter, MAC_MII_ACC, mmd_access);
|
||||
ret = lan743x_mac_mii_wait_till_not_busy(adapter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = lan743x_csr_read(adapter, MAC_MII_DATA);
|
||||
return (int)(ret & 0xFFFF);
|
||||
}
|
||||
|
||||
ret = lan743x_mdiobus_read(bus, phy_id, index);
|
||||
return ret;
|
||||
/* Load Register Address */
|
||||
lan743x_csr_write(adapter, MAC_MII_DATA, index);
|
||||
mmd_access = lan743x_mac_mmd_access(phy_id, dev_addr,
|
||||
MMD_ACCESS_ADDRESS);
|
||||
lan743x_csr_write(adapter, MAC_MII_ACC, mmd_access);
|
||||
ret = lan743x_mac_mii_wait_till_not_busy(adapter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Read Data */
|
||||
mmd_access = lan743x_mac_mmd_access(phy_id, dev_addr,
|
||||
MMD_ACCESS_READ);
|
||||
lan743x_csr_write(adapter, MAC_MII_ACC, mmd_access);
|
||||
ret = lan743x_mac_mii_wait_till_not_busy(adapter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = lan743x_csr_read(adapter, MAC_MII_DATA);
|
||||
return (int)(ret & 0xFFFF);
|
||||
}
|
||||
|
||||
static int lan743x_mdiobus_c45_write(struct mii_bus *bus,
|
||||
int phy_id, int index, u16 regval)
|
||||
static int lan743x_mdiobus_write_c45(struct mii_bus *bus, int phy_id,
|
||||
int dev_addr, int index, u16 regval)
|
||||
{
|
||||
struct lan743x_adapter *adapter = bus->priv;
|
||||
u32 mmd_access;
|
||||
|
@ -903,26 +900,23 @@ static int lan743x_mdiobus_c45_write(struct mii_bus *bus,
|
|||
ret = lan743x_mac_mii_wait_till_not_busy(adapter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (index & MII_ADDR_C45) {
|
||||
/* Load Register Address */
|
||||
lan743x_csr_write(adapter, MAC_MII_DATA, (u32)(index & 0xffff));
|
||||
mmd_access = lan743x_mac_mmd_access(phy_id, index,
|
||||
MMD_ACCESS_ADDRESS);
|
||||
lan743x_csr_write(adapter, MAC_MII_ACC, mmd_access);
|
||||
ret = lan743x_mac_mii_wait_till_not_busy(adapter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Write Data */
|
||||
lan743x_csr_write(adapter, MAC_MII_DATA, (u32)regval);
|
||||
mmd_access = lan743x_mac_mmd_access(phy_id, index,
|
||||
MMD_ACCESS_WRITE);
|
||||
lan743x_csr_write(adapter, MAC_MII_ACC, mmd_access);
|
||||
ret = lan743x_mac_mii_wait_till_not_busy(adapter);
|
||||
} else {
|
||||
ret = lan743x_mdiobus_write(bus, phy_id, index, regval);
|
||||
}
|
||||
|
||||
return ret;
|
||||
/* Load Register Address */
|
||||
lan743x_csr_write(adapter, MAC_MII_DATA, (u32)index);
|
||||
mmd_access = lan743x_mac_mmd_access(phy_id, dev_addr,
|
||||
MMD_ACCESS_ADDRESS);
|
||||
lan743x_csr_write(adapter, MAC_MII_ACC, mmd_access);
|
||||
ret = lan743x_mac_mii_wait_till_not_busy(adapter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Write Data */
|
||||
lan743x_csr_write(adapter, MAC_MII_DATA, (u32)regval);
|
||||
mmd_access = lan743x_mac_mmd_access(phy_id, dev_addr,
|
||||
MMD_ACCESS_WRITE);
|
||||
lan743x_csr_write(adapter, MAC_MII_ACC, mmd_access);
|
||||
|
||||
return lan743x_mac_mii_wait_till_not_busy(adapter);
|
||||
}
|
||||
|
||||
static int lan743x_sgmii_wait_till_not_busy(struct lan743x_adapter *adapter)
|
||||
|
@ -3286,8 +3280,10 @@ static int lan743x_mdiobus_init(struct lan743x_adapter *adapter)
|
|||
netif_dbg(adapter, drv, adapter->netdev,
|
||||
"SGMII operation\n");
|
||||
adapter->mdiobus->probe_capabilities = MDIOBUS_C22_C45;
|
||||
adapter->mdiobus->read = lan743x_mdiobus_c45_read;
|
||||
adapter->mdiobus->write = lan743x_mdiobus_c45_write;
|
||||
adapter->mdiobus->read = lan743x_mdiobus_read_c22;
|
||||
adapter->mdiobus->write = lan743x_mdiobus_write_c22;
|
||||
adapter->mdiobus->read_c45 = lan743x_mdiobus_read_c45;
|
||||
adapter->mdiobus->write_c45 = lan743x_mdiobus_write_c45;
|
||||
adapter->mdiobus->name = "lan743x-mdiobus-c45";
|
||||
netif_dbg(adapter, drv, adapter->netdev,
|
||||
"lan743x-mdiobus-c45\n");
|
||||
|
@ -3300,15 +3296,15 @@ static int lan743x_mdiobus_init(struct lan743x_adapter *adapter)
|
|||
"RGMII operation\n");
|
||||
// Only C22 support when RGMII I/F
|
||||
adapter->mdiobus->probe_capabilities = MDIOBUS_C22;
|
||||
adapter->mdiobus->read = lan743x_mdiobus_read;
|
||||
adapter->mdiobus->write = lan743x_mdiobus_write;
|
||||
adapter->mdiobus->read = lan743x_mdiobus_read_c22;
|
||||
adapter->mdiobus->write = lan743x_mdiobus_write_c22;
|
||||
adapter->mdiobus->name = "lan743x-mdiobus";
|
||||
netif_dbg(adapter, drv, adapter->netdev,
|
||||
"lan743x-mdiobus\n");
|
||||
}
|
||||
} else {
|
||||
adapter->mdiobus->read = lan743x_mdiobus_read;
|
||||
adapter->mdiobus->write = lan743x_mdiobus_write;
|
||||
adapter->mdiobus->read = lan743x_mdiobus_read_c22;
|
||||
adapter->mdiobus->write = lan743x_mdiobus_write_c22;
|
||||
adapter->mdiobus->name = "lan743x-mdiobus";
|
||||
netif_dbg(adapter, drv, adapter->netdev, "lan743x-mdiobus\n");
|
||||
}
|
||||
|
|
|
@ -45,8 +45,8 @@
|
|||
#define MII_XGMAC_PA_SHIFT 16
|
||||
#define MII_XGMAC_DA_SHIFT 21
|
||||
|
||||
static int stmmac_xgmac2_c45_format(struct stmmac_priv *priv, int phyaddr,
|
||||
int phyreg, u32 *hw_addr)
|
||||
static void stmmac_xgmac2_c45_format(struct stmmac_priv *priv, int phyaddr,
|
||||
int devad, int phyreg, u32 *hw_addr)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
|
@ -56,19 +56,14 @@ static int stmmac_xgmac2_c45_format(struct stmmac_priv *priv, int phyaddr,
|
|||
writel(tmp, priv->ioaddr + XGMAC_MDIO_C22P);
|
||||
|
||||
*hw_addr = (phyaddr << MII_XGMAC_PA_SHIFT) | (phyreg & 0xffff);
|
||||
*hw_addr |= (phyreg >> MII_DEVADDR_C45_SHIFT) << MII_XGMAC_DA_SHIFT;
|
||||
return 0;
|
||||
*hw_addr |= devad << MII_XGMAC_DA_SHIFT;
|
||||
}
|
||||
|
||||
static int stmmac_xgmac2_c22_format(struct stmmac_priv *priv, int phyaddr,
|
||||
int phyreg, u32 *hw_addr)
|
||||
static void stmmac_xgmac2_c22_format(struct stmmac_priv *priv, int phyaddr,
|
||||
int phyreg, u32 *hw_addr)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
/* HW does not support C22 addr >= 4 */
|
||||
if (phyaddr > MII_XGMAC_MAX_C22ADDR)
|
||||
return -ENODEV;
|
||||
|
||||
/* Set port as Clause 22 */
|
||||
tmp = readl(priv->ioaddr + XGMAC_MDIO_C22P);
|
||||
tmp &= ~MII_XGMAC_C22P_MASK;
|
||||
|
@ -76,16 +71,14 @@ static int stmmac_xgmac2_c22_format(struct stmmac_priv *priv, int phyaddr,
|
|||
writel(tmp, priv->ioaddr + XGMAC_MDIO_C22P);
|
||||
|
||||
*hw_addr = (phyaddr << MII_XGMAC_PA_SHIFT) | (phyreg & 0x1f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stmmac_xgmac2_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
|
||||
static int stmmac_xgmac2_mdio_read(struct stmmac_priv *priv, u32 addr,
|
||||
u32 value)
|
||||
{
|
||||
struct net_device *ndev = bus->priv;
|
||||
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||
unsigned int mii_address = priv->hw->mii.addr;
|
||||
unsigned int mii_data = priv->hw->mii.data;
|
||||
u32 tmp, addr, value = MII_XGMAC_BUSY;
|
||||
u32 tmp;
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(priv->device);
|
||||
|
@ -99,20 +92,6 @@ static int stmmac_xgmac2_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
|
|||
goto err_disable_clks;
|
||||
}
|
||||
|
||||
if (phyreg & MII_ADDR_C45) {
|
||||
phyreg &= ~MII_ADDR_C45;
|
||||
|
||||
ret = stmmac_xgmac2_c45_format(priv, phyaddr, phyreg, &addr);
|
||||
if (ret)
|
||||
goto err_disable_clks;
|
||||
} else {
|
||||
ret = stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr);
|
||||
if (ret)
|
||||
goto err_disable_clks;
|
||||
|
||||
value |= MII_XGMAC_SADDR;
|
||||
}
|
||||
|
||||
value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
|
||||
& priv->hw->mii.clk_csr_mask;
|
||||
value |= MII_XGMAC_READ;
|
||||
|
@ -144,14 +123,44 @@ err_disable_clks:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int stmmac_xgmac2_mdio_write(struct mii_bus *bus, int phyaddr,
|
||||
int phyreg, u16 phydata)
|
||||
static int stmmac_xgmac2_mdio_read_c22(struct mii_bus *bus, int phyaddr,
|
||||
int phyreg)
|
||||
{
|
||||
struct net_device *ndev = bus->priv;
|
||||
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||
struct stmmac_priv *priv;
|
||||
u32 addr;
|
||||
|
||||
priv = netdev_priv(ndev);
|
||||
|
||||
/* HW does not support C22 addr >= 4 */
|
||||
if (phyaddr > MII_XGMAC_MAX_C22ADDR)
|
||||
return -ENODEV;
|
||||
|
||||
stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr);
|
||||
|
||||
return stmmac_xgmac2_mdio_read(priv, addr, MII_XGMAC_BUSY);
|
||||
}
|
||||
|
||||
static int stmmac_xgmac2_mdio_read_c45(struct mii_bus *bus, int phyaddr,
|
||||
int devad, int phyreg)
|
||||
{
|
||||
struct net_device *ndev = bus->priv;
|
||||
struct stmmac_priv *priv;
|
||||
u32 addr;
|
||||
|
||||
priv = netdev_priv(ndev);
|
||||
|
||||
stmmac_xgmac2_c45_format(priv, phyaddr, devad, phyreg, &addr);
|
||||
|
||||
return stmmac_xgmac2_mdio_read(priv, addr, MII_XGMAC_BUSY);
|
||||
}
|
||||
|
||||
static int stmmac_xgmac2_mdio_write(struct stmmac_priv *priv, u32 addr,
|
||||
u32 value, u16 phydata)
|
||||
{
|
||||
unsigned int mii_address = priv->hw->mii.addr;
|
||||
unsigned int mii_data = priv->hw->mii.data;
|
||||
u32 addr, tmp, value = MII_XGMAC_BUSY;
|
||||
u32 tmp;
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(priv->device);
|
||||
|
@ -165,20 +174,6 @@ static int stmmac_xgmac2_mdio_write(struct mii_bus *bus, int phyaddr,
|
|||
goto err_disable_clks;
|
||||
}
|
||||
|
||||
if (phyreg & MII_ADDR_C45) {
|
||||
phyreg &= ~MII_ADDR_C45;
|
||||
|
||||
ret = stmmac_xgmac2_c45_format(priv, phyaddr, phyreg, &addr);
|
||||
if (ret)
|
||||
goto err_disable_clks;
|
||||
} else {
|
||||
ret = stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr);
|
||||
if (ret)
|
||||
goto err_disable_clks;
|
||||
|
||||
value |= MII_XGMAC_SADDR;
|
||||
}
|
||||
|
||||
value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
|
||||
& priv->hw->mii.clk_csr_mask;
|
||||
value |= phydata;
|
||||
|
@ -205,8 +200,63 @@ err_disable_clks:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int stmmac_xgmac2_mdio_write_c22(struct mii_bus *bus, int phyaddr,
|
||||
int phyreg, u16 phydata)
|
||||
{
|
||||
struct net_device *ndev = bus->priv;
|
||||
struct stmmac_priv *priv;
|
||||
u32 addr;
|
||||
|
||||
priv = netdev_priv(ndev);
|
||||
|
||||
/* HW does not support C22 addr >= 4 */
|
||||
if (phyaddr > MII_XGMAC_MAX_C22ADDR)
|
||||
return -ENODEV;
|
||||
|
||||
stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr);
|
||||
|
||||
return stmmac_xgmac2_mdio_write(priv, addr,
|
||||
MII_XGMAC_BUSY | MII_XGMAC_SADDR, phydata);
|
||||
}
|
||||
|
||||
static int stmmac_xgmac2_mdio_write_c45(struct mii_bus *bus, int phyaddr,
|
||||
int devad, int phyreg, u16 phydata)
|
||||
{
|
||||
struct net_device *ndev = bus->priv;
|
||||
struct stmmac_priv *priv;
|
||||
u32 addr;
|
||||
|
||||
priv = netdev_priv(ndev);
|
||||
|
||||
stmmac_xgmac2_c45_format(priv, phyaddr, devad, phyreg, &addr);
|
||||
|
||||
return stmmac_xgmac2_mdio_write(priv, addr, MII_XGMAC_BUSY,
|
||||
phydata);
|
||||
}
|
||||
|
||||
static int stmmac_mdio_read(struct stmmac_priv *priv, int data, u32 value)
|
||||
{
|
||||
unsigned int mii_address = priv->hw->mii.addr;
|
||||
unsigned int mii_data = priv->hw->mii.data;
|
||||
u32 v;
|
||||
|
||||
if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
|
||||
100, 10000))
|
||||
return -EBUSY;
|
||||
|
||||
writel(data, priv->ioaddr + mii_data);
|
||||
writel(value, priv->ioaddr + mii_address);
|
||||
|
||||
if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
|
||||
100, 10000))
|
||||
return -EBUSY;
|
||||
|
||||
/* Read the data from the MII data register */
|
||||
return readl(priv->ioaddr + mii_data) & MII_DATA_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* stmmac_mdio_read
|
||||
* stmmac_mdio_read_c22
|
||||
* @bus: points to the mii_bus structure
|
||||
* @phyaddr: MII addr
|
||||
* @phyreg: MII reg
|
||||
|
@ -215,15 +265,12 @@ err_disable_clks:
|
|||
* accessing the PHY registers.
|
||||
* Fortunately, it seems this has no drawback for the 7109 MAC.
|
||||
*/
|
||||
static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
|
||||
static int stmmac_mdio_read_c22(struct mii_bus *bus, int phyaddr, int phyreg)
|
||||
{
|
||||
struct net_device *ndev = bus->priv;
|
||||
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||
unsigned int mii_address = priv->hw->mii.addr;
|
||||
unsigned int mii_data = priv->hw->mii.data;
|
||||
u32 value = MII_BUSY;
|
||||
int data = 0;
|
||||
u32 v;
|
||||
|
||||
data = pm_runtime_resume_and_get(priv->device);
|
||||
if (data < 0)
|
||||
|
@ -236,60 +283,94 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
|
|||
& priv->hw->mii.clk_csr_mask;
|
||||
if (priv->plat->has_gmac4) {
|
||||
value |= MII_GMAC4_READ;
|
||||
if (phyreg & MII_ADDR_C45) {
|
||||
value |= MII_GMAC4_C45E;
|
||||
value &= ~priv->hw->mii.reg_mask;
|
||||
value |= ((phyreg >> MII_DEVADDR_C45_SHIFT) <<
|
||||
priv->hw->mii.reg_shift) &
|
||||
priv->hw->mii.reg_mask;
|
||||
|
||||
data |= (phyreg & MII_REGADDR_C45_MASK) <<
|
||||
MII_GMAC4_REG_ADDR_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
|
||||
100, 10000)) {
|
||||
data = -EBUSY;
|
||||
goto err_disable_clks;
|
||||
}
|
||||
data = stmmac_mdio_read(priv, data, value);
|
||||
|
||||
writel(data, priv->ioaddr + mii_data);
|
||||
writel(value, priv->ioaddr + mii_address);
|
||||
|
||||
if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
|
||||
100, 10000)) {
|
||||
data = -EBUSY;
|
||||
goto err_disable_clks;
|
||||
}
|
||||
|
||||
/* Read the data from the MII data register */
|
||||
data = (int)readl(priv->ioaddr + mii_data) & MII_DATA_MASK;
|
||||
|
||||
err_disable_clks:
|
||||
pm_runtime_put(priv->device);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* stmmac_mdio_write
|
||||
* stmmac_mdio_read_c45
|
||||
* @bus: points to the mii_bus structure
|
||||
* @phyaddr: MII addr
|
||||
* @devad: device address to read
|
||||
* @phyreg: MII reg
|
||||
* Description: it reads data from the MII register from within the phy device.
|
||||
* For the 7111 GMAC, we must set the bit 0 in the MII address register while
|
||||
* accessing the PHY registers.
|
||||
* Fortunately, it seems this has no drawback for the 7109 MAC.
|
||||
*/
|
||||
static int stmmac_mdio_read_c45(struct mii_bus *bus, int phyaddr, int devad,
|
||||
int phyreg)
|
||||
{
|
||||
struct net_device *ndev = bus->priv;
|
||||
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||
u32 value = MII_BUSY;
|
||||
int data = 0;
|
||||
|
||||
data = pm_runtime_get_sync(priv->device);
|
||||
if (data < 0) {
|
||||
pm_runtime_put_noidle(priv->device);
|
||||
return data;
|
||||
}
|
||||
|
||||
value |= (phyaddr << priv->hw->mii.addr_shift)
|
||||
& priv->hw->mii.addr_mask;
|
||||
value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
|
||||
value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
|
||||
& priv->hw->mii.clk_csr_mask;
|
||||
value |= MII_GMAC4_READ;
|
||||
value |= MII_GMAC4_C45E;
|
||||
value &= ~priv->hw->mii.reg_mask;
|
||||
value |= (devad << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
|
||||
|
||||
data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT;
|
||||
|
||||
data = stmmac_mdio_read(priv, data, value);
|
||||
|
||||
pm_runtime_put(priv->device);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static int stmmac_mdio_write(struct stmmac_priv *priv, int data, u32 value)
|
||||
{
|
||||
unsigned int mii_address = priv->hw->mii.addr;
|
||||
unsigned int mii_data = priv->hw->mii.data;
|
||||
u32 v;
|
||||
|
||||
/* Wait until any existing MII operation is complete */
|
||||
if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
|
||||
100, 10000))
|
||||
return -EBUSY;
|
||||
|
||||
/* Set the MII address register to write */
|
||||
writel(data, priv->ioaddr + mii_data);
|
||||
writel(value, priv->ioaddr + mii_address);
|
||||
|
||||
/* Wait until any existing MII operation is complete */
|
||||
return readl_poll_timeout(priv->ioaddr + mii_address, v,
|
||||
!(v & MII_BUSY), 100, 10000);
|
||||
}
|
||||
|
||||
/**
|
||||
* stmmac_mdio_write_c22
|
||||
* @bus: points to the mii_bus structure
|
||||
* @phyaddr: MII addr
|
||||
* @phyreg: MII reg
|
||||
* @phydata: phy data
|
||||
* Description: it writes the data into the MII register from within the device.
|
||||
*/
|
||||
static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
|
||||
u16 phydata)
|
||||
static int stmmac_mdio_write_c22(struct mii_bus *bus, int phyaddr, int phyreg,
|
||||
u16 phydata)
|
||||
{
|
||||
struct net_device *ndev = bus->priv;
|
||||
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||
unsigned int mii_address = priv->hw->mii.addr;
|
||||
unsigned int mii_data = priv->hw->mii.data;
|
||||
int ret, data = phydata;
|
||||
u32 value = MII_BUSY;
|
||||
u32 v;
|
||||
|
||||
ret = pm_runtime_resume_and_get(priv->device);
|
||||
if (ret < 0)
|
||||
|
@ -301,38 +382,57 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
|
|||
|
||||
value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
|
||||
& priv->hw->mii.clk_csr_mask;
|
||||
if (priv->plat->has_gmac4) {
|
||||
if (priv->plat->has_gmac4)
|
||||
value |= MII_GMAC4_WRITE;
|
||||
if (phyreg & MII_ADDR_C45) {
|
||||
value |= MII_GMAC4_C45E;
|
||||
value &= ~priv->hw->mii.reg_mask;
|
||||
value |= ((phyreg >> MII_DEVADDR_C45_SHIFT) <<
|
||||
priv->hw->mii.reg_shift) &
|
||||
priv->hw->mii.reg_mask;
|
||||
|
||||
data |= (phyreg & MII_REGADDR_C45_MASK) <<
|
||||
MII_GMAC4_REG_ADDR_SHIFT;
|
||||
}
|
||||
} else {
|
||||
else
|
||||
value |= MII_WRITE;
|
||||
|
||||
ret = stmmac_mdio_write(priv, data, value);
|
||||
|
||||
pm_runtime_put(priv->device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* stmmac_mdio_write_c45
|
||||
* @bus: points to the mii_bus structure
|
||||
* @phyaddr: MII addr
|
||||
* @phyreg: MII reg
|
||||
* @devad: device address to read
|
||||
* @phydata: phy data
|
||||
* Description: it writes the data into the MII register from within the device.
|
||||
*/
|
||||
static int stmmac_mdio_write_c45(struct mii_bus *bus, int phyaddr,
|
||||
int devad, int phyreg, u16 phydata)
|
||||
{
|
||||
struct net_device *ndev = bus->priv;
|
||||
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||
int ret, data = phydata;
|
||||
u32 value = MII_BUSY;
|
||||
|
||||
ret = pm_runtime_get_sync(priv->device);
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_noidle(priv->device);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Wait until any existing MII operation is complete */
|
||||
if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
|
||||
100, 10000)) {
|
||||
ret = -EBUSY;
|
||||
goto err_disable_clks;
|
||||
}
|
||||
value |= (phyaddr << priv->hw->mii.addr_shift)
|
||||
& priv->hw->mii.addr_mask;
|
||||
value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
|
||||
|
||||
/* Set the MII address register to write */
|
||||
writel(data, priv->ioaddr + mii_data);
|
||||
writel(value, priv->ioaddr + mii_address);
|
||||
value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
|
||||
& priv->hw->mii.clk_csr_mask;
|
||||
|
||||
/* Wait until any existing MII operation is complete */
|
||||
ret = readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
|
||||
100, 10000);
|
||||
value |= MII_GMAC4_WRITE;
|
||||
value |= MII_GMAC4_C45E;
|
||||
value &= ~priv->hw->mii.reg_mask;
|
||||
value |= (devad << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
|
||||
|
||||
data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT;
|
||||
|
||||
ret = stmmac_mdio_write(priv, data, value);
|
||||
|
||||
err_disable_clks:
|
||||
pm_runtime_put(priv->device);
|
||||
|
||||
return ret;
|
||||
|
@ -457,8 +557,10 @@ int stmmac_mdio_register(struct net_device *ndev)
|
|||
new_bus->probe_capabilities = MDIOBUS_C22_C45;
|
||||
|
||||
if (priv->plat->has_xgmac) {
|
||||
new_bus->read = &stmmac_xgmac2_mdio_read;
|
||||
new_bus->write = &stmmac_xgmac2_mdio_write;
|
||||
new_bus->read = &stmmac_xgmac2_mdio_read_c22;
|
||||
new_bus->write = &stmmac_xgmac2_mdio_write_c22;
|
||||
new_bus->read_c45 = &stmmac_xgmac2_mdio_read_c45;
|
||||
new_bus->write_c45 = &stmmac_xgmac2_mdio_write_c45;
|
||||
|
||||
/* Right now only C22 phys are supported */
|
||||
max_addr = MII_XGMAC_MAX_C22ADDR + 1;
|
||||
|
@ -468,8 +570,13 @@ int stmmac_mdio_register(struct net_device *ndev)
|
|||
dev_err(dev, "Unsupported phy_addr (max=%d)\n",
|
||||
MII_XGMAC_MAX_C22ADDR);
|
||||
} else {
|
||||
new_bus->read = &stmmac_mdio_read;
|
||||
new_bus->write = &stmmac_mdio_write;
|
||||
new_bus->read = &stmmac_mdio_read_c22;
|
||||
new_bus->write = &stmmac_mdio_write_c22;
|
||||
if (priv->plat->has_gmac4) {
|
||||
new_bus->read_c45 = &stmmac_mdio_read_c45;
|
||||
new_bus->write_c45 = &stmmac_mdio_write_c45;
|
||||
}
|
||||
|
||||
max_addr = PHY_MAX_ADDR;
|
||||
}
|
||||
|
||||
|
@ -490,7 +597,7 @@ int stmmac_mdio_register(struct net_device *ndev)
|
|||
|
||||
/* Looks like we need a dummy read for XGMAC only and C45 PHYs */
|
||||
if (priv->plat->has_xgmac)
|
||||
stmmac_xgmac2_mdio_read(new_bus, 0, MII_ADDR_C45);
|
||||
stmmac_xgmac2_mdio_read_c45(new_bus, 0, 0, 0);
|
||||
|
||||
/* If fixed-link is set, skip PHY scanning */
|
||||
if (!fwnode)
|
||||
|
|
|
@ -104,61 +104,36 @@ static int aspeed_mdio_write_c22(struct mii_bus *bus, int addr, int regnum,
|
|||
addr, regnum, val);
|
||||
}
|
||||
|
||||
static int aspeed_mdio_read_c45(struct mii_bus *bus, int addr, int regnum)
|
||||
static int aspeed_mdio_read_c45(struct mii_bus *bus, int addr, int devad,
|
||||
int regnum)
|
||||
{
|
||||
u8 c45_dev = (regnum >> 16) & 0x1F;
|
||||
u16 c45_addr = regnum & 0xFFFF;
|
||||
int rc;
|
||||
|
||||
rc = aspeed_mdio_op(bus, ASPEED_MDIO_CTRL_ST_C45, MDIO_C45_OP_ADDR,
|
||||
addr, c45_dev, c45_addr);
|
||||
addr, devad, regnum);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = aspeed_mdio_op(bus, ASPEED_MDIO_CTRL_ST_C45, MDIO_C45_OP_READ,
|
||||
addr, c45_dev, 0);
|
||||
addr, devad, 0);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return aspeed_mdio_get_data(bus);
|
||||
}
|
||||
|
||||
static int aspeed_mdio_write_c45(struct mii_bus *bus, int addr, int regnum,
|
||||
u16 val)
|
||||
static int aspeed_mdio_write_c45(struct mii_bus *bus, int addr, int devad,
|
||||
int regnum, u16 val)
|
||||
{
|
||||
u8 c45_dev = (regnum >> 16) & 0x1F;
|
||||
u16 c45_addr = regnum & 0xFFFF;
|
||||
int rc;
|
||||
|
||||
rc = aspeed_mdio_op(bus, ASPEED_MDIO_CTRL_ST_C45, MDIO_C45_OP_ADDR,
|
||||
addr, c45_dev, c45_addr);
|
||||
addr, devad, regnum);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return aspeed_mdio_op(bus, ASPEED_MDIO_CTRL_ST_C45, MDIO_C45_OP_WRITE,
|
||||
addr, c45_dev, val);
|
||||
}
|
||||
|
||||
static int aspeed_mdio_read(struct mii_bus *bus, int addr, int regnum)
|
||||
{
|
||||
dev_dbg(&bus->dev, "%s: addr: %d, regnum: %d\n", __func__, addr,
|
||||
regnum);
|
||||
|
||||
if (regnum & MII_ADDR_C45)
|
||||
return aspeed_mdio_read_c45(bus, addr, regnum);
|
||||
|
||||
return aspeed_mdio_read_c22(bus, addr, regnum);
|
||||
}
|
||||
|
||||
static int aspeed_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
|
||||
{
|
||||
dev_dbg(&bus->dev, "%s: addr: %d, regnum: %d, val: 0x%x\n",
|
||||
__func__, addr, regnum, val);
|
||||
|
||||
if (regnum & MII_ADDR_C45)
|
||||
return aspeed_mdio_write_c45(bus, addr, regnum, val);
|
||||
|
||||
return aspeed_mdio_write_c22(bus, addr, regnum, val);
|
||||
addr, devad, val);
|
||||
}
|
||||
|
||||
static int aspeed_mdio_probe(struct platform_device *pdev)
|
||||
|
@ -185,8 +160,10 @@ static int aspeed_mdio_probe(struct platform_device *pdev)
|
|||
bus->name = DRV_NAME;
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "%s%d", pdev->name, pdev->id);
|
||||
bus->parent = &pdev->dev;
|
||||
bus->read = aspeed_mdio_read;
|
||||
bus->write = aspeed_mdio_write;
|
||||
bus->read = aspeed_mdio_read_c22;
|
||||
bus->write = aspeed_mdio_write_c22;
|
||||
bus->read_c45 = aspeed_mdio_read_c45;
|
||||
bus->write_c45 = aspeed_mdio_write_c45;
|
||||
bus->probe_capabilities = MDIOBUS_C22_C45;
|
||||
|
||||
rc = of_mdiobus_register(bus, pdev->dev.of_node);
|
||||
|
|
|
@ -26,7 +26,7 @@ static void cavium_mdiobus_set_mode(struct cavium_mdiobus *p,
|
|||
}
|
||||
|
||||
static int cavium_mdiobus_c45_addr(struct cavium_mdiobus *p,
|
||||
int phy_id, int regnum)
|
||||
int phy_id, int devad, int regnum)
|
||||
{
|
||||
union cvmx_smix_cmd smi_cmd;
|
||||
union cvmx_smix_wr_dat smi_wr;
|
||||
|
@ -38,12 +38,10 @@ static int cavium_mdiobus_c45_addr(struct cavium_mdiobus *p,
|
|||
smi_wr.s.dat = regnum & 0xffff;
|
||||
oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT);
|
||||
|
||||
regnum = (regnum >> 16) & 0x1f;
|
||||
|
||||
smi_cmd.u64 = 0;
|
||||
smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_45_ADDRESS */
|
||||
smi_cmd.s.phy_adr = phy_id;
|
||||
smi_cmd.s.reg_adr = regnum;
|
||||
smi_cmd.s.reg_adr = devad;
|
||||
oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
|
||||
|
||||
do {
|
||||
|
@ -59,28 +57,17 @@ static int cavium_mdiobus_c45_addr(struct cavium_mdiobus *p,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int cavium_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum)
|
||||
int cavium_mdiobus_read_c22(struct mii_bus *bus, int phy_id, int regnum)
|
||||
{
|
||||
struct cavium_mdiobus *p = bus->priv;
|
||||
union cvmx_smix_cmd smi_cmd;
|
||||
union cvmx_smix_rd_dat smi_rd;
|
||||
unsigned int op = 1; /* MDIO_CLAUSE_22_READ */
|
||||
int timeout = 1000;
|
||||
|
||||
if (regnum & MII_ADDR_C45) {
|
||||
int r = cavium_mdiobus_c45_addr(p, phy_id, regnum);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
regnum = (regnum >> 16) & 0x1f;
|
||||
op = 3; /* MDIO_CLAUSE_45_READ */
|
||||
} else {
|
||||
cavium_mdiobus_set_mode(p, C22);
|
||||
}
|
||||
cavium_mdiobus_set_mode(p, C22);
|
||||
|
||||
smi_cmd.u64 = 0;
|
||||
smi_cmd.s.phy_op = op;
|
||||
smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */;
|
||||
smi_cmd.s.phy_adr = phy_id;
|
||||
smi_cmd.s.reg_adr = regnum;
|
||||
oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
|
||||
|
@ -98,34 +85,58 @@ int cavium_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum)
|
|||
else
|
||||
return -EIO;
|
||||
}
|
||||
EXPORT_SYMBOL(cavium_mdiobus_read);
|
||||
EXPORT_SYMBOL(cavium_mdiobus_read_c22);
|
||||
|
||||
int cavium_mdiobus_write(struct mii_bus *bus, int phy_id, int regnum, u16 val)
|
||||
int cavium_mdiobus_read_c45(struct mii_bus *bus, int phy_id, int devad,
|
||||
int regnum)
|
||||
{
|
||||
struct cavium_mdiobus *p = bus->priv;
|
||||
union cvmx_smix_cmd smi_cmd;
|
||||
union cvmx_smix_rd_dat smi_rd;
|
||||
int timeout = 1000;
|
||||
int r;
|
||||
|
||||
r = cavium_mdiobus_c45_addr(p, phy_id, devad, regnum);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
smi_cmd.u64 = 0;
|
||||
smi_cmd.s.phy_op = 3; /* MDIO_CLAUSE_45_READ */
|
||||
smi_cmd.s.phy_adr = phy_id;
|
||||
smi_cmd.s.reg_adr = regnum;
|
||||
oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
|
||||
|
||||
do {
|
||||
/* Wait 1000 clocks so we don't saturate the RSL bus
|
||||
* doing reads.
|
||||
*/
|
||||
__delay(1000);
|
||||
smi_rd.u64 = oct_mdio_readq(p->register_base + SMI_RD_DAT);
|
||||
} while (smi_rd.s.pending && --timeout);
|
||||
|
||||
if (smi_rd.s.val)
|
||||
return smi_rd.s.dat;
|
||||
else
|
||||
return -EIO;
|
||||
}
|
||||
EXPORT_SYMBOL(cavium_mdiobus_read_c45);
|
||||
|
||||
int cavium_mdiobus_write_c22(struct mii_bus *bus, int phy_id, int regnum,
|
||||
u16 val)
|
||||
{
|
||||
struct cavium_mdiobus *p = bus->priv;
|
||||
union cvmx_smix_cmd smi_cmd;
|
||||
union cvmx_smix_wr_dat smi_wr;
|
||||
unsigned int op = 0; /* MDIO_CLAUSE_22_WRITE */
|
||||
int timeout = 1000;
|
||||
|
||||
if (regnum & MII_ADDR_C45) {
|
||||
int r = cavium_mdiobus_c45_addr(p, phy_id, regnum);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
regnum = (regnum >> 16) & 0x1f;
|
||||
op = 1; /* MDIO_CLAUSE_45_WRITE */
|
||||
} else {
|
||||
cavium_mdiobus_set_mode(p, C22);
|
||||
}
|
||||
cavium_mdiobus_set_mode(p, C22);
|
||||
|
||||
smi_wr.u64 = 0;
|
||||
smi_wr.s.dat = val;
|
||||
oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT);
|
||||
|
||||
smi_cmd.u64 = 0;
|
||||
smi_cmd.s.phy_op = op;
|
||||
smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */;
|
||||
smi_cmd.s.phy_adr = phy_id;
|
||||
smi_cmd.s.reg_adr = regnum;
|
||||
oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
|
||||
|
@ -143,7 +154,45 @@ int cavium_mdiobus_write(struct mii_bus *bus, int phy_id, int regnum, u16 val)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cavium_mdiobus_write);
|
||||
EXPORT_SYMBOL(cavium_mdiobus_write_c22);
|
||||
|
||||
int cavium_mdiobus_write_c45(struct mii_bus *bus, int phy_id, int devad,
|
||||
int regnum, u16 val)
|
||||
{
|
||||
struct cavium_mdiobus *p = bus->priv;
|
||||
union cvmx_smix_cmd smi_cmd;
|
||||
union cvmx_smix_wr_dat smi_wr;
|
||||
int timeout = 1000;
|
||||
int r;
|
||||
|
||||
r = cavium_mdiobus_c45_addr(p, phy_id, devad, regnum);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
smi_wr.u64 = 0;
|
||||
smi_wr.s.dat = val;
|
||||
oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT);
|
||||
|
||||
smi_cmd.u64 = 0;
|
||||
smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_45_WRITE */
|
||||
smi_cmd.s.phy_adr = phy_id;
|
||||
smi_cmd.s.reg_adr = devad;
|
||||
oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
|
||||
|
||||
do {
|
||||
/* Wait 1000 clocks so we don't saturate the RSL bus
|
||||
* doing reads.
|
||||
*/
|
||||
__delay(1000);
|
||||
smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT);
|
||||
} while (smi_wr.s.pending && --timeout);
|
||||
|
||||
if (timeout <= 0)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cavium_mdiobus_write_c45);
|
||||
|
||||
MODULE_DESCRIPTION("Common code for OCTEON and Thunder MDIO bus drivers");
|
||||
MODULE_AUTHOR("David Daney");
|
||||
|
|
|
@ -114,5 +114,10 @@ static inline u64 oct_mdio_readq(void __iomem *addr)
|
|||
#define oct_mdio_readq(addr) readq(addr)
|
||||
#endif
|
||||
|
||||
int cavium_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum);
|
||||
int cavium_mdiobus_write(struct mii_bus *bus, int phy_id, int regnum, u16 val);
|
||||
int cavium_mdiobus_read_c22(struct mii_bus *bus, int phy_id, int regnum);
|
||||
int cavium_mdiobus_write_c22(struct mii_bus *bus, int phy_id, int regnum,
|
||||
u16 val);
|
||||
int cavium_mdiobus_read_c45(struct mii_bus *bus, int phy_id, int devad,
|
||||
int regnum);
|
||||
int cavium_mdiobus_write_c45(struct mii_bus *bus, int phy_id, int devad,
|
||||
int regnum, u16 val);
|
||||
|
|
|
@ -30,7 +30,8 @@ static unsigned int i2c_mii_phy_addr(int phy_id)
|
|||
return phy_id + 0x40;
|
||||
}
|
||||
|
||||
static int i2c_mii_read_default(struct mii_bus *bus, int phy_id, int reg)
|
||||
static int i2c_mii_read_default_c45(struct mii_bus *bus, int phy_id, int devad,
|
||||
int reg)
|
||||
{
|
||||
struct i2c_adapter *i2c = bus->priv;
|
||||
struct i2c_msg msgs[2];
|
||||
|
@ -41,8 +42,8 @@ static int i2c_mii_read_default(struct mii_bus *bus, int phy_id, int reg)
|
|||
return 0xffff;
|
||||
|
||||
p = addr;
|
||||
if (reg & MII_ADDR_C45) {
|
||||
*p++ = 0x20 | ((reg >> 16) & 31);
|
||||
if (devad >= 0) {
|
||||
*p++ = 0x20 | devad;
|
||||
*p++ = reg >> 8;
|
||||
}
|
||||
*p++ = reg;
|
||||
|
@ -64,8 +65,8 @@ static int i2c_mii_read_default(struct mii_bus *bus, int phy_id, int reg)
|
|||
return data[0] << 8 | data[1];
|
||||
}
|
||||
|
||||
static int i2c_mii_write_default(struct mii_bus *bus, int phy_id, int reg,
|
||||
u16 val)
|
||||
static int i2c_mii_write_default_c45(struct mii_bus *bus, int phy_id,
|
||||
int devad, int reg, u16 val)
|
||||
{
|
||||
struct i2c_adapter *i2c = bus->priv;
|
||||
struct i2c_msg msg;
|
||||
|
@ -76,8 +77,8 @@ static int i2c_mii_write_default(struct mii_bus *bus, int phy_id, int reg,
|
|||
return 0;
|
||||
|
||||
p = data;
|
||||
if (reg & MII_ADDR_C45) {
|
||||
*p++ = (reg >> 16) & 31;
|
||||
if (devad >= 0) {
|
||||
*p++ = devad;
|
||||
*p++ = reg >> 8;
|
||||
}
|
||||
*p++ = reg;
|
||||
|
@ -94,6 +95,17 @@ static int i2c_mii_write_default(struct mii_bus *bus, int phy_id, int reg,
|
|||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
static int i2c_mii_read_default_c22(struct mii_bus *bus, int phy_id, int reg)
|
||||
{
|
||||
return i2c_mii_read_default_c45(bus, phy_id, -1, reg);
|
||||
}
|
||||
|
||||
static int i2c_mii_write_default_c22(struct mii_bus *bus, int phy_id, int reg,
|
||||
u16 val)
|
||||
{
|
||||
return i2c_mii_write_default_c45(bus, phy_id, -1, reg, val);
|
||||
}
|
||||
|
||||
/* RollBall SFPs do not access internal PHY via I2C address 0x56, but
|
||||
* instead via address 0x51, when SFP page is set to 0x03 and password to
|
||||
* 0xffffffff.
|
||||
|
@ -403,8 +415,10 @@ struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
|
|||
mii->write = i2c_mii_write_rollball;
|
||||
break;
|
||||
default:
|
||||
mii->read = i2c_mii_read_default;
|
||||
mii->write = i2c_mii_write_default;
|
||||
mii->read = i2c_mii_read_default_c22;
|
||||
mii->write = i2c_mii_write_default_c22;
|
||||
mii->read_c45 = i2c_mii_read_default_c45;
|
||||
mii->write_c45 = i2c_mii_write_default_c45;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,8 @@ static int ipq4019_mdio_wait_busy(struct mii_bus *bus)
|
|||
IPQ4019_MDIO_SLEEP, IPQ4019_MDIO_TIMEOUT);
|
||||
}
|
||||
|
||||
static int ipq4019_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
|
||||
static int ipq4019_mdio_read_c45(struct mii_bus *bus, int mii_id, int mmd,
|
||||
int reg)
|
||||
{
|
||||
struct ipq4019_mdio_data *priv = bus->priv;
|
||||
unsigned int data;
|
||||
|
@ -62,38 +63,19 @@ static int ipq4019_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
|
|||
if (ipq4019_mdio_wait_busy(bus))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* Clause 45 support */
|
||||
if (regnum & MII_ADDR_C45) {
|
||||
unsigned int mmd = (regnum >> 16) & 0x1F;
|
||||
unsigned int reg = regnum & 0xFFFF;
|
||||
data = readl(priv->membase + MDIO_MODE_REG);
|
||||
|
||||
/* Enter Clause 45 mode */
|
||||
data = readl(priv->membase + MDIO_MODE_REG);
|
||||
data |= MDIO_MODE_C45;
|
||||
|
||||
data |= MDIO_MODE_C45;
|
||||
writel(data, priv->membase + MDIO_MODE_REG);
|
||||
|
||||
writel(data, priv->membase + MDIO_MODE_REG);
|
||||
/* issue the phy address and mmd */
|
||||
writel((mii_id << 8) | mmd, priv->membase + MDIO_ADDR_REG);
|
||||
|
||||
/* issue the phy address and mmd */
|
||||
writel((mii_id << 8) | mmd, priv->membase + MDIO_ADDR_REG);
|
||||
/* issue reg */
|
||||
writel(reg, priv->membase + MDIO_DATA_WRITE_REG);
|
||||
|
||||
/* issue reg */
|
||||
writel(reg, priv->membase + MDIO_DATA_WRITE_REG);
|
||||
|
||||
cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_C45_ADDR;
|
||||
} else {
|
||||
/* Enter Clause 22 mode */
|
||||
data = readl(priv->membase + MDIO_MODE_REG);
|
||||
|
||||
data &= ~MDIO_MODE_C45;
|
||||
|
||||
writel(data, priv->membase + MDIO_MODE_REG);
|
||||
|
||||
/* issue the phy address and reg */
|
||||
writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG);
|
||||
|
||||
cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_READ;
|
||||
}
|
||||
cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_C45_ADDR;
|
||||
|
||||
/* issue read command */
|
||||
writel(cmd, priv->membase + MDIO_CMD_REG);
|
||||
|
@ -102,21 +84,18 @@ static int ipq4019_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
|
|||
if (ipq4019_mdio_wait_busy(bus))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
if (regnum & MII_ADDR_C45) {
|
||||
cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_C45_READ;
|
||||
cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_C45_READ;
|
||||
|
||||
writel(cmd, priv->membase + MDIO_CMD_REG);
|
||||
writel(cmd, priv->membase + MDIO_CMD_REG);
|
||||
|
||||
if (ipq4019_mdio_wait_busy(bus))
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
if (ipq4019_mdio_wait_busy(bus))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* Read and return data */
|
||||
return readl(priv->membase + MDIO_DATA_READ_REG);
|
||||
}
|
||||
|
||||
static int ipq4019_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
|
||||
u16 value)
|
||||
static int ipq4019_mdio_read_c22(struct mii_bus *bus, int mii_id, int regnum)
|
||||
{
|
||||
struct ipq4019_mdio_data *priv = bus->priv;
|
||||
unsigned int data;
|
||||
|
@ -125,50 +104,95 @@ static int ipq4019_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
|
|||
if (ipq4019_mdio_wait_busy(bus))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* Clause 45 support */
|
||||
if (regnum & MII_ADDR_C45) {
|
||||
unsigned int mmd = (regnum >> 16) & 0x1F;
|
||||
unsigned int reg = regnum & 0xFFFF;
|
||||
data = readl(priv->membase + MDIO_MODE_REG);
|
||||
|
||||
/* Enter Clause 45 mode */
|
||||
data = readl(priv->membase + MDIO_MODE_REG);
|
||||
data &= ~MDIO_MODE_C45;
|
||||
|
||||
data |= MDIO_MODE_C45;
|
||||
writel(data, priv->membase + MDIO_MODE_REG);
|
||||
|
||||
writel(data, priv->membase + MDIO_MODE_REG);
|
||||
/* issue the phy address and reg */
|
||||
writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG);
|
||||
|
||||
/* issue the phy address and mmd */
|
||||
writel((mii_id << 8) | mmd, priv->membase + MDIO_ADDR_REG);
|
||||
cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_READ;
|
||||
|
||||
/* issue reg */
|
||||
writel(reg, priv->membase + MDIO_DATA_WRITE_REG);
|
||||
/* issue read command */
|
||||
writel(cmd, priv->membase + MDIO_CMD_REG);
|
||||
|
||||
cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_C45_ADDR;
|
||||
/* Wait read complete */
|
||||
if (ipq4019_mdio_wait_busy(bus))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
writel(cmd, priv->membase + MDIO_CMD_REG);
|
||||
/* Read and return data */
|
||||
return readl(priv->membase + MDIO_DATA_READ_REG);
|
||||
}
|
||||
|
||||
if (ipq4019_mdio_wait_busy(bus))
|
||||
return -ETIMEDOUT;
|
||||
} else {
|
||||
/* Enter Clause 22 mode */
|
||||
data = readl(priv->membase + MDIO_MODE_REG);
|
||||
static int ipq4019_mdio_write_c45(struct mii_bus *bus, int mii_id, int mmd,
|
||||
int reg, u16 value)
|
||||
{
|
||||
struct ipq4019_mdio_data *priv = bus->priv;
|
||||
unsigned int data;
|
||||
unsigned int cmd;
|
||||
|
||||
data &= ~MDIO_MODE_C45;
|
||||
if (ipq4019_mdio_wait_busy(bus))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
writel(data, priv->membase + MDIO_MODE_REG);
|
||||
data = readl(priv->membase + MDIO_MODE_REG);
|
||||
|
||||
/* issue the phy address and reg */
|
||||
writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG);
|
||||
}
|
||||
data |= MDIO_MODE_C45;
|
||||
|
||||
writel(data, priv->membase + MDIO_MODE_REG);
|
||||
|
||||
/* issue the phy address and mmd */
|
||||
writel((mii_id << 8) | mmd, priv->membase + MDIO_ADDR_REG);
|
||||
|
||||
/* issue reg */
|
||||
writel(reg, priv->membase + MDIO_DATA_WRITE_REG);
|
||||
|
||||
cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_C45_ADDR;
|
||||
|
||||
writel(cmd, priv->membase + MDIO_CMD_REG);
|
||||
|
||||
if (ipq4019_mdio_wait_busy(bus))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* issue write data */
|
||||
writel(value, priv->membase + MDIO_DATA_WRITE_REG);
|
||||
|
||||
cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_C45_WRITE;
|
||||
writel(cmd, priv->membase + MDIO_CMD_REG);
|
||||
|
||||
/* Wait write complete */
|
||||
if (ipq4019_mdio_wait_busy(bus))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipq4019_mdio_write_c22(struct mii_bus *bus, int mii_id, int regnum,
|
||||
u16 value)
|
||||
{
|
||||
struct ipq4019_mdio_data *priv = bus->priv;
|
||||
unsigned int data;
|
||||
unsigned int cmd;
|
||||
|
||||
if (ipq4019_mdio_wait_busy(bus))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* Enter Clause 22 mode */
|
||||
data = readl(priv->membase + MDIO_MODE_REG);
|
||||
|
||||
data &= ~MDIO_MODE_C45;
|
||||
|
||||
writel(data, priv->membase + MDIO_MODE_REG);
|
||||
|
||||
/* issue the phy address and reg */
|
||||
writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG);
|
||||
|
||||
/* issue write data */
|
||||
writel(value, priv->membase + MDIO_DATA_WRITE_REG);
|
||||
|
||||
/* issue write command */
|
||||
if (regnum & MII_ADDR_C45)
|
||||
cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_C45_WRITE;
|
||||
else
|
||||
cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_WRITE;
|
||||
cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_WRITE;
|
||||
|
||||
writel(cmd, priv->membase + MDIO_CMD_REG);
|
||||
|
||||
|
@ -235,8 +259,10 @@ static int ipq4019_mdio_probe(struct platform_device *pdev)
|
|||
priv->eth_ldo_rdy = devm_ioremap_resource(&pdev->dev, res);
|
||||
|
||||
bus->name = "ipq4019_mdio";
|
||||
bus->read = ipq4019_mdio_read;
|
||||
bus->write = ipq4019_mdio_write;
|
||||
bus->read = ipq4019_mdio_read_c22;
|
||||
bus->write = ipq4019_mdio_write_c22;
|
||||
bus->read_c45 = ipq4019_mdio_read_c45;
|
||||
bus->write_c45 = ipq4019_mdio_write_c45;
|
||||
bus->reset = ipq_mdio_reset;
|
||||
bus->parent = &pdev->dev;
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "%s%d", pdev->name, pdev->id);
|
||||
|
|
|
@ -98,7 +98,7 @@ static int iproc_mdio_wait_for_idle(void __iomem *base, bool result)
|
|||
* Return value: Successful Read operation returns read reg values and write
|
||||
* operation returns 0. Failure operation returns negative error code.
|
||||
*/
|
||||
static int start_miim_ops(void __iomem *base,
|
||||
static int start_miim_ops(void __iomem *base, bool c45,
|
||||
u16 phyid, u32 reg, u16 val, u32 op)
|
||||
{
|
||||
u32 param;
|
||||
|
@ -112,7 +112,7 @@ static int start_miim_ops(void __iomem *base,
|
|||
param = readl(base + MDIO_PARAM_OFFSET);
|
||||
param |= phyid << MDIO_PARAM_PHY_ID;
|
||||
param |= val << MDIO_PARAM_PHY_DATA;
|
||||
if (reg & MII_ADDR_C45)
|
||||
if (c45)
|
||||
param |= BIT(MDIO_PARAM_C45_SEL);
|
||||
|
||||
writel(param, base + MDIO_PARAM_OFFSET);
|
||||
|
@ -131,28 +131,58 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int iproc_mdiomux_read(struct mii_bus *bus, int phyid, int reg)
|
||||
static int iproc_mdiomux_read_c22(struct mii_bus *bus, int phyid, int reg)
|
||||
{
|
||||
struct iproc_mdiomux_desc *md = bus->priv;
|
||||
int ret;
|
||||
|
||||
ret = start_miim_ops(md->base, phyid, reg, 0, MDIO_CTRL_READ_OP);
|
||||
ret = start_miim_ops(md->base, false, phyid, reg, 0, MDIO_CTRL_READ_OP);
|
||||
if (ret < 0)
|
||||
dev_err(&bus->dev, "mdiomux read operation failed!!!");
|
||||
dev_err(&bus->dev, "mdiomux c22 read operation failed!!!");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iproc_mdiomux_write(struct mii_bus *bus,
|
||||
int phyid, int reg, u16 val)
|
||||
static int iproc_mdiomux_read_c45(struct mii_bus *bus, int phyid, int devad,
|
||||
int reg)
|
||||
{
|
||||
struct iproc_mdiomux_desc *md = bus->priv;
|
||||
int ret;
|
||||
|
||||
ret = start_miim_ops(md->base, true, phyid, reg | devad << 16, 0,
|
||||
MDIO_CTRL_READ_OP);
|
||||
if (ret < 0)
|
||||
dev_err(&bus->dev, "mdiomux read c45 operation failed!!!");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iproc_mdiomux_write_c22(struct mii_bus *bus,
|
||||
int phyid, int reg, u16 val)
|
||||
{
|
||||
struct iproc_mdiomux_desc *md = bus->priv;
|
||||
int ret;
|
||||
|
||||
/* Write val at reg offset */
|
||||
ret = start_miim_ops(md->base, phyid, reg, val, MDIO_CTRL_WRITE_OP);
|
||||
ret = start_miim_ops(md->base, false, phyid, reg, val,
|
||||
MDIO_CTRL_WRITE_OP);
|
||||
if (ret < 0)
|
||||
dev_err(&bus->dev, "mdiomux write operation failed!!!");
|
||||
dev_err(&bus->dev, "mdiomux write c22 operation failed!!!");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iproc_mdiomux_write_c45(struct mii_bus *bus,
|
||||
int phyid, int devad, int reg, u16 val)
|
||||
{
|
||||
struct iproc_mdiomux_desc *md = bus->priv;
|
||||
int ret;
|
||||
|
||||
/* Write val at reg offset */
|
||||
ret = start_miim_ops(md->base, true, phyid, reg | devad << 16, val,
|
||||
MDIO_CTRL_WRITE_OP);
|
||||
if (ret < 0)
|
||||
dev_err(&bus->dev, "mdiomux write c45 operation failed!!!");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -223,8 +253,10 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev)
|
|||
bus->name = "iProc MDIO mux bus";
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", pdev->name, pdev->id);
|
||||
bus->parent = &pdev->dev;
|
||||
bus->read = iproc_mdiomux_read;
|
||||
bus->write = iproc_mdiomux_write;
|
||||
bus->read = iproc_mdiomux_read_c22;
|
||||
bus->write = iproc_mdiomux_write_c22;
|
||||
bus->read_c45 = iproc_mdiomux_read_c45;
|
||||
bus->write_c45 = iproc_mdiomux_write_c45;
|
||||
|
||||
bus->phy_mask = ~0;
|
||||
bus->dev.of_node = pdev->dev.of_node;
|
||||
|
|
|
@ -58,8 +58,10 @@ static int octeon_mdiobus_probe(struct platform_device *pdev)
|
|||
snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%px", bus->register_base);
|
||||
bus->mii_bus->parent = &pdev->dev;
|
||||
|
||||
bus->mii_bus->read = cavium_mdiobus_read;
|
||||
bus->mii_bus->write = cavium_mdiobus_write;
|
||||
bus->mii_bus->read = cavium_mdiobus_read_c22;
|
||||
bus->mii_bus->write = cavium_mdiobus_write_c22;
|
||||
bus->mii_bus->read_c45 = cavium_mdiobus_read_c45;
|
||||
bus->mii_bus->write_c45 = cavium_mdiobus_write_c45;
|
||||
|
||||
platform_set_drvdata(pdev, bus);
|
||||
|
||||
|
|
|
@ -93,8 +93,10 @@ static int thunder_mdiobus_pci_probe(struct pci_dev *pdev,
|
|||
bus->mii_bus->name = KBUILD_MODNAME;
|
||||
snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%llx", r.start);
|
||||
bus->mii_bus->parent = &pdev->dev;
|
||||
bus->mii_bus->read = cavium_mdiobus_read;
|
||||
bus->mii_bus->write = cavium_mdiobus_write;
|
||||
bus->mii_bus->read = cavium_mdiobus_read_c22;
|
||||
bus->mii_bus->write = cavium_mdiobus_write_c22;
|
||||
bus->mii_bus->read_c45 = cavium_mdiobus_read_c45;
|
||||
bus->mii_bus->write_c45 = cavium_mdiobus_write_c45;
|
||||
|
||||
err = of_mdiobus_register(bus->mii_bus, node);
|
||||
if (err)
|
||||
|
|
|
@ -37,16 +37,27 @@ struct enetc_mdio_priv {
|
|||
|
||||
#if IS_REACHABLE(CONFIG_FSL_ENETC_MDIO)
|
||||
|
||||
int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum);
|
||||
int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value);
|
||||
int enetc_mdio_read_c22(struct mii_bus *bus, int phy_id, int regnum);
|
||||
int enetc_mdio_write_c22(struct mii_bus *bus, int phy_id, int regnum,
|
||||
u16 value);
|
||||
int enetc_mdio_read_c45(struct mii_bus *bus, int phy_id, int devad, int regnum);
|
||||
int enetc_mdio_write_c45(struct mii_bus *bus, int phy_id, int devad, int regnum,
|
||||
u16 value);
|
||||
struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs);
|
||||
|
||||
#else
|
||||
|
||||
static inline int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
|
||||
static inline int enetc_mdio_read_c22(struct mii_bus *bus, int phy_id,
|
||||
int regnum)
|
||||
{ return -EINVAL; }
|
||||
static inline int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum,
|
||||
u16 value)
|
||||
static inline int enetc_mdio_write_c22(struct mii_bus *bus, int phy_id,
|
||||
int regnum, u16 value)
|
||||
{ return -EINVAL; }
|
||||
static inline int enetc_mdio_read_c45(struct mii_bus *bus, int phy_id,
|
||||
int devad, int regnum)
|
||||
{ return -EINVAL; }
|
||||
static inline int enetc_mdio_write_c45(struct mii_bus *bus, int phy_id,
|
||||
int devad, int regnum, u16 value)
|
||||
{ return -EINVAL; }
|
||||
struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs)
|
||||
{ return ERR_PTR(-EINVAL); }
|
||||
|
|
Loading…
Reference in New Issue