Commit 41799a77 authored by Andrew Lunn's avatar Andrew Lunn Committed by Jakub Kicinski

net: hns: Separate C22 and C45 transactions

The hns 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>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent ab2960f0
...@@ -206,7 +206,7 @@ static void hns_mdio_cmd_write(struct hns_mdio_device *mdio_dev, ...@@ -206,7 +206,7 @@ static void hns_mdio_cmd_write(struct hns_mdio_device *mdio_dev,
} }
/** /**
* hns_mdio_write - access phy register * hns_mdio_write_c22 - access phy register
* @bus: mdio bus * @bus: mdio bus
* @phy_id: phy id * @phy_id: phy id
* @regnum: register num * @regnum: register num
...@@ -214,21 +214,19 @@ static void hns_mdio_cmd_write(struct hns_mdio_device *mdio_dev, ...@@ -214,21 +214,19 @@ static void hns_mdio_cmd_write(struct hns_mdio_device *mdio_dev,
* *
* Return 0 on success, negative on failure * Return 0 on success, negative on failure
*/ */
static int hns_mdio_write(struct mii_bus *bus, static int hns_mdio_write_c22(struct mii_bus *bus,
int phy_id, int regnum, u16 data) int phy_id, int regnum, u16 data)
{ {
int ret;
struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv; struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
u8 devad = ((regnum >> 16) & 0x1f);
u8 is_c45 = !!(regnum & MII_ADDR_C45);
u16 reg = (u16)(regnum & 0xffff); u16 reg = (u16)(regnum & 0xffff);
u8 op;
u16 cmd_reg_cfg; u16 cmd_reg_cfg;
int ret;
u8 op;
dev_dbg(&bus->dev, "mdio write %s,base is %p\n", dev_dbg(&bus->dev, "mdio write %s,base is %p\n",
bus->id, mdio_dev->vbase); bus->id, mdio_dev->vbase);
dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x, write data=%d\n", dev_dbg(&bus->dev, "phy id=%d, reg=%#x, write data=%d\n",
phy_id, is_c45, devad, reg, data); phy_id, reg, data);
/* wait for ready */ /* wait for ready */
ret = hns_mdio_wait_ready(bus); ret = hns_mdio_wait_ready(bus);
...@@ -237,16 +235,53 @@ static int hns_mdio_write(struct mii_bus *bus, ...@@ -237,16 +235,53 @@ static int hns_mdio_write(struct mii_bus *bus,
return ret; return ret;
} }
if (!is_c45) {
cmd_reg_cfg = reg; cmd_reg_cfg = reg;
op = MDIO_C22_WRITE; op = MDIO_C22_WRITE;
} else {
MDIO_SET_REG_FIELD(mdio_dev, MDIO_WDATA_REG, MDIO_WDATA_DATA_M,
MDIO_WDATA_DATA_S, data);
hns_mdio_cmd_write(mdio_dev, false, op, phy_id, cmd_reg_cfg);
return 0;
}
/**
* hns_mdio_write_c45 - access phy register
* @bus: mdio bus
* @phy_id: phy id
* @devad: device address to read
* @regnum: register num
* @data: register value
*
* Return 0 on success, negative on failure
*/
static int hns_mdio_write_c45(struct mii_bus *bus, int phy_id, int devad,
int regnum, u16 data)
{
struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
u16 reg = (u16)(regnum & 0xffff);
u16 cmd_reg_cfg;
int ret;
u8 op;
dev_dbg(&bus->dev, "mdio write %s,base is %p\n",
bus->id, mdio_dev->vbase);
dev_dbg(&bus->dev, "phy id=%d, devad=%d, reg=%#x, write data=%d\n",
phy_id, devad, reg, data);
/* wait for ready */
ret = hns_mdio_wait_ready(bus);
if (ret) {
dev_err(&bus->dev, "MDIO bus is busy\n");
return ret;
}
/* config the cmd-reg to write addr*/ /* config the cmd-reg to write addr*/
MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M, MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
MDIO_ADDR_DATA_S, reg); MDIO_ADDR_DATA_S, reg);
hns_mdio_cmd_write(mdio_dev, is_c45, hns_mdio_cmd_write(mdio_dev, true, MDIO_C45_WRITE_ADDR, phy_id, devad);
MDIO_C45_WRITE_ADDR, phy_id, devad);
/* check for read or write opt is finished */ /* check for read or write opt is finished */
ret = hns_mdio_wait_ready(bus); ret = hns_mdio_wait_ready(bus);
...@@ -258,37 +293,85 @@ static int hns_mdio_write(struct mii_bus *bus, ...@@ -258,37 +293,85 @@ static int hns_mdio_write(struct mii_bus *bus,
/* config the data needed writing */ /* config the data needed writing */
cmd_reg_cfg = devad; cmd_reg_cfg = devad;
op = MDIO_C45_WRITE_DATA; op = MDIO_C45_WRITE_DATA;
}
MDIO_SET_REG_FIELD(mdio_dev, MDIO_WDATA_REG, MDIO_WDATA_DATA_M, MDIO_SET_REG_FIELD(mdio_dev, MDIO_WDATA_REG, MDIO_WDATA_DATA_M,
MDIO_WDATA_DATA_S, data); MDIO_WDATA_DATA_S, data);
hns_mdio_cmd_write(mdio_dev, is_c45, op, phy_id, cmd_reg_cfg); hns_mdio_cmd_write(mdio_dev, true, op, phy_id, cmd_reg_cfg);
return 0; return 0;
} }
/** /**
* hns_mdio_read - access phy register * hns_mdio_read_c22 - access phy register
* @bus: mdio bus * @bus: mdio bus
* @phy_id: phy id * @phy_id: phy id
* @regnum: register num * @regnum: register num
* *
* Return phy register value * Return phy register value
*/ */
static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum) static int hns_mdio_read_c22(struct mii_bus *bus, int phy_id, int regnum)
{ {
int ret; struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
u16 reg_val;
u8 devad = ((regnum >> 16) & 0x1f);
u8 is_c45 = !!(regnum & MII_ADDR_C45);
u16 reg = (u16)(regnum & 0xffff); u16 reg = (u16)(regnum & 0xffff);
u16 reg_val;
int ret;
dev_dbg(&bus->dev, "mdio read %s,base is %p\n",
bus->id, mdio_dev->vbase);
dev_dbg(&bus->dev, "phy id=%d, reg=%#x!\n", phy_id, reg);
/* Step 1: wait for ready */
ret = hns_mdio_wait_ready(bus);
if (ret) {
dev_err(&bus->dev, "MDIO bus is busy\n");
return ret;
}
hns_mdio_cmd_write(mdio_dev, false, MDIO_C22_READ, phy_id, reg);
/* Step 2: waiting for MDIO_COMMAND_REG 's mdio_start==0,*/
/* check for read or write opt is finished */
ret = hns_mdio_wait_ready(bus);
if (ret) {
dev_err(&bus->dev, "MDIO bus is busy\n");
return ret;
}
reg_val = MDIO_GET_REG_BIT(mdio_dev, MDIO_STA_REG, MDIO_STATE_STA_B);
if (reg_val) {
dev_err(&bus->dev, " ERROR! MDIO Read failed!\n");
return -EBUSY;
}
/* Step 3; get out data*/
reg_val = (u16)MDIO_GET_REG_FIELD(mdio_dev, MDIO_RDATA_REG,
MDIO_RDATA_DATA_M, MDIO_RDATA_DATA_S);
return reg_val;
}
/**
* hns_mdio_read_c45 - access phy register
* @bus: mdio bus
* @phy_id: phy id
* @devad: device address to read
* @regnum: register num
*
* Return phy register value
*/
static int hns_mdio_read_c45(struct mii_bus *bus, int phy_id, int devad,
int regnum)
{
struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv; struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
u16 reg = (u16)(regnum & 0xffff);
u16 reg_val;
int ret;
dev_dbg(&bus->dev, "mdio read %s,base is %p\n", dev_dbg(&bus->dev, "mdio read %s,base is %p\n",
bus->id, mdio_dev->vbase); bus->id, mdio_dev->vbase);
dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x!\n", dev_dbg(&bus->dev, "phy id=%d, devad=%d, reg=%#x!\n",
phy_id, is_c45, devad, reg); phy_id, devad, reg);
/* Step 1: wait for ready */ /* Step 1: wait for ready */
ret = hns_mdio_wait_ready(bus); ret = hns_mdio_wait_ready(bus);
...@@ -297,16 +380,11 @@ static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum) ...@@ -297,16 +380,11 @@ static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
return ret; return ret;
} }
if (!is_c45) {
hns_mdio_cmd_write(mdio_dev, is_c45,
MDIO_C22_READ, phy_id, reg);
} else {
MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M, MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
MDIO_ADDR_DATA_S, reg); MDIO_ADDR_DATA_S, reg);
/* Step 2; config the cmd-reg to write addr*/ /* Step 2; config the cmd-reg to write addr*/
hns_mdio_cmd_write(mdio_dev, is_c45, hns_mdio_cmd_write(mdio_dev, true, MDIO_C45_WRITE_ADDR, phy_id, devad);
MDIO_C45_WRITE_ADDR, phy_id, devad);
/* Step 3: check for read or write opt is finished */ /* Step 3: check for read or write opt is finished */
ret = hns_mdio_wait_ready(bus); ret = hns_mdio_wait_ready(bus);
...@@ -315,11 +393,9 @@ static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum) ...@@ -315,11 +393,9 @@ static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
return ret; return ret;
} }
hns_mdio_cmd_write(mdio_dev, is_c45, hns_mdio_cmd_write(mdio_dev, true, MDIO_C45_READ, phy_id, devad);
MDIO_C45_READ, phy_id, devad);
}
/* Step 5: waiting for MDIO_COMMAND_REG's mdio_start==0,*/ /* Step 5: waiting for MDIO_COMMAND_REG 's mdio_start==0,*/
/* check for read or write opt is finished */ /* check for read or write opt is finished */
ret = hns_mdio_wait_ready(bus); ret = hns_mdio_wait_ready(bus);
if (ret) { if (ret) {
...@@ -438,8 +514,10 @@ static int hns_mdio_probe(struct platform_device *pdev) ...@@ -438,8 +514,10 @@ static int hns_mdio_probe(struct platform_device *pdev)
} }
new_bus->name = MDIO_BUS_NAME; new_bus->name = MDIO_BUS_NAME;
new_bus->read = hns_mdio_read; new_bus->read = hns_mdio_read_c22;
new_bus->write = hns_mdio_write; new_bus->write = hns_mdio_write_c22;
new_bus->read_c45 = hns_mdio_read_c45;
new_bus->write_c45 = hns_mdio_write_c45;
new_bus->reset = hns_mdio_reset; new_bus->reset = hns_mdio_reset;
new_bus->priv = mdio_dev; new_bus->priv = mdio_dev;
new_bus->parent = &pdev->dev; new_bus->parent = &pdev->dev;
......
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