2019-01-21 19:05:50 +01:00
// SPDX-License-Identifier: GPL-2.0+
2008-02-03 03:50:54 -08:00
/*
* drivers / net / phy / realtek . c
*
* Driver for Realtek PHYs
*
* Author : Johnson Leung < r58129 @ freescale . com >
*
* Copyright ( c ) 2004 Freescale Semiconductor , Inc .
*/
2017-12-02 22:51:24 +01:00
# include <linux/bitops.h>
2008-02-03 03:50:54 -08:00
# include <linux/phy.h>
2011-07-03 15:21:01 -04:00
# include <linux/module.h>
2008-02-03 03:50:54 -08:00
2017-12-02 22:51:27 +01:00
# define RTL821x_PHYSR 0x11
# define RTL821x_PHYSR_DUPLEX BIT(13)
# define RTL821x_PHYSR_SPEED GENMASK(15, 14)
2017-12-02 22:51:26 +01:00
2017-12-02 22:51:27 +01:00
# define RTL821x_INER 0x12
# define RTL8211B_INER_INIT 0x6400
# define RTL8211E_INER_LINK_STATUS BIT(10)
# define RTL8211F_INER_LINK_STATUS BIT(4)
2017-12-02 22:51:26 +01:00
2017-12-02 22:51:27 +01:00
# define RTL821x_INSR 0x13
2017-12-02 22:51:26 +01:00
2019-05-09 00:51:15 +03:00
# define RTL821x_EXT_PAGE_SELECT 0x1e
2017-12-02 22:51:27 +01:00
# define RTL821x_PAGE_SELECT 0x1f
2008-02-03 03:50:54 -08:00
2017-12-02 22:51:27 +01:00
# define RTL8211F_INSR 0x1d
2013-01-23 00:30:03 +00:00
2017-12-02 22:51:27 +01:00
# define RTL8211F_TX_DELAY BIT(8)
2019-05-09 00:51:15 +03:00
# define RTL8211E_TX_DELAY BIT(1)
# define RTL8211E_RX_DELAY BIT(2)
# define RTL8211E_MODE_MII_GMII BIT(3)
2017-12-02 22:51:27 +01:00
# define RTL8201F_ISR 0x1e
# define RTL8201F_IER 0x13
2017-09-12 18:54:36 +09:00
2018-07-14 11:45:53 +02:00
# define RTL8366RB_POWER_SAVE 0x15
# define RTL8366RB_POWER_SAVE_ON BIT(12)
2019-08-13 08:09:32 +02:00
# define RTL_SUPPORTS_5000FULL BIT(14)
# define RTL_SUPPORTS_2500FULL BIT(13)
# define RTL_SUPPORTS_10000FULL BIT(0)
2019-08-09 20:45:14 +02:00
# define RTL_ADV_2500FULL BIT(7)
# define RTL_LPADV_10000FULL BIT(11)
# define RTL_LPADV_5000FULL BIT(6)
# define RTL_LPADV_2500FULL BIT(5)
2019-08-13 08:09:32 +02:00
# define RTL_GENERIC_PHYID 0x001cc800
2008-02-03 03:50:54 -08:00
MODULE_DESCRIPTION ( " Realtek PHY driver " ) ;
MODULE_AUTHOR ( " Johnson Leung " ) ;
MODULE_LICENSE ( " GPL " ) ;
2018-01-12 23:17:34 +01:00
static int rtl821x_read_page ( struct phy_device * phydev )
2017-12-02 22:51:28 +01:00
{
2018-01-12 23:17:34 +01:00
return __phy_read ( phydev , RTL821x_PAGE_SELECT ) ;
2017-12-02 22:51:28 +01:00
}
2018-01-12 23:17:34 +01:00
static int rtl821x_write_page ( struct phy_device * phydev , int page )
2017-12-02 22:51:28 +01:00
{
2018-01-12 23:17:34 +01:00
return __phy_write ( phydev , RTL821x_PAGE_SELECT , page ) ;
2017-12-02 22:51:28 +01:00
}
2017-09-12 18:54:36 +09:00
static int rtl8201_ack_interrupt ( struct phy_device * phydev )
{
int err ;
err = phy_read ( phydev , RTL8201F_ISR ) ;
return ( err < 0 ) ? err : 0 ;
}
2008-02-03 03:50:54 -08:00
static int rtl821x_ack_interrupt ( struct phy_device * phydev )
{
int err ;
err = phy_read ( phydev , RTL821x_INSR ) ;
return ( err < 0 ) ? err : 0 ;
}
2015-06-18 16:42:47 +08:00
static int rtl8211f_ack_interrupt ( struct phy_device * phydev )
{
int err ;
2018-01-12 23:17:34 +01:00
err = phy_read_paged ( phydev , 0xa43 , RTL8211F_INSR ) ;
2015-06-18 16:42:47 +08:00
return ( err < 0 ) ? err : 0 ;
}
2017-09-12 18:54:36 +09:00
static int rtl8201_config_intr ( struct phy_device * phydev )
{
2017-12-02 22:51:28 +01:00
u16 val ;
2017-09-12 18:54:36 +09:00
if ( phydev - > interrupts = = PHY_INTERRUPT_ENABLED )
2017-12-02 22:51:28 +01:00
val = BIT ( 13 ) | BIT ( 12 ) | BIT ( 11 ) ;
2017-09-12 18:54:36 +09:00
else
2017-12-02 22:51:28 +01:00
val = 0 ;
2017-09-12 18:54:36 +09:00
2018-01-12 23:17:34 +01:00
return phy_write_paged ( phydev , 0x7 , RTL8201F_IER , val ) ;
2017-09-12 18:54:36 +09:00
}
2013-01-23 00:30:03 +00:00
static int rtl8211b_config_intr ( struct phy_device * phydev )
2008-02-03 03:50:54 -08:00
{
int err ;
if ( phydev - > interrupts = = PHY_INTERRUPT_ENABLED )
err = phy_write ( phydev , RTL821x_INER ,
2017-12-02 22:51:25 +01:00
RTL8211B_INER_INIT ) ;
2008-02-03 03:50:54 -08:00
else
err = phy_write ( phydev , RTL821x_INER , 0 ) ;
return err ;
}
2013-01-23 00:30:03 +00:00
static int rtl8211e_config_intr ( struct phy_device * phydev )
{
int err ;
if ( phydev - > interrupts = = PHY_INTERRUPT_ENABLED )
err = phy_write ( phydev , RTL821x_INER ,
2013-08-19 08:48:34 +02:00
RTL8211E_INER_LINK_STATUS ) ;
2013-01-23 00:30:03 +00:00
else
err = phy_write ( phydev , RTL821x_INER , 0 ) ;
return err ;
}
2015-06-18 16:42:47 +08:00
static int rtl8211f_config_intr ( struct phy_device * phydev )
{
2017-12-02 22:51:28 +01:00
u16 val ;
2015-06-18 16:42:47 +08:00
if ( phydev - > interrupts = = PHY_INTERRUPT_ENABLED )
2017-12-02 22:51:28 +01:00
val = RTL8211F_INER_LINK_STATUS ;
2015-06-18 16:42:47 +08:00
else
2017-12-02 22:51:28 +01:00
val = 0 ;
2015-06-18 16:42:47 +08:00
2018-01-12 23:17:34 +01:00
return phy_write_paged ( phydev , 0xa42 , RTL821x_INER , val ) ;
2015-06-18 16:42:47 +08:00
}
2018-06-28 20:46:45 +02:00
static int rtl8211_config_aneg ( struct phy_device * phydev )
{
int ret ;
ret = genphy_config_aneg ( phydev ) ;
if ( ret < 0 )
return ret ;
/* Quirk was copied from vendor driver. Unfortunately it includes no
* description of the magic numbers .
*/
if ( phydev - > speed = = SPEED_100 & & phydev - > autoneg = = AUTONEG_DISABLE ) {
phy_write ( phydev , 0x17 , 0x2138 ) ;
phy_write ( phydev , 0x0e , 0x0260 ) ;
} else {
phy_write ( phydev , 0x17 , 0x2108 ) ;
phy_write ( phydev , 0x0e , 0x0000 ) ;
}
return 0 ;
}
2018-07-02 08:08:13 +02:00
static int rtl8211c_config_init ( struct phy_device * phydev )
{
/* RTL8211C has an issue when operating in Gigabit slave mode */
2019-03-27 22:00:32 +01:00
return phy_set_bits ( phydev , MII_CTRL1000 ,
CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER ) ;
2018-07-02 08:08:13 +02:00
}
2015-06-18 16:42:47 +08:00
static int rtl8211f_config_init ( struct phy_device * phydev )
{
2019-05-09 00:51:17 +03:00
u16 val ;
2015-06-18 16:42:47 +08:00
2019-05-09 00:51:17 +03:00
/* enable TX-delay for rgmii-{id,txid}, and disable it for rgmii and
* rgmii - rxid . The RX - delay can be enabled by the external RXDLY pin .
*/
switch ( phydev - > interface ) {
case PHY_INTERFACE_MODE_RGMII :
case PHY_INTERFACE_MODE_RGMII_RXID :
val = 0 ;
break ;
case PHY_INTERFACE_MODE_RGMII_ID :
case PHY_INTERFACE_MODE_RGMII_TXID :
2018-01-12 23:17:34 +01:00
val = RTL8211F_TX_DELAY ;
2019-05-09 00:51:17 +03:00
break ;
default : /* the rest of the modes imply leaving delay as is. */
return 0 ;
}
2015-06-18 16:42:47 +08:00
2018-01-12 23:17:34 +01:00
return phy_modify_paged ( phydev , 0xd08 , 0x11 , RTL8211F_TX_DELAY , val ) ;
2015-06-18 16:42:47 +08:00
}
2019-05-09 00:51:15 +03:00
static int rtl8211e_config_init ( struct phy_device * phydev )
{
int ret = 0 , oldpage ;
u16 val ;
/* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */
switch ( phydev - > interface ) {
case PHY_INTERFACE_MODE_RGMII :
val = 0 ;
break ;
case PHY_INTERFACE_MODE_RGMII_ID :
val = RTL8211E_TX_DELAY | RTL8211E_RX_DELAY ;
break ;
case PHY_INTERFACE_MODE_RGMII_RXID :
val = RTL8211E_RX_DELAY ;
break ;
case PHY_INTERFACE_MODE_RGMII_TXID :
val = RTL8211E_TX_DELAY ;
break ;
default : /* the rest of the modes imply leaving delays as is. */
return 0 ;
}
/* According to a sample driver there is a 0x1c config register on the
* 0xa4 extension page ( 0x7 ) layout . It can be used to disable / enable
* the RX / TX delays otherwise controlled by RXDLY / TXDLY pins . It can
* also be used to customize the whole configuration register :
* 8 : 6 = PHY Address , 5 : 4 = Auto - Negotiation , 3 = Interface Mode Select ,
* 2 = RX Delay , 1 = TX Delay , 0 = SELRGV ( see original PHY datasheet
* for details ) .
*/
oldpage = phy_select_page ( phydev , 0x7 ) ;
if ( oldpage < 0 )
goto err_restore_page ;
2019-05-13 15:41:45 +09:00
ret = __phy_write ( phydev , RTL821x_EXT_PAGE_SELECT , 0xa4 ) ;
2019-05-09 00:51:15 +03:00
if ( ret )
goto err_restore_page ;
2019-05-13 15:41:45 +09:00
ret = __phy_modify ( phydev , 0x1c , RTL8211E_TX_DELAY | RTL8211E_RX_DELAY ,
val ) ;
2019-05-09 00:51:15 +03:00
err_restore_page :
return phy_restore_page ( phydev , oldpage , ret ) ;
}
2018-05-24 22:40:12 +02:00
static int rtl8211b_suspend ( struct phy_device * phydev )
{
phy_write ( phydev , MII_MMD_DATA , BIT ( 9 ) ) ;
return genphy_suspend ( phydev ) ;
}
static int rtl8211b_resume ( struct phy_device * phydev )
{
phy_write ( phydev , MII_MMD_DATA , 0 ) ;
return genphy_resume ( phydev ) ;
}
2018-07-14 11:45:53 +02:00
static int rtl8366rb_config_init ( struct phy_device * phydev )
{
int ret ;
ret = phy_set_bits ( phydev , RTL8366RB_POWER_SAVE ,
RTL8366RB_POWER_SAVE_ON ) ;
if ( ret ) {
dev_err ( & phydev - > mdio . dev ,
" error enabling power management \n " ) ;
}
return ret ;
}
2019-08-15 14:12:55 +02:00
static int rtlgen_read_mmd ( struct phy_device * phydev , int devnum , u16 regnum )
{
int ret ;
if ( devnum = = MDIO_MMD_PCS & & regnum = = MDIO_PCS_EEE_ABLE ) {
rtl821x_write_page ( phydev , 0xa5c ) ;
ret = __phy_read ( phydev , 0x12 ) ;
rtl821x_write_page ( phydev , 0 ) ;
} else if ( devnum = = MDIO_MMD_AN & & regnum = = MDIO_AN_EEE_ADV ) {
rtl821x_write_page ( phydev , 0xa5d ) ;
ret = __phy_read ( phydev , 0x10 ) ;
rtl821x_write_page ( phydev , 0 ) ;
} else if ( devnum = = MDIO_MMD_AN & & regnum = = MDIO_AN_EEE_LPABLE ) {
rtl821x_write_page ( phydev , 0xa5d ) ;
ret = __phy_read ( phydev , 0x11 ) ;
rtl821x_write_page ( phydev , 0 ) ;
} else {
ret = - EOPNOTSUPP ;
}
return ret ;
}
static int rtlgen_write_mmd ( struct phy_device * phydev , int devnum , u16 regnum ,
u16 val )
{
int ret ;
if ( devnum = = MDIO_MMD_AN & & regnum = = MDIO_AN_EEE_ADV ) {
rtl821x_write_page ( phydev , 0xa5d ) ;
ret = __phy_write ( phydev , 0x10 , val ) ;
rtl821x_write_page ( phydev , 0 ) ;
} else {
ret = - EOPNOTSUPP ;
}
return ret ;
}
2019-08-16 21:57:38 +02:00
static int rtl8125_read_mmd ( struct phy_device * phydev , int devnum , u16 regnum )
{
int ret = rtlgen_read_mmd ( phydev , devnum , regnum ) ;
if ( ret ! = - EOPNOTSUPP )
return ret ;
if ( devnum = = MDIO_MMD_PCS & & regnum = = MDIO_PCS_EEE_ABLE2 ) {
rtl821x_write_page ( phydev , 0xa6e ) ;
ret = __phy_read ( phydev , 0x16 ) ;
rtl821x_write_page ( phydev , 0 ) ;
} else if ( devnum = = MDIO_MMD_AN & & regnum = = MDIO_AN_EEE_ADV2 ) {
rtl821x_write_page ( phydev , 0xa6d ) ;
ret = __phy_read ( phydev , 0x12 ) ;
rtl821x_write_page ( phydev , 0 ) ;
} else if ( devnum = = MDIO_MMD_AN & & regnum = = MDIO_AN_EEE_LPABLE2 ) {
rtl821x_write_page ( phydev , 0xa6d ) ;
ret = __phy_read ( phydev , 0x10 ) ;
rtl821x_write_page ( phydev , 0 ) ;
}
return ret ;
}
static int rtl8125_write_mmd ( struct phy_device * phydev , int devnum , u16 regnum ,
u16 val )
{
int ret = rtlgen_write_mmd ( phydev , devnum , regnum , val ) ;
if ( ret ! = - EOPNOTSUPP )
return ret ;
if ( devnum = = MDIO_MMD_AN & & regnum = = MDIO_AN_EEE_ADV2 ) {
rtl821x_write_page ( phydev , 0xa6d ) ;
ret = __phy_write ( phydev , 0x12 , val ) ;
rtl821x_write_page ( phydev , 0 ) ;
}
return ret ;
}
2019-08-09 20:45:14 +02:00
static int rtl8125_get_features ( struct phy_device * phydev )
{
2019-08-13 08:09:32 +02:00
int val ;
val = phy_read_paged ( phydev , 0xa61 , 0x13 ) ;
if ( val < 0 )
return val ;
linkmode_mod_bit ( ETHTOOL_LINK_MODE_2500baseT_Full_BIT ,
phydev - > supported , val & RTL_SUPPORTS_2500FULL ) ;
linkmode_mod_bit ( ETHTOOL_LINK_MODE_5000baseT_Full_BIT ,
phydev - > supported , val & RTL_SUPPORTS_5000FULL ) ;
linkmode_mod_bit ( ETHTOOL_LINK_MODE_10000baseT_Full_BIT ,
phydev - > supported , val & RTL_SUPPORTS_10000FULL ) ;
2019-08-09 20:45:14 +02:00
return genphy_read_abilities ( phydev ) ;
}
static int rtl8125_config_aneg ( struct phy_device * phydev )
{
int ret = 0 ;
if ( phydev - > autoneg = = AUTONEG_ENABLE ) {
u16 adv2500 = 0 ;
if ( linkmode_test_bit ( ETHTOOL_LINK_MODE_2500baseT_Full_BIT ,
phydev - > advertising ) )
adv2500 = RTL_ADV_2500FULL ;
ret = phy_modify_paged_changed ( phydev , 0xa5d , 0x12 ,
RTL_ADV_2500FULL , adv2500 ) ;
if ( ret < 0 )
return ret ;
}
return __genphy_config_aneg ( phydev , ret ) ;
}
static int rtl8125_read_status ( struct phy_device * phydev )
{
if ( phydev - > autoneg = = AUTONEG_ENABLE ) {
int lpadv = phy_read_paged ( phydev , 0xa5d , 0x13 ) ;
if ( lpadv < 0 )
return lpadv ;
linkmode_mod_bit ( ETHTOOL_LINK_MODE_10000baseT_Full_BIT ,
phydev - > lp_advertising , lpadv & RTL_LPADV_10000FULL ) ;
linkmode_mod_bit ( ETHTOOL_LINK_MODE_5000baseT_Full_BIT ,
phydev - > lp_advertising , lpadv & RTL_LPADV_5000FULL ) ;
linkmode_mod_bit ( ETHTOOL_LINK_MODE_2500baseT_Full_BIT ,
phydev - > lp_advertising , lpadv & RTL_LPADV_2500FULL ) ;
}
return genphy_read_status ( phydev ) ;
}
2019-08-13 08:09:32 +02:00
static bool rtlgen_supports_2_5gbps ( struct phy_device * phydev )
{
int val ;
phy_write ( phydev , RTL821x_PAGE_SELECT , 0xa61 ) ;
val = phy_read ( phydev , 0x13 ) ;
phy_write ( phydev , RTL821x_PAGE_SELECT , 0 ) ;
return val > = 0 & & val & RTL_SUPPORTS_2500FULL ;
}
static int rtlgen_match_phy_device ( struct phy_device * phydev )
{
return phydev - > phy_id = = RTL_GENERIC_PHYID & &
! rtlgen_supports_2_5gbps ( phydev ) ;
}
static int rtl8125_match_phy_device ( struct phy_device * phydev )
{
return phydev - > phy_id = = RTL_GENERIC_PHYID & &
rtlgen_supports_2_5gbps ( phydev ) ;
}
2014-06-10 12:50:12 +09:00
static struct phy_driver realtek_drvs [ ] = {
{
2018-11-10 00:40:37 +01:00
PHY_ID_MATCH_EXACT ( 0x00008201 ) ,
2014-06-10 12:50:12 +09:00
. name = " RTL8201CP Ethernet " ,
2017-09-12 18:54:36 +09:00
} , {
2018-11-10 00:40:37 +01:00
PHY_ID_MATCH_EXACT ( 0x001cc816 ) ,
2018-11-04 19:02:42 +01:00
. name = " RTL8201F Fast Ethernet " ,
2017-09-12 18:54:36 +09:00
. ack_interrupt = & rtl8201_ack_interrupt ,
. config_intr = & rtl8201_config_intr ,
. suspend = genphy_suspend ,
. resume = genphy_resume ,
2018-01-12 23:17:34 +01:00
. read_page = rtl821x_read_page ,
. write_page = rtl821x_write_page ,
2019-12-01 10:51:47 +01:00
} , {
PHY_ID_MATCH_MODEL ( 0x001cc880 ) ,
. name = " RTL8208 Fast Ethernet " ,
. read_mmd = genphy_read_mmd_unsupported ,
. write_mmd = genphy_write_mmd_unsupported ,
. suspend = genphy_suspend ,
. resume = genphy_resume ,
. read_page = rtl821x_read_page ,
. write_page = rtl821x_write_page ,
2018-06-28 20:46:45 +02:00
} , {
2018-11-10 00:40:37 +01:00
PHY_ID_MATCH_EXACT ( 0x001cc910 ) ,
2018-06-28 20:46:45 +02:00
. name = " RTL8211 Gigabit Ethernet " ,
. config_aneg = rtl8211_config_aneg ,
. read_mmd = & genphy_read_mmd_unsupported ,
. write_mmd = & genphy_write_mmd_unsupported ,
2019-05-10 22:11:26 +02:00
. read_page = rtl821x_read_page ,
. write_page = rtl821x_write_page ,
2014-06-10 12:50:12 +09:00
} , {
2018-11-10 00:40:37 +01:00
PHY_ID_MATCH_EXACT ( 0x001cc912 ) ,
2014-06-10 12:50:12 +09:00
. name = " RTL8211B Gigabit Ethernet " ,
. ack_interrupt = & rtl821x_ack_interrupt ,
. config_intr = & rtl8211b_config_intr ,
2018-03-20 09:44:53 +08:00
. read_mmd = & genphy_read_mmd_unsupported ,
. write_mmd = & genphy_write_mmd_unsupported ,
2018-05-24 22:40:12 +02:00
. suspend = rtl8211b_suspend ,
. resume = rtl8211b_resume ,
2019-05-10 22:11:26 +02:00
. read_page = rtl821x_read_page ,
. write_page = rtl821x_write_page ,
2018-07-02 08:08:13 +02:00
} , {
2018-11-10 00:40:37 +01:00
PHY_ID_MATCH_EXACT ( 0x001cc913 ) ,
2018-07-02 08:08:13 +02:00
. name = " RTL8211C Gigabit Ethernet " ,
. config_init = rtl8211c_config_init ,
. read_mmd = & genphy_read_mmd_unsupported ,
. write_mmd = & genphy_write_mmd_unsupported ,
2019-05-10 22:11:26 +02:00
. read_page = rtl821x_read_page ,
. write_page = rtl821x_write_page ,
2015-08-06 19:03:35 +08:00
} , {
2018-11-10 00:40:37 +01:00
PHY_ID_MATCH_EXACT ( 0x001cc914 ) ,
2015-08-06 19:03:35 +08:00
. name = " RTL8211DN Gigabit Ethernet " ,
. ack_interrupt = rtl821x_ack_interrupt ,
. config_intr = rtl8211e_config_intr ,
. suspend = genphy_suspend ,
. resume = genphy_resume ,
2019-05-10 22:11:26 +02:00
. read_page = rtl821x_read_page ,
. write_page = rtl821x_write_page ,
2014-06-10 12:50:12 +09:00
} , {
2018-11-10 00:40:37 +01:00
PHY_ID_MATCH_EXACT ( 0x001cc915 ) ,
2014-06-10 12:50:12 +09:00
. name = " RTL8211E Gigabit Ethernet " ,
2019-05-09 00:51:15 +03:00
. config_init = & rtl8211e_config_init ,
2014-06-10 12:50:12 +09:00
. ack_interrupt = & rtl821x_ack_interrupt ,
. config_intr = & rtl8211e_config_intr ,
. suspend = genphy_suspend ,
. resume = genphy_resume ,
2019-05-10 22:11:26 +02:00
. read_page = rtl821x_read_page ,
. write_page = rtl821x_write_page ,
2015-06-18 16:42:47 +08:00
} , {
2018-11-10 00:40:37 +01:00
PHY_ID_MATCH_EXACT ( 0x001cc916 ) ,
2015-06-18 16:42:47 +08:00
. name = " RTL8211F Gigabit Ethernet " ,
. config_init = & rtl8211f_config_init ,
. ack_interrupt = & rtl8211f_ack_interrupt ,
. config_intr = & rtl8211f_config_intr ,
. suspend = genphy_suspend ,
. resume = genphy_resume ,
2018-01-12 23:17:34 +01:00
. read_page = rtl821x_read_page ,
. write_page = rtl821x_write_page ,
2019-02-03 16:07:33 +01:00
} , {
2019-08-13 08:09:32 +02:00
. name = " Generic FE-GE Realtek PHY " ,
. match_phy_device = rtlgen_match_phy_device ,
2019-02-03 16:07:33 +01:00
. suspend = genphy_suspend ,
. resume = genphy_resume ,
. read_page = rtl821x_read_page ,
. write_page = rtl821x_write_page ,
2019-08-15 14:12:55 +02:00
. read_mmd = rtlgen_read_mmd ,
. write_mmd = rtlgen_write_mmd ,
2019-08-09 20:45:14 +02:00
} , {
. name = " RTL8125 2.5Gbps internal " ,
2019-08-13 08:09:32 +02:00
. match_phy_device = rtl8125_match_phy_device ,
2019-08-09 20:45:14 +02:00
. get_features = rtl8125_get_features ,
. config_aneg = rtl8125_config_aneg ,
. read_status = rtl8125_read_status ,
. suspend = genphy_suspend ,
. resume = genphy_resume ,
. read_page = rtl821x_read_page ,
. write_page = rtl821x_write_page ,
2019-08-16 21:57:38 +02:00
. read_mmd = rtl8125_read_mmd ,
. write_mmd = rtl8125_write_mmd ,
2018-07-14 11:45:53 +02:00
} , {
2018-11-10 00:40:37 +01:00
PHY_ID_MATCH_EXACT ( 0x001cc961 ) ,
2018-07-14 11:45:53 +02:00
. name = " RTL8366RB Gigabit Ethernet " ,
. config_init = & rtl8366rb_config_init ,
2019-02-24 01:11:15 +01:00
/* These interrupts are handled by the irq controller
* embedded inside the RTL8366RB , they get unmasked when the
* irq is requested and ACKed by reading the status register ,
* which is done by the irqchip code .
*/
. ack_interrupt = genphy_no_ack_interrupt ,
. config_intr = genphy_no_config_intr ,
2018-07-14 11:45:53 +02:00
. suspend = genphy_suspend ,
. resume = genphy_resume ,
2014-06-10 12:50:12 +09:00
} ,
2008-02-03 03:50:54 -08:00
} ;
2014-11-11 19:45:59 +01:00
module_phy_driver ( realtek_drvs ) ;
2010-04-02 01:05:56 +00:00
2018-11-07 08:52:46 +01:00
static const struct mdio_device_id __maybe_unused realtek_tbl [ ] = {
2018-11-10 00:40:37 +01:00
{ PHY_ID_MATCH_VENDOR ( 0x001cc800 ) } ,
2010-04-02 01:05:56 +00:00
{ }
} ;
MODULE_DEVICE_TABLE ( mdio , realtek_tbl ) ;