Skip to content

Commit

Permalink
net: phy: mscc: 1588 block initialization
Browse files Browse the repository at this point in the history
This patch adds the first parts of the 1588 support in the MSCC PHY,
with registers definition and the 1588 block initialization.

Those PHYs are distributed in hardware packages containing multiple
times the PHY. The VSC8584 for example is composed of 4 PHYs. With
hardware packages, parts of the logic is usually common and one of the
PHY has to be used for some parts of the initialization. Following this
logic, the 1588 blocks of those PHYs are shared between two PHYs and
accessing the registers has to be done using the "base" PHY of the
group. This is handled thanks to helpers in the PTP code (and locks).
We also need the MDIO bus lock while performing a single read or write
to the 1588 registers as the read/write are composed of multiple MDIO
transactions (and we don't want other threads updating the page).

Co-developed-by: Antoine Tenart <antoine.tenart@bootlin.com>
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
  • Loading branch information
QSchulz authored and intel-lab-lkp committed Jun 23, 2020
1 parent 189ca52 commit b322596
Show file tree
Hide file tree
Showing 5 changed files with 1,552 additions and 2 deletions.
4 changes: 4 additions & 0 deletions drivers/net/phy/mscc/Makefile
Expand Up @@ -8,3 +8,7 @@ mscc-objs := mscc_main.o
ifdef CONFIG_MACSEC
mscc-objs += mscc_macsec.o
endif

ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
mscc-objs += mscc_ptp.o
endif
33 changes: 33 additions & 0 deletions drivers/net/phy/mscc/mscc.h
Expand Up @@ -133,6 +133,7 @@ enum rgmii_clock_delay {
* in the same package.
*/
#define MSCC_PHY_PAGE_EXTENDED_GPIO 0x0010 /* Extended reg - GPIO */
#define MSCC_PHY_PAGE_1588 0x1588 /* PTP (1588) */
#define MSCC_PHY_PAGE_TEST 0x2a30 /* Test reg */
#define MSCC_PHY_PAGE_TR 0x52b5 /* Token ring registers */

Expand Down Expand Up @@ -373,6 +374,20 @@ struct vsc8531_private {
unsigned long ingr_flows;
unsigned long egr_flows;
#endif

bool input_clk_init;
struct vsc85xx_ptp *ptp;

/* For multiple port PHYs; the MDIO address of the base PHY in the
* pair of two PHYs that share a 1588 engine. PHY0 and PHY2 are coupled.
* PHY1 and PHY3 as well. PHY0 and PHY1 are base PHYs for their
* respective pair.
*/
unsigned int ts_base_addr;
u8 ts_base_phy;

/* ts_lock: used for per-PHY timestamping operations. */
struct mutex ts_lock;
};

#if IS_ENABLED(CONFIG_OF_MDIO)
Expand All @@ -399,4 +414,22 @@ static inline void vsc8584_config_macsec_intr(struct phy_device *phydev)
}
#endif

#if IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)
void vsc85xx_link_change_notify(struct phy_device *phydev);
int vsc8584_ptp_init(struct phy_device *phydev);
int vsc8584_ptp_probe(struct phy_device *phydev);
#else
static inline void vsc85xx_link_change_notify(struct phy_device *phydev)
{
}
static inline int vsc8584_ptp_init(struct phy_device *phydev)
{
return 0;
}
static inline int vsc8584_ptp_probe(struct phy_device *phydev)
{
return 0;
}
#endif

#endif /* _MSCC_PHY_H_ */
30 changes: 28 additions & 2 deletions drivers/net/phy/mscc/mscc_main.c
Expand Up @@ -1299,10 +1299,26 @@ static void vsc8584_get_base_addr(struct phy_device *phydev)
__phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
mutex_unlock(&phydev->mdio.bus->mdio_lock);

if (val & PHY_ADDR_REVERSED)
/* In the package, there are two pairs of PHYs (PHY0 + PHY2 and
* PHY1 + PHY3). The first PHY of each pair (PHY0 and PHY1) is
* the base PHY for timestamping operations.
*/
vsc8531->ts_base_addr = phydev->mdio.addr;
vsc8531->ts_base_phy = addr;

if (val & PHY_ADDR_REVERSED) {
vsc8531->base_addr = phydev->mdio.addr + addr;
else
if (addr > 1) {
vsc8531->ts_base_addr += 2;
vsc8531->ts_base_phy += 2;
}
} else {
vsc8531->base_addr = phydev->mdio.addr - addr;
if (addr > 1) {
vsc8531->ts_base_addr -= 2;
vsc8531->ts_base_phy -= 2;
}
}

vsc8531->addr = addr;
}
Expand Down Expand Up @@ -1418,6 +1434,10 @@ static int vsc8584_config_init(struct phy_device *phydev)
if (ret)
return ret;

ret = vsc8584_ptp_init(phydev);
if (ret)
goto err;

phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);

val = phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_1);
Expand Down Expand Up @@ -1999,6 +2019,7 @@ static int vsc8584_probe(struct phy_device *phydev)
u32 default_mode[4] = {VSC8531_LINK_1000_ACTIVITY,
VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY,
VSC8531_DUPLEX_COLLISION};
int ret;

if ((phydev->phy_id & MSCC_DEV_REV_MASK) != VSC8584_REVB) {
dev_err(&phydev->mdio.dev, "Only VSC8584 revB is supported.\n");
Expand All @@ -2024,6 +2045,10 @@ static int vsc8584_probe(struct phy_device *phydev)
if (!vsc8531->stats)
return -ENOMEM;

ret = vsc8584_ptp_probe(phydev);
if (ret)
return ret;

return vsc85xx_dt_led_modes_get(phydev, default_mode);
}

Expand Down Expand Up @@ -2403,6 +2428,7 @@ static struct phy_driver vsc85xx_driver[] = {
.get_sset_count = &vsc85xx_get_sset_count,
.get_strings = &vsc85xx_get_strings,
.get_stats = &vsc85xx_get_stats,
.link_change_notify = &vsc85xx_link_change_notify,
}

};
Expand Down

0 comments on commit b322596

Please sign in to comment.