drivers/net/ethernet/engleder/tsnep_ptp.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/engleder/tsnep_ptp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/engleder/tsnep_ptp.c
Extension
.c
Size
6703 bytes
Lines
243
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

// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2021 Gerhard Engleder <gerhard@engleder-embedded.com> */

#include "tsnep.h"

void tsnep_get_system_time(struct tsnep_adapter *adapter, u64 *time)
{
	u32 high_before;
	u32 low;
	u32 high;

	/* read high dword twice to detect overrun */
	high = ioread32(adapter->addr + ECM_SYSTEM_TIME_HIGH);
	do {
		low = ioread32(adapter->addr + ECM_SYSTEM_TIME_LOW);
		high_before = high;
		high = ioread32(adapter->addr + ECM_SYSTEM_TIME_HIGH);
	} while (high != high_before);
	*time = (((u64)high) << 32) | ((u64)low);
}

int tsnep_ptp_hwtstamp_get(struct net_device *netdev,
			   struct kernel_hwtstamp_config *config)
{
	struct tsnep_adapter *adapter = netdev_priv(netdev);

	*config = adapter->hwtstamp_config;
	return 0;
}

int tsnep_ptp_hwtstamp_set(struct net_device *netdev,
			   struct kernel_hwtstamp_config *config,
			   struct netlink_ext_ack *extack)
{
	struct tsnep_adapter *adapter = netdev_priv(netdev);

	switch (config->tx_type) {
	case HWTSTAMP_TX_OFF:
	case HWTSTAMP_TX_ON:
		break;
	default:
		return -ERANGE;
	}

	switch (config->rx_filter) {
	case HWTSTAMP_FILTER_NONE:
		break;
	case HWTSTAMP_FILTER_ALL:
	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V2_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
	case HWTSTAMP_FILTER_NTP_ALL:
		config->rx_filter = HWTSTAMP_FILTER_ALL;
		break;
	default:
		return -ERANGE;
	}

	adapter->hwtstamp_config = *config;
	return 0;
}

static int tsnep_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{
	struct tsnep_adapter *adapter = container_of(ptp, struct tsnep_adapter,
						     ptp_clock_info);
	bool negative = false;
	u64 rate_offset;

	if (scaled_ppm < 0) {
		scaled_ppm = -scaled_ppm;
		negative = true;
	}

	/* convert from 16 bit to 32 bit binary fractional, divide by 1000000 to
	 * eliminate ppm, multiply with 8 to compensate 8ns clock cycle time,
	 * simplify calculation because 15625 * 8 = 1000000 / 8
	 */
	rate_offset = scaled_ppm;
	rate_offset <<= 16 - 3;
	rate_offset = div_u64(rate_offset, 15625);

Annotation

Implementation Notes