Skip to content

Commit 7d272e6

Browse files
atenartdavem330
authored andcommitted
net: phy: mscc: timestamping and PHC support
This patch adds support for PHC and timestamping operations for the MSCC PHY. PTP 1-step and 2-step modes are supported, over Ethernet and UDP. To get and set the PHC time, a GPIO has to be used and changes are only retrieved or committed when on a rising edge. The same GPIO is shared by all PHYs, so the granularity of the lock protecting it has to be different from the ones protecting the 1588 registers (the VSC8584 PHY has 2 1588 blocks, and a single load/save pin). Co-developed-by: Quentin Schulz <[email protected]> Signed-off-by: Quentin Schulz <[email protected]> Signed-off-by: Antoine Tenart <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ab2bf93 commit 7d272e6

File tree

3 files changed

+630
-4
lines changed

3 files changed

+630
-4
lines changed

drivers/net/phy/mscc/mscc.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,12 @@ struct vsc8531_private {
375375
unsigned long egr_flows;
376376
#endif
377377

378+
struct mii_timestamper mii_ts;
379+
378380
bool input_clk_init;
379381
struct vsc85xx_ptp *ptp;
382+
/* LOAD/SAVE GPIO pin, used for retrieving or setting time to the PHC. */
383+
struct gpio_desc *load_save;
380384

381385
/* For multiple port PHYs; the MDIO address of the base PHY in the
382386
* pair of two PHYs that share a 1588 engine. PHY0 and PHY2 are coupled.
@@ -386,8 +390,19 @@ struct vsc8531_private {
386390
unsigned int ts_base_addr;
387391
u8 ts_base_phy;
388392

389-
/* ts_lock: used for per-PHY timestamping operations. */
393+
/* ts_lock: used for per-PHY timestamping operations.
394+
* phc_lock: used for per-PHY PHC opertations.
395+
*/
390396
struct mutex ts_lock;
397+
struct mutex phc_lock;
398+
};
399+
400+
/* Shared structure between the PHYs of the same package.
401+
* gpio_lock: used for PHC operations. Common for all PHYs as the load/save GPIO
402+
* is shared.
403+
*/
404+
struct vsc85xx_shared_private {
405+
struct mutex gpio_lock;
391406
};
392407

393408
#if IS_ENABLED(CONFIG_OF_MDIO)
@@ -416,20 +431,34 @@ static inline void vsc8584_config_macsec_intr(struct phy_device *phydev)
416431

417432
#if IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)
418433
void vsc85xx_link_change_notify(struct phy_device *phydev);
434+
void vsc8584_config_ts_intr(struct phy_device *phydev);
419435
int vsc8584_ptp_init(struct phy_device *phydev);
436+
int vsc8584_ptp_probe_once(struct phy_device *phydev);
420437
int vsc8584_ptp_probe(struct phy_device *phydev);
438+
irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev);
421439
#else
422440
static inline void vsc85xx_link_change_notify(struct phy_device *phydev)
423441
{
424442
}
443+
static inline void vsc8584_config_ts_intr(struct phy_device *phydev)
444+
{
445+
}
425446
static inline int vsc8584_ptp_init(struct phy_device *phydev)
426447
{
427448
return 0;
428449
}
450+
static inline int vsc8584_ptp_probe_once(struct phy_device *phydev)
451+
{
452+
return 0;
453+
}
429454
static inline int vsc8584_ptp_probe(struct phy_device *phydev)
430455
{
431456
return 0;
432457
}
458+
static inline irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev)
459+
{
460+
return IRQ_NONE;
461+
}
433462
#endif
434463

435464
#endif /* _MSCC_PHY_H_ */

drivers/net/phy/mscc/mscc_main.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,12 +1475,20 @@ static int vsc8584_config_init(struct phy_device *phydev)
14751475

14761476
static irqreturn_t vsc8584_handle_interrupt(struct phy_device *phydev)
14771477
{
1478+
irqreturn_t ret;
14781479
int irq_status;
14791480

14801481
irq_status = phy_read(phydev, MII_VSC85XX_INT_STATUS);
1481-
if (irq_status < 0 || !(irq_status & MII_VSC85XX_INT_MASK_MASK))
1482+
if (irq_status < 0)
14821483
return IRQ_NONE;
14831484

1485+
/* Timestamping IRQ does not set a bit in the global INT_STATUS, so
1486+
* irq_status would be 0.
1487+
*/
1488+
ret = vsc8584_handle_ts_interrupt(phydev);
1489+
if (!(irq_status & MII_VSC85XX_INT_MASK_MASK))
1490+
return ret;
1491+
14841492
if (irq_status & MII_VSC85XX_INT_MASK_EXT)
14851493
vsc8584_handle_macsec_interrupt(phydev);
14861494

@@ -1920,6 +1928,7 @@ static int vsc85xx_config_intr(struct phy_device *phydev)
19201928

19211929
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
19221930
vsc8584_config_macsec_intr(phydev);
1931+
vsc8584_config_ts_intr(phydev);
19231932

19241933
rc = phy_write(phydev, MII_VSC85XX_INT_MASK,
19251934
MII_VSC85XX_INT_MASK_MASK);
@@ -2033,8 +2042,8 @@ static int vsc8584_probe(struct phy_device *phydev)
20332042
phydev->priv = vsc8531;
20342043

20352044
vsc8584_get_base_addr(phydev);
2036-
devm_phy_package_join(&phydev->mdio.dev, phydev,
2037-
vsc8531->base_addr, 0);
2045+
devm_phy_package_join(&phydev->mdio.dev, phydev, vsc8531->base_addr,
2046+
sizeof(struct vsc85xx_shared_private));
20382047

20392048
vsc8531->nleds = 4;
20402049
vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES;
@@ -2045,6 +2054,12 @@ static int vsc8584_probe(struct phy_device *phydev)
20452054
if (!vsc8531->stats)
20462055
return -ENOMEM;
20472056

2057+
if (phy_package_probe_once(phydev)) {
2058+
ret = vsc8584_ptp_probe_once(phydev);
2059+
if (ret)
2060+
return ret;
2061+
}
2062+
20482063
ret = vsc8584_ptp_probe(phydev);
20492064
if (ret)
20502065
return ret;

0 commit comments

Comments
 (0)