drivers/net/phy/mscc/mscc_ptp.c

Source file repositories/reference/linux-study-clean/drivers/net/phy/mscc/mscc_ptp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/phy/mscc/mscc_ptp.c
Extension
.c
Size
49356 bytes
Lines
1646
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source 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

if (get_sig(skb, skb_sig) < 0) {
			kfree_skb(skb);
			continue;
		}

		/* Check if we found the signature we were looking for. */
		if (!memcmp(skb_sig, fifo.sig, sizeof(fifo.sig))) {
			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
			shhwtstamps.hwtstamp = ktime_set(fifo.secs, fifo.ns);
			skb_complete_tx_timestamp(skb, &shhwtstamps);

			return;
		}

		/* Valid signature but does not match the one of the
		 * packet in the FIFO right now, reschedule it for later
		 * packets.
		 */
		skb_queue_tail(&ptp->tx_queue, skb);
	}
}

static void vsc85xx_get_tx_ts(struct vsc85xx_ptp *ptp)
{
	u32 reg;

	do {
		vsc85xx_dequeue_skb(ptp);

		/* If other timestamps are available in the FIFO, process them. */
		reg = vsc85xx_ts_read_csr(ptp->phydev, PROCESSOR,
					  MSCC_PHY_PTP_EGR_TS_FIFO_CTRL);
	} while (PTP_EGR_FIFO_LEVEL_LAST_READ(reg) > 1);
}

static int vsc85xx_ptp_cmp_init(struct phy_device *phydev, enum ts_blk blk)
{
	struct vsc8531_private *vsc8531 = phydev->priv;
	bool base = phydev->mdio.addr == vsc8531->ts_base_addr;
	static const u8 msgs[] = {
		PTP_MSGTYPE_SYNC,
		PTP_MSGTYPE_DELAY_REQ
	};
	u32 val;
	u8 i;

	for (i = 0; i < ARRAY_SIZE(msgs); i++) {
		vsc85xx_ts_write_csr(phydev, blk, MSCC_ANA_PTP_FLOW_ENA(i),
				     base ? PTP_FLOW_VALID_CH0 :
				     PTP_FLOW_VALID_CH1);

		val = vsc85xx_ts_read_csr(phydev, blk,
					  MSCC_ANA_PTP_FLOW_DOMAIN_RANGE(i));
		val &= ~PTP_FLOW_DOMAIN_RANGE_ENA;
		vsc85xx_ts_write_csr(phydev, blk,
				     MSCC_ANA_PTP_FLOW_DOMAIN_RANGE(i), val);

		vsc85xx_ts_write_csr(phydev, blk,
				     MSCC_ANA_PTP_FLOW_MATCH_UPPER(i),
				     msgs[i] << 24);

		vsc85xx_ts_write_csr(phydev, blk,
				     MSCC_ANA_PTP_FLOW_MASK_UPPER(i),
				     PTP_FLOW_MSG_TYPE_MASK);
	}

	return 0;
}

static int vsc85xx_eth_cmp1_init(struct phy_device *phydev, enum ts_blk blk)
{
	struct vsc8531_private *vsc8531 = phydev->priv;
	bool base = phydev->mdio.addr == vsc8531->ts_base_addr;
	u32 val;

	vsc85xx_ts_write_csr(phydev, blk, MSCC_PHY_ANA_ETH1_NXT_PROT_TAG, 0);
	vsc85xx_ts_write_csr(phydev, blk, MSCC_PHY_ANA_ETH1_NTX_PROT_VLAN_TPID,
			     ANA_ETH1_NTX_PROT_VLAN_TPID(ETH_P_8021AD));

	vsc85xx_ts_write_csr(phydev, blk, MSCC_ANA_ETH1_FLOW_ENA(0),
			     base ? ETH1_FLOW_VALID_CH0 : ETH1_FLOW_VALID_CH1);
	vsc85xx_ts_write_csr(phydev, blk, MSCC_ANA_ETH1_FLOW_MATCH_MODE(0),
			     ANA_ETH1_FLOW_MATCH_VLAN_TAG2);
	vsc85xx_ts_write_csr(phydev, blk, MSCC_ANA_ETH1_FLOW_ADDR_MATCH1(0), 0);
	vsc85xx_ts_write_csr(phydev, blk, MSCC_ANA_ETH1_FLOW_ADDR_MATCH2(0), 0);
	vsc85xx_ts_write_csr(phydev, blk,
			     MSCC_ANA_ETH1_FLOW_VLAN_RANGE_I_TAG(0), 0);
	vsc85xx_ts_write_csr(phydev, blk, MSCC_ANA_ETH1_FLOW_VLAN_TAG1(0), 0);
	vsc85xx_ts_write_csr(phydev, blk,
			     MSCC_ANA_ETH1_FLOW_VLAN_TAG2_I_TAG(0), 0);

Annotation

Implementation Notes