drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
Extension
.c
Size
11308 bytes
Lines
401
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 (target_ns < ns + PTP_SAFE_TIME_OFFSET_NS) {
			cfg->start = timespec64_add_safe(cfg->start, curr_time);
			if (cfg->start.tv_sec == TIME64_MAX)
				return -EINVAL;
		}

		cfg->period.tv_sec = rq->perout.period.sec;
		cfg->period.tv_nsec = rq->perout.period.nsec;

		write_lock_irqsave(&priv->ptp_lock, flags);
		ret = stmmac_flex_pps_config(priv, priv->ioaddr,
					     rq->perout.index, cfg, on,
					     priv->sub_second_inc,
					     priv->systime_flags);
		write_unlock_irqrestore(&priv->ptp_lock, flags);
		break;
	}
	case PTP_CLK_REQ_EXTTS: {
		u8 channel;

		mutex_lock(&priv->aux_ts_lock);
		acr_value = readl(ptpaddr + PTP_ACR);
		channel = ilog2(FIELD_GET(PTP_ACR_MASK, acr_value));
		acr_value &= ~PTP_ACR_MASK;

		if (on) {
			if (FIELD_GET(PTP_ACR_MASK, acr_value)) {
				netdev_err(priv->dev,
					   "Cannot enable auxiliary snapshot %d as auxiliary snapshot %d is already enabled",
					rq->extts.index, channel);
				mutex_unlock(&priv->aux_ts_lock);
				return -EBUSY;
			}

			priv->plat->flags |= STMMAC_FLAG_EXT_SNAPSHOT_EN;

			/* Enable External snapshot trigger */
			acr_value |= PTP_ACR_ATSEN(rq->extts.index);
			acr_value |= PTP_ACR_ATSFC;
		} else {
			priv->plat->flags &= ~STMMAC_FLAG_EXT_SNAPSHOT_EN;
		}
		netdev_dbg(priv->dev, "Auxiliary Snapshot %d %s.\n",
			   rq->extts.index, on ? "enabled" : "disabled");
		writel(acr_value, ptpaddr + PTP_ACR);
		mutex_unlock(&priv->aux_ts_lock);
		/* wait for auxts fifo clear to finish */
		ret = readl_poll_timeout(ptpaddr + PTP_ACR, acr_value,
					 !(acr_value & PTP_ACR_ATSFC),
					 10, 10000);
		break;
	}

	default:
		break;
	}

	return ret;
}

/**
 * stmmac_get_syncdevicetime
 * @device: current device time
 * @system: system counter value read synchronously with device time
 * @ctx: context provided by timekeeping code
 * Description: Read device and system clock simultaneously and return the
 * corrected clock values in ns.
 **/
static int stmmac_get_syncdevicetime(ktime_t *device,
				     struct system_counterval_t *system,
				     void *ctx)
{
	struct stmmac_priv *priv = (struct stmmac_priv *)ctx;

	return priv->plat->crosststamp(device, system, ctx);
}

static int stmmac_getcrosststamp(struct ptp_clock_info *ptp,
				 struct system_device_crosststamp *xtstamp)
{
	struct stmmac_priv *priv =
		container_of(ptp, struct stmmac_priv, ptp_clock_ops);

	return get_device_system_crosststamp(stmmac_get_syncdevicetime,
					     priv, NULL, xtstamp);
}

/* structure describing a PTP hardware clock */
const struct ptp_clock_info stmmac_ptp_clock_ops = {
	.owner = THIS_MODULE,

Annotation

Implementation Notes