Commit 070f6186 authored by Andrew Lunn's avatar Andrew Lunn Committed by Jakub Kicinski

amd-xgbe: Separate C22 and C45 transactions

The xgbe MDIO bus driver can perform both C22 and C45 transfers, when
using its MDIO bus hardware. The SFP I2C mdio bus driver only supports
C22. 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 41799a77
...@@ -1287,11 +1287,20 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad, ...@@ -1287,11 +1287,20 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
} }
} }
static unsigned int xgbe_create_mdio_sca(int port, int reg) static unsigned int xgbe_create_mdio_sca_c22(int port, int reg)
{ {
unsigned int mdio_sca, da; unsigned int mdio_sca;
da = (reg & MII_ADDR_C45) ? reg >> 16 : 0; mdio_sca = 0;
XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, RA, reg);
XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, PA, port);
return mdio_sca;
}
static unsigned int xgbe_create_mdio_sca_c45(int port, unsigned int da, int reg)
{
unsigned int mdio_sca;
mdio_sca = 0; mdio_sca = 0;
XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, RA, reg); XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, RA, reg);
...@@ -1301,14 +1310,13 @@ static unsigned int xgbe_create_mdio_sca(int port, int reg) ...@@ -1301,14 +1310,13 @@ static unsigned int xgbe_create_mdio_sca(int port, int reg)
return mdio_sca; return mdio_sca;
} }
static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr, static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata,
int reg, u16 val) unsigned int mdio_sca, u16 val)
{ {
unsigned int mdio_sca, mdio_sccd; unsigned int mdio_sccd;
reinit_completion(&pdata->mdio_complete); reinit_completion(&pdata->mdio_complete);
mdio_sca = xgbe_create_mdio_sca(addr, reg);
XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca); XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
mdio_sccd = 0; mdio_sccd = 0;
...@@ -1325,14 +1333,33 @@ static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr, ...@@ -1325,14 +1333,33 @@ static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
return 0; return 0;
} }
static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr, static int xgbe_write_ext_mii_regs_c22(struct xgbe_prv_data *pdata, int addr,
int reg) int reg, u16 val)
{
unsigned int mdio_sca;
mdio_sca = xgbe_create_mdio_sca_c22(addr, reg);
return xgbe_write_ext_mii_regs(pdata, mdio_sca, val);
}
static int xgbe_write_ext_mii_regs_c45(struct xgbe_prv_data *pdata, int addr,
int devad, int reg, u16 val)
{ {
unsigned int mdio_sca, mdio_sccd; unsigned int mdio_sca;
mdio_sca = xgbe_create_mdio_sca_c45(addr, devad, reg);
return xgbe_write_ext_mii_regs(pdata, mdio_sca, val);
}
static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata,
unsigned int mdio_sca)
{
unsigned int mdio_sccd;
reinit_completion(&pdata->mdio_complete); reinit_completion(&pdata->mdio_complete);
mdio_sca = xgbe_create_mdio_sca(addr, reg);
XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca); XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
mdio_sccd = 0; mdio_sccd = 0;
...@@ -1348,6 +1375,26 @@ static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr, ...@@ -1348,6 +1375,26 @@ static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
return XGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, DATA); return XGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, DATA);
} }
static int xgbe_read_ext_mii_regs_c22(struct xgbe_prv_data *pdata, int addr,
int reg)
{
unsigned int mdio_sca;
mdio_sca = xgbe_create_mdio_sca_c22(addr, reg);
return xgbe_read_ext_mii_regs(pdata, mdio_sca);
}
static int xgbe_read_ext_mii_regs_c45(struct xgbe_prv_data *pdata, int addr,
int devad, int reg)
{
unsigned int mdio_sca;
mdio_sca = xgbe_create_mdio_sca_c45(addr, devad, reg);
return xgbe_read_ext_mii_regs(pdata, mdio_sca);
}
static int xgbe_set_ext_mii_mode(struct xgbe_prv_data *pdata, unsigned int port, static int xgbe_set_ext_mii_mode(struct xgbe_prv_data *pdata, unsigned int port,
enum xgbe_mdio_mode mode) enum xgbe_mdio_mode mode)
{ {
...@@ -3561,8 +3608,10 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if) ...@@ -3561,8 +3608,10 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
hw_if->set_speed = xgbe_set_speed; hw_if->set_speed = xgbe_set_speed;
hw_if->set_ext_mii_mode = xgbe_set_ext_mii_mode; hw_if->set_ext_mii_mode = xgbe_set_ext_mii_mode;
hw_if->read_ext_mii_regs = xgbe_read_ext_mii_regs; hw_if->read_ext_mii_regs_c22 = xgbe_read_ext_mii_regs_c22;
hw_if->write_ext_mii_regs = xgbe_write_ext_mii_regs; hw_if->write_ext_mii_regs_c22 = xgbe_write_ext_mii_regs_c22;
hw_if->read_ext_mii_regs_c45 = xgbe_read_ext_mii_regs_c45;
hw_if->write_ext_mii_regs_c45 = xgbe_write_ext_mii_regs_c45;
hw_if->set_gpio = xgbe_set_gpio; hw_if->set_gpio = xgbe_set_gpio;
hw_if->clr_gpio = xgbe_clr_gpio; hw_if->clr_gpio = xgbe_clr_gpio;
......
...@@ -600,20 +600,27 @@ static int xgbe_phy_get_comm_ownership(struct xgbe_prv_data *pdata) ...@@ -600,20 +600,27 @@ static int xgbe_phy_get_comm_ownership(struct xgbe_prv_data *pdata)
return -ETIMEDOUT; return -ETIMEDOUT;
} }
static int xgbe_phy_mdio_mii_write(struct xgbe_prv_data *pdata, int addr, static int xgbe_phy_mdio_mii_write_c22(struct xgbe_prv_data *pdata, int addr,
int reg, u16 val) int reg, u16 val)
{ {
struct xgbe_phy_data *phy_data = pdata->phy_data; struct xgbe_phy_data *phy_data = pdata->phy_data;
if (reg & MII_ADDR_C45) {
if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL45)
return -ENOTSUPP;
} else {
if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL22) if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL22)
return -ENOTSUPP; return -EOPNOTSUPP;
}
return pdata->hw_if.write_ext_mii_regs(pdata, addr, reg, val); return pdata->hw_if.write_ext_mii_regs_c22(pdata, addr, reg, val);
}
static int xgbe_phy_mdio_mii_write_c45(struct xgbe_prv_data *pdata, int addr,
int devad, int reg, u16 val)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL45)
return -EOPNOTSUPP;
return pdata->hw_if.write_ext_mii_regs_c45(pdata, addr, devad,
reg, val);
} }
static int xgbe_phy_i2c_mii_write(struct xgbe_prv_data *pdata, int reg, u16 val) static int xgbe_phy_i2c_mii_write(struct xgbe_prv_data *pdata, int reg, u16 val)
...@@ -638,7 +645,8 @@ static int xgbe_phy_i2c_mii_write(struct xgbe_prv_data *pdata, int reg, u16 val) ...@@ -638,7 +645,8 @@ static int xgbe_phy_i2c_mii_write(struct xgbe_prv_data *pdata, int reg, u16 val)
return ret; return ret;
} }
static int xgbe_phy_mii_write(struct mii_bus *mii, int addr, int reg, u16 val) static int xgbe_phy_mii_write_c22(struct mii_bus *mii, int addr, int reg,
u16 val)
{ {
struct xgbe_prv_data *pdata = mii->priv; struct xgbe_prv_data *pdata = mii->priv;
struct xgbe_phy_data *phy_data = pdata->phy_data; struct xgbe_phy_data *phy_data = pdata->phy_data;
...@@ -651,29 +659,58 @@ static int xgbe_phy_mii_write(struct mii_bus *mii, int addr, int reg, u16 val) ...@@ -651,29 +659,58 @@ static int xgbe_phy_mii_write(struct mii_bus *mii, int addr, int reg, u16 val)
if (phy_data->conn_type == XGBE_CONN_TYPE_SFP) if (phy_data->conn_type == XGBE_CONN_TYPE_SFP)
ret = xgbe_phy_i2c_mii_write(pdata, reg, val); ret = xgbe_phy_i2c_mii_write(pdata, reg, val);
else if (phy_data->conn_type & XGBE_CONN_TYPE_MDIO) else if (phy_data->conn_type & XGBE_CONN_TYPE_MDIO)
ret = xgbe_phy_mdio_mii_write(pdata, addr, reg, val); ret = xgbe_phy_mdio_mii_write_c22(pdata, addr, reg, val);
else else
ret = -ENOTSUPP; ret = -EOPNOTSUPP;
xgbe_phy_put_comm_ownership(pdata);
return ret;
}
static int xgbe_phy_mii_write_c45(struct mii_bus *mii, int addr, int devad,
int reg, u16 val)
{
struct xgbe_prv_data *pdata = mii->priv;
struct xgbe_phy_data *phy_data = pdata->phy_data;
int ret;
ret = xgbe_phy_get_comm_ownership(pdata);
if (ret)
return ret;
if (phy_data->conn_type == XGBE_CONN_TYPE_SFP)
ret = -EOPNOTSUPP;
else if (phy_data->conn_type & XGBE_CONN_TYPE_MDIO)
ret = xgbe_phy_mdio_mii_write_c45(pdata, addr, devad, reg, val);
else
ret = -EOPNOTSUPP;
xgbe_phy_put_comm_ownership(pdata); xgbe_phy_put_comm_ownership(pdata);
return ret; return ret;
} }
static int xgbe_phy_mdio_mii_read(struct xgbe_prv_data *pdata, int addr, static int xgbe_phy_mdio_mii_read_c22(struct xgbe_prv_data *pdata, int addr,
int reg) int reg)
{ {
struct xgbe_phy_data *phy_data = pdata->phy_data; struct xgbe_phy_data *phy_data = pdata->phy_data;
if (reg & MII_ADDR_C45) {
if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL45)
return -ENOTSUPP;
} else {
if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL22) if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL22)
return -ENOTSUPP; return -EOPNOTSUPP;
}
return pdata->hw_if.read_ext_mii_regs(pdata, addr, reg); return pdata->hw_if.read_ext_mii_regs_c22(pdata, addr, reg);
}
static int xgbe_phy_mdio_mii_read_c45(struct xgbe_prv_data *pdata, int addr,
int devad, int reg)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL45)
return -EOPNOTSUPP;
return pdata->hw_if.read_ext_mii_regs_c45(pdata, addr, devad, reg);
} }
static int xgbe_phy_i2c_mii_read(struct xgbe_prv_data *pdata, int reg) static int xgbe_phy_i2c_mii_read(struct xgbe_prv_data *pdata, int reg)
...@@ -698,7 +735,7 @@ static int xgbe_phy_i2c_mii_read(struct xgbe_prv_data *pdata, int reg) ...@@ -698,7 +735,7 @@ static int xgbe_phy_i2c_mii_read(struct xgbe_prv_data *pdata, int reg)
return ret; return ret;
} }
static int xgbe_phy_mii_read(struct mii_bus *mii, int addr, int reg) static int xgbe_phy_mii_read_c22(struct mii_bus *mii, int addr, int reg)
{ {
struct xgbe_prv_data *pdata = mii->priv; struct xgbe_prv_data *pdata = mii->priv;
struct xgbe_phy_data *phy_data = pdata->phy_data; struct xgbe_phy_data *phy_data = pdata->phy_data;
...@@ -711,7 +748,30 @@ static int xgbe_phy_mii_read(struct mii_bus *mii, int addr, int reg) ...@@ -711,7 +748,30 @@ static int xgbe_phy_mii_read(struct mii_bus *mii, int addr, int reg)
if (phy_data->conn_type == XGBE_CONN_TYPE_SFP) if (phy_data->conn_type == XGBE_CONN_TYPE_SFP)
ret = xgbe_phy_i2c_mii_read(pdata, reg); ret = xgbe_phy_i2c_mii_read(pdata, reg);
else if (phy_data->conn_type & XGBE_CONN_TYPE_MDIO) else if (phy_data->conn_type & XGBE_CONN_TYPE_MDIO)
ret = xgbe_phy_mdio_mii_read(pdata, addr, reg); ret = xgbe_phy_mdio_mii_read_c22(pdata, addr, reg);
else
ret = -EOPNOTSUPP;
xgbe_phy_put_comm_ownership(pdata);
return ret;
}
static int xgbe_phy_mii_read_c45(struct mii_bus *mii, int addr, int devad,
int reg)
{
struct xgbe_prv_data *pdata = mii->priv;
struct xgbe_phy_data *phy_data = pdata->phy_data;
int ret;
ret = xgbe_phy_get_comm_ownership(pdata);
if (ret)
return ret;
if (phy_data->conn_type == XGBE_CONN_TYPE_SFP)
ret = -EOPNOTSUPP;
else if (phy_data->conn_type & XGBE_CONN_TYPE_MDIO)
ret = xgbe_phy_mdio_mii_read_c45(pdata, addr, devad, reg);
else else
ret = -ENOTSUPP; ret = -ENOTSUPP;
...@@ -1929,7 +1989,7 @@ static int xgbe_phy_set_redrv_mode_mdio(struct xgbe_prv_data *pdata, ...@@ -1929,7 +1989,7 @@ static int xgbe_phy_set_redrv_mode_mdio(struct xgbe_prv_data *pdata,
redrv_reg = XGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000); redrv_reg = XGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000);
redrv_val = (u16)mode; redrv_val = (u16)mode;
return pdata->hw_if.write_ext_mii_regs(pdata, phy_data->redrv_addr, return pdata->hw_if.write_ext_mii_regs_c22(pdata, phy_data->redrv_addr,
redrv_reg, redrv_val); redrv_reg, redrv_val);
} }
...@@ -3502,8 +3562,10 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) ...@@ -3502,8 +3562,10 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
mii->priv = pdata; mii->priv = pdata;
mii->name = "amd-xgbe-mii"; mii->name = "amd-xgbe-mii";
mii->read = xgbe_phy_mii_read; mii->read = xgbe_phy_mii_read_c22;
mii->write = xgbe_phy_mii_write; mii->write = xgbe_phy_mii_write_c22;
mii->read_c45 = xgbe_phy_mii_read_c45;
mii->write_c45 = xgbe_phy_mii_write_c45;
mii->parent = pdata->dev; mii->parent = pdata->dev;
mii->phy_mask = ~0; mii->phy_mask = ~0;
snprintf(mii->id, sizeof(mii->id), "%s", dev_name(pdata->dev)); snprintf(mii->id, sizeof(mii->id), "%s", dev_name(pdata->dev));
......
...@@ -775,8 +775,11 @@ struct xgbe_hw_if { ...@@ -775,8 +775,11 @@ struct xgbe_hw_if {
int (*set_ext_mii_mode)(struct xgbe_prv_data *, unsigned int, int (*set_ext_mii_mode)(struct xgbe_prv_data *, unsigned int,
enum xgbe_mdio_mode); enum xgbe_mdio_mode);
int (*read_ext_mii_regs)(struct xgbe_prv_data *, int, int); int (*read_ext_mii_regs_c22)(struct xgbe_prv_data *, int, int);
int (*write_ext_mii_regs)(struct xgbe_prv_data *, int, int, u16); int (*write_ext_mii_regs_c22)(struct xgbe_prv_data *, int, int, u16);
int (*read_ext_mii_regs_c45)(struct xgbe_prv_data *, int, int, int);
int (*write_ext_mii_regs_c45)(struct xgbe_prv_data *, int, int, int,
u16);
int (*set_gpio)(struct xgbe_prv_data *, unsigned int); int (*set_gpio)(struct xgbe_prv_data *, unsigned int);
int (*clr_gpio)(struct xgbe_prv_data *, unsigned int); int (*clr_gpio)(struct xgbe_prv_data *, unsigned int);
......
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