drivers/ptp/ptp_clockmatrix.c

Source file repositories/reference/linux-study-clean/drivers/ptp/ptp_clockmatrix.c

File Facts

System
Linux kernel
Corpus path
drivers/ptp/ptp_clockmatrix.c
Extension
.c
Size
56098 bytes
Lines
2468
Domain
Driver Families
Bucket
drivers/ptp
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 (ref < 0) {
			dev_err(idtcm->dev, "%s: No valid pin found for TOD%d!\n",
				__func__, channel->tod);
			return -EBUSY;
		}

		err = arm_tod_read_trig_sel_refclk(&idtcm->channel[index], ref);

		if (err == 0) {
			idtcm->extts_mask |= mask;
			idtcm->event_channel[index] = channel;
			idtcm->channel[index].refn = ref;
			idtcm->extts_single_shot = is_single_shot(idtcm->extts_mask);

			if (old_mask)
				return 0;

			schedule_delayed_work(&idtcm->extts_work,
					      msecs_to_jiffies(EXTTS_PERIOD_MS));
		}
	} else {
		idtcm->extts_mask &= ~mask;
		idtcm->extts_single_shot = is_single_shot(idtcm->extts_mask);

		if (idtcm->extts_mask == 0)
			cancel_delayed_work(&idtcm->extts_work);
	}

	return err;
}

static int read_sys_apll_status(struct idtcm *idtcm, u8 *status)
{
	return idtcm_read(idtcm, STATUS, DPLL_SYS_APLL_STATUS, status,
			  sizeof(u8));
}

static int read_sys_dpll_status(struct idtcm *idtcm, u8 *status)
{
	return idtcm_read(idtcm, STATUS, DPLL_SYS_STATUS, status, sizeof(u8));
}

static int wait_for_sys_apll_dpll_lock(struct idtcm *idtcm)
{
	unsigned long timeout = jiffies + msecs_to_jiffies(LOCK_TIMEOUT_MS);
	u8 apll = 0;
	u8 dpll = 0;
	int err;

	do {
		err = read_sys_apll_status(idtcm, &apll);
		if (err)
			return err;

		err = read_sys_dpll_status(idtcm, &dpll);
		if (err)
			return err;

		apll &= SYS_APLL_LOSS_LOCK_LIVE_MASK;
		dpll &= DPLL_SYS_STATE_MASK;

		if (apll == SYS_APLL_LOSS_LOCK_LIVE_LOCKED &&
		    dpll == DPLL_STATE_LOCKED) {
			return 0;
		} else if (dpll == DPLL_STATE_FREERUN ||
			   dpll == DPLL_STATE_HOLDOVER ||
			   dpll == DPLL_STATE_OPEN_LOOP) {
			dev_warn(idtcm->dev,
				"No wait state: DPLL_SYS_STATE %d", dpll);
			return -EPERM;
		}

		msleep(LOCK_POLL_INTERVAL_MS);
	} while (time_is_after_jiffies(timeout));

	dev_warn(idtcm->dev,
		 "%d ms lock timeout: SYS APLL Loss Lock %d  SYS DPLL state %d",
		 LOCK_TIMEOUT_MS, apll, dpll);

	return -ETIME;
}

static void wait_for_chip_ready(struct idtcm *idtcm)
{
	if (wait_for_boot_status_ready(idtcm))
		dev_warn(idtcm->dev, "BOOT_STATUS != 0xA0");

	if (wait_for_sys_apll_dpll_lock(idtcm))
		dev_warn(idtcm->dev,
			 "Continuing while SYS APLL/DPLL is not locked");

Annotation

Implementation Notes