drivers/net/phy/bcm-phy-ptp.c

Source file repositories/reference/linux-study-clean/drivers/net/phy/bcm-phy-ptp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/phy/bcm-phy-ptp.c
Extension
.c
Size
23679 bytes
Lines
958
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct bcm_ptp_private {
	struct phy_device *phydev;
	struct mii_timestamper mii_ts;
	struct ptp_clock *ptp_clock;
	struct ptp_clock_info ptp_info;
	struct ptp_pin_desc pin;
	struct mutex mutex;
	struct sk_buff_head tx_queue;
	int tx_type;
	bool hwts_rx;
	u16 nse_ctrl;
	bool pin_active;
	struct delayed_work pin_work;
};

struct bcm_ptp_skb_cb {
	unsigned long timeout;
	u16 seq_id;
	u8 msgtype;
	bool discard;
};

struct bcm_ptp_capture {
	ktime_t	hwtstamp;
	u16 seq_id;
	u8 msgtype;
	bool tx_dir;
};

#define BCM_SKB_CB(skb)		((struct bcm_ptp_skb_cb *)(skb)->cb)
#define SKB_TS_TIMEOUT		10			/* jiffies */

#define BCM_MAX_PULSE_8NS	((1U << 9) - 1)
#define BCM_MAX_PERIOD_8NS	((1U << 30) - 1)

#define BRCM_PHY_MODEL(phydev) \
	((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)

static struct bcm_ptp_private *mii2priv(struct mii_timestamper *mii_ts)
{
	return container_of(mii_ts, struct bcm_ptp_private, mii_ts);
}

static struct bcm_ptp_private *ptp2priv(struct ptp_clock_info *info)
{
	return container_of(info, struct bcm_ptp_private, ptp_info);
}

static void bcm_ptp_get_framesync_ts(struct phy_device *phydev,
				     struct timespec64 *ts)
{
	u16 hb[4];

	bcm_phy_write_exp(phydev, HB_STAT_CTRL, HB_READ_START);

	hb[0] = bcm_phy_read_exp(phydev, HB_REG_0);
	hb[1] = bcm_phy_read_exp(phydev, HB_REG_1);
	hb[2] = bcm_phy_read_exp(phydev, HB_REG_2);
	hb[3] = bcm_phy_read_exp(phydev, HB_REG_3);

	bcm_phy_write_exp(phydev, HB_STAT_CTRL, HB_READ_END);
	bcm_phy_write_exp(phydev, HB_STAT_CTRL, 0);

	ts->tv_sec = (hb[3] << 16) | hb[2];
	ts->tv_nsec = (hb[1] << 16) | hb[0];
}

static u16 bcm_ptp_framesync_disable(struct phy_device *phydev, u16 orig_ctrl)
{
	u16 ctrl = orig_ctrl & ~(NSE_FRAMESYNC_MASK | NSE_CAPTURE_EN);

	bcm_phy_write_exp(phydev, NSE_CTRL, ctrl);

	return ctrl;
}

static void bcm_ptp_framesync_restore(struct phy_device *phydev, u16 orig_ctrl)
{
	if (orig_ctrl & NSE_FRAMESYNC_MASK)
		bcm_phy_write_exp(phydev, NSE_CTRL, orig_ctrl);
}

static void bcm_ptp_framesync(struct phy_device *phydev, u16 ctrl)
{
	/* trigger framesync - must have 0->1 transition. */
	bcm_phy_write_exp(phydev, NSE_CTRL, ctrl | NSE_CPU_FRAMESYNC);
}

static int bcm_ptp_framesync_ts(struct phy_device *phydev,
				struct ptp_system_timestamp *sts,

Annotation

Implementation Notes