Commit fa288a42 authored by David S. Miller's avatar David S. Miller

Merge branch 'genphy_read_abilities'

Heiner Kallweit says:

====================
net: phy: add and use new function genphy_read_abilities

Similar to genphy_c45_pma_read_abilities() add a function to dynamically
detect the abilities of a Clause 22 PHY. This is mainly copied from
genphy_config_init(). Main benefit is that PHY drivers no longer have
to specify whether they support GBit or not (provided they keep to
the C22 standard).
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6d670497 48e4adf9
...@@ -1880,6 +1880,54 @@ int genphy_config_init(struct phy_device *phydev) ...@@ -1880,6 +1880,54 @@ int genphy_config_init(struct phy_device *phydev)
} }
EXPORT_SYMBOL(genphy_config_init); EXPORT_SYMBOL(genphy_config_init);
/**
* genphy_read_abilities - read PHY abilities from Clause 22 registers
* @phydev: target phy_device struct
*
* Description: Reads the PHY's abilities and populates
* phydev->supported accordingly.
*
* Returns: 0 on success, < 0 on failure
*/
int genphy_read_abilities(struct phy_device *phydev)
{
int val;
linkmode_set_bit_array(phy_basic_ports_array,
ARRAY_SIZE(phy_basic_ports_array),
phydev->supported);
val = phy_read(phydev, MII_BMSR);
if (val < 0)
return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported,
val & BMSR_ANEGCAPABLE);
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->supported,
val & BMSR_100FULL);
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, phydev->supported,
val & BMSR_100HALF);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, phydev->supported,
val & BMSR_10FULL);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, phydev->supported,
val & BMSR_10HALF);
if (val & BMSR_ESTATEN) {
val = phy_read(phydev, MII_ESTATUS);
if (val < 0)
return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->supported, val & ESTATUS_1000_TFULL);
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
phydev->supported, val & ESTATUS_1000_THALF);
}
return 0;
}
EXPORT_SYMBOL(genphy_read_abilities);
/* This is used for the phy device which doesn't support the MMD extended /* This is used for the phy device which doesn't support the MMD extended
* register access, but it does have side effect when we are trying to access * register access, but it does have side effect when we are trying to access
* the MMD register via indirect method. * the MMD register via indirect method.
...@@ -2236,8 +2284,7 @@ static struct phy_driver genphy_driver = { ...@@ -2236,8 +2284,7 @@ static struct phy_driver genphy_driver = {
.phy_id_mask = 0xffffffff, .phy_id_mask = 0xffffffff,
.name = "Generic PHY", .name = "Generic PHY",
.soft_reset = genphy_no_soft_reset, .soft_reset = genphy_no_soft_reset,
.config_init = genphy_config_init, .get_features = genphy_read_abilities,
.features = PHY_GBIT_ALL_PORTS_FEATURES,
.aneg_done = genphy_aneg_done, .aneg_done = genphy_aneg_done,
.suspend = genphy_suspend, .suspend = genphy_suspend,
.resume = genphy_resume, .resume = genphy_resume,
......
...@@ -151,21 +151,14 @@ static int rtl8211_config_aneg(struct phy_device *phydev) ...@@ -151,21 +151,14 @@ static int rtl8211_config_aneg(struct phy_device *phydev)
static int rtl8211c_config_init(struct phy_device *phydev) static int rtl8211c_config_init(struct phy_device *phydev)
{ {
/* RTL8211C has an issue when operating in Gigabit slave mode */ /* RTL8211C has an issue when operating in Gigabit slave mode */
phy_set_bits(phydev, MII_CTRL1000, return phy_set_bits(phydev, MII_CTRL1000,
CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER); CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER);
return genphy_config_init(phydev);
} }
static int rtl8211f_config_init(struct phy_device *phydev) static int rtl8211f_config_init(struct phy_device *phydev)
{ {
int ret;
u16 val = 0; u16 val = 0;
ret = genphy_config_init(phydev);
if (ret < 0)
return ret;
/* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
...@@ -192,10 +185,6 @@ static int rtl8366rb_config_init(struct phy_device *phydev) ...@@ -192,10 +185,6 @@ static int rtl8366rb_config_init(struct phy_device *phydev)
{ {
int ret; int ret;
ret = genphy_config_init(phydev);
if (ret < 0)
return ret;
ret = phy_set_bits(phydev, RTL8366RB_POWER_SAVE, ret = phy_set_bits(phydev, RTL8366RB_POWER_SAVE,
RTL8366RB_POWER_SAVE_ON); RTL8366RB_POWER_SAVE_ON);
if (ret) { if (ret) {
...@@ -210,11 +199,11 @@ static struct phy_driver realtek_drvs[] = { ...@@ -210,11 +199,11 @@ static struct phy_driver realtek_drvs[] = {
{ {
PHY_ID_MATCH_EXACT(0x00008201), PHY_ID_MATCH_EXACT(0x00008201),
.name = "RTL8201CP Ethernet", .name = "RTL8201CP Ethernet",
.features = PHY_BASIC_FEATURES, .get_features = genphy_read_abilities,
}, { }, {
PHY_ID_MATCH_EXACT(0x001cc816), PHY_ID_MATCH_EXACT(0x001cc816),
.name = "RTL8201F Fast Ethernet", .name = "RTL8201F Fast Ethernet",
.features = PHY_BASIC_FEATURES, .get_features = genphy_read_abilities,
.ack_interrupt = &rtl8201_ack_interrupt, .ack_interrupt = &rtl8201_ack_interrupt,
.config_intr = &rtl8201_config_intr, .config_intr = &rtl8201_config_intr,
.suspend = genphy_suspend, .suspend = genphy_suspend,
...@@ -224,14 +213,14 @@ static struct phy_driver realtek_drvs[] = { ...@@ -224,14 +213,14 @@ static struct phy_driver realtek_drvs[] = {
}, { }, {
PHY_ID_MATCH_EXACT(0x001cc910), PHY_ID_MATCH_EXACT(0x001cc910),
.name = "RTL8211 Gigabit Ethernet", .name = "RTL8211 Gigabit Ethernet",
.features = PHY_GBIT_FEATURES, .get_features = genphy_read_abilities,
.config_aneg = rtl8211_config_aneg, .config_aneg = rtl8211_config_aneg,
.read_mmd = &genphy_read_mmd_unsupported, .read_mmd = &genphy_read_mmd_unsupported,
.write_mmd = &genphy_write_mmd_unsupported, .write_mmd = &genphy_write_mmd_unsupported,
}, { }, {
PHY_ID_MATCH_EXACT(0x001cc912), PHY_ID_MATCH_EXACT(0x001cc912),
.name = "RTL8211B Gigabit Ethernet", .name = "RTL8211B Gigabit Ethernet",
.features = PHY_GBIT_FEATURES, .get_features = genphy_read_abilities,
.ack_interrupt = &rtl821x_ack_interrupt, .ack_interrupt = &rtl821x_ack_interrupt,
.config_intr = &rtl8211b_config_intr, .config_intr = &rtl8211b_config_intr,
.read_mmd = &genphy_read_mmd_unsupported, .read_mmd = &genphy_read_mmd_unsupported,
...@@ -241,14 +230,14 @@ static struct phy_driver realtek_drvs[] = { ...@@ -241,14 +230,14 @@ static struct phy_driver realtek_drvs[] = {
}, { }, {
PHY_ID_MATCH_EXACT(0x001cc913), PHY_ID_MATCH_EXACT(0x001cc913),
.name = "RTL8211C Gigabit Ethernet", .name = "RTL8211C Gigabit Ethernet",
.features = PHY_GBIT_FEATURES, .get_features = genphy_read_abilities,
.config_init = rtl8211c_config_init, .config_init = rtl8211c_config_init,
.read_mmd = &genphy_read_mmd_unsupported, .read_mmd = &genphy_read_mmd_unsupported,
.write_mmd = &genphy_write_mmd_unsupported, .write_mmd = &genphy_write_mmd_unsupported,
}, { }, {
PHY_ID_MATCH_EXACT(0x001cc914), PHY_ID_MATCH_EXACT(0x001cc914),
.name = "RTL8211DN Gigabit Ethernet", .name = "RTL8211DN Gigabit Ethernet",
.features = PHY_GBIT_FEATURES, .get_features = genphy_read_abilities,
.ack_interrupt = rtl821x_ack_interrupt, .ack_interrupt = rtl821x_ack_interrupt,
.config_intr = rtl8211e_config_intr, .config_intr = rtl8211e_config_intr,
.suspend = genphy_suspend, .suspend = genphy_suspend,
...@@ -256,7 +245,7 @@ static struct phy_driver realtek_drvs[] = { ...@@ -256,7 +245,7 @@ static struct phy_driver realtek_drvs[] = {
}, { }, {
PHY_ID_MATCH_EXACT(0x001cc915), PHY_ID_MATCH_EXACT(0x001cc915),
.name = "RTL8211E Gigabit Ethernet", .name = "RTL8211E Gigabit Ethernet",
.features = PHY_GBIT_FEATURES, .get_features = genphy_read_abilities,
.ack_interrupt = &rtl821x_ack_interrupt, .ack_interrupt = &rtl821x_ack_interrupt,
.config_intr = &rtl8211e_config_intr, .config_intr = &rtl8211e_config_intr,
.suspend = genphy_suspend, .suspend = genphy_suspend,
...@@ -264,7 +253,7 @@ static struct phy_driver realtek_drvs[] = { ...@@ -264,7 +253,7 @@ static struct phy_driver realtek_drvs[] = {
}, { }, {
PHY_ID_MATCH_EXACT(0x001cc916), PHY_ID_MATCH_EXACT(0x001cc916),
.name = "RTL8211F Gigabit Ethernet", .name = "RTL8211F Gigabit Ethernet",
.features = PHY_GBIT_FEATURES, .get_features = genphy_read_abilities,
.config_init = &rtl8211f_config_init, .config_init = &rtl8211f_config_init,
.ack_interrupt = &rtl8211f_ack_interrupt, .ack_interrupt = &rtl8211f_ack_interrupt,
.config_intr = &rtl8211f_config_intr, .config_intr = &rtl8211f_config_intr,
...@@ -275,8 +264,7 @@ static struct phy_driver realtek_drvs[] = { ...@@ -275,8 +264,7 @@ static struct phy_driver realtek_drvs[] = {
}, { }, {
PHY_ID_MATCH_EXACT(0x001cc800), PHY_ID_MATCH_EXACT(0x001cc800),
.name = "Generic Realtek PHY", .name = "Generic Realtek PHY",
.features = PHY_GBIT_FEATURES, .get_features = genphy_read_abilities,
.config_init = genphy_config_init,
.suspend = genphy_suspend, .suspend = genphy_suspend,
.resume = genphy_resume, .resume = genphy_resume,
.read_page = rtl821x_read_page, .read_page = rtl821x_read_page,
...@@ -284,7 +272,7 @@ static struct phy_driver realtek_drvs[] = { ...@@ -284,7 +272,7 @@ static struct phy_driver realtek_drvs[] = {
}, { }, {
PHY_ID_MATCH_EXACT(0x001cc961), PHY_ID_MATCH_EXACT(0x001cc961),
.name = "RTL8366RB Gigabit Ethernet", .name = "RTL8366RB Gigabit Ethernet",
.features = PHY_GBIT_FEATURES, .get_features = genphy_read_abilities,
.config_init = &rtl8366rb_config_init, .config_init = &rtl8366rb_config_init,
/* These interrupts are handled by the irq controller /* These interrupts are handled by the irq controller
* embedded inside the RTL8366RB, they get unmasked when the * embedded inside the RTL8366RB, they get unmasked when the
......
...@@ -1075,6 +1075,7 @@ void phy_attached_info(struct phy_device *phydev); ...@@ -1075,6 +1075,7 @@ void phy_attached_info(struct phy_device *phydev);
/* Clause 22 PHY */ /* Clause 22 PHY */
int genphy_config_init(struct phy_device *phydev); int genphy_config_init(struct phy_device *phydev);
int genphy_read_abilities(struct phy_device *phydev);
int genphy_setup_forced(struct phy_device *phydev); int genphy_setup_forced(struct phy_device *phydev);
int genphy_restart_aneg(struct phy_device *phydev); int genphy_restart_aneg(struct phy_device *phydev);
int genphy_config_eee_advert(struct phy_device *phydev); int genphy_config_eee_advert(struct phy_device *phydev);
......
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