18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* drivers/net/phy/realtek.c 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Driver for Realtek PHYs 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Author: Johnson Leung <r58129@freescale.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Copyright (c) 2004 Freescale Semiconductor, Inc. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci#include <linux/bitops.h> 118c2ecf20Sopenharmony_ci#include <linux/phy.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/delay.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define RTL821x_PHYSR 0x11 168c2ecf20Sopenharmony_ci#define RTL821x_PHYSR_DUPLEX BIT(13) 178c2ecf20Sopenharmony_ci#define RTL821x_PHYSR_SPEED GENMASK(15, 14) 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define RTL821x_INER 0x12 208c2ecf20Sopenharmony_ci#define RTL8211B_INER_INIT 0x6400 218c2ecf20Sopenharmony_ci#define RTL8211E_INER_LINK_STATUS BIT(10) 228c2ecf20Sopenharmony_ci#define RTL8211F_INER_LINK_STATUS BIT(4) 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define RTL821x_INSR 0x13 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define RTL821x_EXT_PAGE_SELECT 0x1e 278c2ecf20Sopenharmony_ci#define RTL821x_PAGE_SELECT 0x1f 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define RTL8211F_PHYCR1 0x18 308c2ecf20Sopenharmony_ci#define RTL8211F_INSR 0x1d 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define RTL8211F_TX_DELAY BIT(8) 338c2ecf20Sopenharmony_ci#define RTL8211F_RX_DELAY BIT(3) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define RTL8211F_ALDPS_PLL_OFF BIT(1) 368c2ecf20Sopenharmony_ci#define RTL8211F_ALDPS_ENABLE BIT(2) 378c2ecf20Sopenharmony_ci#define RTL8211F_ALDPS_XTAL_OFF BIT(12) 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define RTL8211E_CTRL_DELAY BIT(13) 408c2ecf20Sopenharmony_ci#define RTL8211E_TX_DELAY BIT(12) 418c2ecf20Sopenharmony_ci#define RTL8211E_RX_DELAY BIT(11) 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define RTL8201F_ISR 0x1e 448c2ecf20Sopenharmony_ci#define RTL8201F_IER 0x13 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define RTL8366RB_POWER_SAVE 0x15 478c2ecf20Sopenharmony_ci#define RTL8366RB_POWER_SAVE_ON BIT(12) 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#define RTL_SUPPORTS_5000FULL BIT(14) 508c2ecf20Sopenharmony_ci#define RTL_SUPPORTS_2500FULL BIT(13) 518c2ecf20Sopenharmony_ci#define RTL_SUPPORTS_10000FULL BIT(0) 528c2ecf20Sopenharmony_ci#define RTL_ADV_2500FULL BIT(7) 538c2ecf20Sopenharmony_ci#define RTL_LPADV_10000FULL BIT(11) 548c2ecf20Sopenharmony_ci#define RTL_LPADV_5000FULL BIT(6) 558c2ecf20Sopenharmony_ci#define RTL_LPADV_2500FULL BIT(5) 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci#define RTLGEN_SPEED_MASK 0x0630 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#define RTL_GENERIC_PHYID 0x001cc800 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Realtek PHY driver"); 628c2ecf20Sopenharmony_ciMODULE_AUTHOR("Johnson Leung"); 638c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic int rtl821x_read_page(struct phy_device *phydev) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci return __phy_read(phydev, RTL821x_PAGE_SELECT); 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic int rtl821x_write_page(struct phy_device *phydev, int page) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci return __phy_write(phydev, RTL821x_PAGE_SELECT, page); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic int rtl8201_ack_interrupt(struct phy_device *phydev) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci int err; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci err = phy_read(phydev, RTL8201F_ISR); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci return (err < 0) ? err : 0; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic int rtl821x_ack_interrupt(struct phy_device *phydev) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci int err; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci err = phy_read(phydev, RTL821x_INSR); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci return (err < 0) ? err : 0; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic int rtl8211f_ack_interrupt(struct phy_device *phydev) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci int err; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci err = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci return (err < 0) ? err : 0; 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic int rtl8201_config_intr(struct phy_device *phydev) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci u16 val; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 1078c2ecf20Sopenharmony_ci val = BIT(13) | BIT(12) | BIT(11); 1088c2ecf20Sopenharmony_ci else 1098c2ecf20Sopenharmony_ci val = 0; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci return phy_write_paged(phydev, 0x7, RTL8201F_IER, val); 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic int rtl8211b_config_intr(struct phy_device *phydev) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci int err; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 1198c2ecf20Sopenharmony_ci err = phy_write(phydev, RTL821x_INER, 1208c2ecf20Sopenharmony_ci RTL8211B_INER_INIT); 1218c2ecf20Sopenharmony_ci else 1228c2ecf20Sopenharmony_ci err = phy_write(phydev, RTL821x_INER, 0); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci return err; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic int rtl8211e_config_intr(struct phy_device *phydev) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci int err; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 1328c2ecf20Sopenharmony_ci err = phy_write(phydev, RTL821x_INER, 1338c2ecf20Sopenharmony_ci RTL8211E_INER_LINK_STATUS); 1348c2ecf20Sopenharmony_ci else 1358c2ecf20Sopenharmony_ci err = phy_write(phydev, RTL821x_INER, 0); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci return err; 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic int rtl8211f_config_intr(struct phy_device *phydev) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci u16 val; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 1458c2ecf20Sopenharmony_ci val = RTL8211F_INER_LINK_STATUS; 1468c2ecf20Sopenharmony_ci else 1478c2ecf20Sopenharmony_ci val = 0; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci return phy_write_paged(phydev, 0xa42, RTL821x_INER, val); 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic int rtl8211_config_aneg(struct phy_device *phydev) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci int ret; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci ret = genphy_config_aneg(phydev); 1578c2ecf20Sopenharmony_ci if (ret < 0) 1588c2ecf20Sopenharmony_ci return ret; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* Quirk was copied from vendor driver. Unfortunately it includes no 1618c2ecf20Sopenharmony_ci * description of the magic numbers. 1628c2ecf20Sopenharmony_ci */ 1638c2ecf20Sopenharmony_ci if (phydev->speed == SPEED_100 && phydev->autoneg == AUTONEG_DISABLE) { 1648c2ecf20Sopenharmony_ci phy_write(phydev, 0x17, 0x2138); 1658c2ecf20Sopenharmony_ci phy_write(phydev, 0x0e, 0x0260); 1668c2ecf20Sopenharmony_ci } else { 1678c2ecf20Sopenharmony_ci phy_write(phydev, 0x17, 0x2108); 1688c2ecf20Sopenharmony_ci phy_write(phydev, 0x0e, 0x0000); 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci return 0; 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic int rtl8211c_config_init(struct phy_device *phydev) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci /* RTL8211C has an issue when operating in Gigabit slave mode */ 1778c2ecf20Sopenharmony_ci return phy_set_bits(phydev, MII_CTRL1000, 1788c2ecf20Sopenharmony_ci CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER); 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic int rtl8211f_config_init(struct phy_device *phydev) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci struct device *dev = &phydev->mdio.dev; 1848c2ecf20Sopenharmony_ci u16 val_txdly, val_rxdly; 1858c2ecf20Sopenharmony_ci u16 val; 1868c2ecf20Sopenharmony_ci int ret; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci val = RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_XTAL_OFF; 1898c2ecf20Sopenharmony_ci phy_modify_paged_changed(phydev, 0xa43, RTL8211F_PHYCR1, val, val); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci switch (phydev->interface) { 1928c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII: 1938c2ecf20Sopenharmony_ci val_txdly = 0; 1948c2ecf20Sopenharmony_ci val_rxdly = 0; 1958c2ecf20Sopenharmony_ci break; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII_RXID: 1988c2ecf20Sopenharmony_ci val_txdly = 0; 1998c2ecf20Sopenharmony_ci val_rxdly = RTL8211F_RX_DELAY; 2008c2ecf20Sopenharmony_ci break; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII_TXID: 2038c2ecf20Sopenharmony_ci val_txdly = RTL8211F_TX_DELAY; 2048c2ecf20Sopenharmony_ci val_rxdly = 0; 2058c2ecf20Sopenharmony_ci break; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII_ID: 2088c2ecf20Sopenharmony_ci val_txdly = RTL8211F_TX_DELAY; 2098c2ecf20Sopenharmony_ci val_rxdly = RTL8211F_RX_DELAY; 2108c2ecf20Sopenharmony_ci break; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci default: /* the rest of the modes imply leaving delay as is. */ 2138c2ecf20Sopenharmony_ci return 0; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci ret = phy_modify_paged_changed(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, 2178c2ecf20Sopenharmony_ci val_txdly); 2188c2ecf20Sopenharmony_ci if (ret < 0) { 2198c2ecf20Sopenharmony_ci dev_err(dev, "Failed to update the TX delay register\n"); 2208c2ecf20Sopenharmony_ci return ret; 2218c2ecf20Sopenharmony_ci } else if (ret) { 2228c2ecf20Sopenharmony_ci dev_dbg(dev, 2238c2ecf20Sopenharmony_ci "%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader)\n", 2248c2ecf20Sopenharmony_ci val_txdly ? "Enabling" : "Disabling"); 2258c2ecf20Sopenharmony_ci } else { 2268c2ecf20Sopenharmony_ci dev_dbg(dev, 2278c2ecf20Sopenharmony_ci "2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n", 2288c2ecf20Sopenharmony_ci val_txdly ? "enabled" : "disabled"); 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci ret = phy_modify_paged_changed(phydev, 0xd08, 0x15, RTL8211F_RX_DELAY, 2328c2ecf20Sopenharmony_ci val_rxdly); 2338c2ecf20Sopenharmony_ci if (ret < 0) { 2348c2ecf20Sopenharmony_ci dev_err(dev, "Failed to update the RX delay register\n"); 2358c2ecf20Sopenharmony_ci return ret; 2368c2ecf20Sopenharmony_ci } else if (ret) { 2378c2ecf20Sopenharmony_ci dev_dbg(dev, 2388c2ecf20Sopenharmony_ci "%s 2ns RX delay (and changing the value from pin-strapping RXD0 or the bootloader)\n", 2398c2ecf20Sopenharmony_ci val_rxdly ? "Enabling" : "Disabling"); 2408c2ecf20Sopenharmony_ci } else { 2418c2ecf20Sopenharmony_ci dev_dbg(dev, 2428c2ecf20Sopenharmony_ci "2ns RX delay was already %s (by pin-strapping RXD0 or bootloader configuration)\n", 2438c2ecf20Sopenharmony_ci val_rxdly ? "enabled" : "disabled"); 2448c2ecf20Sopenharmony_ci } 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci return 0; 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic int rtl821x_resume(struct phy_device *phydev) 2508c2ecf20Sopenharmony_ci{ 2518c2ecf20Sopenharmony_ci int ret; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci ret = genphy_resume(phydev); 2548c2ecf20Sopenharmony_ci if (ret < 0) 2558c2ecf20Sopenharmony_ci return ret; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci msleep(20); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci return 0; 2608c2ecf20Sopenharmony_ci} 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_cistatic int rtl8211e_config_init(struct phy_device *phydev) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci int ret = 0, oldpage; 2658c2ecf20Sopenharmony_ci u16 val; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */ 2688c2ecf20Sopenharmony_ci switch (phydev->interface) { 2698c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII: 2708c2ecf20Sopenharmony_ci val = RTL8211E_CTRL_DELAY | 0; 2718c2ecf20Sopenharmony_ci break; 2728c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII_ID: 2738c2ecf20Sopenharmony_ci val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY; 2748c2ecf20Sopenharmony_ci break; 2758c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII_RXID: 2768c2ecf20Sopenharmony_ci val = RTL8211E_CTRL_DELAY | RTL8211E_RX_DELAY; 2778c2ecf20Sopenharmony_ci break; 2788c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII_TXID: 2798c2ecf20Sopenharmony_ci val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY; 2808c2ecf20Sopenharmony_ci break; 2818c2ecf20Sopenharmony_ci default: /* the rest of the modes imply leaving delays as is. */ 2828c2ecf20Sopenharmony_ci return 0; 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci /* According to a sample driver there is a 0x1c config register on the 2868c2ecf20Sopenharmony_ci * 0xa4 extension page (0x7) layout. It can be used to disable/enable 2878c2ecf20Sopenharmony_ci * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. 2888c2ecf20Sopenharmony_ci * The configuration register definition: 2898c2ecf20Sopenharmony_ci * 14 = reserved 2908c2ecf20Sopenharmony_ci * 13 = Force Tx RX Delay controlled by bit12 bit11, 2918c2ecf20Sopenharmony_ci * 12 = RX Delay, 11 = TX Delay 2928c2ecf20Sopenharmony_ci * 10:0 = Test && debug settings reserved by realtek 2938c2ecf20Sopenharmony_ci */ 2948c2ecf20Sopenharmony_ci oldpage = phy_select_page(phydev, 0x7); 2958c2ecf20Sopenharmony_ci if (oldpage < 0) 2968c2ecf20Sopenharmony_ci goto err_restore_page; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4); 2998c2ecf20Sopenharmony_ci if (ret) 3008c2ecf20Sopenharmony_ci goto err_restore_page; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci ret = __phy_modify(phydev, 0x1c, RTL8211E_CTRL_DELAY 3038c2ecf20Sopenharmony_ci | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY, 3048c2ecf20Sopenharmony_ci val); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cierr_restore_page: 3078c2ecf20Sopenharmony_ci return phy_restore_page(phydev, oldpage, ret); 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cistatic int rtl8211b_suspend(struct phy_device *phydev) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci phy_write(phydev, MII_MMD_DATA, BIT(9)); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci return genphy_suspend(phydev); 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic int rtl8211b_resume(struct phy_device *phydev) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci phy_write(phydev, MII_MMD_DATA, 0); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci return genphy_resume(phydev); 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistatic int rtl8366rb_config_init(struct phy_device *phydev) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci int ret; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci ret = phy_set_bits(phydev, RTL8366RB_POWER_SAVE, 3298c2ecf20Sopenharmony_ci RTL8366RB_POWER_SAVE_ON); 3308c2ecf20Sopenharmony_ci if (ret) { 3318c2ecf20Sopenharmony_ci dev_err(&phydev->mdio.dev, 3328c2ecf20Sopenharmony_ci "error enabling power management\n"); 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci return ret; 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci/* get actual speed to cover the downshift case */ 3398c2ecf20Sopenharmony_cistatic int rtlgen_get_speed(struct phy_device *phydev) 3408c2ecf20Sopenharmony_ci{ 3418c2ecf20Sopenharmony_ci int val; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (!phydev->link) 3448c2ecf20Sopenharmony_ci return 0; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci val = phy_read_paged(phydev, 0xa43, 0x12); 3478c2ecf20Sopenharmony_ci if (val < 0) 3488c2ecf20Sopenharmony_ci return val; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci switch (val & RTLGEN_SPEED_MASK) { 3518c2ecf20Sopenharmony_ci case 0x0000: 3528c2ecf20Sopenharmony_ci phydev->speed = SPEED_10; 3538c2ecf20Sopenharmony_ci break; 3548c2ecf20Sopenharmony_ci case 0x0010: 3558c2ecf20Sopenharmony_ci phydev->speed = SPEED_100; 3568c2ecf20Sopenharmony_ci break; 3578c2ecf20Sopenharmony_ci case 0x0020: 3588c2ecf20Sopenharmony_ci phydev->speed = SPEED_1000; 3598c2ecf20Sopenharmony_ci break; 3608c2ecf20Sopenharmony_ci case 0x0200: 3618c2ecf20Sopenharmony_ci phydev->speed = SPEED_10000; 3628c2ecf20Sopenharmony_ci break; 3638c2ecf20Sopenharmony_ci case 0x0210: 3648c2ecf20Sopenharmony_ci phydev->speed = SPEED_2500; 3658c2ecf20Sopenharmony_ci break; 3668c2ecf20Sopenharmony_ci case 0x0220: 3678c2ecf20Sopenharmony_ci phydev->speed = SPEED_5000; 3688c2ecf20Sopenharmony_ci break; 3698c2ecf20Sopenharmony_ci default: 3708c2ecf20Sopenharmony_ci break; 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci return 0; 3748c2ecf20Sopenharmony_ci} 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cistatic int rtlgen_read_status(struct phy_device *phydev) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci int ret; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci ret = genphy_read_status(phydev); 3818c2ecf20Sopenharmony_ci if (ret < 0) 3828c2ecf20Sopenharmony_ci return ret; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci return rtlgen_get_speed(phydev); 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cistatic int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci int ret; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) { 3928c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0xa5c); 3938c2ecf20Sopenharmony_ci ret = __phy_read(phydev, 0x12); 3948c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0); 3958c2ecf20Sopenharmony_ci } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { 3968c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0xa5d); 3978c2ecf20Sopenharmony_ci ret = __phy_read(phydev, 0x10); 3988c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0); 3998c2ecf20Sopenharmony_ci } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE) { 4008c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0xa5d); 4018c2ecf20Sopenharmony_ci ret = __phy_read(phydev, 0x11); 4028c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0); 4038c2ecf20Sopenharmony_ci } else { 4048c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci return ret; 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cistatic int rtlgen_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, 4118c2ecf20Sopenharmony_ci u16 val) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci int ret; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { 4168c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0xa5d); 4178c2ecf20Sopenharmony_ci ret = __phy_write(phydev, 0x10, val); 4188c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0); 4198c2ecf20Sopenharmony_ci } else { 4208c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci return ret; 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_cistatic int rtl822x_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci int ret = rtlgen_read_mmd(phydev, devnum, regnum); 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci if (ret != -EOPNOTSUPP) 4318c2ecf20Sopenharmony_ci return ret; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE2) { 4348c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0xa6e); 4358c2ecf20Sopenharmony_ci ret = __phy_read(phydev, 0x16); 4368c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0); 4378c2ecf20Sopenharmony_ci } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { 4388c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0xa6d); 4398c2ecf20Sopenharmony_ci ret = __phy_read(phydev, 0x12); 4408c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0); 4418c2ecf20Sopenharmony_ci } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE2) { 4428c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0xa6d); 4438c2ecf20Sopenharmony_ci ret = __phy_read(phydev, 0x10); 4448c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0); 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci return ret; 4488c2ecf20Sopenharmony_ci} 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_cistatic int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, 4518c2ecf20Sopenharmony_ci u16 val) 4528c2ecf20Sopenharmony_ci{ 4538c2ecf20Sopenharmony_ci int ret = rtlgen_write_mmd(phydev, devnum, regnum, val); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci if (ret != -EOPNOTSUPP) 4568c2ecf20Sopenharmony_ci return ret; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { 4598c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0xa6d); 4608c2ecf20Sopenharmony_ci ret = __phy_write(phydev, 0x12, val); 4618c2ecf20Sopenharmony_ci rtl821x_write_page(phydev, 0); 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci return ret; 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_cistatic int rtl822x_get_features(struct phy_device *phydev) 4688c2ecf20Sopenharmony_ci{ 4698c2ecf20Sopenharmony_ci int val; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci val = phy_read_paged(phydev, 0xa61, 0x13); 4728c2ecf20Sopenharmony_ci if (val < 0) 4738c2ecf20Sopenharmony_ci return val; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, 4768c2ecf20Sopenharmony_ci phydev->supported, val & RTL_SUPPORTS_2500FULL); 4778c2ecf20Sopenharmony_ci linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, 4788c2ecf20Sopenharmony_ci phydev->supported, val & RTL_SUPPORTS_5000FULL); 4798c2ecf20Sopenharmony_ci linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, 4808c2ecf20Sopenharmony_ci phydev->supported, val & RTL_SUPPORTS_10000FULL); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci return genphy_read_abilities(phydev); 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic int rtl822x_config_aneg(struct phy_device *phydev) 4868c2ecf20Sopenharmony_ci{ 4878c2ecf20Sopenharmony_ci int ret = 0; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci if (phydev->autoneg == AUTONEG_ENABLE) { 4908c2ecf20Sopenharmony_ci u16 adv2500 = 0; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, 4938c2ecf20Sopenharmony_ci phydev->advertising)) 4948c2ecf20Sopenharmony_ci adv2500 = RTL_ADV_2500FULL; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12, 4978c2ecf20Sopenharmony_ci RTL_ADV_2500FULL, adv2500); 4988c2ecf20Sopenharmony_ci if (ret < 0) 4998c2ecf20Sopenharmony_ci return ret; 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci return __genphy_config_aneg(phydev, ret); 5038c2ecf20Sopenharmony_ci} 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_cistatic int rtl822x_read_status(struct phy_device *phydev) 5068c2ecf20Sopenharmony_ci{ 5078c2ecf20Sopenharmony_ci int ret; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci if (phydev->autoneg == AUTONEG_ENABLE) { 5108c2ecf20Sopenharmony_ci int lpadv = phy_read_paged(phydev, 0xa5d, 0x13); 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci if (lpadv < 0) 5138c2ecf20Sopenharmony_ci return lpadv; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, 5168c2ecf20Sopenharmony_ci phydev->lp_advertising, lpadv & RTL_LPADV_10000FULL); 5178c2ecf20Sopenharmony_ci linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, 5188c2ecf20Sopenharmony_ci phydev->lp_advertising, lpadv & RTL_LPADV_5000FULL); 5198c2ecf20Sopenharmony_ci linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, 5208c2ecf20Sopenharmony_ci phydev->lp_advertising, lpadv & RTL_LPADV_2500FULL); 5218c2ecf20Sopenharmony_ci } 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci ret = genphy_read_status(phydev); 5248c2ecf20Sopenharmony_ci if (ret < 0) 5258c2ecf20Sopenharmony_ci return ret; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci return rtlgen_get_speed(phydev); 5288c2ecf20Sopenharmony_ci} 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_cistatic bool rtlgen_supports_2_5gbps(struct phy_device *phydev) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci int val; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci phy_write(phydev, RTL821x_PAGE_SELECT, 0xa61); 5358c2ecf20Sopenharmony_ci val = phy_read(phydev, 0x13); 5368c2ecf20Sopenharmony_ci phy_write(phydev, RTL821x_PAGE_SELECT, 0); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci return val >= 0 && val & RTL_SUPPORTS_2500FULL; 5398c2ecf20Sopenharmony_ci} 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_cistatic int rtlgen_match_phy_device(struct phy_device *phydev) 5428c2ecf20Sopenharmony_ci{ 5438c2ecf20Sopenharmony_ci return phydev->phy_id == RTL_GENERIC_PHYID && 5448c2ecf20Sopenharmony_ci !rtlgen_supports_2_5gbps(phydev); 5458c2ecf20Sopenharmony_ci} 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_cistatic int rtl8226_match_phy_device(struct phy_device *phydev) 5488c2ecf20Sopenharmony_ci{ 5498c2ecf20Sopenharmony_ci return phydev->phy_id == RTL_GENERIC_PHYID && 5508c2ecf20Sopenharmony_ci rtlgen_supports_2_5gbps(phydev); 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic int rtlgen_resume(struct phy_device *phydev) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci int ret = genphy_resume(phydev); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci /* Internal PHY's from RTL8168h up may not be instantly ready */ 5588c2ecf20Sopenharmony_ci msleep(20); 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci return ret; 5618c2ecf20Sopenharmony_ci} 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_cistatic struct phy_driver realtek_drvs[] = { 5648c2ecf20Sopenharmony_ci { 5658c2ecf20Sopenharmony_ci PHY_ID_MATCH_EXACT(0x00008201), 5668c2ecf20Sopenharmony_ci .name = "RTL8201CP Ethernet", 5678c2ecf20Sopenharmony_ci .read_page = rtl821x_read_page, 5688c2ecf20Sopenharmony_ci .write_page = rtl821x_write_page, 5698c2ecf20Sopenharmony_ci }, { 5708c2ecf20Sopenharmony_ci PHY_ID_MATCH_EXACT(0x001cc816), 5718c2ecf20Sopenharmony_ci .name = "RTL8201F Fast Ethernet", 5728c2ecf20Sopenharmony_ci .ack_interrupt = &rtl8201_ack_interrupt, 5738c2ecf20Sopenharmony_ci .config_intr = &rtl8201_config_intr, 5748c2ecf20Sopenharmony_ci .suspend = genphy_suspend, 5758c2ecf20Sopenharmony_ci .resume = genphy_resume, 5768c2ecf20Sopenharmony_ci .read_page = rtl821x_read_page, 5778c2ecf20Sopenharmony_ci .write_page = rtl821x_write_page, 5788c2ecf20Sopenharmony_ci }, { 5798c2ecf20Sopenharmony_ci PHY_ID_MATCH_MODEL(0x001cc880), 5808c2ecf20Sopenharmony_ci .name = "RTL8208 Fast Ethernet", 5818c2ecf20Sopenharmony_ci .read_mmd = genphy_read_mmd_unsupported, 5828c2ecf20Sopenharmony_ci .write_mmd = genphy_write_mmd_unsupported, 5838c2ecf20Sopenharmony_ci .suspend = genphy_suspend, 5848c2ecf20Sopenharmony_ci .resume = genphy_resume, 5858c2ecf20Sopenharmony_ci .read_page = rtl821x_read_page, 5868c2ecf20Sopenharmony_ci .write_page = rtl821x_write_page, 5878c2ecf20Sopenharmony_ci }, { 5888c2ecf20Sopenharmony_ci PHY_ID_MATCH_EXACT(0x001cc910), 5898c2ecf20Sopenharmony_ci .name = "RTL8211 Gigabit Ethernet", 5908c2ecf20Sopenharmony_ci .config_aneg = rtl8211_config_aneg, 5918c2ecf20Sopenharmony_ci .read_mmd = &genphy_read_mmd_unsupported, 5928c2ecf20Sopenharmony_ci .write_mmd = &genphy_write_mmd_unsupported, 5938c2ecf20Sopenharmony_ci .read_page = rtl821x_read_page, 5948c2ecf20Sopenharmony_ci .write_page = rtl821x_write_page, 5958c2ecf20Sopenharmony_ci }, { 5968c2ecf20Sopenharmony_ci PHY_ID_MATCH_EXACT(0x001cc912), 5978c2ecf20Sopenharmony_ci .name = "RTL8211B Gigabit Ethernet", 5988c2ecf20Sopenharmony_ci .ack_interrupt = &rtl821x_ack_interrupt, 5998c2ecf20Sopenharmony_ci .config_intr = &rtl8211b_config_intr, 6008c2ecf20Sopenharmony_ci .read_mmd = &genphy_read_mmd_unsupported, 6018c2ecf20Sopenharmony_ci .write_mmd = &genphy_write_mmd_unsupported, 6028c2ecf20Sopenharmony_ci .suspend = rtl8211b_suspend, 6038c2ecf20Sopenharmony_ci .resume = rtl8211b_resume, 6048c2ecf20Sopenharmony_ci .read_page = rtl821x_read_page, 6058c2ecf20Sopenharmony_ci .write_page = rtl821x_write_page, 6068c2ecf20Sopenharmony_ci }, { 6078c2ecf20Sopenharmony_ci PHY_ID_MATCH_EXACT(0x001cc913), 6088c2ecf20Sopenharmony_ci .name = "RTL8211C Gigabit Ethernet", 6098c2ecf20Sopenharmony_ci .config_init = rtl8211c_config_init, 6108c2ecf20Sopenharmony_ci .read_mmd = &genphy_read_mmd_unsupported, 6118c2ecf20Sopenharmony_ci .write_mmd = &genphy_write_mmd_unsupported, 6128c2ecf20Sopenharmony_ci .read_page = rtl821x_read_page, 6138c2ecf20Sopenharmony_ci .write_page = rtl821x_write_page, 6148c2ecf20Sopenharmony_ci }, { 6158c2ecf20Sopenharmony_ci PHY_ID_MATCH_EXACT(0x001cc914), 6168c2ecf20Sopenharmony_ci .name = "RTL8211DN Gigabit Ethernet", 6178c2ecf20Sopenharmony_ci .ack_interrupt = rtl821x_ack_interrupt, 6188c2ecf20Sopenharmony_ci .config_intr = rtl8211e_config_intr, 6198c2ecf20Sopenharmony_ci .suspend = genphy_suspend, 6208c2ecf20Sopenharmony_ci .resume = genphy_resume, 6218c2ecf20Sopenharmony_ci .read_page = rtl821x_read_page, 6228c2ecf20Sopenharmony_ci .write_page = rtl821x_write_page, 6238c2ecf20Sopenharmony_ci }, { 6248c2ecf20Sopenharmony_ci PHY_ID_MATCH_EXACT(0x001cc915), 6258c2ecf20Sopenharmony_ci .name = "RTL8211E Gigabit Ethernet", 6268c2ecf20Sopenharmony_ci .config_init = &rtl8211e_config_init, 6278c2ecf20Sopenharmony_ci .ack_interrupt = &rtl821x_ack_interrupt, 6288c2ecf20Sopenharmony_ci .config_intr = &rtl8211e_config_intr, 6298c2ecf20Sopenharmony_ci .suspend = genphy_suspend, 6308c2ecf20Sopenharmony_ci .resume = genphy_resume, 6318c2ecf20Sopenharmony_ci .read_page = rtl821x_read_page, 6328c2ecf20Sopenharmony_ci .write_page = rtl821x_write_page, 6338c2ecf20Sopenharmony_ci }, { 6348c2ecf20Sopenharmony_ci PHY_ID_MATCH_EXACT(0x001cc916), 6358c2ecf20Sopenharmony_ci .name = "RTL8211F Gigabit Ethernet", 6368c2ecf20Sopenharmony_ci .config_init = &rtl8211f_config_init, 6378c2ecf20Sopenharmony_ci .ack_interrupt = &rtl8211f_ack_interrupt, 6388c2ecf20Sopenharmony_ci .config_intr = &rtl8211f_config_intr, 6398c2ecf20Sopenharmony_ci .suspend = genphy_suspend, 6408c2ecf20Sopenharmony_ci .resume = rtl821x_resume, 6418c2ecf20Sopenharmony_ci .read_page = rtl821x_read_page, 6428c2ecf20Sopenharmony_ci .write_page = rtl821x_write_page, 6438c2ecf20Sopenharmony_ci }, { 6448c2ecf20Sopenharmony_ci .name = "Generic FE-GE Realtek PHY", 6458c2ecf20Sopenharmony_ci .match_phy_device = rtlgen_match_phy_device, 6468c2ecf20Sopenharmony_ci .read_status = rtlgen_read_status, 6478c2ecf20Sopenharmony_ci .suspend = genphy_suspend, 6488c2ecf20Sopenharmony_ci .resume = rtlgen_resume, 6498c2ecf20Sopenharmony_ci .read_page = rtl821x_read_page, 6508c2ecf20Sopenharmony_ci .write_page = rtl821x_write_page, 6518c2ecf20Sopenharmony_ci .read_mmd = rtlgen_read_mmd, 6528c2ecf20Sopenharmony_ci .write_mmd = rtlgen_write_mmd, 6538c2ecf20Sopenharmony_ci }, { 6548c2ecf20Sopenharmony_ci .name = "RTL8226 2.5Gbps PHY", 6558c2ecf20Sopenharmony_ci .match_phy_device = rtl8226_match_phy_device, 6568c2ecf20Sopenharmony_ci .get_features = rtl822x_get_features, 6578c2ecf20Sopenharmony_ci .config_aneg = rtl822x_config_aneg, 6588c2ecf20Sopenharmony_ci .read_status = rtl822x_read_status, 6598c2ecf20Sopenharmony_ci .suspend = genphy_suspend, 6608c2ecf20Sopenharmony_ci .resume = rtlgen_resume, 6618c2ecf20Sopenharmony_ci .read_page = rtl821x_read_page, 6628c2ecf20Sopenharmony_ci .write_page = rtl821x_write_page, 6638c2ecf20Sopenharmony_ci .read_mmd = rtl822x_read_mmd, 6648c2ecf20Sopenharmony_ci .write_mmd = rtl822x_write_mmd, 6658c2ecf20Sopenharmony_ci }, { 6668c2ecf20Sopenharmony_ci PHY_ID_MATCH_EXACT(0x001cc840), 6678c2ecf20Sopenharmony_ci .name = "RTL8226B_RTL8221B 2.5Gbps PHY", 6688c2ecf20Sopenharmony_ci .get_features = rtl822x_get_features, 6698c2ecf20Sopenharmony_ci .config_aneg = rtl822x_config_aneg, 6708c2ecf20Sopenharmony_ci .read_status = rtl822x_read_status, 6718c2ecf20Sopenharmony_ci .suspend = genphy_suspend, 6728c2ecf20Sopenharmony_ci .resume = rtlgen_resume, 6738c2ecf20Sopenharmony_ci .read_page = rtl821x_read_page, 6748c2ecf20Sopenharmony_ci .write_page = rtl821x_write_page, 6758c2ecf20Sopenharmony_ci .read_mmd = rtl822x_read_mmd, 6768c2ecf20Sopenharmony_ci .write_mmd = rtl822x_write_mmd, 6778c2ecf20Sopenharmony_ci }, { 6788c2ecf20Sopenharmony_ci PHY_ID_MATCH_EXACT(0x001cc961), 6798c2ecf20Sopenharmony_ci .name = "RTL8366RB Gigabit Ethernet", 6808c2ecf20Sopenharmony_ci .config_init = &rtl8366rb_config_init, 6818c2ecf20Sopenharmony_ci /* These interrupts are handled by the irq controller 6828c2ecf20Sopenharmony_ci * embedded inside the RTL8366RB, they get unmasked when the 6838c2ecf20Sopenharmony_ci * irq is requested and ACKed by reading the status register, 6848c2ecf20Sopenharmony_ci * which is done by the irqchip code. 6858c2ecf20Sopenharmony_ci */ 6868c2ecf20Sopenharmony_ci .ack_interrupt = genphy_no_ack_interrupt, 6878c2ecf20Sopenharmony_ci .config_intr = genphy_no_config_intr, 6888c2ecf20Sopenharmony_ci .suspend = genphy_suspend, 6898c2ecf20Sopenharmony_ci .resume = genphy_resume, 6908c2ecf20Sopenharmony_ci }, 6918c2ecf20Sopenharmony_ci}; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_cimodule_phy_driver(realtek_drvs); 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_cistatic const struct mdio_device_id __maybe_unused realtek_tbl[] = { 6968c2ecf20Sopenharmony_ci { PHY_ID_MATCH_VENDOR(0x001cc800) }, 6978c2ecf20Sopenharmony_ci { } 6988c2ecf20Sopenharmony_ci}; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(mdio, realtek_tbl); 701