mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
Merge branch 'ksz886x-forced-link-modes'
Oleksij Rempel says: ==================== fix forced link mode for KSZ886X switches changes v3: - squash patch 1 and 2 - use genphy_config_aneg() instead of genphy_setup_forced() changes v2: - address kernel test robot warning - change comment explaining clearing of KSZ886X_CTRL_FORCE_LINK bit - s/PHY we create/PHY will create/ ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
095c3ea6fd
3 changed files with 109 additions and 3 deletions
|
@ -632,6 +632,50 @@ static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
|
|||
ksz8_w_table(dev, TABLE_VLAN, addr, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* ksz8_r_phy_ctrl - Translates and reads from the SMI interface to a MIIM PHY
|
||||
* Control register (Reg. 31).
|
||||
* @dev: The KSZ device instance.
|
||||
* @port: The port number to be read.
|
||||
* @val: The value read from the SMI interface.
|
||||
*
|
||||
* This function reads the SMI interface and translates the hardware register
|
||||
* bit values into their corresponding control settings for a MIIM PHY Control
|
||||
* register.
|
||||
*
|
||||
* Return: 0 on success, error code on failure.
|
||||
*/
|
||||
static int ksz8_r_phy_ctrl(struct ksz_device *dev, int port, u16 *val)
|
||||
{
|
||||
const u16 *regs = dev->info->regs;
|
||||
u8 reg_val;
|
||||
int ret;
|
||||
|
||||
*val = 0;
|
||||
|
||||
ret = ksz_pread8(dev, port, regs[P_LINK_STATUS], ®_val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (reg_val & PORT_MDIX_STATUS)
|
||||
*val |= KSZ886X_CTRL_MDIX_STAT;
|
||||
|
||||
ret = ksz_pread8(dev, port, REG_PORT_LINK_MD_CTRL, ®_val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (reg_val & PORT_FORCE_LINK)
|
||||
*val |= KSZ886X_CTRL_FORCE_LINK;
|
||||
|
||||
if (reg_val & PORT_POWER_SAVING)
|
||||
*val |= KSZ886X_CTRL_PWRSAVE;
|
||||
|
||||
if (reg_val & PORT_PHY_REMOTE_LOOPBACK)
|
||||
*val |= KSZ886X_CTRL_REMOTE_LOOPBACK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
|
||||
{
|
||||
u8 restart, speed, ctrl, link;
|
||||
|
@ -769,12 +813,10 @@ int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
|
|||
FIELD_GET(PORT_CABLE_FAULT_COUNTER_L, val2));
|
||||
break;
|
||||
case PHY_REG_PHY_CTRL:
|
||||
ret = ksz_pread8(dev, p, regs[P_LINK_STATUS], &link);
|
||||
ret = ksz8_r_phy_ctrl(dev, p, &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (link & PORT_MDIX_STATUS)
|
||||
data |= KSZ886X_CTRL_MDIX_STAT;
|
||||
break;
|
||||
default:
|
||||
processed = false;
|
||||
|
@ -786,6 +828,38 @@ int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ksz8_w_phy_ctrl - Translates and writes to the SMI interface from a MIIM PHY
|
||||
* Control register (Reg. 31).
|
||||
* @dev: The KSZ device instance.
|
||||
* @port: The port number to be configured.
|
||||
* @val: The register value to be written.
|
||||
*
|
||||
* This function translates control settings from a MIIM PHY Control register
|
||||
* into their corresponding hardware register bit values for the SMI
|
||||
* interface.
|
||||
*
|
||||
* Return: 0 on success, error code on failure.
|
||||
*/
|
||||
static int ksz8_w_phy_ctrl(struct ksz_device *dev, int port, u16 val)
|
||||
{
|
||||
u8 reg_val = 0;
|
||||
int ret;
|
||||
|
||||
if (val & KSZ886X_CTRL_FORCE_LINK)
|
||||
reg_val |= PORT_FORCE_LINK;
|
||||
|
||||
if (val & KSZ886X_CTRL_PWRSAVE)
|
||||
reg_val |= PORT_POWER_SAVING;
|
||||
|
||||
if (val & KSZ886X_CTRL_REMOTE_LOOPBACK)
|
||||
reg_val |= PORT_PHY_REMOTE_LOOPBACK;
|
||||
|
||||
ret = ksz_prmw8(dev, port, REG_PORT_LINK_MD_CTRL, PORT_FORCE_LINK |
|
||||
PORT_POWER_SAVING | PORT_PHY_REMOTE_LOOPBACK, reg_val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
|
||||
{
|
||||
u8 restart, speed, ctrl, data;
|
||||
|
@ -926,6 +1000,12 @@ int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
|
|||
if (val & PHY_START_CABLE_DIAG)
|
||||
ksz_port_cfg(dev, p, REG_PORT_LINK_MD_CTRL, PORT_START_CABLE_DIAG, true);
|
||||
break;
|
||||
|
||||
case PHY_REG_PHY_CTRL:
|
||||
ret = ksz8_w_phy_ctrl(dev, p, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1733,6 +1733,28 @@ static int ksz886x_config_aneg(struct phy_device *phydev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (phydev->autoneg != AUTONEG_ENABLE) {
|
||||
/* When autonegotation is disabled, we need to manually force
|
||||
* the link state. If we don't do this, the PHY will keep
|
||||
* sending Fast Link Pulses (FLPs) which are part of the
|
||||
* autonegotiation process. This is not desired when
|
||||
* autonegotiation is off.
|
||||
*/
|
||||
ret = phy_set_bits(phydev, MII_KSZPHY_CTRL,
|
||||
KSZ886X_CTRL_FORCE_LINK);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* If we had previously forced the link state, we need to
|
||||
* clear KSZ886X_CTRL_FORCE_LINK bit now. Otherwise, the PHY
|
||||
* will not perform autonegotiation.
|
||||
*/
|
||||
ret = phy_clear_bits(phydev, MII_KSZPHY_CTRL,
|
||||
KSZ886X_CTRL_FORCE_LINK);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The MDI-X configuration is automatically changed by the PHY after
|
||||
* switching from autoneg off to on. So, take MDI-X configuration under
|
||||
* own control and set it after autoneg configuration was done.
|
||||
|
|
|
@ -64,6 +64,10 @@
|
|||
#define KSZ886X_BMCR_DISABLE_TRANSMIT BIT(1)
|
||||
#define KSZ886X_BMCR_DISABLE_LED BIT(0)
|
||||
|
||||
/* PHY Special Control/Status Register (Reg 31) */
|
||||
#define KSZ886X_CTRL_MDIX_STAT BIT(4)
|
||||
#define KSZ886X_CTRL_FORCE_LINK BIT(3)
|
||||
#define KSZ886X_CTRL_PWRSAVE BIT(2)
|
||||
#define KSZ886X_CTRL_REMOTE_LOOPBACK BIT(1)
|
||||
|
||||
#endif /* _MICREL_PHY_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue