Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: phy: realtek: add interrupt support for RTL8221B

This commit introduces interrupt support for RTL8221B (C45 mode).
Interrupts are mapped on the VEND2 page. VEND2 registers are only
accessible via C45 reads and cannot be accessed by C45 over C22.

Signed-off-by: Jianhui Zhao <zhaojh329@gmail.com>
[Enable only link state change interrupts]
Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20251102152644.1676482-1-olek2@wp.pl
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Jianhui Zhao and committed by
Jakub Kicinski
18aa3623 acbf1d0a

+56
+56
drivers/net/phy/realtek/realtek_main.c
··· 128 128 */ 129 129 #define RTL822X_VND2_C22_REG(reg) (0xa400 + 2 * (reg)) 130 130 131 + #define RTL8221B_VND2_INER 0xa4d2 132 + #define RTL8221B_VND2_INER_LINK_STATUS BIT(4) 133 + 134 + #define RTL8221B_VND2_INSR 0xa4d4 135 + 131 136 #define RTL8224_MII_RTCT 0x11 132 137 #define RTL8224_MII_RTCT_ENABLE BIT(0) 133 138 #define RTL8224_MII_RTCT_PAIR_A BIT(4) ··· 1885 1880 return IRQ_HANDLED; 1886 1881 } 1887 1882 1883 + static int rtl8221b_ack_interrupt(struct phy_device *phydev) 1884 + { 1885 + int err; 1886 + 1887 + err = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL8221B_VND2_INSR); 1888 + 1889 + return (err < 0) ? err : 0; 1890 + } 1891 + 1892 + static int rtl8221b_config_intr(struct phy_device *phydev) 1893 + { 1894 + int err; 1895 + 1896 + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 1897 + err = rtl8221b_ack_interrupt(phydev); 1898 + if (err) 1899 + return err; 1900 + 1901 + err = phy_write_mmd(phydev, MDIO_MMD_VEND2, RTL8221B_VND2_INER, 1902 + RTL8221B_VND2_INER_LINK_STATUS); 1903 + } else { 1904 + err = phy_write_mmd(phydev, MDIO_MMD_VEND2, 1905 + RTL8221B_VND2_INER, 0); 1906 + if (err) 1907 + return err; 1908 + 1909 + err = rtl8221b_ack_interrupt(phydev); 1910 + } 1911 + 1912 + return err; 1913 + } 1914 + 1915 + static irqreturn_t rtl8221b_handle_interrupt(struct phy_device *phydev) 1916 + { 1917 + int err; 1918 + 1919 + err = rtl8221b_ack_interrupt(phydev); 1920 + if (err) { 1921 + phy_error(phydev); 1922 + return IRQ_NONE; 1923 + } 1924 + 1925 + phy_trigger_machine(phydev); 1926 + 1927 + return IRQ_HANDLED; 1928 + } 1929 + 1888 1930 static struct phy_driver realtek_drvs[] = { 1889 1931 { 1890 1932 PHY_ID_MATCH_EXACT(0x00008201), ··· 2106 2054 }, { 2107 2055 .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, 2108 2056 .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", 2057 + .config_intr = rtl8221b_config_intr, 2058 + .handle_interrupt = rtl8221b_handle_interrupt, 2109 2059 .probe = rtl822x_probe, 2110 2060 .config_init = rtl822xb_config_init, 2111 2061 .get_rate_matching = rtl822xb_get_rate_matching, ··· 2132 2078 }, { 2133 2079 .match_phy_device = rtl8221b_vm_cg_c45_match_phy_device, 2134 2080 .name = "RTL8221B-VM-CG 2.5Gbps PHY (C45)", 2081 + .config_intr = rtl8221b_config_intr, 2082 + .handle_interrupt = rtl8221b_handle_interrupt, 2135 2083 .probe = rtl822x_probe, 2136 2084 .config_init = rtl822xb_config_init, 2137 2085 .get_rate_matching = rtl822xb_get_rate_matching,