Commit 8d03ad1a authored by Andrew Lunn's avatar Andrew Lunn Committed by Jakub Kicinski

net: fec: Separate C22 and C45 transactions

The fec MDIO bus driver can perform both C22 and C45 transfers.
Create separate functions for each and register the C45 versions using
the new API calls where appropriate.
Signed-off-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarMichael Walle <michael@walle.cc>
Reviewed-by: default avatarWei Fang <wei.fang@nxp.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent c0fc8e6d
...@@ -1987,24 +1987,58 @@ static int fec_enet_mdio_wait(struct fec_enet_private *fep) ...@@ -1987,24 +1987,58 @@ static int fec_enet_mdio_wait(struct fec_enet_private *fep)
return ret; return ret;
} }
static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) static int fec_enet_mdio_read_c22(struct mii_bus *bus, int mii_id, int regnum)
{ {
struct fec_enet_private *fep = bus->priv; struct fec_enet_private *fep = bus->priv;
struct device *dev = &fep->pdev->dev; struct device *dev = &fep->pdev->dev;
int ret = 0, frame_start, frame_addr, frame_op; int ret = 0, frame_start, frame_addr, frame_op;
bool is_c45 = !!(regnum & MII_ADDR_C45);
ret = pm_runtime_resume_and_get(dev); ret = pm_runtime_resume_and_get(dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (is_c45) { /* C22 read */
frame_op = FEC_MMFR_OP_READ;
frame_start = FEC_MMFR_ST;
frame_addr = regnum;
/* start a read op */
writel(frame_start | frame_op |
FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
/* wait for end of transfer */
ret = fec_enet_mdio_wait(fep);
if (ret) {
netdev_err(fep->netdev, "MDIO read timeout\n");
goto out;
}
ret = FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA));
out:
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return ret;
}
static int fec_enet_mdio_read_c45(struct mii_bus *bus, int mii_id,
int devad, int regnum)
{
struct fec_enet_private *fep = bus->priv;
struct device *dev = &fep->pdev->dev;
int ret = 0, frame_start, frame_op;
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
return ret;
frame_start = FEC_MMFR_ST_C45; frame_start = FEC_MMFR_ST_C45;
/* write address */ /* write address */
frame_addr = (regnum >> 16);
writel(frame_start | FEC_MMFR_OP_ADDR_WRITE | writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
FEC_MMFR_TA | (regnum & 0xFFFF), FEC_MMFR_TA | (regnum & 0xFFFF),
fep->hwp + FEC_MII_DATA); fep->hwp + FEC_MII_DATA);
...@@ -2017,16 +2051,9 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) ...@@ -2017,16 +2051,9 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
frame_op = FEC_MMFR_OP_READ_C45; frame_op = FEC_MMFR_OP_READ_C45;
} else {
/* C22 read */
frame_op = FEC_MMFR_OP_READ;
frame_start = FEC_MMFR_ST;
frame_addr = regnum;
}
/* start a read op */ /* start a read op */
writel(frame_start | frame_op | writel(frame_start | frame_op |
FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
FEC_MMFR_TA, fep->hwp + FEC_MII_DATA); FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
/* wait for end of transfer */ /* wait for end of transfer */
...@@ -2045,25 +2072,54 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) ...@@ -2045,25 +2072,54 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
return ret; return ret;
} }
static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, static int fec_enet_mdio_write_c22(struct mii_bus *bus, int mii_id, int regnum,
u16 value) u16 value)
{ {
struct fec_enet_private *fep = bus->priv; struct fec_enet_private *fep = bus->priv;
struct device *dev = &fep->pdev->dev; struct device *dev = &fep->pdev->dev;
int ret, frame_start, frame_addr; int ret, frame_start, frame_addr;
bool is_c45 = !!(regnum & MII_ADDR_C45);
ret = pm_runtime_resume_and_get(dev); ret = pm_runtime_resume_and_get(dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (is_c45) { /* C22 write */
frame_start = FEC_MMFR_ST;
frame_addr = regnum;
/* start a write op */
writel(frame_start | FEC_MMFR_OP_WRITE |
FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
FEC_MMFR_TA | FEC_MMFR_DATA(value),
fep->hwp + FEC_MII_DATA);
/* wait for end of transfer */
ret = fec_enet_mdio_wait(fep);
if (ret)
netdev_err(fep->netdev, "MDIO write timeout\n");
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return ret;
}
static int fec_enet_mdio_write_c45(struct mii_bus *bus, int mii_id,
int devad, int regnum, u16 value)
{
struct fec_enet_private *fep = bus->priv;
struct device *dev = &fep->pdev->dev;
int ret, frame_start;
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
return ret;
frame_start = FEC_MMFR_ST_C45; frame_start = FEC_MMFR_ST_C45;
/* write address */ /* write address */
frame_addr = (regnum >> 16);
writel(frame_start | FEC_MMFR_OP_ADDR_WRITE | writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
FEC_MMFR_TA | (regnum & 0xFFFF), FEC_MMFR_TA | (regnum & 0xFFFF),
fep->hwp + FEC_MII_DATA); fep->hwp + FEC_MII_DATA);
...@@ -2073,15 +2129,10 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, ...@@ -2073,15 +2129,10 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
netdev_err(fep->netdev, "MDIO address write timeout\n"); netdev_err(fep->netdev, "MDIO address write timeout\n");
goto out; goto out;
} }
} else {
/* C22 write */
frame_start = FEC_MMFR_ST;
frame_addr = regnum;
}
/* start a write op */ /* start a write op */
writel(frame_start | FEC_MMFR_OP_WRITE | writel(frame_start | FEC_MMFR_OP_WRITE |
FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
FEC_MMFR_TA | FEC_MMFR_DATA(value), FEC_MMFR_TA | FEC_MMFR_DATA(value),
fep->hwp + FEC_MII_DATA); fep->hwp + FEC_MII_DATA);
...@@ -2381,8 +2432,10 @@ static int fec_enet_mii_init(struct platform_device *pdev) ...@@ -2381,8 +2432,10 @@ static int fec_enet_mii_init(struct platform_device *pdev)
} }
fep->mii_bus->name = "fec_enet_mii_bus"; fep->mii_bus->name = "fec_enet_mii_bus";
fep->mii_bus->read = fec_enet_mdio_read; fep->mii_bus->read = fec_enet_mdio_read_c22;
fep->mii_bus->write = fec_enet_mdio_write; fep->mii_bus->write = fec_enet_mdio_write_c22;
fep->mii_bus->read_c45 = fec_enet_mdio_read_c45;
fep->mii_bus->write_c45 = fec_enet_mdio_write_c45;
snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
pdev->name, fep->dev_id + 1); pdev->name, fep->dev_id + 1);
fep->mii_bus->priv = fep; fep->mii_bus->priv = fep;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment