Commit 308c8ffd authored by Andrew Lunn's avatar Andrew Lunn Committed by Jakub Kicinski

ixgbe: Separate C22 and C45 transactions

The ixgbe 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 a4d65b1d
......@@ -680,14 +680,14 @@ static s32 ixgbe_msca_cmd(struct ixgbe_hw *hw, u32 cmd)
}
/**
* ixgbe_mii_bus_read_generic - Read a clause 22/45 register with gssr flags
* ixgbe_mii_bus_read_generic_c22 - Read a clause 22 register with gssr flags
* @hw: pointer to hardware structure
* @addr: address
* @regnum: register number
* @gssr: semaphore flags to acquire
**/
static s32 ixgbe_mii_bus_read_generic(struct ixgbe_hw *hw, int addr,
int regnum, u32 gssr)
static s32 ixgbe_mii_bus_read_generic_c22(struct ixgbe_hw *hw, int addr,
int regnum, u32 gssr)
{
u32 hwaddr, cmd;
s32 data;
......@@ -696,31 +696,52 @@ static s32 ixgbe_mii_bus_read_generic(struct ixgbe_hw *hw, int addr,
return -EBUSY;
hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
if (regnum & MII_ADDR_C45) {
hwaddr |= regnum & GENMASK(21, 0);
cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
} else {
hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL |
IXGBE_MSCA_READ_AUTOINC | IXGBE_MSCA_MDI_COMMAND;
}
hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL |
IXGBE_MSCA_READ_AUTOINC | IXGBE_MSCA_MDI_COMMAND;
data = ixgbe_msca_cmd(hw, cmd);
if (data < 0)
goto mii_bus_read_done;
/* For a clause 45 access the address cycle just completed, we still
* need to do the read command, otherwise just get the data
*/
if (!(regnum & MII_ADDR_C45))
goto do_mii_bus_read;
data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
data = (data >> IXGBE_MSRWD_READ_DATA_SHIFT) & GENMASK(16, 0);
mii_bus_read_done:
hw->mac.ops.release_swfw_sync(hw, gssr);
return data;
}
/**
* ixgbe_mii_bus_read_generic_c45 - Read a clause 45 register with gssr flags
* @hw: pointer to hardware structure
* @addr: address
* @devad: device address to read
* @regnum: register number
* @gssr: semaphore flags to acquire
**/
static s32 ixgbe_mii_bus_read_generic_c45(struct ixgbe_hw *hw, int addr,
int devad, int regnum, u32 gssr)
{
u32 hwaddr, cmd;
s32 data;
if (hw->mac.ops.acquire_swfw_sync(hw, gssr))
return -EBUSY;
hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
hwaddr |= devad << 16 | regnum;
cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
data = ixgbe_msca_cmd(hw, cmd);
if (data < 0)
goto mii_bus_read_done;
cmd = hwaddr | IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND;
data = ixgbe_msca_cmd(hw, cmd);
if (data < 0)
goto mii_bus_read_done;
do_mii_bus_read:
data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
data = (data >> IXGBE_MSRWD_READ_DATA_SHIFT) & GENMASK(16, 0);
......@@ -730,15 +751,15 @@ static s32 ixgbe_mii_bus_read_generic(struct ixgbe_hw *hw, int addr,
}
/**
* ixgbe_mii_bus_write_generic - Write a clause 22/45 register with gssr flags
* ixgbe_mii_bus_write_generic_c22 - Write a clause 22 register with gssr flags
* @hw: pointer to hardware structure
* @addr: address
* @regnum: register number
* @val: value to write
* @gssr: semaphore flags to acquire
**/
static s32 ixgbe_mii_bus_write_generic(struct ixgbe_hw *hw, int addr,
int regnum, u16 val, u32 gssr)
static s32 ixgbe_mii_bus_write_generic_c22(struct ixgbe_hw *hw, int addr,
int regnum, u16 val, u32 gssr)
{
u32 hwaddr, cmd;
s32 err;
......@@ -749,20 +770,43 @@ static s32 ixgbe_mii_bus_write_generic(struct ixgbe_hw *hw, int addr,
IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)val);
hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
if (regnum & MII_ADDR_C45) {
hwaddr |= regnum & GENMASK(21, 0);
cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
} else {
hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE |
IXGBE_MSCA_MDI_COMMAND;
}
hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE |
IXGBE_MSCA_MDI_COMMAND;
err = ixgbe_msca_cmd(hw, cmd);
hw->mac.ops.release_swfw_sync(hw, gssr);
return err;
}
/**
* ixgbe_mii_bus_write_generic_c45 - Write a clause 45 register with gssr flags
* @hw: pointer to hardware structure
* @addr: address
* @devad: device address to read
* @regnum: register number
* @val: value to write
* @gssr: semaphore flags to acquire
**/
static s32 ixgbe_mii_bus_write_generic_c45(struct ixgbe_hw *hw, int addr,
int devad, int regnum, u16 val,
u32 gssr)
{
u32 hwaddr, cmd;
s32 err;
if (hw->mac.ops.acquire_swfw_sync(hw, gssr))
return -EBUSY;
IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)val);
hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
hwaddr |= devad << 16 | regnum;
cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
/* For clause 45 this is an address cycle, for clause 22 this is the
* entire transaction
*/
err = ixgbe_msca_cmd(hw, cmd);
if (err < 0 || !(regnum & MII_ADDR_C45))
if (err < 0)
goto mii_bus_write_done;
cmd = hwaddr | IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND;
......@@ -774,70 +818,144 @@ static s32 ixgbe_mii_bus_write_generic(struct ixgbe_hw *hw, int addr,
}
/**
* ixgbe_mii_bus_read - Read a clause 22/45 register
* ixgbe_mii_bus_read_c22 - Read a clause 22 register
* @bus: pointer to mii_bus structure which points to our driver private
* @addr: address
* @regnum: register number
**/
static s32 ixgbe_mii_bus_read_c22(struct mii_bus *bus, int addr, int regnum)
{
struct ixgbe_adapter *adapter = bus->priv;
struct ixgbe_hw *hw = &adapter->hw;
u32 gssr = hw->phy.phy_semaphore_mask;
return ixgbe_mii_bus_read_generic_c22(hw, addr, regnum, gssr);
}
/**
* ixgbe_mii_bus_read_c45 - Read a clause 45 register
* @bus: pointer to mii_bus structure which points to our driver private
* @devad: device address to read
* @addr: address
* @regnum: register number
**/
static s32 ixgbe_mii_bus_read(struct mii_bus *bus, int addr, int regnum)
static s32 ixgbe_mii_bus_read_c45(struct mii_bus *bus, int devad, int addr,
int regnum)
{
struct ixgbe_adapter *adapter = bus->priv;
struct ixgbe_hw *hw = &adapter->hw;
u32 gssr = hw->phy.phy_semaphore_mask;
return ixgbe_mii_bus_read_generic_c45(hw, addr, devad, regnum, gssr);
}
/**
* ixgbe_mii_bus_write_c22 - Write a clause 22 register
* @bus: pointer to mii_bus structure which points to our driver private
* @addr: address
* @regnum: register number
* @val: value to write
**/
static s32 ixgbe_mii_bus_write_c22(struct mii_bus *bus, int addr, int regnum,
u16 val)
{
struct ixgbe_adapter *adapter = bus->priv;
struct ixgbe_hw *hw = &adapter->hw;
u32 gssr = hw->phy.phy_semaphore_mask;
return ixgbe_mii_bus_read_generic(hw, addr, regnum, gssr);
return ixgbe_mii_bus_write_generic_c22(hw, addr, regnum, val, gssr);
}
/**
* ixgbe_mii_bus_write - Write a clause 22/45 register
* ixgbe_mii_bus_write_c45 - Write a clause 45 register
* @bus: pointer to mii_bus structure which points to our driver private
* @addr: address
* @devad: device address to read
* @regnum: register number
* @val: value to write
**/
static s32 ixgbe_mii_bus_write(struct mii_bus *bus, int addr, int regnum,
u16 val)
static s32 ixgbe_mii_bus_write_c45(struct mii_bus *bus, int addr, int devad,
int regnum, u16 val)
{
struct ixgbe_adapter *adapter = bus->priv;
struct ixgbe_hw *hw = &adapter->hw;
u32 gssr = hw->phy.phy_semaphore_mask;
return ixgbe_mii_bus_write_generic(hw, addr, regnum, val, gssr);
return ixgbe_mii_bus_write_generic_c45(hw, addr, devad, regnum, val,
gssr);
}
/**
* ixgbe_x550em_a_mii_bus_read - Read a clause 22/45 register on x550em_a
* ixgbe_x550em_a_mii_bus_read_c22 - Read a clause 22 register on x550em_a
* @bus: pointer to mii_bus structure which points to our driver private
* @addr: address
* @regnum: register number
**/
static s32 ixgbe_x550em_a_mii_bus_read(struct mii_bus *bus, int addr,
int regnum)
static s32 ixgbe_x550em_a_mii_bus_read_c22(struct mii_bus *bus, int addr,
int regnum)
{
struct ixgbe_adapter *adapter = bus->priv;
struct ixgbe_hw *hw = &adapter->hw;
u32 gssr = hw->phy.phy_semaphore_mask;
gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
return ixgbe_mii_bus_read_generic_c22(hw, addr, regnum, gssr);
}
/**
* ixgbe_x550em_a_mii_bus_read_c45 - Read a clause 45 register on x550em_a
* @bus: pointer to mii_bus structure which points to our driver private
* @addr: address
* @devad: device address to read
* @regnum: register number
**/
static s32 ixgbe_x550em_a_mii_bus_read_c45(struct mii_bus *bus, int addr,
int devad, int regnum)
{
struct ixgbe_adapter *adapter = bus->priv;
struct ixgbe_hw *hw = &adapter->hw;
u32 gssr = hw->phy.phy_semaphore_mask;
gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
return ixgbe_mii_bus_read_generic_c45(hw, addr, devad, regnum, gssr);
}
/**
* ixgbe_x550em_a_mii_bus_write_c22 - Write a clause 22 register on x550em_a
* @bus: pointer to mii_bus structure which points to our driver private
* @addr: address
* @regnum: register number
* @val: value to write
**/
static s32 ixgbe_x550em_a_mii_bus_write_c22(struct mii_bus *bus, int addr,
int regnum, u16 val)
{
struct ixgbe_adapter *adapter = bus->priv;
struct ixgbe_hw *hw = &adapter->hw;
u32 gssr = hw->phy.phy_semaphore_mask;
gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
return ixgbe_mii_bus_read_generic(hw, addr, regnum, gssr);
return ixgbe_mii_bus_write_generic_c22(hw, addr, regnum, val, gssr);
}
/**
* ixgbe_x550em_a_mii_bus_write - Write a clause 22/45 register on x550em_a
* ixgbe_x550em_a_mii_bus_write_c45 - Write a clause 45 register on x550em_a
* @bus: pointer to mii_bus structure which points to our driver private
* @addr: address
* @devad: device address to read
* @regnum: register number
* @val: value to write
**/
static s32 ixgbe_x550em_a_mii_bus_write(struct mii_bus *bus, int addr,
int regnum, u16 val)
static s32 ixgbe_x550em_a_mii_bus_write_c45(struct mii_bus *bus, int addr,
int devad, int regnum, u16 val)
{
struct ixgbe_adapter *adapter = bus->priv;
struct ixgbe_hw *hw = &adapter->hw;
u32 gssr = hw->phy.phy_semaphore_mask;
gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
return ixgbe_mii_bus_write_generic(hw, addr, regnum, val, gssr);
return ixgbe_mii_bus_write_generic_c45(hw, addr, devad, regnum, val,
gssr);
}
/**
......@@ -909,8 +1027,11 @@ static bool ixgbe_x550em_a_has_mii(struct ixgbe_hw *hw)
**/
s32 ixgbe_mii_bus_init(struct ixgbe_hw *hw)
{
s32 (*write)(struct mii_bus *bus, int addr, int regnum, u16 val);
s32 (*read)(struct mii_bus *bus, int addr, int regnum);
s32 (*write_c22)(struct mii_bus *bus, int addr, int regnum, u16 val);
s32 (*read_c22)(struct mii_bus *bus, int addr, int regnum);
s32 (*write_c45)(struct mii_bus *bus, int addr, int devad, int regnum,
u16 val);
s32 (*read_c45)(struct mii_bus *bus, int addr, int devad, int regnum);
struct ixgbe_adapter *adapter = hw->back;
struct pci_dev *pdev = adapter->pdev;
struct device *dev = &adapter->netdev->dev;
......@@ -929,12 +1050,16 @@ s32 ixgbe_mii_bus_init(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_X550EM_A_1G_T_L:
if (!ixgbe_x550em_a_has_mii(hw))
return 0;
read = &ixgbe_x550em_a_mii_bus_read;
write = &ixgbe_x550em_a_mii_bus_write;
read_c22 = ixgbe_x550em_a_mii_bus_read_c22;
write_c22 = ixgbe_x550em_a_mii_bus_write_c22;
read_c45 = ixgbe_x550em_a_mii_bus_read_c45;
write_c45 = ixgbe_x550em_a_mii_bus_write_c45;
break;
default:
read = &ixgbe_mii_bus_read;
write = &ixgbe_mii_bus_write;
read_c22 = ixgbe_mii_bus_read_c22;
write_c22 = ixgbe_mii_bus_write_c22;
read_c45 = ixgbe_mii_bus_read_c45;
write_c45 = ixgbe_mii_bus_write_c45;
break;
}
......@@ -942,8 +1067,10 @@ s32 ixgbe_mii_bus_init(struct ixgbe_hw *hw)
if (!bus)
return -ENOMEM;
bus->read = read;
bus->write = write;
bus->read = read_c22;
bus->write = write_c22;
bus->read_c45 = read_c45;
bus->write_c45 = write_c45;
/* Use the position of the device in the PCI hierarchy as the id */
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mdio-%s", ixgbe_driver_name,
......
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