Commit c4791b31 authored by Jakub Kicinski's avatar Jakub Kicinski

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 third (and hopefully last) patch set in the series which
separates the C22 and C45 MDIO bus transactions at the API level to the
MDIO bus drivers.

The first patch is a newer version of the former "net: dsa: Separate C22
and C45 MDIO bus transaction methods", which only contains the mt7530
changes. Although posted as v1, because this is a new series, there
is a changelog included in the patch comment section.

The last patch is a new one, which isn't from Andrew's tree.
====================

Link: https://lore.kernel.org/r/20230116-net-next-c45-seperation-part-3-v1-0-0c53afa56aad@walle.ccSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 860edff5 95331514
......@@ -608,17 +608,29 @@ mt7530_mib_reset(struct dsa_switch *ds)
mt7530_write(priv, MT7530_MIB_CCR, CCR_MIB_ACTIVATE);
}
static int mt7530_phy_read(struct mt7530_priv *priv, int port, int regnum)
static int mt7530_phy_read_c22(struct mt7530_priv *priv, int port, int regnum)
{
return mdiobus_read_nested(priv->bus, port, regnum);
}
static int mt7530_phy_write(struct mt7530_priv *priv, int port, int regnum,
u16 val)
static int mt7530_phy_write_c22(struct mt7530_priv *priv, int port, int regnum,
u16 val)
{
return mdiobus_write_nested(priv->bus, port, regnum, val);
}
static int mt7530_phy_read_c45(struct mt7530_priv *priv, int port,
int devad, int regnum)
{
return mdiobus_c45_read_nested(priv->bus, port, devad, regnum);
}
static int mt7530_phy_write_c45(struct mt7530_priv *priv, int port, int devad,
int regnum, u16 val)
{
return mdiobus_c45_write_nested(priv->bus, port, devad, regnum, val);
}
static int
mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
int regnum)
......@@ -670,7 +682,7 @@ mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
static int
mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
int regnum, u32 data)
int regnum, u16 data)
{
struct mii_bus *bus = priv->bus;
struct mt7530_dummy_poll p;
......@@ -793,55 +805,36 @@ mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
}
static int
mt7531_ind_phy_read(struct mt7530_priv *priv, int port, int regnum)
mt753x_phy_read_c22(struct mii_bus *bus, int port, int regnum)
{
int devad;
int ret;
if (regnum & MII_ADDR_C45) {
devad = (regnum >> MII_DEVADDR_C45_SHIFT) & 0x1f;
ret = mt7531_ind_c45_phy_read(priv, port, devad,
regnum & MII_REGADDR_C45_MASK);
} else {
ret = mt7531_ind_c22_phy_read(priv, port, regnum);
}
struct mt7530_priv *priv = bus->priv;
return ret;
return priv->info->phy_read_c22(priv, port, regnum);
}
static int
mt7531_ind_phy_write(struct mt7530_priv *priv, int port, int regnum,
u16 data)
mt753x_phy_read_c45(struct mii_bus *bus, int port, int devad, int regnum)
{
int devad;
int ret;
if (regnum & MII_ADDR_C45) {
devad = (regnum >> MII_DEVADDR_C45_SHIFT) & 0x1f;
ret = mt7531_ind_c45_phy_write(priv, port, devad,
regnum & MII_REGADDR_C45_MASK,
data);
} else {
ret = mt7531_ind_c22_phy_write(priv, port, regnum, data);
}
struct mt7530_priv *priv = bus->priv;
return ret;
return priv->info->phy_read_c45(priv, port, devad, regnum);
}
static int
mt753x_phy_read(struct mii_bus *bus, int port, int regnum)
mt753x_phy_write_c22(struct mii_bus *bus, int port, int regnum, u16 val)
{
struct mt7530_priv *priv = bus->priv;
return priv->info->phy_read(priv, port, regnum);
return priv->info->phy_write_c22(priv, port, regnum, val);
}
static int
mt753x_phy_write(struct mii_bus *bus, int port, int regnum, u16 val)
mt753x_phy_write_c45(struct mii_bus *bus, int port, int devad, int regnum,
u16 val)
{
struct mt7530_priv *priv = bus->priv;
return priv->info->phy_write(priv, port, regnum, val);
return priv->info->phy_write_c45(priv, port, devad, regnum, val);
}
static void
......@@ -2086,8 +2079,10 @@ mt7530_setup_mdio(struct mt7530_priv *priv)
bus->priv = priv;
bus->name = KBUILD_MODNAME "-mii";
snprintf(bus->id, MII_BUS_ID_SIZE, KBUILD_MODNAME "-%d", idx++);
bus->read = mt753x_phy_read;
bus->write = mt753x_phy_write;
bus->read = mt753x_phy_read_c22;
bus->write = mt753x_phy_write_c22;
bus->read_c45 = mt753x_phy_read_c45;
bus->write_c45 = mt753x_phy_write_c45;
bus->parent = dev;
bus->phy_mask = ~ds->phys_mii_mask;
......@@ -3182,8 +3177,10 @@ static const struct mt753x_info mt753x_table[] = {
.id = ID_MT7621,
.pcs_ops = &mt7530_pcs_ops,
.sw_setup = mt7530_setup,
.phy_read = mt7530_phy_read,
.phy_write = mt7530_phy_write,
.phy_read_c22 = mt7530_phy_read_c22,
.phy_write_c22 = mt7530_phy_write_c22,
.phy_read_c45 = mt7530_phy_read_c45,
.phy_write_c45 = mt7530_phy_write_c45,
.pad_setup = mt7530_pad_clk_setup,
.mac_port_get_caps = mt7530_mac_port_get_caps,
.mac_port_config = mt7530_mac_config,
......@@ -3192,8 +3189,10 @@ static const struct mt753x_info mt753x_table[] = {
.id = ID_MT7530,
.pcs_ops = &mt7530_pcs_ops,
.sw_setup = mt7530_setup,
.phy_read = mt7530_phy_read,
.phy_write = mt7530_phy_write,
.phy_read_c22 = mt7530_phy_read_c22,
.phy_write_c22 = mt7530_phy_write_c22,
.phy_read_c45 = mt7530_phy_read_c45,
.phy_write_c45 = mt7530_phy_write_c45,
.pad_setup = mt7530_pad_clk_setup,
.mac_port_get_caps = mt7530_mac_port_get_caps,
.mac_port_config = mt7530_mac_config,
......@@ -3202,8 +3201,10 @@ static const struct mt753x_info mt753x_table[] = {
.id = ID_MT7531,
.pcs_ops = &mt7531_pcs_ops,
.sw_setup = mt7531_setup,
.phy_read = mt7531_ind_phy_read,
.phy_write = mt7531_ind_phy_write,
.phy_read_c22 = mt7531_ind_c22_phy_read,
.phy_write_c22 = mt7531_ind_c22_phy_write,
.phy_read_c45 = mt7531_ind_c45_phy_read,
.phy_write_c45 = mt7531_ind_c45_phy_write,
.pad_setup = mt7531_pad_setup,
.cpu_port_config = mt7531_cpu_port_config,
.mac_port_get_caps = mt7531_mac_port_get_caps,
......@@ -3263,7 +3264,7 @@ mt7530_probe(struct mdio_device *mdiodev)
* properly.
*/
if (!priv->info->sw_setup || !priv->info->pad_setup ||
!priv->info->phy_read || !priv->info->phy_write ||
!priv->info->phy_read_c22 || !priv->info->phy_write_c22 ||
!priv->info->mac_port_get_caps ||
!priv->info->mac_port_config)
return -EINVAL;
......
......@@ -750,8 +750,10 @@ struct mt753x_pcs {
/* struct mt753x_info - This is the main data structure for holding the specific
* part for each supported device
* @sw_setup: Holding the handler to a device initialization
* @phy_read: Holding the way reading PHY port
* @phy_write: Holding the way writing PHY port
* @phy_read_c22: Holding the way reading PHY port using C22
* @phy_write_c22: Holding the way writing PHY port using C22
* @phy_read_c45: Holding the way reading PHY port using C45
* @phy_write_c45: Holding the way writing PHY port using C45
* @pad_setup: Holding the way setting up the bus pad for a certain
* MAC port
* @phy_mode_supported: Check if the PHY type is being supported on a certain
......@@ -767,8 +769,13 @@ struct mt753x_info {
const struct phylink_pcs_ops *pcs_ops;
int (*sw_setup)(struct dsa_switch *ds);
int (*phy_read)(struct mt7530_priv *priv, int port, int regnum);
int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val);
int (*phy_read_c22)(struct mt7530_priv *priv, int port, int regnum);
int (*phy_write_c22)(struct mt7530_priv *priv, int port, int regnum,
u16 val);
int (*phy_read_c45)(struct mt7530_priv *priv, int port, int devad,
int regnum);
int (*phy_write_c45)(struct mt7530_priv *priv, int port, int devad,
int regnum, u16 val);
int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface);
int (*cpu_port_config)(struct dsa_switch *ds, int port);
void (*mac_port_get_caps)(struct dsa_switch *ds, int port,
......
......@@ -149,8 +149,10 @@ struct sja1105_info {
bool (*rxtstamp)(struct dsa_switch *ds, int port, struct sk_buff *skb);
void (*txtstamp)(struct dsa_switch *ds, int port, struct sk_buff *skb);
int (*clocking_setup)(struct sja1105_private *priv);
int (*pcs_mdio_read)(struct mii_bus *bus, int phy, int reg);
int (*pcs_mdio_write)(struct mii_bus *bus, int phy, int reg, u16 val);
int (*pcs_mdio_read_c45)(struct mii_bus *bus, int phy, int mmd,
int reg);
int (*pcs_mdio_write_c45)(struct mii_bus *bus, int phy, int mmd,
int reg, u16 val);
int (*disable_microcontroller)(struct sja1105_private *priv);
const char *name;
bool supports_mii[SJA1105_MAX_NUM_PORTS];
......@@ -303,10 +305,12 @@ void sja1105_frame_memory_partitioning(struct sja1105_private *priv);
/* From sja1105_mdio.c */
int sja1105_mdiobus_register(struct dsa_switch *ds);
void sja1105_mdiobus_unregister(struct dsa_switch *ds);
int sja1105_pcs_mdio_read(struct mii_bus *bus, int phy, int reg);
int sja1105_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val);
int sja1110_pcs_mdio_read(struct mii_bus *bus, int phy, int reg);
int sja1110_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val);
int sja1105_pcs_mdio_read_c45(struct mii_bus *bus, int phy, int mmd, int reg);
int sja1105_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int mmd, int reg,
u16 val);
int sja1110_pcs_mdio_read_c45(struct mii_bus *bus, int phy, int mmd, int reg);
int sja1110_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int mmd, int reg,
u16 val);
/* From sja1105_devlink.c */
int sja1105_devlink_setup(struct dsa_switch *ds);
......
......@@ -7,20 +7,15 @@
#define SJA1110_PCS_BANK_REG SJA1110_SPI_ADDR(0x3fc)
int sja1105_pcs_mdio_read(struct mii_bus *bus, int phy, int reg)
int sja1105_pcs_mdio_read_c45(struct mii_bus *bus, int phy, int mmd, int reg)
{
struct sja1105_mdio_private *mdio_priv = bus->priv;
struct sja1105_private *priv = mdio_priv->priv;
u64 addr;
u32 tmp;
u16 mmd;
int rc;
if (!(reg & MII_ADDR_C45))
return -EINVAL;
mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
addr = (mmd << 16) | (reg & GENMASK(15, 0));
addr = (mmd << 16) | reg;
if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
return 0xffff;
......@@ -37,19 +32,15 @@ int sja1105_pcs_mdio_read(struct mii_bus *bus, int phy, int reg)
return tmp & 0xffff;
}
int sja1105_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
int sja1105_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int mmd,
int reg, u16 val)
{
struct sja1105_mdio_private *mdio_priv = bus->priv;
struct sja1105_private *priv = mdio_priv->priv;
u64 addr;
u32 tmp;
u16 mmd;
if (!(reg & MII_ADDR_C45))
return -EINVAL;
mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
addr = (mmd << 16) | (reg & GENMASK(15, 0));
addr = (mmd << 16) | reg;
tmp = val;
if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
......@@ -58,7 +49,7 @@ int sja1105_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
}
int sja1110_pcs_mdio_read(struct mii_bus *bus, int phy, int reg)
int sja1110_pcs_mdio_read_c45(struct mii_bus *bus, int phy, int mmd, int reg)
{
struct sja1105_mdio_private *mdio_priv = bus->priv;
struct sja1105_private *priv = mdio_priv->priv;
......@@ -66,17 +57,12 @@ int sja1110_pcs_mdio_read(struct mii_bus *bus, int phy, int reg)
int offset, bank;
u64 addr;
u32 tmp;
u16 mmd;
int rc;
if (!(reg & MII_ADDR_C45))
return -EINVAL;
if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
return -ENODEV;
mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
addr = (mmd << 16) | (reg & GENMASK(15, 0));
addr = (mmd << 16) | reg;
if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID1)
return NXP_SJA1110_XPCS_ID >> 16;
......@@ -108,7 +94,8 @@ int sja1110_pcs_mdio_read(struct mii_bus *bus, int phy, int reg)
return tmp & 0xffff;
}
int sja1110_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
int sja1110_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int reg, int mmd,
u16 val)
{
struct sja1105_mdio_private *mdio_priv = bus->priv;
struct sja1105_private *priv = mdio_priv->priv;
......@@ -116,17 +103,12 @@ int sja1110_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
int offset, bank;
u64 addr;
u32 tmp;
u16 mmd;
int rc;
if (!(reg & MII_ADDR_C45))
return -EINVAL;
if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
return -ENODEV;
mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
addr = (mmd << 16) | (reg & GENMASK(15, 0));
addr = (mmd << 16) | reg;
bank = addr >> 8;
offset = addr & GENMASK(7, 0);
......@@ -167,7 +149,7 @@ static u64 sja1105_base_t1_encode_addr(struct sja1105_private *priv,
return regs->mdio_100base_t1 | (phy << 7) | (op << 5) | (xad << 0);
}
static int sja1105_base_t1_mdio_read(struct mii_bus *bus, int phy, int reg)
static int sja1105_base_t1_mdio_read_c22(struct mii_bus *bus, int phy, int reg)
{
struct sja1105_mdio_private *mdio_priv = bus->priv;
struct sja1105_private *priv = mdio_priv->priv;
......@@ -175,30 +157,31 @@ static int sja1105_base_t1_mdio_read(struct mii_bus *bus, int phy, int reg)
u32 tmp;
int rc;
if (reg & MII_ADDR_C45) {
u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
mmd);
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
tmp = reg & MII_REGADDR_C45_MASK;
rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
if (rc < 0)
return rc;
rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
if (rc < 0)
return rc;
return tmp & 0xffff;
}
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
mmd);
static int sja1105_base_t1_mdio_read_c45(struct mii_bus *bus, int phy,
int mmd, int reg)
{
struct sja1105_mdio_private *mdio_priv = bus->priv;
struct sja1105_private *priv = mdio_priv->priv;
u64 addr;
u32 tmp;
int rc;
rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
if (rc < 0)
return rc;
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR, mmd);
return tmp & 0xffff;
}
rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &reg, NULL);
if (rc < 0)
return rc;
/* Clause 22 read */
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA, mmd);
rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
if (rc < 0)
......@@ -207,41 +190,37 @@ static int sja1105_base_t1_mdio_read(struct mii_bus *bus, int phy, int reg)
return tmp & 0xffff;
}
static int sja1105_base_t1_mdio_write(struct mii_bus *bus, int phy, int reg,
u16 val)
static int sja1105_base_t1_mdio_write_c22(struct mii_bus *bus, int phy, int reg,
u16 val)
{
struct sja1105_mdio_private *mdio_priv = bus->priv;
struct sja1105_private *priv = mdio_priv->priv;
u64 addr;
u32 tmp;
int rc;
if (reg & MII_ADDR_C45) {
u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
mmd);
tmp = reg & MII_REGADDR_C45_MASK;
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
if (rc < 0)
return rc;
tmp = val & 0xffff;
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
mmd);
return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
}
tmp = val & 0xffff;
static int sja1105_base_t1_mdio_write_c45(struct mii_bus *bus, int phy,
int mmd, int reg, u16 val)
{
struct sja1105_mdio_private *mdio_priv = bus->priv;
struct sja1105_private *priv = mdio_priv->priv;
u64 addr;
u32 tmp;
int rc;
rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
if (rc < 0)
return rc;
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR, mmd);
return 0;
}
rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &reg, NULL);
if (rc < 0)
return rc;
/* Clause 22 write */
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA, mmd);
tmp = val & 0xffff;
......@@ -360,8 +339,10 @@ static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv,
bus->name = "SJA1110 100base-T1 MDIO bus";
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-t1",
dev_name(priv->ds->dev));
bus->read = sja1105_base_t1_mdio_read;
bus->write = sja1105_base_t1_mdio_write;
bus->read = sja1105_base_t1_mdio_read_c22;
bus->write = sja1105_base_t1_mdio_write_c22;
bus->read_c45 = sja1105_base_t1_mdio_read_c45;
bus->write_c45 = sja1105_base_t1_mdio_write_c45;
bus->parent = priv->ds->dev;
mdio_priv = bus->priv;
mdio_priv->priv = priv;
......@@ -398,7 +379,7 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
int rc = 0;
int port;
if (!priv->info->pcs_mdio_read || !priv->info->pcs_mdio_write)
if (!priv->info->pcs_mdio_read_c45 || !priv->info->pcs_mdio_write_c45)
return 0;
bus = mdiobus_alloc_size(sizeof(*mdio_priv));
......@@ -408,8 +389,8 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
bus->name = "SJA1105 PCS MDIO bus";
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-pcs",
dev_name(ds->dev));
bus->read = priv->info->pcs_mdio_read;
bus->write = priv->info->pcs_mdio_write;
bus->read_c45 = priv->info->pcs_mdio_read_c45;
bus->write_c45 = priv->info->pcs_mdio_write_c45;
bus->parent = ds->dev;
/* There is no PHY on this MDIO bus => mask out all PHY addresses
* from auto probing.
......
......@@ -719,8 +719,8 @@ const struct sja1105_info sja1105r_info = {
.ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing,
.rxtstamp = sja1105_rxtstamp,
.clocking_setup = sja1105_clocking_setup,
.pcs_mdio_read = sja1105_pcs_mdio_read,
.pcs_mdio_write = sja1105_pcs_mdio_write,
.pcs_mdio_read_c45 = sja1105_pcs_mdio_read_c45,
.pcs_mdio_write_c45 = sja1105_pcs_mdio_write_c45,
.regs = &sja1105pqrs_regs,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
......@@ -756,8 +756,8 @@ const struct sja1105_info sja1105s_info = {
.ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing,
.rxtstamp = sja1105_rxtstamp,
.clocking_setup = sja1105_clocking_setup,
.pcs_mdio_read = sja1105_pcs_mdio_read,
.pcs_mdio_write = sja1105_pcs_mdio_write,
.pcs_mdio_read_c45 = sja1105_pcs_mdio_read_c45,
.pcs_mdio_write_c45 = sja1105_pcs_mdio_write_c45,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 3,
......@@ -794,8 +794,8 @@ const struct sja1105_info sja1110a_info = {
.rxtstamp = sja1110_rxtstamp,
.txtstamp = sja1110_txtstamp,
.disable_microcontroller = sja1110_disable_microcontroller,
.pcs_mdio_read = sja1110_pcs_mdio_read,
.pcs_mdio_write = sja1110_pcs_mdio_write,
.pcs_mdio_read_c45 = sja1110_pcs_mdio_read_c45,
.pcs_mdio_write_c45 = sja1110_pcs_mdio_write_c45,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 4,
......@@ -844,8 +844,8 @@ const struct sja1105_info sja1110b_info = {
.rxtstamp = sja1110_rxtstamp,
.txtstamp = sja1110_txtstamp,
.disable_microcontroller = sja1110_disable_microcontroller,
.pcs_mdio_read = sja1110_pcs_mdio_read,
.pcs_mdio_write = sja1110_pcs_mdio_write,
.pcs_mdio_read_c45 = sja1110_pcs_mdio_read_c45,
.pcs_mdio_write_c45 = sja1110_pcs_mdio_write_c45,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 4,
......@@ -894,8 +894,8 @@ const struct sja1105_info sja1110c_info = {
.rxtstamp = sja1110_rxtstamp,
.txtstamp = sja1110_txtstamp,
.disable_microcontroller = sja1110_disable_microcontroller,
.pcs_mdio_read = sja1110_pcs_mdio_read,
.pcs_mdio_write = sja1110_pcs_mdio_write,
.pcs_mdio_read_c45 = sja1110_pcs_mdio_read_c45,
.pcs_mdio_write_c45 = sja1110_pcs_mdio_write_c45,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 4,
......@@ -944,8 +944,8 @@ const struct sja1105_info sja1110d_info = {
.rxtstamp = sja1110_rxtstamp,
.txtstamp = sja1110_txtstamp,
.disable_microcontroller = sja1110_disable_microcontroller,
.pcs_mdio_read = sja1110_pcs_mdio_read,
.pcs_mdio_write = sja1110_pcs_mdio_write,
.pcs_mdio_read_c45 = sja1110_pcs_mdio_read_c45,
.pcs_mdio_write_c45 = sja1110_pcs_mdio_write_c45,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 4,
......
......@@ -1699,20 +1699,21 @@ do { \
} while (0)
/* Macros for building, reading or writing register values or bits
* using MDIO. Different from above because of the use of standardized
* Linux include values. No shifting is performed with the bit
* operations, everything works on mask values.
* using MDIO.
*/
#define XGBE_ADDR_C45 BIT(30)
#define XMDIO_READ(_pdata, _mmd, _reg) \
((_pdata)->hw_if.read_mmd_regs((_pdata), 0, \
MII_ADDR_C45 | (_mmd << 16) | ((_reg) & 0xffff)))
XGBE_ADDR_C45 | (_mmd << 16) | ((_reg) & 0xffff)))
#define XMDIO_READ_BITS(_pdata, _mmd, _reg, _mask) \
(XMDIO_READ((_pdata), _mmd, _reg) & _mask)
#define XMDIO_WRITE(_pdata, _mmd, _reg, _val) \
((_pdata)->hw_if.write_mmd_regs((_pdata), 0, \
MII_ADDR_C45 | (_mmd << 16) | ((_reg) & 0xffff), (_val)))
XGBE_ADDR_C45 | (_mmd << 16) | ((_reg) & 0xffff), (_val)))
#define XMDIO_WRITE_BITS(_pdata, _mmd, _reg, _mask, _val) \
do { \
......
......@@ -1150,8 +1150,8 @@ static int xgbe_read_mmd_regs_v2(struct xgbe_prv_data *pdata, int prtad,
unsigned int mmd_address, index, offset;
int mmd_data;
if (mmd_reg & MII_ADDR_C45)
mmd_address = mmd_reg & ~MII_ADDR_C45;
if (mmd_reg & XGBE_ADDR_C45)
mmd_address = mmd_reg & ~XGBE_ADDR_C45;
else
mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
......@@ -1182,8 +1182,8 @@ static void xgbe_write_mmd_regs_v2(struct xgbe_prv_data *pdata, int prtad,
unsigned long flags;
unsigned int mmd_address, index, offset;
if (mmd_reg & MII_ADDR_C45)
mmd_address = mmd_reg & ~MII_ADDR_C45;
if (mmd_reg & XGBE_ADDR_C45)
mmd_address = mmd_reg & ~XGBE_ADDR_C45;
else
mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
......@@ -1213,8 +1213,8 @@ static int xgbe_read_mmd_regs_v1(struct xgbe_prv_data *pdata, int prtad,
unsigned int mmd_address;
int mmd_data;
if (mmd_reg & MII_ADDR_C45)
mmd_address = mmd_reg & ~MII_ADDR_C45;
if (mmd_reg & XGBE_ADDR_C45)
mmd_address = mmd_reg & ~XGBE_ADDR_C45;
else
mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
......@@ -1241,8 +1241,8 @@ static void xgbe_write_mmd_regs_v1(struct xgbe_prv_data *pdata, int prtad,
unsigned int mmd_address;
unsigned long flags;
if (mmd_reg & MII_ADDR_C45)
mmd_address = mmd_reg & ~MII_ADDR_C45;
if (mmd_reg & XGBE_ADDR_C45)
mmd_address = mmd_reg & ~XGBE_ADDR_C45;
else
mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
......@@ -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;
XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, RA, reg);
......@@ -1301,14 +1310,13 @@ static unsigned int xgbe_create_mdio_sca(int port, int reg)
return mdio_sca;
}
static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
int reg, u16 val)
static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata,
unsigned int mdio_sca, u16 val)
{
unsigned int mdio_sca, mdio_sccd;
unsigned int mdio_sccd;
reinit_completion(&pdata->mdio_complete);
mdio_sca = xgbe_create_mdio_sca(addr, reg);
XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
mdio_sccd = 0;
......@@ -1325,14 +1333,33 @@ static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
return 0;
}
static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
int reg)
static int xgbe_write_ext_mii_regs_c22(struct xgbe_prv_data *pdata, int addr,
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_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_sca, mdio_sccd;
unsigned int mdio_sccd;
reinit_completion(&pdata->mdio_complete);
mdio_sca = xgbe_create_mdio_sca(addr, reg);
XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
mdio_sccd = 0;
......@@ -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);
}
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,
enum xgbe_mdio_mode mode)
{
......@@ -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_ext_mii_mode = xgbe_set_ext_mii_mode;
hw_if->read_ext_mii_regs = xgbe_read_ext_mii_regs;
hw_if->write_ext_mii_regs = xgbe_write_ext_mii_regs;
hw_if->read_ext_mii_regs_c22 = xgbe_read_ext_mii_regs_c22;
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->clr_gpio = xgbe_clr_gpio;
......
......@@ -600,20 +600,27 @@ static int xgbe_phy_get_comm_ownership(struct xgbe_prv_data *pdata)
return -ETIMEDOUT;
}
static int xgbe_phy_mdio_mii_write(struct xgbe_prv_data *pdata, int addr,
int reg, u16 val)
static int xgbe_phy_mdio_mii_write_c22(struct xgbe_prv_data *pdata, int addr,
int reg, u16 val)
{
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)
return -ENOTSUPP;
}
if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL22)
return -EOPNOTSUPP;
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;
return pdata->hw_if.write_ext_mii_regs(pdata, addr, reg, val);
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)
......@@ -638,7 +645,8 @@ static int xgbe_phy_i2c_mii_write(struct xgbe_prv_data *pdata, int reg, u16 val)
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_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)
if (phy_data->conn_type == XGBE_CONN_TYPE_SFP)
ret = xgbe_phy_i2c_mii_write(pdata, reg, val);
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
ret = -ENOTSUPP;
ret = -EOPNOTSUPP;
xgbe_phy_put_comm_ownership(pdata);
return ret;
}
static int xgbe_phy_mdio_mii_read(struct xgbe_prv_data *pdata, int addr,
int reg)
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;
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)
return -ENOTSUPP;
}
ret = xgbe_phy_get_comm_ownership(pdata);
if (ret)
return ret;
return pdata->hw_if.read_ext_mii_regs(pdata, addr, reg);
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);
return ret;
}
static int xgbe_phy_mdio_mii_read_c22(struct xgbe_prv_data *pdata, int addr,
int reg)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL22)
return -EOPNOTSUPP;
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)
......@@ -698,7 +735,7 @@ static int xgbe_phy_i2c_mii_read(struct xgbe_prv_data *pdata, int reg)
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_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)
if (phy_data->conn_type == XGBE_CONN_TYPE_SFP)
ret = xgbe_phy_i2c_mii_read(pdata, reg);
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
ret = -ENOTSUPP;
......@@ -1929,8 +1989,8 @@ 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_val = (u16)mode;
return pdata->hw_if.write_ext_mii_regs(pdata, phy_data->redrv_addr,
redrv_reg, redrv_val);
return pdata->hw_if.write_ext_mii_regs_c22(pdata, phy_data->redrv_addr,
redrv_reg, redrv_val);
}
static int xgbe_phy_set_redrv_mode_i2c(struct xgbe_prv_data *pdata,
......@@ -3502,8 +3562,10 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
mii->priv = pdata;
mii->name = "amd-xgbe-mii";
mii->read = xgbe_phy_mii_read;
mii->write = xgbe_phy_mii_write;
mii->read = xgbe_phy_mii_read_c22;
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->phy_mask = ~0;
snprintf(mii->id, sizeof(mii->id), "%s", dev_name(pdata->dev));
......
......@@ -775,8 +775,11 @@ struct xgbe_hw_if {
int (*set_ext_mii_mode)(struct xgbe_prv_data *, unsigned int,
enum xgbe_mdio_mode);
int (*read_ext_mii_regs)(struct xgbe_prv_data *, int, int);
int (*write_ext_mii_regs)(struct xgbe_prv_data *, int, int, u16);
int (*read_ext_mii_regs_c22)(struct xgbe_prv_data *, int, int);
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 (*clr_gpio)(struct xgbe_prv_data *, unsigned int);
......
......@@ -334,7 +334,7 @@ static int macb_mdio_wait_for_idle(struct macb *bp)
1, MACB_MDIO_TIMEOUT);
}
static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
static int macb_mdio_read_c22(struct mii_bus *bus, int mii_id, int regnum)
{
struct macb *bp = bus->priv;
int status;
......@@ -347,31 +347,58 @@ static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
if (status < 0)
goto mdio_read_exit;
if (regnum & MII_ADDR_C45) {
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
| MACB_BF(RW, MACB_MAN_C45_ADDR)
| MACB_BF(PHYA, mii_id)
| MACB_BF(REGA, (regnum >> 16) & 0x1F)
| MACB_BF(DATA, regnum & 0xFFFF)
| MACB_BF(CODE, MACB_MAN_C45_CODE)));
status = macb_mdio_wait_for_idle(bp);
if (status < 0)
goto mdio_read_exit;
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
| MACB_BF(RW, MACB_MAN_C45_READ)
| MACB_BF(PHYA, mii_id)
| MACB_BF(REGA, (regnum >> 16) & 0x1F)
| MACB_BF(CODE, MACB_MAN_C45_CODE)));
} else {
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C22_SOF)
| MACB_BF(RW, MACB_MAN_C22_READ)
| MACB_BF(PHYA, mii_id)
| MACB_BF(REGA, regnum)
| MACB_BF(CODE, MACB_MAN_C22_CODE)));
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C22_SOF)
| MACB_BF(RW, MACB_MAN_C22_READ)
| MACB_BF(PHYA, mii_id)
| MACB_BF(REGA, regnum)
| MACB_BF(CODE, MACB_MAN_C22_CODE)));
status = macb_mdio_wait_for_idle(bp);
if (status < 0)
goto mdio_read_exit;
status = MACB_BFEXT(DATA, macb_readl(bp, MAN));
mdio_read_exit:
pm_runtime_mark_last_busy(&bp->pdev->dev);
pm_runtime_put_autosuspend(&bp->pdev->dev);
mdio_pm_exit:
return status;
}
static int macb_mdio_read_c45(struct mii_bus *bus, int mii_id, int devad,
int regnum)
{
struct macb *bp = bus->priv;
int status;
status = pm_runtime_get_sync(&bp->pdev->dev);
if (status < 0) {
pm_runtime_put_noidle(&bp->pdev->dev);
goto mdio_pm_exit;
}
status = macb_mdio_wait_for_idle(bp);
if (status < 0)
goto mdio_read_exit;
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
| MACB_BF(RW, MACB_MAN_C45_ADDR)
| MACB_BF(PHYA, mii_id)
| MACB_BF(REGA, devad & 0x1F)
| MACB_BF(DATA, regnum & 0xFFFF)
| MACB_BF(CODE, MACB_MAN_C45_CODE)));
status = macb_mdio_wait_for_idle(bp);
if (status < 0)
goto mdio_read_exit;
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
| MACB_BF(RW, MACB_MAN_C45_READ)
| MACB_BF(PHYA, mii_id)
| MACB_BF(REGA, devad & 0x1F)
| MACB_BF(CODE, MACB_MAN_C45_CODE)));
status = macb_mdio_wait_for_idle(bp);
if (status < 0)
goto mdio_read_exit;
......@@ -385,8 +412,8 @@ static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
return status;
}
static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
u16 value)
static int macb_mdio_write_c22(struct mii_bus *bus, int mii_id, int regnum,
u16 value)
{
struct macb *bp = bus->priv;
int status;
......@@ -399,37 +426,63 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
if (status < 0)
goto mdio_write_exit;
if (regnum & MII_ADDR_C45) {
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
| MACB_BF(RW, MACB_MAN_C45_ADDR)
| MACB_BF(PHYA, mii_id)
| MACB_BF(REGA, (regnum >> 16) & 0x1F)
| MACB_BF(DATA, regnum & 0xFFFF)
| MACB_BF(CODE, MACB_MAN_C45_CODE)));
status = macb_mdio_wait_for_idle(bp);
if (status < 0)
goto mdio_write_exit;
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
| MACB_BF(RW, MACB_MAN_C45_WRITE)
| MACB_BF(PHYA, mii_id)
| MACB_BF(REGA, (regnum >> 16) & 0x1F)
| MACB_BF(CODE, MACB_MAN_C45_CODE)
| MACB_BF(DATA, value)));
} else {
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C22_SOF)
| MACB_BF(RW, MACB_MAN_C22_WRITE)
| MACB_BF(PHYA, mii_id)
| MACB_BF(REGA, regnum)
| MACB_BF(CODE, MACB_MAN_C22_CODE)
| MACB_BF(DATA, value)));
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C22_SOF)
| MACB_BF(RW, MACB_MAN_C22_WRITE)
| MACB_BF(PHYA, mii_id)
| MACB_BF(REGA, regnum)
| MACB_BF(CODE, MACB_MAN_C22_CODE)
| MACB_BF(DATA, value)));
status = macb_mdio_wait_for_idle(bp);
if (status < 0)
goto mdio_write_exit;
mdio_write_exit:
pm_runtime_mark_last_busy(&bp->pdev->dev);
pm_runtime_put_autosuspend(&bp->pdev->dev);
mdio_pm_exit:
return status;
}
static int macb_mdio_write_c45(struct mii_bus *bus, int mii_id,
int devad, int regnum,
u16 value)
{
struct macb *bp = bus->priv;
int status;
status = pm_runtime_get_sync(&bp->pdev->dev);
if (status < 0) {
pm_runtime_put_noidle(&bp->pdev->dev);
goto mdio_pm_exit;
}
status = macb_mdio_wait_for_idle(bp);
if (status < 0)
goto mdio_write_exit;
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
| MACB_BF(RW, MACB_MAN_C45_ADDR)
| MACB_BF(PHYA, mii_id)
| MACB_BF(REGA, devad & 0x1F)
| MACB_BF(DATA, regnum & 0xFFFF)
| MACB_BF(CODE, MACB_MAN_C45_CODE)));
status = macb_mdio_wait_for_idle(bp);
if (status < 0)
goto mdio_write_exit;
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
| MACB_BF(RW, MACB_MAN_C45_WRITE)
| MACB_BF(PHYA, mii_id)
| MACB_BF(REGA, devad & 0x1F)
| MACB_BF(CODE, MACB_MAN_C45_CODE)
| MACB_BF(DATA, value)));
status = macb_mdio_wait_for_idle(bp);
if (status < 0)
goto mdio_write_exit;
mdio_write_exit:
pm_runtime_mark_last_busy(&bp->pdev->dev);
pm_runtime_put_autosuspend(&bp->pdev->dev);
......@@ -902,8 +955,10 @@ static int macb_mii_init(struct macb *bp)
}
bp->mii_bus->name = "MACB_mii_bus";
bp->mii_bus->read = &macb_mdio_read;
bp->mii_bus->write = &macb_mdio_write;
bp->mii_bus->read = &macb_mdio_read_c22;
bp->mii_bus->write = &macb_mdio_write_c22;
bp->mii_bus->read_c45 = &macb_mdio_read_c45;
bp->mii_bus->write_c45 = &macb_mdio_write_c45;
snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
bp->pdev->name, bp->pdev->id);
bp->mii_bus->priv = bp;
......
......@@ -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
* @phy_id: phy id
* @regnum: register num
......@@ -214,21 +214,19 @@ static void hns_mdio_cmd_write(struct hns_mdio_device *mdio_dev,
*
* Return 0 on success, negative on failure
*/
static int hns_mdio_write(struct mii_bus *bus,
int phy_id, int regnum, u16 data)
static int hns_mdio_write_c22(struct mii_bus *bus,
int phy_id, int regnum, u16 data)
{
int ret;
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);
u8 op;
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, is_c45=%d, devad=%d, reg=%#x, write data=%d\n",
phy_id, is_c45, devad, reg, data);
dev_dbg(&bus->dev, "phy id=%d, reg=%#x, write data=%d\n",
phy_id, reg, data);
/* wait for ready */
ret = hns_mdio_wait_ready(bus);
......@@ -237,58 +235,91 @@ static int hns_mdio_write(struct mii_bus *bus,
return ret;
}
if (!is_c45) {
cmd_reg_cfg = reg;
op = MDIO_C22_WRITE;
} else {
/* config the cmd-reg to write addr*/
MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
MDIO_ADDR_DATA_S, reg);
cmd_reg_cfg = reg;
op = MDIO_C22_WRITE;
hns_mdio_cmd_write(mdio_dev, is_c45,
MDIO_C45_WRITE_ADDR, phy_id, devad);
MDIO_SET_REG_FIELD(mdio_dev, MDIO_WDATA_REG, MDIO_WDATA_DATA_M,
MDIO_WDATA_DATA_S, data);
/* 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;
}
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*/
MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
MDIO_ADDR_DATA_S, reg);
/* config the data needed writing */
cmd_reg_cfg = devad;
op = MDIO_C45_WRITE_DATA;
hns_mdio_cmd_write(mdio_dev, true, MDIO_C45_WRITE_ADDR, phy_id, devad);
/* 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;
}
/* config the data needed writing */
cmd_reg_cfg = devad;
op = MDIO_C45_WRITE_DATA;
MDIO_SET_REG_FIELD(mdio_dev, MDIO_WDATA_REG, MDIO_WDATA_DATA_M,
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;
}
/**
* hns_mdio_read - access phy register
* hns_mdio_read_c22 - access phy register
* @bus: mdio bus
* @phy_id: phy id
* @regnum: register num
*
* 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;
u16 reg_val;
u8 devad = ((regnum >> 16) & 0x1f);
u8 is_c45 = !!(regnum & MII_ADDR_C45);
u16 reg = (u16)(regnum & 0xffff);
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",
bus->id, mdio_dev->vbase);
dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x!\n",
phy_id, is_c45, devad, reg);
dev_dbg(&bus->dev, "phy id=%d, reg=%#x!\n", phy_id, reg);
/* Step 1: wait for ready */
ret = hns_mdio_wait_ready(bus);
......@@ -297,29 +328,74 @@ static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
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_ADDR_DATA_S, reg);
hns_mdio_cmd_write(mdio_dev, false, MDIO_C22_READ, phy_id, reg);
/* Step 2; config the cmd-reg to write addr*/
hns_mdio_cmd_write(mdio_dev, is_c45,
MDIO_C45_WRITE_ADDR, phy_id, devad);
/* 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;
}
/* Step 3: 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;
}
hns_mdio_cmd_write(mdio_dev, is_c45,
MDIO_C45_READ, phy_id, devad);
/* 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;
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, devad=%d, reg=%#x!\n",
phy_id, devad, 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;
}
MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
MDIO_ADDR_DATA_S, reg);
/* Step 2; config the cmd-reg to write addr*/
hns_mdio_cmd_write(mdio_dev, true, MDIO_C45_WRITE_ADDR, phy_id, devad);
/* Step 3: 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;
}
/* Step 5: waiting for MDIO_COMMAND_REG's mdio_start==0,*/
hns_mdio_cmd_write(mdio_dev, true, MDIO_C45_READ, phy_id, devad);
/* Step 5: 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) {
......@@ -438,8 +514,10 @@ static int hns_mdio_probe(struct platform_device *pdev)
}
new_bus->name = MDIO_BUS_NAME;
new_bus->read = hns_mdio_read;
new_bus->write = hns_mdio_write;
new_bus->read = hns_mdio_read_c22;
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->priv = mdio_dev;
new_bus->parent = &pdev->dev;
......
......@@ -8937,7 +8937,8 @@ ixgbe_mdio_read(struct net_device *netdev, int prtad, int devad, u16 addr)
int regnum = addr;
if (devad != MDIO_DEVAD_NONE)
regnum |= (devad << 16) | MII_ADDR_C45;
return mdiobus_c45_read(adapter->mii_bus, prtad,
devad, regnum);
return mdiobus_read(adapter->mii_bus, prtad, regnum);
}
......@@ -8960,7 +8961,8 @@ static int ixgbe_mdio_write(struct net_device *netdev, int prtad, int devad,
int regnum = addr;
if (devad != MDIO_DEVAD_NONE)
regnum |= (devad << 16) | MII_ADDR_C45;
return mdiobus_c45_write(adapter->mii_bus, prtad, devad,
regnum, value);
return mdiobus_write(adapter->mii_bus, prtad, regnum, value);
}
......
......@@ -1081,40 +1081,59 @@ static const struct ethtool_ops nixge_ethtool_ops = {
.get_link = ethtool_op_get_link,
};
static int nixge_mdio_read(struct mii_bus *bus, int phy_id, int reg)
static int nixge_mdio_read_c22(struct mii_bus *bus, int phy_id, int reg)
{
struct nixge_priv *priv = bus->priv;
u32 status, tmp;
int err;
u16 device;
if (reg & MII_ADDR_C45) {
device = (reg >> 16) & 0x1f;
device = reg & 0x1f;
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_ADDR, reg & 0xffff);
tmp = NIXGE_MDIO_CLAUSE22 | NIXGE_MDIO_OP(NIXGE_MDIO_C22_READ) |
NIXGE_MDIO_ADDR(phy_id) | NIXGE_MDIO_MMD(device);
tmp = NIXGE_MDIO_CLAUSE45 | NIXGE_MDIO_OP(NIXGE_MDIO_OP_ADDRESS)
| NIXGE_MDIO_ADDR(phy_id) | NIXGE_MDIO_MMD(device);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_OP, tmp);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_CTRL, 1);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_OP, tmp);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_CTRL, 1);
err = nixge_ctrl_poll_timeout(priv, NIXGE_REG_MDIO_CTRL, status,
!status, 10, 1000);
if (err) {
dev_err(priv->dev, "timeout setting read command");
return err;
}
err = nixge_ctrl_poll_timeout(priv, NIXGE_REG_MDIO_CTRL, status,
!status, 10, 1000);
if (err) {
dev_err(priv->dev, "timeout setting address");
return err;
}
status = nixge_ctrl_read_reg(priv, NIXGE_REG_MDIO_DATA);
tmp = NIXGE_MDIO_CLAUSE45 | NIXGE_MDIO_OP(NIXGE_MDIO_C45_READ) |
NIXGE_MDIO_ADDR(phy_id) | NIXGE_MDIO_MMD(device);
} else {
device = reg & 0x1f;
return status;
}
tmp = NIXGE_MDIO_CLAUSE22 | NIXGE_MDIO_OP(NIXGE_MDIO_C22_READ) |
NIXGE_MDIO_ADDR(phy_id) | NIXGE_MDIO_MMD(device);
static int nixge_mdio_read_c45(struct mii_bus *bus, int phy_id, int device,
int reg)
{
struct nixge_priv *priv = bus->priv;
u32 status, tmp;
int err;
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_ADDR, reg & 0xffff);
tmp = NIXGE_MDIO_CLAUSE45 |
NIXGE_MDIO_OP(NIXGE_MDIO_OP_ADDRESS) |
NIXGE_MDIO_ADDR(phy_id) | NIXGE_MDIO_MMD(device);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_OP, tmp);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_CTRL, 1);
err = nixge_ctrl_poll_timeout(priv, NIXGE_REG_MDIO_CTRL, status,
!status, 10, 1000);
if (err) {
dev_err(priv->dev, "timeout setting address");
return err;
}
tmp = NIXGE_MDIO_CLAUSE45 | NIXGE_MDIO_OP(NIXGE_MDIO_C45_READ) |
NIXGE_MDIO_ADDR(phy_id) | NIXGE_MDIO_MMD(device);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_OP, tmp);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_CTRL, 1);
......@@ -1130,57 +1149,65 @@ static int nixge_mdio_read(struct mii_bus *bus, int phy_id, int reg)
return status;
}
static int nixge_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
static int nixge_mdio_write_c22(struct mii_bus *bus, int phy_id, int reg,
u16 val)
{
struct nixge_priv *priv = bus->priv;
u32 status, tmp;
u16 device;
int err;
if (reg & MII_ADDR_C45) {
device = (reg >> 16) & 0x1f;
device = reg & 0x1f;
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_ADDR, reg & 0xffff);
tmp = NIXGE_MDIO_CLAUSE22 | NIXGE_MDIO_OP(NIXGE_MDIO_C22_WRITE) |
NIXGE_MDIO_ADDR(phy_id) | NIXGE_MDIO_MMD(device);
tmp = NIXGE_MDIO_CLAUSE45 | NIXGE_MDIO_OP(NIXGE_MDIO_OP_ADDRESS)
| NIXGE_MDIO_ADDR(phy_id) | NIXGE_MDIO_MMD(device);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_DATA, val);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_OP, tmp);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_CTRL, 1);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_OP, tmp);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_CTRL, 1);
err = nixge_ctrl_poll_timeout(priv, NIXGE_REG_MDIO_CTRL, status,
!status, 10, 1000);
if (err)
dev_err(priv->dev, "timeout setting write command");
err = nixge_ctrl_poll_timeout(priv, NIXGE_REG_MDIO_CTRL, status,
!status, 10, 1000);
if (err) {
dev_err(priv->dev, "timeout setting address");
return err;
}
return err;
}
tmp = NIXGE_MDIO_CLAUSE45 | NIXGE_MDIO_OP(NIXGE_MDIO_C45_WRITE)
| NIXGE_MDIO_ADDR(phy_id) | NIXGE_MDIO_MMD(device);
static int nixge_mdio_write_c45(struct mii_bus *bus, int phy_id,
int device, int reg, u16 val)
{
struct nixge_priv *priv = bus->priv;
u32 status, tmp;
int err;
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_DATA, val);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_OP, tmp);
err = nixge_ctrl_poll_timeout(priv, NIXGE_REG_MDIO_CTRL, status,
!status, 10, 1000);
if (err)
dev_err(priv->dev, "timeout setting write command");
} else {
device = reg & 0x1f;
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_ADDR, reg & 0xffff);
tmp = NIXGE_MDIO_CLAUSE22 |
NIXGE_MDIO_OP(NIXGE_MDIO_C22_WRITE) |
NIXGE_MDIO_ADDR(phy_id) | NIXGE_MDIO_MMD(device);
tmp = NIXGE_MDIO_CLAUSE45 |
NIXGE_MDIO_OP(NIXGE_MDIO_OP_ADDRESS) |
NIXGE_MDIO_ADDR(phy_id) | NIXGE_MDIO_MMD(device);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_DATA, val);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_OP, tmp);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_CTRL, 1);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_OP, tmp);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_CTRL, 1);
err = nixge_ctrl_poll_timeout(priv, NIXGE_REG_MDIO_CTRL, status,
!status, 10, 1000);
if (err)
dev_err(priv->dev, "timeout setting write command");
err = nixge_ctrl_poll_timeout(priv, NIXGE_REG_MDIO_CTRL, status,
!status, 10, 1000);
if (err) {
dev_err(priv->dev, "timeout setting address");
return err;
}
tmp = NIXGE_MDIO_CLAUSE45 | NIXGE_MDIO_OP(NIXGE_MDIO_C45_WRITE) |
NIXGE_MDIO_ADDR(phy_id) | NIXGE_MDIO_MMD(device);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_DATA, val);
nixge_ctrl_write_reg(priv, NIXGE_REG_MDIO_OP, tmp);
err = nixge_ctrl_poll_timeout(priv, NIXGE_REG_MDIO_CTRL, status,
!status, 10, 1000);
if (err)
dev_err(priv->dev, "timeout setting write command");
return err;
}
......@@ -1195,8 +1222,10 @@ static int nixge_mdio_setup(struct nixge_priv *priv, struct device_node *np)
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(priv->dev));
bus->priv = priv;
bus->name = "nixge_mii_bus";
bus->read = nixge_mdio_read;
bus->write = nixge_mdio_write;
bus->read = nixge_mdio_read_c22;
bus->write = nixge_mdio_write_c22;
bus->read_c45 = nixge_mdio_read_c45;
bus->write_c45 = nixge_mdio_write_c45;
bus->parent = priv->dev;
priv->mii_bus = bus;
......
......@@ -1024,34 +1024,18 @@ static int rswitch_etha_set_access(struct rswitch_etha *etha, bool read,
return ret;
}
static int rswitch_etha_mii_read(struct mii_bus *bus, int addr, int regnum)
static int rswitch_etha_mii_read_c45(struct mii_bus *bus, int addr, int devad,
int regad)
{
struct rswitch_etha *etha = bus->priv;
int mode, devad, regad;
mode = regnum & MII_ADDR_C45;
devad = (regnum >> MII_DEVADDR_C45_SHIFT) & 0x1f;
regad = regnum & MII_REGADDR_C45_MASK;
/* Not support Clause 22 access method */
if (!mode)
return -EOPNOTSUPP;
return rswitch_etha_set_access(etha, true, addr, devad, regad, 0);
}
static int rswitch_etha_mii_write(struct mii_bus *bus, int addr, int regnum, u16 val)
static int rswitch_etha_mii_write_c45(struct mii_bus *bus, int addr, int devad,
int regad, u16 val)
{
struct rswitch_etha *etha = bus->priv;
int mode, devad, regad;
mode = regnum & MII_ADDR_C45;
devad = (regnum >> MII_DEVADDR_C45_SHIFT) & 0x1f;
regad = regnum & MII_REGADDR_C45_MASK;
/* Not support Clause 22 access method */
if (!mode)
return -EOPNOTSUPP;
return rswitch_etha_set_access(etha, false, addr, devad, regad, val);
}
......@@ -1142,8 +1126,8 @@ static int rswitch_mii_register(struct rswitch_device *rdev)
mii_bus->name = "rswitch_mii";
sprintf(mii_bus->id, "etha%d", rdev->etha->index);
mii_bus->priv = rdev->etha;
mii_bus->read = rswitch_etha_mii_read;
mii_bus->write = rswitch_etha_mii_write;
mii_bus->read_c45 = rswitch_etha_mii_read_c45;
mii_bus->write_c45 = rswitch_etha_mii_write_c45;
mii_bus->parent = &rdev->priv->pdev->dev;
mdio_np = rswitch_get_mdio_node(rdev);
......
......@@ -50,12 +50,12 @@ static void sxgbe_mdio_ctrl_data(struct sxgbe_priv_data *sp, u32 cmd,
}
static void sxgbe_mdio_c45(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr,
int phyreg, u16 phydata)
int devad, int phyreg, u16 phydata)
{
u32 reg;
/* set mdio address register */
reg = ((phyreg >> 16) & 0x1f) << 21;
reg = (devad & 0x1f) << 21;
reg |= (phyaddr << 16) | (phyreg & 0xffff);
writel(reg, sp->ioaddr + sp->hw->mii.addr);
......@@ -76,8 +76,8 @@ static void sxgbe_mdio_c22(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr,
sxgbe_mdio_ctrl_data(sp, cmd, phydata);
}
static int sxgbe_mdio_access(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr,
int phyreg, u16 phydata)
static int sxgbe_mdio_access_c22(struct sxgbe_priv_data *sp, u32 cmd,
int phyaddr, int phyreg, u16 phydata)
{
const struct mii_regs *mii = &sp->hw->mii;
int rc;
......@@ -86,33 +86,46 @@ static int sxgbe_mdio_access(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr,
if (rc < 0)
return rc;
if (phyreg & MII_ADDR_C45) {
sxgbe_mdio_c45(sp, cmd, phyaddr, phyreg, phydata);
} else {
/* Ports 0-3 only support C22. */
if (phyaddr >= 4)
return -ENODEV;
/* Ports 0-3 only support C22. */
if (phyaddr >= 4)
return -ENODEV;
sxgbe_mdio_c22(sp, cmd, phyaddr, phyreg, phydata);
}
sxgbe_mdio_c22(sp, cmd, phyaddr, phyreg, phydata);
return sxgbe_mdio_busy_wait(sp->ioaddr, mii->data);
}
static int sxgbe_mdio_access_c45(struct sxgbe_priv_data *sp, u32 cmd,
int phyaddr, int devad, int phyreg,
u16 phydata)
{
const struct mii_regs *mii = &sp->hw->mii;
int rc;
rc = sxgbe_mdio_busy_wait(sp->ioaddr, mii->data);
if (rc < 0)
return rc;
sxgbe_mdio_c45(sp, cmd, phyaddr, devad, phyreg, phydata);
return sxgbe_mdio_busy_wait(sp->ioaddr, mii->data);
}
/**
* sxgbe_mdio_read
* sxgbe_mdio_read_c22
* @bus: points to the mii_bus structure
* @phyaddr: address of phy port
* @phyreg: address of register with in phy register
* Description: this function used for C45 and C22 MDIO Read
* Description: this function used for C22 MDIO Read
*/
static int sxgbe_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
static int sxgbe_mdio_read_c22(struct mii_bus *bus, int phyaddr, int phyreg)
{
struct net_device *ndev = bus->priv;
struct sxgbe_priv_data *priv = netdev_priv(ndev);
int rc;
rc = sxgbe_mdio_access(priv, SXGBE_SMA_READ_CMD, phyaddr, phyreg, 0);
rc = sxgbe_mdio_access_c22(priv, SXGBE_SMA_READ_CMD, phyaddr,
phyreg, 0);
if (rc < 0)
return rc;
......@@ -120,21 +133,63 @@ static int sxgbe_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
}
/**
* sxgbe_mdio_write
* sxgbe_mdio_read_c45
* @bus: points to the mii_bus structure
* @phyaddr: address of phy port
* @devad: device (MMD) address
* @phyreg: address of register with in phy register
* Description: this function used for C45 MDIO Read
*/
static int sxgbe_mdio_read_c45(struct mii_bus *bus, int phyaddr, int devad,
int phyreg)
{
struct net_device *ndev = bus->priv;
struct sxgbe_priv_data *priv = netdev_priv(ndev);
int rc;
rc = sxgbe_mdio_access_c45(priv, SXGBE_SMA_READ_CMD, phyaddr,
devad, phyreg, 0);
if (rc < 0)
return rc;
return readl(priv->ioaddr + priv->hw->mii.data) & 0xffff;
}
/**
* sxgbe_mdio_write_c22
* @bus: points to the mii_bus structure
* @phyaddr: address of phy port
* @phyreg: address of phy registers
* @phydata: data to be written into phy register
* Description: this function is used for C22 MDIO write
*/
static int sxgbe_mdio_write_c22(struct mii_bus *bus, int phyaddr, int phyreg,
u16 phydata)
{
struct net_device *ndev = bus->priv;
struct sxgbe_priv_data *priv = netdev_priv(ndev);
return sxgbe_mdio_access_c22(priv, SXGBE_SMA_WRITE_CMD, phyaddr, phyreg,
phydata);
}
/**
* sxgbe_mdio_write_c45
* @bus: points to the mii_bus structure
* @phyaddr: address of phy port
* @phyreg: address of phy registers
* @devad: device (MMD) address
* @phydata: data to be written into phy register
* Description: this function is used for C45 and C22 MDIO write
* Description: this function is used for C45 MDIO write
*/
static int sxgbe_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
u16 phydata)
static int sxgbe_mdio_write_c45(struct mii_bus *bus, int phyaddr, int devad,
int phyreg, u16 phydata)
{
struct net_device *ndev = bus->priv;
struct sxgbe_priv_data *priv = netdev_priv(ndev);
return sxgbe_mdio_access(priv, SXGBE_SMA_WRITE_CMD, phyaddr, phyreg,
phydata);
return sxgbe_mdio_access_c45(priv, SXGBE_SMA_WRITE_CMD, phyaddr,
devad, phyreg, phydata);
}
int sxgbe_mdio_register(struct net_device *ndev)
......@@ -161,8 +216,10 @@ int sxgbe_mdio_register(struct net_device *ndev)
/* assign mii bus fields */
mdio_bus->name = "sxgbe";
mdio_bus->read = &sxgbe_mdio_read;
mdio_bus->write = &sxgbe_mdio_write;
mdio_bus->read = sxgbe_mdio_read_c22;
mdio_bus->write = sxgbe_mdio_write_c22;
mdio_bus->read_c45 = sxgbe_mdio_read_c45;
mdio_bus->write_c45 = sxgbe_mdio_write_c45;
snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%x",
mdio_bus->name, priv->plat->bus_id);
mdio_bus->priv = ndev;
......
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