--- zzzz-none-000/linux-3.10.107/drivers/net/phy/realtek.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/net/phy/realtek.c 2021-02-04 17:41:59.000000000 +0000 @@ -22,8 +22,12 @@ #define RTL821x_INER 0x12 #define RTL821x_INER_INIT 0x6400 #define RTL821x_INSR 0x13 +#define RTL8211E_INER_LINK_STATUS 0x400 -#define RTL8211E_INER_LINK_STAT 0x10 +#define RTL8211F_INER_LINK_STATUS 0x0010 +#define RTL8211F_INSR 0x1d +#define RTL8211F_PAGE_SELECT 0x1f +#define RTL8211F_TX_DELAY 0x100 MODULE_DESCRIPTION("Realtek PHY driver"); MODULE_AUTHOR("Johnson Leung"); @@ -38,6 +42,18 @@ return (err < 0) ? err : 0; } +static int rtl8211f_ack_interrupt(struct phy_device *phydev) +{ + int err; + + phy_write(phydev, RTL8211F_PAGE_SELECT, 0xa43); + err = phy_read(phydev, RTL8211F_INSR); + /* restore to default page 0 */ + phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0); + + return (err < 0) ? err : 0; +} + static int rtl8211b_config_intr(struct phy_device *phydev) { int err; @@ -57,65 +73,119 @@ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) err = phy_write(phydev, RTL821x_INER, - RTL8211E_INER_LINK_STAT); + RTL8211E_INER_LINK_STATUS); else err = phy_write(phydev, RTL821x_INER, 0); return err; } -/* RTL8211B */ -static struct phy_driver rtl8211b_driver = { - .phy_id = 0x001cc912, - .name = "RTL8211B Gigabit Ethernet", - .phy_id_mask = 0x001fffff, - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_aneg = &genphy_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &rtl821x_ack_interrupt, - .config_intr = &rtl8211b_config_intr, - .driver = { .owner = THIS_MODULE,}, -}; +static int rtl8211f_config_intr(struct phy_device *phydev) +{ + int err; -/* RTL8211E */ -static struct phy_driver rtl8211e_driver = { - .phy_id = 0x001cc915, - .name = "RTL8211E Gigabit Ethernet", - .phy_id_mask = 0x001fffff, - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_aneg = &genphy_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &rtl821x_ack_interrupt, - .config_intr = &rtl8211e_config_intr, - .suspend = genphy_suspend, - .resume = genphy_resume, - .driver = { .owner = THIS_MODULE,}, -}; + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + err = phy_write(phydev, RTL821x_INER, + RTL8211F_INER_LINK_STATUS); + else + err = phy_write(phydev, RTL821x_INER, 0); + + return err; +} -static int __init realtek_init(void) +static int rtl8211f_config_init(struct phy_device *phydev) { int ret; + u16 reg; - ret = phy_driver_register(&rtl8211b_driver); + ret = genphy_config_init(phydev); if (ret < 0) - return -ENODEV; - return phy_driver_register(&rtl8211e_driver); -} + return ret; -static void __exit realtek_exit(void) -{ - phy_driver_unregister(&rtl8211b_driver); - phy_driver_unregister(&rtl8211e_driver); + if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { + /* enable TXDLY */ + phy_write(phydev, RTL8211F_PAGE_SELECT, 0xd08); + reg = phy_read(phydev, 0x11); + reg |= RTL8211F_TX_DELAY; + phy_write(phydev, 0x11, reg); + /* restore to default page 0 */ + phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0); + } + + return 0; } -module_init(realtek_init); -module_exit(realtek_exit); +static struct phy_driver realtek_drvs[] = { + { + .phy_id = 0x00008201, + .name = "RTL8201CP Ethernet", + .phy_id_mask = 0x0000ffff, + .features = PHY_BASIC_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .driver = { .owner = THIS_MODULE,}, + }, { + .phy_id = 0x001cc912, + .name = "RTL8211B Gigabit Ethernet", + .phy_id_mask = 0x001fffff, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &rtl821x_ack_interrupt, + .config_intr = &rtl8211b_config_intr, + .driver = { .owner = THIS_MODULE,}, + }, { + .phy_id = 0x001cc914, + .name = "RTL8211DN Gigabit Ethernet", + .phy_id_mask = 0x001fffff, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .ack_interrupt = rtl821x_ack_interrupt, + .config_intr = rtl8211e_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + .driver = { .owner = THIS_MODULE,}, + }, { + .phy_id = 0x001cc915, + .name = "RTL8211E Gigabit Ethernet", + .phy_id_mask = 0x001fffff, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &rtl821x_ack_interrupt, + .config_intr = &rtl8211e_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + .driver = { .owner = THIS_MODULE,}, + }, { + .phy_id = 0x001cc916, + .name = "RTL8211F Gigabit Ethernet", + .phy_id_mask = 0x001fffff, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &genphy_config_aneg, + .config_init = &rtl8211f_config_init, + .read_status = &genphy_read_status, + .ack_interrupt = &rtl8211f_ack_interrupt, + .config_intr = &rtl8211f_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + .driver = { .owner = THIS_MODULE }, + }, +}; + +module_phy_driver(realtek_drvs); static struct mdio_device_id __maybe_unused realtek_tbl[] = { { 0x001cc912, 0x001fffff }, + { 0x001cc914, 0x001fffff }, { 0x001cc915, 0x001fffff }, + { 0x001cc916, 0x001fffff }, { } };