in ptp_clockmatrix.c [752:811]
static int _idtcm_set_dpll_scsr_tod(struct idtcm_channel *channel,
struct timespec64 const *ts,
enum scsr_tod_write_trig_sel wr_trig,
enum scsr_tod_write_type_sel wr_type)
{
struct idtcm *idtcm = channel->idtcm;
unsigned char buf[TOD_BYTE_COUNT], cmd;
struct timespec64 local_ts = *ts;
int err, count = 0;
timespec64_add_ns(&local_ts, SETTIME_CORRECTION);
err = timespec_to_char_array(&local_ts, buf, sizeof(buf));
if (err)
return err;
err = idtcm_write(idtcm, channel->tod_write, TOD_WRITE,
buf, sizeof(buf));
if (err)
return err;
/* Trigger the write operation. */
err = idtcm_read(idtcm, channel->tod_write, TOD_WRITE_CMD,
&cmd, sizeof(cmd));
if (err)
return err;
cmd &= ~(TOD_WRITE_SELECTION_MASK << TOD_WRITE_SELECTION_SHIFT);
cmd &= ~(TOD_WRITE_TYPE_MASK << TOD_WRITE_TYPE_SHIFT);
cmd |= (wr_trig << TOD_WRITE_SELECTION_SHIFT);
cmd |= (wr_type << TOD_WRITE_TYPE_SHIFT);
err = idtcm_write(idtcm, channel->tod_write, TOD_WRITE_CMD,
&cmd, sizeof(cmd));
if (err)
return err;
/* Wait for the operation to complete. */
while (1) {
/* pps trigger takes up to 1 sec to complete */
if (wr_trig == SCSR_TOD_WR_TRIG_SEL_TODPPS)
msleep(50);
err = idtcm_read(idtcm, channel->tod_write, TOD_WRITE_CMD,
&cmd, sizeof(cmd));
if (err)
return err;
if ((cmd & TOD_WRITE_SELECTION_MASK) == 0)
break;
if (++count > 20) {
dev_err(idtcm->dev,
"Timed out waiting for the write counter");
return -EIO;
}
}
return 0;
}