diff --git a/target/linux/realtek/files-6.6/drivers/net/phy/rtl83xx-phy.c b/target/linux/realtek/files-6.6/drivers/net/phy/rtl83xx-phy.c index dcb7f1570bf..2e52924f803 100644 --- a/target/linux/realtek/files-6.6/drivers/net/phy/rtl83xx-phy.c +++ b/target/linux/realtek/files-6.6/drivers/net/phy/rtl83xx-phy.c @@ -147,6 +147,79 @@ static int resume_polling(u64 saved_state) return 0; } +int rtl821x_match_phy_device(struct phy_device *phydev) +{ + u64 poll_state; + int rawpage, port = phydev->mdio.addr & ~3; + int oldpage, chip_mode, chip_cfg_mode; + + if (phydev->phy_id == PHY_ID_RTL8218B_E) + return PHY_IS_RTL8218B_E; + + if (phydev->phy_id != PHY_ID_RTL8214_OR_8218) + return PHY_IS_NOT_RTL821X; + + if (soc_info.family == RTL8380_FAMILY_ID) + rawpage = RTL838X_PAGE_RAW; + else if (soc_info.family == RTL8390_FAMILY_ID) + rawpage = RTL839X_PAGE_RAW; + else + return PHY_IS_NOT_RTL821X; + + poll_state = disable_polling(port); + /* + * At this stage the write_page()/read_page() PHY functions are not yet + * registered and normal paged access is not possible. The following + * detection routine works because our MDIO bus has all the Realtek + * PHY page handling (register 31) integrated into the port functions. + */ + oldpage = phy_port_read_paged(phydev, port, rawpage, 31); + phy_port_write_paged(phydev, port, rawpage, 31, 0xa42); + phy_port_write_paged(phydev, port, rawpage, 29, 0x008); + phy_port_write_paged(phydev, port, rawpage, 31, 0x278); + phy_port_write_paged(phydev, port, rawpage, 18, 0x455); + phy_port_write_paged(phydev, port, rawpage, 31, 0x260); + chip_mode = phy_port_read_paged(phydev, port, rawpage, 18); + phy_port_write_paged(phydev, port, rawpage, 31, 0xa42); + phy_port_write_paged(phydev, port, rawpage, 29, 0x000); + phy_port_write_paged(phydev, port, rawpage, 31, oldpage); + + resume_polling(poll_state); + + pr_debug("%s(%d): got chip mode %x\n", __func__, phydev->mdio.addr, chip_mode); + + /* we checked the 4th port of a RTL8218B and got no config values */ + if (!chip_mode) + return PHY_IS_RTL8218B_E; + + chip_cfg_mode = (chip_mode >> 4) & 0xf; + chip_mode &= 0xf; + + if (chip_mode == 0xd || chip_mode == 0xf) + return PHY_IS_RTL8218B_E; + + if (chip_mode == 0x4 || chip_mode == 0x6) + return PHY_IS_RTL8214FC; + + if (chip_mode != 0xc && chip_mode != 0xe) + return PHY_IS_NOT_RTL821X; + + if (chip_cfg_mode == 0x4 || chip_cfg_mode == 0x6) + return PHY_IS_RTL8214FC; + + return PHY_IS_RTL8214FB; +} + +static int rtl8218b_ext_match_phy_device(struct phy_device *phydev) +{ + return rtl821x_match_phy_device(phydev) == PHY_IS_RTL8218B_E; +} + +static int rtl8214fc_match_phy_device(struct phy_device *phydev) +{ + return rtl821x_match_phy_device(phydev) == PHY_IS_RTL8214FC; +} + static void rtl8380_int_phy_on_off(struct phy_device *phydev, bool on) { phy_modify(phydev, 0, BMCR_PDOWN, on ? 0 : BMCR_PDOWN); @@ -936,21 +1009,6 @@ static int rtl8380_configure_ext_rtl8218b(struct phy_device *phydev) return 0; } -static int rtl8218b_ext_match_phy_device(struct phy_device *phydev) -{ - int addr = phydev->mdio.addr; - - /* Both the RTL8214FC and the external RTL8218B have the same - * PHY ID. On the RTL838x, the RTL8218B can only be attached_dev - * at PHY IDs 0-7, while the RTL8214FC must be attached via - * the pair of SGMII/1000Base-X with higher PHY-IDs - */ - if (soc_info.family == RTL8380_FAMILY_ID) - return phydev->phy_id == PHY_ID_RTL8218B_E && addr < 8; - else - return phydev->phy_id == PHY_ID_RTL8218B_E; -} - static bool rtl8214fc_media_is_fibre(struct phy_device *phydev) { int mac = phydev->mdio.addr; @@ -1459,13 +1517,6 @@ static int rtl8380_configure_rtl8214fc(struct phy_device *phydev) return 0; } -static int rtl8214fc_match_phy_device(struct phy_device *phydev) -{ - int addr = phydev->mdio.addr; - - return phydev->phy_id == PHY_ID_RTL8214FC && addr >= 24; -} - static int rtl8380_configure_serdes(struct phy_device *phydev) { u32 v; @@ -3856,10 +3907,9 @@ static struct phy_driver rtl83xx_phy_driver[] = { .set_loopback = genphy_loopback, }, { - PHY_ID_MATCH_MODEL(PHY_ID_RTL8214FC), + .match_phy_device = rtl8214fc_match_phy_device, .name = "Realtek RTL8214FC", .features = PHY_GBIT_FIBRE_FEATURES, - .match_phy_device = rtl8214fc_match_phy_device, .probe = rtl8214fc_phy_probe, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, @@ -3872,10 +3922,9 @@ static struct phy_driver rtl83xx_phy_driver[] = { .get_eee = rtl8214fc_get_eee, }, { - PHY_ID_MATCH_MODEL(PHY_ID_RTL8218B_E), + .match_phy_device = rtl8218b_ext_match_phy_device, .name = "Realtek RTL8218B (external)", .features = PHY_GBIT_FEATURES, - .match_phy_device = rtl8218b_ext_match_phy_device, .probe = rtl8218b_ext_phy_probe, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, @@ -3991,7 +4040,7 @@ static struct phy_driver rtl83xx_phy_driver[] = { module_phy_driver(rtl83xx_phy_driver); static struct mdio_device_id __maybe_unused rtl83xx_tbl[] = { - { PHY_ID_MATCH_MODEL(PHY_ID_RTL8214FC) }, + { PHY_ID_MATCH_MODEL(PHY_ID_RTL8214_OR_8218) }, { } }; diff --git a/target/linux/realtek/files-6.6/drivers/net/phy/rtl83xx-phy.h b/target/linux/realtek/files-6.6/drivers/net/phy/rtl83xx-phy.h index fb79560e6b6..781ecb3c7ca 100644 --- a/target/linux/realtek/files-6.6/drivers/net/phy/rtl83xx-phy.h +++ b/target/linux/realtek/files-6.6/drivers/net/phy/rtl83xx-phy.h @@ -19,21 +19,26 @@ struct __attribute__ ((__packed__)) fw_header { }; /* TODO: fixed path? */ -#define FIRMWARE_838X_8380_1 "rtl838x_phy/rtl838x_8380.fw" -#define FIRMWARE_838X_8214FC_1 "rtl838x_phy/rtl838x_8214fc.fw" -#define FIRMWARE_838X_8218b_1 "rtl838x_phy/rtl838x_8218b.fw" +#define FIRMWARE_838X_8380_1 "rtl838x_phy/rtl838x_8380.fw" +#define FIRMWARE_838X_8214FC_1 "rtl838x_phy/rtl838x_8214fc.fw" +#define FIRMWARE_838X_8218b_1 "rtl838x_phy/rtl838x_8218b.fw" -/* External RTL8218B and RTL8214FC IDs are identical */ -#define PHY_ID_RTL8214C 0x001cc942 -#define PHY_ID_RTL8214FC 0x001cc981 -#define PHY_ID_RTL8218B_E 0x001cc981 -#define PHY_ID_RTL8218D 0x001cc983 -#define PHY_ID_RTL8218B_I 0x001cca40 -#define PHY_ID_RTL8221B 0x001cc849 -#define PHY_ID_RTL8226 0x001cc838 -#define PHY_ID_RTL8390_GENERIC 0x001ccab0 -#define PHY_ID_RTL8393_I 0x001c8393 -#define PHY_ID_RTL9300_I 0x70d03106 +#define PHY_ID_RTL8214C 0x001cc942 +#define PHY_ID_RTL8218B_E 0x001cc980 +#define PHY_ID_RTL8214_OR_8218 0x001cc981 +#define PHY_ID_RTL8218D 0x001cc983 +#define PHY_ID_RTL8218B_I 0x001cca40 +#define PHY_ID_RTL8221B 0x001cc849 +#define PHY_ID_RTL8226 0x001cc838 +#define PHY_ID_RTL8390_GENERIC 0x001ccab0 +#define PHY_ID_RTL8393_I 0x001c8393 +#define PHY_ID_RTL9300_I 0x70d03106 + +/* These PHYs share the same id (0x001cc981) */ +#define PHY_IS_NOT_RTL821X 0 +#define PHY_IS_RTL8214FC 1 +#define PHY_IS_RTL8214FB 2 +#define PHY_IS_RTL8218B_E 3 /* Registers of the internal Serdes of the 8380 */ #define RTL838X_SDS_MODE_SEL (0x0028)