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,47 +1987,74 @@ static int fec_enet_mdio_wait(struct fec_enet_private *fep) ...@@ -1987,47 +1987,74 @@ 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_start = FEC_MMFR_ST_C45; frame_op = FEC_MMFR_OP_READ;
frame_start = FEC_MMFR_ST;
frame_addr = regnum;
/* write address */ /* start a read op */
frame_addr = (regnum >> 16); writel(frame_start | frame_op |
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(frame_addr) | FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
FEC_MMFR_TA | (regnum & 0xFFFF),
fep->hwp + FEC_MII_DATA);
/* wait for end of transfer */ /* wait for end of transfer */
ret = fec_enet_mdio_wait(fep); ret = fec_enet_mdio_wait(fep);
if (ret) { if (ret) {
netdev_err(fep->netdev, "MDIO address write timeout\n"); netdev_err(fep->netdev, "MDIO read timeout\n");
goto out; goto out;
} }
frame_op = FEC_MMFR_OP_READ_C45; ret = FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA));
} else { out:
/* C22 read */ pm_runtime_mark_last_busy(dev);
frame_op = FEC_MMFR_OP_READ; pm_runtime_put_autosuspend(dev);
frame_start = FEC_MMFR_ST;
frame_addr = regnum; 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;
/* write address */
writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
FEC_MMFR_TA | (regnum & 0xFFFF),
fep->hwp + FEC_MII_DATA);
/* wait for end of transfer */
ret = fec_enet_mdio_wait(fep);
if (ret) {
netdev_err(fep->netdev, "MDIO address write timeout\n");
goto out;
} }
frame_op = FEC_MMFR_OP_READ_C45;
/* 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 */
ret = fec_enet_mdio_wait(fep); ret = fec_enet_mdio_wait(fep);
...@@ -2045,45 +2072,69 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) ...@@ -2045,45 +2072,69 @@ 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_C45; frame_start = FEC_MMFR_ST;
frame_addr = regnum;
/* write address */ /* start a write op */
frame_addr = (regnum >> 16); writel(frame_start | FEC_MMFR_OP_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(frame_addr) | FEC_MMFR_TA | FEC_MMFR_DATA(value),
FEC_MMFR_TA | (regnum & 0xFFFF), fep->hwp + FEC_MII_DATA);
fep->hwp + FEC_MII_DATA);
/* wait for end of transfer */ /* wait for end of transfer */
ret = fec_enet_mdio_wait(fep); ret = fec_enet_mdio_wait(fep);
if (ret) { if (ret)
netdev_err(fep->netdev, "MDIO address write timeout\n"); netdev_err(fep->netdev, "MDIO write timeout\n");
goto out;
} pm_runtime_mark_last_busy(dev);
} else { pm_runtime_put_autosuspend(dev);
/* C22 write */
frame_start = FEC_MMFR_ST; return ret;
frame_addr = regnum; }
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;
/* write address */
writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
FEC_MMFR_TA | (regnum & 0xFFFF),
fep->hwp + FEC_MII_DATA);
/* wait for end of transfer */
ret = fec_enet_mdio_wait(fep);
if (ret) {
netdev_err(fep->netdev, "MDIO address write timeout\n");
goto out;
} }
/* 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);
/* wait for end of transfer */ /* wait for end of transfer */
ret = fec_enet_mdio_wait(fep); ret = fec_enet_mdio_wait(fep);
...@@ -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