@@ -1537,6 +1537,65 @@ static int ksz886x_cable_test_get_status(struct phy_device *phydev,
15371537 return ret ;
15381538}
15391539
1540+ #define LAN_EXT_PAGE_ACCESS_CONTROL 0x16
1541+ #define LAN_EXT_PAGE_ACCESS_ADDRESS_DATA 0x17
1542+ #define LAN_EXT_PAGE_ACCESS_CTRL_EP_FUNC 0x4000
1543+
1544+ #define LAN8804_ALIGN_SWAP 0x4a
1545+ #define LAN8804_ALIGN_TX_A_B_SWAP 0x1
1546+ #define LAN8804_ALIGN_TX_A_B_SWAP_MASK GENMASK(2, 0)
1547+ #define LAN8814_CLOCK_MANAGEMENT 0xd
1548+ #define LAN8814_LINK_QUALITY 0x8e
1549+
1550+ static int lanphy_read_page_reg (struct phy_device * phydev , int page , u32 addr )
1551+ {
1552+ u32 data ;
1553+
1554+ phy_write (phydev , LAN_EXT_PAGE_ACCESS_CONTROL , page );
1555+ phy_write (phydev , LAN_EXT_PAGE_ACCESS_ADDRESS_DATA , addr );
1556+ phy_write (phydev , LAN_EXT_PAGE_ACCESS_CONTROL ,
1557+ (page | LAN_EXT_PAGE_ACCESS_CTRL_EP_FUNC ));
1558+ data = phy_read (phydev , LAN_EXT_PAGE_ACCESS_ADDRESS_DATA );
1559+
1560+ return data ;
1561+ }
1562+
1563+ static int lanphy_write_page_reg (struct phy_device * phydev , int page , u16 addr ,
1564+ u16 val )
1565+ {
1566+ phy_write (phydev , LAN_EXT_PAGE_ACCESS_CONTROL , page );
1567+ phy_write (phydev , LAN_EXT_PAGE_ACCESS_ADDRESS_DATA , addr );
1568+ phy_write (phydev , LAN_EXT_PAGE_ACCESS_CONTROL ,
1569+ (page | LAN_EXT_PAGE_ACCESS_CTRL_EP_FUNC ));
1570+
1571+ val = phy_write (phydev , LAN_EXT_PAGE_ACCESS_ADDRESS_DATA , val );
1572+ if (val ) {
1573+ phydev_err (phydev , "Error: phy_write has returned error %d\n" ,
1574+ val );
1575+ return val ;
1576+ }
1577+ return 0 ;
1578+ }
1579+
1580+ static int lan8804_config_init (struct phy_device * phydev )
1581+ {
1582+ int val ;
1583+
1584+ /* MDI-X setting for swap A,B transmit */
1585+ val = lanphy_read_page_reg (phydev , 2 , LAN8804_ALIGN_SWAP );
1586+ val &= ~LAN8804_ALIGN_TX_A_B_SWAP_MASK ;
1587+ val |= LAN8804_ALIGN_TX_A_B_SWAP ;
1588+ lanphy_write_page_reg (phydev , 2 , LAN8804_ALIGN_SWAP , val );
1589+
1590+ /* Make sure that the PHY will not stop generating the clock when the
1591+ * link partner goes down
1592+ */
1593+ lanphy_write_page_reg (phydev , 31 , LAN8814_CLOCK_MANAGEMENT , 0x27e );
1594+ lanphy_read_page_reg (phydev , 1 , LAN8814_LINK_QUALITY );
1595+
1596+ return 0 ;
1597+ }
1598+
15401599static struct phy_driver ksphy_driver [] = {
15411600{
15421601 .phy_id = PHY_ID_KS8737 ,
@@ -1718,6 +1777,20 @@ static struct phy_driver ksphy_driver[] = {
17181777 .get_stats = kszphy_get_stats ,
17191778 .suspend = genphy_suspend ,
17201779 .resume = kszphy_resume ,
1780+ }, {
1781+ .phy_id = PHY_ID_LAN8804 ,
1782+ .phy_id_mask = MICREL_PHY_ID_MASK ,
1783+ .name = "Microchip LAN966X Gigabit PHY" ,
1784+ .config_init = lan8804_config_init ,
1785+ .driver_data = & ksz9021_type ,
1786+ .probe = kszphy_probe ,
1787+ .soft_reset = genphy_soft_reset ,
1788+ .read_status = ksz9031_read_status ,
1789+ .get_sset_count = kszphy_get_sset_count ,
1790+ .get_strings = kszphy_get_strings ,
1791+ .get_stats = kszphy_get_stats ,
1792+ .suspend = genphy_suspend ,
1793+ .resume = kszphy_resume ,
17211794}, {
17221795 .phy_id = PHY_ID_KSZ9131 ,
17231796 .phy_id_mask = MICREL_PHY_ID_MASK ,
@@ -1794,6 +1867,7 @@ static struct mdio_device_id __maybe_unused micrel_tbl[] = {
17941867 { PHY_ID_KSZ8873MLL , MICREL_PHY_ID_MASK },
17951868 { PHY_ID_KSZ886X , MICREL_PHY_ID_MASK },
17961869 { PHY_ID_LAN8814 , MICREL_PHY_ID_MASK },
1870+ { PHY_ID_LAN8804 , MICREL_PHY_ID_MASK },
17971871 { }
17981872};
17991873
0 commit comments