Skip to content

Commit

Permalink
net: phy: micrel: Add support for LAN8804 PHY
Browse files Browse the repository at this point in the history
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: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Horatiu Vultur authored and David S. Miller committed Sep 29, 2021
1 parent 49f0134 commit 7c2dcfa
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
74 changes: 74 additions & 0 deletions drivers/net/phy/micrel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 },
{ }
};

Expand Down
1 change: 1 addition & 0 deletions include/linux/micrel_phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 7c2dcfa

Please sign in to comment.