Commit 7c2dcfa2 authored by Horatiu Vultur's avatar Horatiu Vultur Committed by David S. Miller

net: phy: micrel: Add support for LAN8804 PHY

The LAN8804 PHY has same features as that of LAN8814 PHY except that it
doesn't support 1588, SyncE or Q-USGMII.

This PHY is found inside the LAN966X switches.
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarHoratiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 49f01349
......@@ -1537,6 +1537,65 @@ static int ksz886x_cable_test_get_status(struct phy_device *phydev,
return ret;
}
#define LAN_EXT_PAGE_ACCESS_CONTROL 0x16
#define LAN_EXT_PAGE_ACCESS_ADDRESS_DATA 0x17
#define LAN_EXT_PAGE_ACCESS_CTRL_EP_FUNC 0x4000
#define LAN8804_ALIGN_SWAP 0x4a
#define LAN8804_ALIGN_TX_A_B_SWAP 0x1
#define LAN8804_ALIGN_TX_A_B_SWAP_MASK GENMASK(2, 0)
#define LAN8814_CLOCK_MANAGEMENT 0xd
#define LAN8814_LINK_QUALITY 0x8e
static int lanphy_read_page_reg(struct phy_device *phydev, int page, u32 addr)
{
u32 data;
phy_write(phydev, LAN_EXT_PAGE_ACCESS_CONTROL, page);
phy_write(phydev, LAN_EXT_PAGE_ACCESS_ADDRESS_DATA, addr);
phy_write(phydev, LAN_EXT_PAGE_ACCESS_CONTROL,
(page | LAN_EXT_PAGE_ACCESS_CTRL_EP_FUNC));
data = phy_read(phydev, LAN_EXT_PAGE_ACCESS_ADDRESS_DATA);
return data;
}
static int lanphy_write_page_reg(struct phy_device *phydev, int page, u16 addr,
u16 val)
{
phy_write(phydev, LAN_EXT_PAGE_ACCESS_CONTROL, page);
phy_write(phydev, LAN_EXT_PAGE_ACCESS_ADDRESS_DATA, addr);
phy_write(phydev, LAN_EXT_PAGE_ACCESS_CONTROL,
(page | LAN_EXT_PAGE_ACCESS_CTRL_EP_FUNC));
val = phy_write(phydev, LAN_EXT_PAGE_ACCESS_ADDRESS_DATA, val);
if (val) {
phydev_err(phydev, "Error: phy_write has returned error %d\n",
val);
return val;
}
return 0;
}
static int lan8804_config_init(struct phy_device *phydev)
{
int val;
/* MDI-X setting for swap A,B transmit */
val = lanphy_read_page_reg(phydev, 2, LAN8804_ALIGN_SWAP);
val &= ~LAN8804_ALIGN_TX_A_B_SWAP_MASK;
val |= LAN8804_ALIGN_TX_A_B_SWAP;
lanphy_write_page_reg(phydev, 2, LAN8804_ALIGN_SWAP, val);
/* Make sure that the PHY will not stop generating the clock when the
* link partner goes down
*/
lanphy_write_page_reg(phydev, 31, LAN8814_CLOCK_MANAGEMENT, 0x27e);
lanphy_read_page_reg(phydev, 1, LAN8814_LINK_QUALITY);
return 0;
}
static struct phy_driver ksphy_driver[] = {
{
.phy_id = PHY_ID_KS8737,
......@@ -1718,6 +1777,20 @@ static struct phy_driver ksphy_driver[] = {
.get_stats = kszphy_get_stats,
.suspend = genphy_suspend,
.resume = kszphy_resume,
}, {
.phy_id = PHY_ID_LAN8804,
.phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Microchip LAN966X Gigabit PHY",
.config_init = lan8804_config_init,
.driver_data = &ksz9021_type,
.probe = kszphy_probe,
.soft_reset = genphy_soft_reset,
.read_status = ksz9031_read_status,
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
.suspend = genphy_suspend,
.resume = kszphy_resume,
}, {
.phy_id = PHY_ID_KSZ9131,
.phy_id_mask = MICREL_PHY_ID_MASK,
......@@ -1794,6 +1867,7 @@ static struct mdio_device_id __maybe_unused micrel_tbl[] = {
{ PHY_ID_KSZ8873MLL, MICREL_PHY_ID_MASK },
{ PHY_ID_KSZ886X, MICREL_PHY_ID_MASK },
{ PHY_ID_LAN8814, MICREL_PHY_ID_MASK },
{ PHY_ID_LAN8804, MICREL_PHY_ID_MASK },
{ }
};
......
......@@ -28,6 +28,7 @@
#define PHY_ID_KSZ9031 0x00221620
#define PHY_ID_KSZ9131 0x00221640
#define PHY_ID_LAN8814 0x00221660
#define PHY_ID_LAN8804 0x00221670
#define PHY_ID_KSZ886X 0x00221430
#define PHY_ID_KSZ8863 0x00221435
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment