2021-09-14 01:07:09

by Min Li

[permalink] [raw]
Subject: [PATCH net 1/3] ptp: ptp_clockmatrix: Remove idtcm_enable_tod_sync()

From: Min Li <[email protected]>

Not need since TCS firmware file will configure it properlly.

Signed-off-by: Min Li <[email protected]>
---
drivers/ptp/ptp_clockmatrix.c | 229 +-----------------------------------------
1 file changed, 2 insertions(+), 227 deletions(-)

diff --git a/drivers/ptp/ptp_clockmatrix.c b/drivers/ptp/ptp_clockmatrix.c
index fa63695..9b1c6b2 100644
--- a/drivers/ptp/ptp_clockmatrix.c
+++ b/drivers/ptp/ptp_clockmatrix.c
@@ -353,8 +353,8 @@ static int wait_for_sys_apll_dpll_lock(struct idtcm *idtcm)
apll &= SYS_APLL_LOSS_LOCK_LIVE_MASK;
dpll &= DPLL_SYS_STATE_MASK;

- if (apll == SYS_APLL_LOSS_LOCK_LIVE_LOCKED &&
- dpll == DPLL_STATE_LOCKED) {
+ if (apll == SYS_APLL_LOSS_LOCK_LIVE_LOCKED
+ && dpll == DPLL_STATE_LOCKED) {
return 0;
} else if (dpll == DPLL_STATE_FREERUN ||
dpll == DPLL_STATE_HOLDOVER ||
@@ -1675,222 +1675,6 @@ static int idtcm_enable(struct ptp_clock_info *ptp,
return -EOPNOTSUPP;
}

-static int _enable_pll_tod_sync(struct idtcm *idtcm,
- u8 pll,
- u8 sync_src,
- u8 qn,
- u8 qn_plus_1)
-{
- int err;
- u8 val;
- u16 dpll;
- u16 out0 = 0, out1 = 0;
-
- if (qn == 0 && qn_plus_1 == 0)
- return 0;
-
- switch (pll) {
- case 0:
- dpll = DPLL_0;
- if (qn)
- out0 = OUTPUT_0;
- if (qn_plus_1)
- out1 = OUTPUT_1;
- break;
- case 1:
- dpll = DPLL_1;
- if (qn)
- out0 = OUTPUT_2;
- if (qn_plus_1)
- out1 = OUTPUT_3;
- break;
- case 2:
- dpll = DPLL_2;
- if (qn)
- out0 = OUTPUT_4;
- if (qn_plus_1)
- out1 = OUTPUT_5;
- break;
- case 3:
- dpll = DPLL_3;
- if (qn)
- out0 = OUTPUT_6;
- if (qn_plus_1)
- out1 = OUTPUT_7;
- break;
- case 4:
- dpll = DPLL_4;
- if (qn)
- out0 = OUTPUT_8;
- break;
- case 5:
- dpll = DPLL_5;
- if (qn)
- out0 = OUTPUT_9;
- if (qn_plus_1)
- out1 = OUTPUT_8;
- break;
- case 6:
- dpll = DPLL_6;
- if (qn)
- out0 = OUTPUT_10;
- if (qn_plus_1)
- out1 = OUTPUT_11;
- break;
- case 7:
- dpll = DPLL_7;
- if (qn)
- out0 = OUTPUT_11;
- break;
- default:
- return -EINVAL;
- }
-
- /*
- * Enable OUTPUT OUT_SYNC.
- */
- if (out0) {
- err = idtcm_read(idtcm, out0, OUT_CTRL_1, &val, sizeof(val));
- if (err)
- return err;
-
- val &= ~OUT_SYNC_DISABLE;
-
- err = idtcm_write(idtcm, out0, OUT_CTRL_1, &val, sizeof(val));
- if (err)
- return err;
- }
-
- if (out1) {
- err = idtcm_read(idtcm, out1, OUT_CTRL_1, &val, sizeof(val));
- if (err)
- return err;
-
- val &= ~OUT_SYNC_DISABLE;
-
- err = idtcm_write(idtcm, out1, OUT_CTRL_1, &val, sizeof(val));
- if (err)
- return err;
- }
-
- /* enable dpll sync tod pps, must be set before dpll_mode */
- err = idtcm_read(idtcm, dpll, DPLL_TOD_SYNC_CFG, &val, sizeof(val));
- if (err)
- return err;
-
- val &= ~(TOD_SYNC_SOURCE_MASK << TOD_SYNC_SOURCE_SHIFT);
- val |= (sync_src << TOD_SYNC_SOURCE_SHIFT);
- val |= TOD_SYNC_EN;
-
- return idtcm_write(idtcm, dpll, DPLL_TOD_SYNC_CFG, &val, sizeof(val));
-}
-
-static int idtcm_enable_tod_sync(struct idtcm_channel *channel)
-{
- struct idtcm *idtcm = channel->idtcm;
- u8 pll;
- u8 sync_src;
- u8 qn;
- u8 qn_plus_1;
- u8 cfg;
- int err = 0;
- u16 output_mask = channel->output_mask;
- u8 out8_mux = 0;
- u8 out11_mux = 0;
- u8 temp;
-
- /*
- * set tod_out_sync_enable to 0.
- */
- err = idtcm_read(idtcm, channel->tod_n, TOD_CFG, &cfg, sizeof(cfg));
- if (err)
- return err;
-
- cfg &= ~TOD_OUT_SYNC_ENABLE;
-
- err = idtcm_write(idtcm, channel->tod_n, TOD_CFG, &cfg, sizeof(cfg));
- if (err)
- return err;
-
- switch (channel->tod_n) {
- case TOD_0:
- sync_src = 0;
- break;
- case TOD_1:
- sync_src = 1;
- break;
- case TOD_2:
- sync_src = 2;
- break;
- case TOD_3:
- sync_src = 3;
- break;
- default:
- return -EINVAL;
- }
-
- err = idtcm_read(idtcm, 0, HW_Q8_CTRL_SPARE, &temp, sizeof(temp));
- if (err)
- return err;
-
- if ((temp & Q9_TO_Q8_FANOUT_AND_CLOCK_SYNC_ENABLE_MASK) ==
- Q9_TO_Q8_FANOUT_AND_CLOCK_SYNC_ENABLE_MASK)
- out8_mux = 1;
-
- err = idtcm_read(idtcm, 0, HW_Q11_CTRL_SPARE, &temp, sizeof(temp));
- if (err)
- return err;
-
- if ((temp & Q10_TO_Q11_FANOUT_AND_CLOCK_SYNC_ENABLE_MASK) ==
- Q10_TO_Q11_FANOUT_AND_CLOCK_SYNC_ENABLE_MASK)
- out11_mux = 1;
-
- for (pll = 0; pll < 8; pll++) {
- qn = 0;
- qn_plus_1 = 0;
-
- if (pll < 4) {
- /* First 4 pll has 2 outputs */
- qn = output_mask & 0x1;
- output_mask = output_mask >> 1;
- qn_plus_1 = output_mask & 0x1;
- output_mask = output_mask >> 1;
- } else if (pll == 4) {
- if (out8_mux == 0) {
- qn = output_mask & 0x1;
- output_mask = output_mask >> 1;
- }
- } else if (pll == 5) {
- if (out8_mux) {
- qn_plus_1 = output_mask & 0x1;
- output_mask = output_mask >> 1;
- }
- qn = output_mask & 0x1;
- output_mask = output_mask >> 1;
- } else if (pll == 6) {
- qn = output_mask & 0x1;
- output_mask = output_mask >> 1;
- if (out11_mux) {
- qn_plus_1 = output_mask & 0x1;
- output_mask = output_mask >> 1;
- }
- } else if (pll == 7) {
- if (out11_mux == 0) {
- qn = output_mask & 0x1;
- output_mask = output_mask >> 1;
- }
- }
-
- if (qn != 0 || qn_plus_1 != 0)
- err = _enable_pll_tod_sync(idtcm, pll, sync_src, qn,
- qn_plus_1);
- if (err)
- return err;
- }
-
- return err;
-}
-
static int idtcm_enable_tod(struct idtcm_channel *channel)
{
struct idtcm *idtcm = channel->idtcm;
@@ -2101,15 +1885,6 @@ static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
snprintf(channel->caps.name, sizeof(channel->caps.name),
"IDT CM TOD%u", index);

- if (!idtcm->deprecated) {
- err = idtcm_enable_tod_sync(channel);
- if (err) {
- dev_err(&idtcm->client->dev,
- "Failed at line %d in %s!", __LINE__, __func__);
- return err;
- }
- }
-
/* Sync pll mode with hardware */
err = idtcm_get_pll_mode(channel, &channel->pll_mode);
if (err) {
--
2.7.4


2021-09-14 01:07:17

by Min Li

[permalink] [raw]
Subject: [PATCH net 3/3] ptp: ptp_clockmatrix: Add support for pll_mode=0 and manual ref switch of WF and WP

From: Min Li <[email protected]>

Also correct how initialize_dco_operating_mode is called

Signed-off-by: Min Li <[email protected]>
---
drivers/ptp/idt8a340_reg.h | 4 +
drivers/ptp/ptp_clockmatrix.c | 372 +++++++++++++++++++++++++++++++++++++-----
drivers/ptp/ptp_clockmatrix.h | 47 +++++-
3 files changed, 376 insertions(+), 47 deletions(-)

diff --git a/drivers/ptp/idt8a340_reg.h b/drivers/ptp/idt8a340_reg.h
index dea8e1d..1c52101 100644
--- a/drivers/ptp/idt8a340_reg.h
+++ b/drivers/ptp/idt8a340_reg.h
@@ -635,6 +635,10 @@
#define STATE_MODE_SHIFT (0)
#define STATE_MODE_MASK (0x7)

+/* Bit definitions for the DPLL_MANU_REF_CFG register */
+#define MANUAL_REFERENCE_SHIFT (0)
+#define MANUAL_REFERENCE_MASK (0x1f)
+
/* Bit definitions for the GPIO_CFG_GBL register */
#define SUPPLY_MODE_SHIFT (0)
#define SUPPLY_MODE_MASK (0x3)
diff --git a/drivers/ptp/ptp_clockmatrix.c b/drivers/ptp/ptp_clockmatrix.c
index 2c552a0..1a2e3c2 100644
--- a/drivers/ptp/ptp_clockmatrix.c
+++ b/drivers/ptp/ptp_clockmatrix.c
@@ -33,6 +33,8 @@ module_param(firmware, charp, 0);

#define SETTIME_CORRECTION (0)

+static int _idtcm_adjfine(struct idtcm_channel *channel, long scaled_ppm);
+
static int contains_full_configuration(struct idtcm *idtcm,
const struct firmware *fw)
{
@@ -657,8 +659,8 @@ static int idtcm_sync_pps_output(struct idtcm_channel *channel)
}

static int _idtcm_set_dpll_hw_tod(struct idtcm_channel *channel,
- struct timespec64 const *ts,
- enum hw_tod_write_trig_sel wr_trig)
+ struct timespec64 const *ts,
+ enum hw_tod_write_trig_sel wr_trig)
{
struct idtcm *idtcm = channel->idtcm;
u8 buf[TOD_BYTE_COUNT];
@@ -920,9 +922,9 @@ static int idtcm_start_phase_pull_in(struct idtcm_channel *channel)
return err;
}

-static int idtcm_do_phase_pull_in(struct idtcm_channel *channel,
- s32 offset_ns,
- u32 max_ffo_ppb)
+static int do_phase_pull_in_fw(struct idtcm_channel *channel,
+ s32 offset_ns,
+ u32 max_ffo_ppb)
{
int err;

@@ -991,7 +993,7 @@ static int _idtcm_adjtime_deprecated(struct idtcm_channel *channel, s64 delta)
s64 now;

if (abs(delta) < PHASE_PULL_IN_THRESHOLD_NS_DEPRECATED) {
- err = idtcm_do_phase_pull_in(channel, delta, 0);
+ err = channel->do_phase_pull_in(channel, delta, 0);
} else {
idtcm->calculate_overhead_flag = 1;

@@ -1220,7 +1222,7 @@ static int idtcm_load_firmware(struct idtcm *idtcm,
if (firmware) /* module parameter */
snprintf(fname, sizeof(fname), "%s", firmware);

- dev_dbg(&idtcm->client->dev, "requesting firmware '%s'", fname);
+ dev_info(&idtcm->client->dev, "firmware '%s'", fname);

err = request_firmware(&fw, fname, dev);
if (err) {
@@ -1354,7 +1356,7 @@ static int idtcm_perout_enable(struct idtcm_channel *channel,
}

static int idtcm_get_pll_mode(struct idtcm_channel *channel,
- enum pll_mode *pll_mode)
+ enum pll_mode *mode)
{
struct idtcm *idtcm = channel->idtcm;
int err;
@@ -1366,13 +1368,13 @@ static int idtcm_get_pll_mode(struct idtcm_channel *channel,
if (err)
return err;

- *pll_mode = (dpll_mode >> PLL_MODE_SHIFT) & PLL_MODE_MASK;
+ *mode = (dpll_mode >> PLL_MODE_SHIFT) & PLL_MODE_MASK;

return 0;
}

static int idtcm_set_pll_mode(struct idtcm_channel *channel,
- enum pll_mode pll_mode)
+ enum pll_mode mode)
{
struct idtcm *idtcm = channel->idtcm;
int err;
@@ -1386,23 +1388,298 @@ static int idtcm_set_pll_mode(struct idtcm_channel *channel,

dpll_mode &= ~(PLL_MODE_MASK << PLL_MODE_SHIFT);

- dpll_mode |= (pll_mode << PLL_MODE_SHIFT);
-
- channel->pll_mode = pll_mode;
+ dpll_mode |= (mode << PLL_MODE_SHIFT);

err = idtcm_write(idtcm, channel->dpll_n,
IDTCM_FW_REG(idtcm->fw_ver, V520, DPLL_MODE),
&dpll_mode, sizeof(dpll_mode));
+ return err;
+}
+
+static int idtcm_get_manual_reference(struct idtcm_channel *channel,
+ enum manual_reference *ref)
+{
+ struct idtcm *idtcm = channel->idtcm;
+ u8 dpll_manu_ref_cfg;
+ int err;
+
+ err = idtcm_read(idtcm, channel->dpll_ctrl_n,
+ DPLL_CTRL_DPLL_MANU_REF_CFG,
+ &dpll_manu_ref_cfg, sizeof(dpll_manu_ref_cfg));
+ if (err)
+ return err;
+
+ dpll_manu_ref_cfg &= (MANUAL_REFERENCE_MASK << MANUAL_REFERENCE_SHIFT);
+
+ *ref = dpll_manu_ref_cfg >> MANUAL_REFERENCE_SHIFT;
+
+ return 0;
+}
+
+static int idtcm_set_manual_reference(struct idtcm_channel *channel,
+ enum manual_reference ref)
+{
+ struct idtcm *idtcm = channel->idtcm;
+ u8 dpll_manu_ref_cfg;
+ int err;
+
+ err = idtcm_read(idtcm, channel->dpll_ctrl_n,
+ DPLL_CTRL_DPLL_MANU_REF_CFG,
+ &dpll_manu_ref_cfg, sizeof(dpll_manu_ref_cfg));
+ if (err)
+ return err;
+
+ dpll_manu_ref_cfg &= ~(MANUAL_REFERENCE_MASK << MANUAL_REFERENCE_SHIFT);
+
+ dpll_manu_ref_cfg |= (ref << MANUAL_REFERENCE_SHIFT);
+
+ err = idtcm_write(idtcm, channel->dpll_ctrl_n,
+ DPLL_CTRL_DPLL_MANU_REF_CFG,
+ &dpll_manu_ref_cfg, sizeof(dpll_manu_ref_cfg));
+
+ return err;
+}
+
+static int configure_dpll_mode_write_frequency(struct idtcm_channel *channel)
+{
+ struct idtcm *idtcm = channel->idtcm;
+ int err;
+
+ err = idtcm_set_pll_mode(channel, PLL_MODE_WRITE_FREQUENCY);
+
+ if (err)
+ dev_err(&idtcm->client->dev, "Failed to set pll mode to write frequency");
+ else
+ channel->mode = PTP_PLL_MODE_WRITE_FREQUENCY;
+
+ return err;
+}
+
+static int configure_dpll_mode_write_phase(struct idtcm_channel *channel)
+{
+ struct idtcm *idtcm = channel->idtcm;
+ int err;
+
+ err = idtcm_set_pll_mode(channel, PLL_MODE_WRITE_PHASE);
+
+ if (err)
+ dev_err(&idtcm->client->dev, "Failed to set pll mode to write phase");
+ else
+ channel->mode = PTP_PLL_MODE_WRITE_PHASE;
+
+ return err;
+}
+
+static int configure_manual_reference_write_frequency(struct idtcm_channel *channel)
+{
+ struct idtcm *idtcm = channel->idtcm;
+ int err;
+
+ err = idtcm_set_manual_reference(channel, MANU_REF_WRITE_FREQUENCY);
+
+ if (err)
+ dev_err(&idtcm->client->dev, "Failed to set manual reference to write frequency");
+ else
+ channel->mode = PTP_PLL_MODE_WRITE_FREQUENCY;
+
+ return err;
+}
+
+static int configure_manual_reference_write_phase(struct idtcm_channel *channel)
+{
+ struct idtcm *idtcm = channel->idtcm;
+ int err;
+
+ err = idtcm_set_manual_reference(channel, MANU_REF_WRITE_PHASE);
+
+ if (err)
+ dev_err(&idtcm->client->dev, "Failed to set manual reference to write phase");
+ else
+ channel->mode = PTP_PLL_MODE_WRITE_PHASE;
+
+ return err;
+}
+
+static int idtcm_stop_phase_pull_in(struct idtcm_channel *channel)
+{
+ int err;
+
+ err = _idtcm_adjfine(channel, channel->current_freq_scaled_ppm);
if (err)
return err;

+ channel->phase_pull_in = false;
+
return 0;
}

+static long idtcm_work_handler(struct ptp_clock_info *ptp)
+{
+ struct idtcm_channel *channel = container_of(ptp, struct idtcm_channel, caps);
+ struct idtcm *idtcm = channel->idtcm;
+
+ mutex_lock(&idtcm->reg_lock);
+
+ (void)idtcm_stop_phase_pull_in(channel);
+
+ mutex_unlock(&idtcm->reg_lock);
+
+ /* Return a negative value here to not reschedule */
+ return -1;
+}
+
+static s32 phase_pull_in_scaled_ppm(s32 current_ppm, s32 phase_pull_in_ppb)
+{
+ /* ppb = scaled_ppm * 125 / 2^13 */
+ /* scaled_ppm = ppb * 2^13 / 125 */
+
+ s64 max_scaled_ppm = (PHASE_PULL_IN_MAX_PPB << 13) / 125;
+ s64 scaled_ppm = (phase_pull_in_ppb << 13) / 125;
+
+ current_ppm += scaled_ppm;
+
+ if (current_ppm > max_scaled_ppm)
+ current_ppm = max_scaled_ppm;
+ else if (current_ppm < -max_scaled_ppm)
+ current_ppm = -max_scaled_ppm;
+
+ return current_ppm;
+}
+
+static int do_phase_pull_in_sw(struct idtcm_channel *channel,
+ s32 delta_ns,
+ u32 max_ffo_ppb)
+{
+ s32 current_ppm = channel->current_freq_scaled_ppm;
+ u32 duration_ms = MSEC_PER_SEC;
+ s32 delta_ppm;
+ s32 ppb;
+ int err;
+
+ /* If the ToD correction is less than PHASE_PULL_IN_MIN_THRESHOLD_NS,
+ * skip. The error introduced by the ToD adjustment procedure would
+ * be bigger than the required ToD correction
+ */
+ if (abs(delta_ns) < PHASE_PULL_IN_MIN_THRESHOLD_NS)
+ return 0;
+
+ if (max_ffo_ppb == 0)
+ max_ffo_ppb = PHASE_PULL_IN_MAX_PPB;
+
+ /* For most cases, keep phase pull-in duration 1 second */
+ ppb = delta_ns;
+ while (abs(ppb) > max_ffo_ppb) {
+ duration_ms *= 2;
+ ppb /= 2;
+ }
+
+ delta_ppm = phase_pull_in_scaled_ppm(current_ppm, ppb);
+
+ err = _idtcm_adjfine(channel, delta_ppm);
+
+ if (err)
+ return err;
+
+ /* schedule the worker to cancel phase pull-in */
+ ptp_schedule_worker(channel->ptp_clock,
+ msecs_to_jiffies(duration_ms) - 1);
+
+ channel->phase_pull_in = true;
+
+ return 0;
+}
+
+static int initialize_operating_mode_with_manual_reference(struct idtcm_channel *channel,
+ enum manual_reference ref)
+{
+ struct idtcm *idtcm = channel->idtcm;
+
+ channel->mode = PTP_PLL_MODE_UNSUPPORTED;
+ channel->configure_write_frequency = configure_manual_reference_write_frequency;
+ channel->configure_write_phase = configure_manual_reference_write_phase;
+ channel->do_phase_pull_in = do_phase_pull_in_sw;
+
+ switch (ref) {
+ case MANU_REF_WRITE_PHASE:
+ channel->mode = PTP_PLL_MODE_WRITE_PHASE;
+ break;
+ case MANU_REF_WRITE_FREQUENCY:
+ channel->mode = PTP_PLL_MODE_WRITE_FREQUENCY;
+ break;
+ default:
+ dev_warn(&idtcm->client->dev,
+ "Unsupported MANUAL_REFERENCE: 0x%02x", ref);
+ }
+
+ return 0;
+}
+
+static int initialize_operating_mode_with_pll_mode(struct idtcm_channel *channel,
+ enum pll_mode mode)
+{
+ struct idtcm *idtcm = channel->idtcm;
+ int err = 0;
+
+ channel->mode = PTP_PLL_MODE_UNSUPPORTED;
+ channel->configure_write_frequency = configure_dpll_mode_write_frequency;
+ channel->configure_write_phase = configure_dpll_mode_write_phase;
+ channel->do_phase_pull_in = do_phase_pull_in_fw;
+
+ switch (mode) {
+ case PLL_MODE_WRITE_PHASE:
+ channel->mode = PTP_PLL_MODE_WRITE_PHASE;
+ break;
+ case PLL_MODE_WRITE_FREQUENCY:
+ channel->mode = PTP_PLL_MODE_WRITE_FREQUENCY;
+ break;
+ default:
+ dev_err(&idtcm->client->dev,
+ "Unsupported PLL_MODE: 0x%02x", mode);
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+static int initialize_dco_operating_mode(struct idtcm_channel *channel)
+{
+ enum manual_reference ref = MANU_REF_XO_DPLL;
+ enum pll_mode mode = PLL_MODE_DISABLED;
+ struct idtcm *idtcm = channel->idtcm;
+ int err;
+
+ channel->mode = PTP_PLL_MODE_UNSUPPORTED;
+
+ err = idtcm_get_pll_mode(channel, &mode);
+ if (err) {
+ dev_err(&idtcm->client->dev, "Unable to read pll mode!");
+ return err;
+ }
+
+ if (mode == PLL_MODE_PLL) {
+ err = idtcm_get_manual_reference(channel, &ref);
+ if (err) {
+ dev_err(&idtcm->client->dev, "Unable to read manual reference!");
+ return err;
+ }
+ err = initialize_operating_mode_with_manual_reference(channel, ref);
+ } else {
+ err = initialize_operating_mode_with_pll_mode(channel, mode);
+ }
+
+ if (channel->mode == PTP_PLL_MODE_WRITE_PHASE)
+ channel->configure_write_frequency(channel);
+
+ return err;
+}
+
/* PTP Hardware Clock interface */

/**
- * @brief Maximum absolute value for write phase offset in picoseconds
+ * Maximum absolute value for write phase offset in picoseconds
+ *
+ * @channel: channel
+ * @delta_ns: delta in nanoseconds
*
* Destination signed register is 32-bit register in resolution of 50ps
*
@@ -1417,8 +1694,8 @@ static int _idtcm_adjphase(struct idtcm_channel *channel, s32 delta_ns)
s32 phase_50ps;
s64 offset_ps;

- if (channel->pll_mode != PLL_MODE_WRITE_PHASE) {
- err = idtcm_set_pll_mode(channel, PLL_MODE_WRITE_PHASE);
+ if (channel->mode != PTP_PLL_MODE_WRITE_PHASE) {
+ err = channel->configure_write_phase(channel);
if (err)
return err;
}
@@ -1456,8 +1733,8 @@ static int _idtcm_adjfine(struct idtcm_channel *channel, long scaled_ppm)
u8 buf[6] = {0};
s64 fcw;

- if (channel->pll_mode != PLL_MODE_WRITE_FREQUENCY) {
- err = idtcm_set_pll_mode(channel, PLL_MODE_WRITE_FREQUENCY);
+ if (channel->mode != PTP_PLL_MODE_WRITE_FREQUENCY) {
+ err = channel->configure_write_frequency(channel);
if (err)
return err;
}
@@ -1574,29 +1851,29 @@ static int idtcm_adjtime(struct ptp_clock_info *ptp, s64 delta)
enum scsr_tod_write_type_sel type;
int err;

+ if (channel->phase_pull_in == true)
+ return 0;
+
+ mutex_lock(&idtcm->reg_lock);
+
if (abs(delta) < PHASE_PULL_IN_THRESHOLD_NS) {
- err = idtcm_do_phase_pull_in(channel, delta, 0);
+ err = channel->do_phase_pull_in(channel, delta, 0);
if (err)
dev_err(&idtcm->client->dev,
"Failed at line %d in %s!", __LINE__, __func__);
- return err;
- }
-
- if (delta >= 0) {
- ts = ns_to_timespec64(delta);
- type = SCSR_TOD_WR_TYPE_SEL_DELTA_PLUS;
} else {
- ts = ns_to_timespec64(-delta);
- type = SCSR_TOD_WR_TYPE_SEL_DELTA_MINUS;
+ if (delta >= 0) {
+ ts = ns_to_timespec64(delta);
+ type = SCSR_TOD_WR_TYPE_SEL_DELTA_PLUS;
+ } else {
+ ts = ns_to_timespec64(-delta);
+ type = SCSR_TOD_WR_TYPE_SEL_DELTA_MINUS;
+ }
+ err = _idtcm_settime(channel, &ts, type);
+ if (err)
+ dev_err(&idtcm->client->dev,
+ "Failed at line %d in %s!", __LINE__, __func__);
}
-
- mutex_lock(&idtcm->reg_lock);
-
- err = _idtcm_settime(channel, &ts, type);
- if (err)
- dev_err(&idtcm->client->dev,
- "Failed at line %d in %s!", __LINE__, __func__);
-
mutex_unlock(&idtcm->reg_lock);

return err;
@@ -1626,15 +1903,21 @@ static int idtcm_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
struct idtcm *idtcm = channel->idtcm;
int err;

+ if (channel->phase_pull_in == true)
+ return 0;
+
+ if (scaled_ppm == channel->current_freq_scaled_ppm)
+ return 0;
+
mutex_lock(&idtcm->reg_lock);

err = _idtcm_adjfine(channel, scaled_ppm);
- if (err)
- dev_err(&idtcm->client->dev,
- "Failed at line %d in %s!", __LINE__, __func__);

mutex_unlock(&idtcm->reg_lock);

+ if (!err)
+ channel->current_freq_scaled_ppm = scaled_ppm;
+
return err;
}

@@ -1746,6 +2029,7 @@ static const struct ptp_clock_info idtcm_caps = {
.gettime64 = &idtcm_gettime,
.settime64 = &idtcm_settime,
.enable = &idtcm_enable,
+ .do_aux_work = &idtcm_work_handler,
};

static const struct ptp_clock_info idtcm_caps_deprecated = {
@@ -1758,6 +2042,7 @@ static const struct ptp_clock_info idtcm_caps_deprecated = {
.gettime64 = &idtcm_gettime,
.settime64 = &idtcm_settime_deprecated,
.enable = &idtcm_enable,
+ .do_aux_work = &idtcm_work_handler,
};

static int configure_channel_pll(struct idtcm_channel *channel)
@@ -1847,7 +2132,9 @@ static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
return -EINVAL;

channel = &idtcm->channel[index];
+
channel->idtcm = idtcm;
+ channel->current_freq_scaled_ppm = 0;

/* Set pll addresses */
err = configure_channel_pll(channel);
@@ -1892,13 +2179,9 @@ static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
snprintf(channel->caps.name, sizeof(channel->caps.name),
"IDT CM TOD%u", index);

- /* Sync pll mode with hardware */
- err = idtcm_get_pll_mode(channel, &channel->pll_mode);
- if (err) {
- dev_err(&idtcm->client->dev,
- "Error: %s - Unable to read pll mode", __func__);
+ err = initialize_dco_operating_mode(channel);
+ if (err)
return err;
- }

err = idtcm_enable_tod(channel);
if (err) {
@@ -1931,7 +2214,6 @@ static void ptp_clock_unregister_all(struct idtcm *idtcm)

for (i = 0; i < MAX_TOD; i++) {
channel = &idtcm->channel[i];
-
if (channel->ptp_clock)
ptp_clock_unregister(channel->ptp_clock);
}
diff --git a/drivers/ptp/ptp_clockmatrix.h b/drivers/ptp/ptp_clockmatrix.h
index 843a9d7..833e590 100644
--- a/drivers/ptp/ptp_clockmatrix.h
+++ b/drivers/ptp/ptp_clockmatrix.h
@@ -57,15 +57,27 @@

#define IDTCM_MAX_WRITE_COUNT (512)

+#define PHASE_PULL_IN_MAX_PPB (144000)
+#define PHASE_PULL_IN_MIN_THRESHOLD_NS (2)
+
/*
* Return register address based on passed in firmware version
*/
#define IDTCM_FW_REG(FW, VER, REG) (((FW) < (VER)) ? (REG) : (REG##_##VER))

+/* PTP PLL Mode */
+enum ptp_pll_mode {
+ PTP_PLL_MODE_MIN = 0,
+ PTP_PLL_MODE_WRITE_FREQUENCY = PTP_PLL_MODE_MIN,
+ PTP_PLL_MODE_WRITE_PHASE,
+ PTP_PLL_MODE_UNSUPPORTED,
+ PTP_PLL_MODE_MAX = PTP_PLL_MODE_UNSUPPORTED,
+};
+
/* Values of DPLL_N.DPLL_MODE.PLL_MODE */
enum pll_mode {
PLL_MODE_MIN = 0,
- PLL_MODE_NORMAL = PLL_MODE_MIN,
+ PLL_MODE_PLL = PLL_MODE_MIN,
PLL_MODE_WRITE_PHASE = 1,
PLL_MODE_WRITE_FREQUENCY = 2,
PLL_MODE_GPIO_INC_DEC = 3,
@@ -75,6 +87,31 @@ enum pll_mode {
PLL_MODE_MAX = PLL_MODE_DISABLED,
};

+/* Values of DPLL_CTRL_n.DPLL_MANU_REF_CFG.MANUAL_REFERENCE */
+enum manual_reference {
+ MANU_REF_MIN = 0,
+ MANU_REF_CLK0 = MANU_REF_MIN,
+ MANU_REF_CLK1,
+ MANU_REF_CLK2,
+ MANU_REF_CLK3,
+ MANU_REF_CLK4,
+ MANU_REF_CLK5,
+ MANU_REF_CLK6,
+ MANU_REF_CLK7,
+ MANU_REF_CLK8,
+ MANU_REF_CLK9,
+ MANU_REF_CLK10,
+ MANU_REF_CLK11,
+ MANU_REF_CLK12,
+ MANU_REF_CLK13,
+ MANU_REF_CLK14,
+ MANU_REF_CLK15,
+ MANU_REF_WRITE_PHASE,
+ MANU_REF_WRITE_FREQUENCY,
+ MANU_REF_XO_DPLL,
+ MANU_REF_MAX = MANU_REF_XO_DPLL,
+};
+
enum hw_tod_write_trig_sel {
HW_TOD_WR_TRIG_SEL_MIN = 0,
HW_TOD_WR_TRIG_SEL_MSB = HW_TOD_WR_TRIG_SEL_MIN,
@@ -141,7 +178,13 @@ struct idtcm_channel {
u16 tod_n;
u16 hw_dpll_n;
u8 sync_src;
- enum pll_mode pll_mode;
+ enum ptp_pll_mode mode;
+ int (*configure_write_frequency)(struct idtcm_channel *channel);
+ int (*configure_write_phase)(struct idtcm_channel *channel);
+ int (*do_phase_pull_in)(struct idtcm_channel *channel,
+ s32 offset_ns, u32 max_ffo_ppb);
+ s32 current_freq_scaled_ppm;
+ bool phase_pull_in;
u8 pll;
u16 output_mask;
};
--
2.7.4

2021-09-14 01:08:27

by Min Li

[permalink] [raw]
Subject: [PATCH net 2/3] ptp: ptp_clockmatrix: Add support for FW 5.2 (8A34005)

From: Min Li <[email protected]>

So far we don't need to support new 5.2 functions but different register
addresses

Signed-off-by: Min Li <[email protected]>
---
drivers/ptp/idt8a340_reg.h | 61 +++++++++++++-
drivers/ptp/ptp_clockmatrix.c | 179 ++++++++++++++++++++++--------------------
drivers/ptp/ptp_clockmatrix.h | 17 ++--
3 files changed, 165 insertions(+), 92 deletions(-)

diff --git a/drivers/ptp/idt8a340_reg.h b/drivers/ptp/idt8a340_reg.h
index ac524cf..dea8e1d 100644
--- a/drivers/ptp/idt8a340_reg.h
+++ b/drivers/ptp/idt8a340_reg.h
@@ -5,7 +5,7 @@
* https://github.com/richardcochran/regen
*
* Hand modified to include some HW registers.
- * Based on 4.8.0, SCSR rev C commit a03c7ae5
+ * Based on 5.2.0, Family Programming Guide (Sept 30, 2020)
*/
#ifndef HAVE_IDT8A340_REG
#define HAVE_IDT8A340_REG
@@ -100,6 +100,7 @@

#define RESET_CTRL 0xc000
#define SM_RESET 0x0012
+#define SM_RESET_V520 0x0013
#define SM_RESET_CMD 0x5A

#define GENERAL_STATUS 0xc014
@@ -130,6 +131,8 @@
#define GPIO_USER_CONTROL 0xc160
#define GPIO0_TO_7_OUT 0x0000
#define GPIO8_TO_15_OUT 0x0001
+#define GPIO0_TO_7_OUT_V520 0x0002
+#define GPIO8_TO_15_OUT_V520 0x0003

#define STICKY_STATUS_CLEAR 0xc164

@@ -216,22 +219,27 @@
#define DPLL_REF_MODE 0x0035
#define DPLL_PHASE_MEASUREMENT_CFG 0x0036
#define DPLL_MODE 0x0037
+#define DPLL_MODE_V520 0x003B

#define DPLL_1 0xc400

#define DPLL_2 0xc438
+#define DPLL_2_V520 0xc43c

#define DPLL_3 0xc480

#define DPLL_4 0xc4b8
+#define DPLL_4_V520 0xc4bc

#define DPLL_5 0xc500

#define DPLL_6 0xc538
+#define DPLL_6_V520 0xc53c

#define DPLL_7 0xc580

#define SYS_DPLL 0xc5b8
+#define SYS_DPLL_V520 0xc5bc

#define DPLL_CTRL_0 0xc600
#define DPLL_CTRL_DPLL_MANU_REF_CFG 0x0001
@@ -331,6 +339,7 @@
#define GPIO_ALERT_OUT_CFG 0x000e
#define GPIO_TOD_NOTIFICATION_CFG 0x000f
#define GPIO_CTRL 0x0010
+#define GPIO_CTRL_V520 0x0011

#define GPIO_1 0xc8d4

@@ -365,6 +374,7 @@
#define OUT_DIV_MUX 0xca12

#define OUTPUT_0 0xca14
+#define OUTPUT_0_V520 0xca20
/* FOD frequency output divider value */
#define OUT_DIV 0x0000
#define OUT_DUTY_CYCLE_HIGH 0x0004
@@ -374,28 +384,40 @@
#define OUT_PHASE_ADJ 0x000c

#define OUTPUT_1 0xca24
+#define OUTPUT_1_V520 0xca30

#define OUTPUT_2 0xca34
+#define OUTPUT_2_V520 0xca40

#define OUTPUT_3 0xca44
+#define OUTPUT_3_V520 0xca50

#define OUTPUT_4 0xca54
+#define OUTPUT_4_V520 0xca60

#define OUTPUT_5 0xca64
+#define OUTPUT_5_V520 0xca80

#define OUTPUT_6 0xca80
+#define OUTPUT_6_V520 0xca90

#define OUTPUT_7 0xca90
+#define OUTPUT_7_V520 0xcaa0

#define OUTPUT_8 0xcaa0
+#define OUTPUT_8_V520 0xcab0

#define OUTPUT_9 0xcab0
+#define OUTPUT_9_V520 0xcac0

#define OUTPUT_10 0xcac0
+#define OUTPUT_10_V520 0xcad0

#define OUTPUT_11 0xcad0
+#define OUTPUT_11_V520 0xcae0

#define SERIAL 0xcae0
+#define SERIAL_V520 0xcaf0

#define PWM_ENCODER_0 0xcb00

@@ -416,50 +438,72 @@
#define PWM_DECODER_0 0xcb40

#define PWM_DECODER_1 0xcb48
+#define PWM_DECODER_1_V520 0xcb4a

#define PWM_DECODER_2 0xcb50
+#define PWM_DECODER_2_V520 0xcb54

#define PWM_DECODER_3 0xcb58
+#define PWM_DECODER_3_V520 0xcb5e

#define PWM_DECODER_4 0xcb60
+#define PWM_DECODER_4_V520 0xcb68

#define PWM_DECODER_5 0xcb68
+#define PWM_DECODER_5_V520 0xcb80

#define PWM_DECODER_6 0xcb70
+#define PWM_DECODER_6_V520 0xcb8a

#define PWM_DECODER_7 0xcb80
+#define PWM_DECODER_7_V520 0xcb94

#define PWM_DECODER_8 0xcb88
+#define PWM_DECODER_8_V520 0xcb9e

#define PWM_DECODER_9 0xcb90
+#define PWM_DECODER_9_V520 0xcba8

#define PWM_DECODER_10 0xcb98
+#define PWM_DECODER_10_V520 0xcbb2

#define PWM_DECODER_11 0xcba0
+#define PWM_DECODER_11_V520 0xcbbc

#define PWM_DECODER_12 0xcba8
+#define PWM_DECODER_12_V520 0xcbc6

#define PWM_DECODER_13 0xcbb0
+#define PWM_DECODER_13_V520 0xcbd0

#define PWM_DECODER_14 0xcbb8
+#define PWM_DECODER_14_V520 0xcbda

#define PWM_DECODER_15 0xcbc0
+#define PWM_DECODER_15_V520 0xcbe4

#define PWM_USER_DATA 0xcbc8
+#define PWM_USER_DATA_V520 0xcbf0

#define TOD_0 0xcbcc
+#define TOD_0_V520 0xcc00

/* Enable TOD counter, output channel sync and even-PPS mode */
#define TOD_CFG 0x0000
+#define TOD_CFG_V520 0x0001

#define TOD_1 0xcbce
+#define TOD_1_V520 0xcc02

#define TOD_2 0xcbd0
+#define TOD_2_V520 0xcc04

#define TOD_3 0xcbd2
+#define TOD_3_V520 0xcc06


#define TOD_WRITE_0 0xcc00
+#define TOD_WRITE_0_V520 0xcc10
/* 8-bit subns, 32-bit ns, 48-bit seconds */
#define TOD_WRITE 0x0000
/* Counter increments after TOD write is completed */
@@ -470,12 +514,16 @@
#define TOD_WRITE_CMD 0x000f

#define TOD_WRITE_1 0xcc10
+#define TOD_WRITE_1_V520 0xcc20

#define TOD_WRITE_2 0xcc20
+#define TOD_WRITE_2_V520 0xcc30

#define TOD_WRITE_3 0xcc30
+#define TOD_WRITE_3_V520 0xcc40

#define TOD_READ_PRIMARY_0 0xcc40
+#define TOD_READ_PRIMARY_0_V520 0xcc50
/* 8-bit subns, 32-bit ns, 48-bit seconds */
#define TOD_READ_PRIMARY 0x0000
/* Counter increments after TOD write is completed */
@@ -484,22 +532,31 @@
#define TOD_READ_PRIMARY_SEL_CFG_0 0x000c
/* Read trigger selection */
#define TOD_READ_PRIMARY_CMD 0x000e
+#define TOD_READ_PRIMARY_CMD_V520 0x000f

#define TOD_READ_PRIMARY_1 0xcc50
+#define TOD_READ_PRIMARY_1_V520 0xcc60

#define TOD_READ_PRIMARY_2 0xcc60
+#define TOD_READ_PRIMARY_2_V520 0xcc80

#define TOD_READ_PRIMARY_3 0xcc80
+#define TOD_READ_PRIMARY_3_V520 0xcc90

#define TOD_READ_SECONDARY_0 0xcc90
+#define TOD_READ_SECONDARY_0_V520 0xcca0

#define TOD_READ_SECONDARY_1 0xcca0
+#define TOD_READ_SECONDARY_1_V520 0xccb0

#define TOD_READ_SECONDARY_2 0xccb0
+#define TOD_READ_SECONDARY_2_V520 0xccc0

#define TOD_READ_SECONDARY_3 0xccc0
+#define TOD_READ_SECONDARY_3_V520 0xccd0

#define OUTPUT_TDC_CFG 0xccd0
+#define OUTPUT_TDC_CFG_V520 0xcce0

#define OUTPUT_TDC_0 0xcd00

@@ -512,8 +569,10 @@
#define INPUT_TDC 0xcd20

#define SCRATCH 0xcf50
+#define SCRATCH_V520 0xcf4c

#define EEPROM 0xcf68
+#define EEPROM_V520 0xcf64

#define OTP 0xcf70

diff --git a/drivers/ptp/ptp_clockmatrix.c b/drivers/ptp/ptp_clockmatrix.c
index 9b1c6b2..2c552a0 100644
--- a/drivers/ptp/ptp_clockmatrix.c
+++ b/drivers/ptp/ptp_clockmatrix.c
@@ -33,15 +33,21 @@ module_param(firmware, charp, 0);

#define SETTIME_CORRECTION (0)

-static int contains_full_configuration(const struct firmware *fw)
+static int contains_full_configuration(struct idtcm *idtcm,
+ const struct firmware *fw)
{
- s32 full_count = FULL_FW_CFG_BYTES - FULL_FW_CFG_SKIPPED_BYTES;
struct idtcm_fwrc *rec = (struct idtcm_fwrc *)fw->data;
+ u16 scratch = IDTCM_FW_REG(idtcm->fw_ver, V520, SCRATCH);
+ s32 full_count;
s32 count = 0;
u16 regaddr;
u8 loaddr;
s32 len;

+ /* 4 bytes skipped every 0x80 */
+ full_count = (scratch - GPIO_USER_CONTROL) -
+ ((scratch >> 7) - (GPIO_USER_CONTROL >> 7)) * 4;
+
/* If the firmware contains 'full configuration' SM_RESET can be used
* to ensure proper configuration.
*
@@ -57,7 +63,7 @@ static int contains_full_configuration(const struct firmware *fw)
rec++;

/* Top (status registers) and bottom are read-only */
- if (regaddr < GPIO_USER_CONTROL || regaddr >= SCRATCH)
+ if (regaddr < GPIO_USER_CONTROL || regaddr >= scratch)
continue;

/* Page size 128, last 4 bytes of page skipped */
@@ -152,6 +158,19 @@ static int idtcm_strverscmp(const char *version1, const char *version2)
return 0;
}

+static enum fw_version idtcm_fw_version(const char *version)
+{
+ enum fw_version ver = V_DEFAULT;
+
+ if (idtcm_strverscmp(version, "4.8.7") >= 0)
+ ver = V487;
+
+ if (idtcm_strverscmp(version, "5.2.0") >= 0)
+ ver = V520;
+
+ return ver;
+}
+
static int idtcm_xfer_read(struct idtcm *idtcm,
u8 regaddr,
u8 *buf,
@@ -353,8 +372,8 @@ static int wait_for_sys_apll_dpll_lock(struct idtcm *idtcm)
apll &= SYS_APLL_LOSS_LOCK_LIVE_MASK;
dpll &= DPLL_SYS_STATE_MASK;

- if (apll == SYS_APLL_LOSS_LOCK_LIVE_LOCKED
- && dpll == DPLL_STATE_LOCKED) {
+ if (apll == SYS_APLL_LOSS_LOCK_LIVE_LOCKED &&
+ dpll == DPLL_STATE_LOCKED) {
return 0;
} else if (dpll == DPLL_STATE_FREERUN ||
dpll == DPLL_STATE_HOLDOVER ||
@@ -388,13 +407,14 @@ static int _idtcm_gettime(struct idtcm_channel *channel,
struct timespec64 *ts)
{
struct idtcm *idtcm = channel->idtcm;
+ u16 tod_read_cmd = IDTCM_FW_REG(idtcm->fw_ver, V520, TOD_READ_PRIMARY_CMD);
u8 buf[TOD_BYTE_COUNT];
u8 timeout = 10;
u8 trigger;
int err;

err = idtcm_read(idtcm, channel->tod_read_primary,
- TOD_READ_PRIMARY_CMD, &trigger, sizeof(trigger));
+ tod_read_cmd, &trigger, sizeof(trigger));
if (err)
return err;

@@ -403,7 +423,7 @@ static int _idtcm_gettime(struct idtcm_channel *channel,
trigger &= ~TOD_READ_TRIGGER_MODE; /* single shot */

err = idtcm_write(idtcm, channel->tod_read_primary,
- TOD_READ_PRIMARY_CMD, &trigger, sizeof(trigger));
+ tod_read_cmd, &trigger, sizeof(trigger));
if (err)
return err;

@@ -413,7 +433,7 @@ static int _idtcm_gettime(struct idtcm_channel *channel,
idtcm->start_time = ktime_get_raw();

err = idtcm_read(idtcm, channel->tod_read_primary,
- TOD_READ_PRIMARY_CMD, &trigger,
+ tod_read_cmd, &trigger,
sizeof(trigger));
if (err)
return err;
@@ -559,35 +579,10 @@ static int _sync_pll_output(struct idtcm *idtcm,
return err;
}

-static int sync_source_dpll_tod_pps(u16 tod_addr, u8 *sync_src)
-{
- int err = 0;
-
- switch (tod_addr) {
- case TOD_0:
- *sync_src = SYNC_SOURCE_DPLL0_TOD_PPS;
- break;
- case TOD_1:
- *sync_src = SYNC_SOURCE_DPLL1_TOD_PPS;
- break;
- case TOD_2:
- *sync_src = SYNC_SOURCE_DPLL2_TOD_PPS;
- break;
- case TOD_3:
- *sync_src = SYNC_SOURCE_DPLL3_TOD_PPS;
- break;
- default:
- err = -EINVAL;
- }
-
- return err;
-}
-
static int idtcm_sync_pps_output(struct idtcm_channel *channel)
{
struct idtcm *idtcm = channel->idtcm;
u8 pll;
- u8 sync_src;
u8 qn;
u8 qn_plus_1;
int err = 0;
@@ -596,10 +591,6 @@ static int idtcm_sync_pps_output(struct idtcm_channel *channel)
u8 temp;
u16 output_mask = channel->output_mask;

- err = sync_source_dpll_tod_pps(channel->tod_n, &sync_src);
- if (err)
- return err;
-
err = idtcm_read(idtcm, 0, HW_Q8_CTRL_SPARE,
&temp, sizeof(temp));
if (err)
@@ -655,8 +646,8 @@ static int idtcm_sync_pps_output(struct idtcm_channel *channel)
}

if (qn != 0 || qn_plus_1 != 0)
- err = _sync_pll_output(idtcm, pll, sync_src, qn,
- qn_plus_1);
+ err = _sync_pll_output(idtcm, pll, channel->sync_src,
+ qn, qn_plus_1);

if (err)
return err;
@@ -793,46 +784,46 @@ static int _idtcm_set_dpll_scsr_tod(struct idtcm_channel *channel,
return 0;
}

-static int get_output_base_addr(u8 outn)
+static int get_output_base_addr(enum fw_version ver, u8 outn)
{
int base;

switch (outn) {
case 0:
- base = OUTPUT_0;
+ base = IDTCM_FW_REG(ver, V520, OUTPUT_0);
break;
case 1:
- base = OUTPUT_1;
+ base = IDTCM_FW_REG(ver, V520, OUTPUT_1);
break;
case 2:
- base = OUTPUT_2;
+ base = IDTCM_FW_REG(ver, V520, OUTPUT_2);
break;
case 3:
- base = OUTPUT_3;
+ base = IDTCM_FW_REG(ver, V520, OUTPUT_3);
break;
case 4:
- base = OUTPUT_4;
+ base = IDTCM_FW_REG(ver, V520, OUTPUT_4);
break;
case 5:
- base = OUTPUT_5;
+ base = IDTCM_FW_REG(ver, V520, OUTPUT_5);
break;
case 6:
- base = OUTPUT_6;
+ base = IDTCM_FW_REG(ver, V520, OUTPUT_6);
break;
case 7:
- base = OUTPUT_7;
+ base = IDTCM_FW_REG(ver, V520, OUTPUT_7);
break;
case 8:
- base = OUTPUT_8;
+ base = IDTCM_FW_REG(ver, V520, OUTPUT_8);
break;
case 9:
- base = OUTPUT_9;
+ base = IDTCM_FW_REG(ver, V520, OUTPUT_9);
break;
case 10:
- base = OUTPUT_10;
+ base = IDTCM_FW_REG(ver, V520, OUTPUT_10);
break;
case 11:
- base = OUTPUT_11;
+ base = IDTCM_FW_REG(ver, V520, OUTPUT_11);
break;
default:
base = -EINVAL;
@@ -1032,7 +1023,9 @@ static int idtcm_state_machine_reset(struct idtcm *idtcm)

clear_boot_status(idtcm);

- err = idtcm_write(idtcm, RESET_CTRL, SM_RESET, &byte, sizeof(byte));
+ err = idtcm_write(idtcm, RESET_CTRL,
+ IDTCM_FW_REG(idtcm->fw_ver, V520, SM_RESET),
+ &byte, sizeof(byte));

if (!err) {
for (i = 0; i < 30; i++) {
@@ -1214,6 +1207,7 @@ static void display_pll_and_masks(struct idtcm *idtcm)
static int idtcm_load_firmware(struct idtcm *idtcm,
struct device *dev)
{
+ u16 scratch = IDTCM_FW_REG(idtcm->fw_ver, V520, SCRATCH);
char fname[128] = FW_FILENAME;
const struct firmware *fw;
struct idtcm_fwrc *rec;
@@ -1239,7 +1233,7 @@ static int idtcm_load_firmware(struct idtcm *idtcm,

rec = (struct idtcm_fwrc *) fw->data;

- if (contains_full_configuration(fw))
+ if (contains_full_configuration(idtcm, fw))
idtcm_state_machine_reset(idtcm);

for (len = fw->size; len > 0; len -= sizeof(*rec)) {
@@ -1263,7 +1257,7 @@ static int idtcm_load_firmware(struct idtcm *idtcm,
err = 0;

/* Top (status registers) and bottom are read-only */
- if (regaddr < GPIO_USER_CONTROL || regaddr >= SCRATCH)
+ if (regaddr < GPIO_USER_CONTROL || regaddr >= scratch)
continue;

/* Page size 128, last 4 bytes of page skipped */
@@ -1292,7 +1286,7 @@ static int idtcm_output_enable(struct idtcm_channel *channel,
int err;
u8 val;

- base = get_output_base_addr(outn);
+ base = get_output_base_addr(idtcm->fw_ver, outn);

if (!(base > 0)) {
dev_err(&idtcm->client->dev,
@@ -1366,7 +1360,8 @@ static int idtcm_get_pll_mode(struct idtcm_channel *channel,
int err;
u8 dpll_mode;

- err = idtcm_read(idtcm, channel->dpll_n, DPLL_MODE,
+ err = idtcm_read(idtcm, channel->dpll_n,
+ IDTCM_FW_REG(idtcm->fw_ver, V520, DPLL_MODE),
&dpll_mode, sizeof(dpll_mode));
if (err)
return err;
@@ -1383,7 +1378,8 @@ static int idtcm_set_pll_mode(struct idtcm_channel *channel,
int err;
u8 dpll_mode;

- err = idtcm_read(idtcm, channel->dpll_n, DPLL_MODE,
+ err = idtcm_read(idtcm, channel->dpll_n,
+ IDTCM_FW_REG(idtcm->fw_ver, V520, DPLL_MODE),
&dpll_mode, sizeof(dpll_mode));
if (err)
return err;
@@ -1394,7 +1390,8 @@ static int idtcm_set_pll_mode(struct idtcm_channel *channel,

channel->pll_mode = pll_mode;

- err = idtcm_write(idtcm, channel->dpll_n, DPLL_MODE,
+ err = idtcm_write(idtcm, channel->dpll_n,
+ IDTCM_FW_REG(idtcm->fw_ver, V520, DPLL_MODE),
&dpll_mode, sizeof(dpll_mode));
if (err)
return err;
@@ -1404,8 +1401,8 @@ static int idtcm_set_pll_mode(struct idtcm_channel *channel,

/* PTP Hardware Clock interface */

-/*
- * Maximum absolute value for write phase offset in picoseconds
+/**
+ * @brief Maximum absolute value for write phase offset in picoseconds
*
* Destination signed register is 32-bit register in resolution of 50ps
*
@@ -1679,23 +1676,31 @@ static int idtcm_enable_tod(struct idtcm_channel *channel)
{
struct idtcm *idtcm = channel->idtcm;
struct timespec64 ts = {0, 0};
+ u16 tod_cfg = IDTCM_FW_REG(idtcm->fw_ver, V520, TOD_CFG);
u8 cfg;
int err;

+ /* STEELAI-366 - Temporary workaround for ts2phc compatibility */
+ if (0) {
+ err = idtcm_output_mask_enable(channel, false);
+ if (err)
+ return err;
+ }
+
/*
* Start the TOD clock ticking.
*/
- err = idtcm_read(idtcm, channel->tod_n, TOD_CFG, &cfg, sizeof(cfg));
+ err = idtcm_read(idtcm, channel->tod_n, tod_cfg, &cfg, sizeof(cfg));
if (err)
return err;

cfg |= TOD_ENABLE;

- err = idtcm_write(idtcm, channel->tod_n, TOD_CFG, &cfg, sizeof(cfg));
+ err = idtcm_write(idtcm, channel->tod_n, tod_cfg, &cfg, sizeof(cfg));
if (err)
return err;

- if (idtcm->deprecated)
+ if (idtcm->fw_ver < V487)
return _idtcm_settime_deprecated(channel, &ts);
else
return _idtcm_settime(channel, &ts,
@@ -1723,10 +1728,7 @@ static void idtcm_set_version_info(struct idtcm *idtcm)
snprintf(idtcm->version, sizeof(idtcm->version), "%u.%u.%u",
major, minor, hotfix);

- if (idtcm_strverscmp(idtcm->version, "4.8.7") >= 0)
- idtcm->deprecated = 0;
- else
- idtcm->deprecated = 1;
+ idtcm->fw_ver = idtcm_fw_version(idtcm->version);

dev_info(&idtcm->client->dev,
"%d.%d.%d, Id: 0x%04x HW Rev: %d OTP Config Select: %d",
@@ -1760,6 +1762,7 @@ static const struct ptp_clock_info idtcm_caps_deprecated = {

static int configure_channel_pll(struct idtcm_channel *channel)
{
+ struct idtcm *idtcm = channel->idtcm;
int err = 0;

switch (channel->pll) {
@@ -1781,7 +1784,7 @@ static int configure_channel_pll(struct idtcm_channel *channel)
break;
case 2:
channel->dpll_freq = DPLL_FREQ_2;
- channel->dpll_n = DPLL_2;
+ channel->dpll_n = IDTCM_FW_REG(idtcm->fw_ver, V520, DPLL_2);
channel->hw_dpll_n = HW_DPLL_2;
channel->dpll_phase = DPLL_PHASE_2;
channel->dpll_ctrl_n = DPLL_CTRL_2;
@@ -1797,7 +1800,7 @@ static int configure_channel_pll(struct idtcm_channel *channel)
break;
case 4:
channel->dpll_freq = DPLL_FREQ_4;
- channel->dpll_n = DPLL_4;
+ channel->dpll_n = IDTCM_FW_REG(idtcm->fw_ver, V520, DPLL_4);
channel->hw_dpll_n = HW_DPLL_4;
channel->dpll_phase = DPLL_PHASE_4;
channel->dpll_ctrl_n = DPLL_CTRL_4;
@@ -1813,7 +1816,7 @@ static int configure_channel_pll(struct idtcm_channel *channel)
break;
case 6:
channel->dpll_freq = DPLL_FREQ_6;
- channel->dpll_n = DPLL_6;
+ channel->dpll_n = IDTCM_FW_REG(idtcm->fw_ver, V520, DPLL_6);
channel->hw_dpll_n = HW_DPLL_6;
channel->dpll_phase = DPLL_PHASE_6;
channel->dpll_ctrl_n = DPLL_CTRL_6;
@@ -1836,6 +1839,7 @@ static int configure_channel_pll(struct idtcm_channel *channel)

static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
{
+ enum fw_version fw_ver = idtcm->fw_ver;
struct idtcm_channel *channel;
int err;

@@ -1843,6 +1847,7 @@ static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
return -EINVAL;

channel = &idtcm->channel[index];
+ channel->idtcm = idtcm;

/* Set pll addresses */
err = configure_channel_pll(channel);
@@ -1852,32 +1857,34 @@ static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
/* Set tod addresses */
switch (index) {
case 0:
- channel->tod_read_primary = TOD_READ_PRIMARY_0;
- channel->tod_write = TOD_WRITE_0;
- channel->tod_n = TOD_0;
+ channel->tod_read_primary = IDTCM_FW_REG(fw_ver, V520, TOD_READ_PRIMARY_0);
+ channel->tod_write = IDTCM_FW_REG(fw_ver, V520, TOD_WRITE_0);
+ channel->tod_n = IDTCM_FW_REG(fw_ver, V520, TOD_0);
+ channel->sync_src = SYNC_SOURCE_DPLL0_TOD_PPS;
break;
case 1:
- channel->tod_read_primary = TOD_READ_PRIMARY_1;
- channel->tod_write = TOD_WRITE_1;
- channel->tod_n = TOD_1;
+ channel->tod_read_primary = IDTCM_FW_REG(fw_ver, V520, TOD_READ_PRIMARY_1);
+ channel->tod_write = IDTCM_FW_REG(fw_ver, V520, TOD_WRITE_1);
+ channel->tod_n = IDTCM_FW_REG(fw_ver, V520, TOD_1);
+ channel->sync_src = SYNC_SOURCE_DPLL1_TOD_PPS;
break;
case 2:
- channel->tod_read_primary = TOD_READ_PRIMARY_2;
- channel->tod_write = TOD_WRITE_2;
- channel->tod_n = TOD_2;
+ channel->tod_read_primary = IDTCM_FW_REG(fw_ver, V520, TOD_READ_PRIMARY_2);
+ channel->tod_write = IDTCM_FW_REG(fw_ver, V520, TOD_WRITE_2);
+ channel->tod_n = IDTCM_FW_REG(fw_ver, V520, TOD_2);
+ channel->sync_src = SYNC_SOURCE_DPLL2_TOD_PPS;
break;
case 3:
- channel->tod_read_primary = TOD_READ_PRIMARY_3;
- channel->tod_write = TOD_WRITE_3;
- channel->tod_n = TOD_3;
+ channel->tod_read_primary = IDTCM_FW_REG(fw_ver, V520, TOD_READ_PRIMARY_3);
+ channel->tod_write = IDTCM_FW_REG(fw_ver, V520, TOD_WRITE_3);
+ channel->tod_n = IDTCM_FW_REG(fw_ver, V520, TOD_3);
+ channel->sync_src = SYNC_SOURCE_DPLL3_TOD_PPS;
break;
default:
return -EINVAL;
}

- channel->idtcm = idtcm;
-
- if (idtcm->deprecated)
+ if (idtcm->fw_ver < V487)
channel->caps = idtcm_caps_deprecated;
else
channel->caps = idtcm_caps;
diff --git a/drivers/ptp/ptp_clockmatrix.h b/drivers/ptp/ptp_clockmatrix.h
index fb32327..843a9d7 100644
--- a/drivers/ptp/ptp_clockmatrix.h
+++ b/drivers/ptp/ptp_clockmatrix.h
@@ -57,10 +57,10 @@

#define IDTCM_MAX_WRITE_COUNT (512)

-#define FULL_FW_CFG_BYTES (SCRATCH - GPIO_USER_CONTROL)
-#define FULL_FW_CFG_SKIPPED_BYTES (((SCRATCH >> 7) \
- - (GPIO_USER_CONTROL >> 7)) \
- * 4) /* 4 bytes skipped every 0x80 */
+/*
+ * Return register address based on passed in firmware version
+ */
+#define IDTCM_FW_REG(FW, VER, REG) (((FW) < (VER)) ? (REG) : (REG##_##VER))

/* Values of DPLL_N.DPLL_MODE.PLL_MODE */
enum pll_mode {
@@ -119,6 +119,12 @@ enum dpll_state {
DPLL_STATE_MAX = DPLL_STATE_OPEN_LOOP,
};

+enum fw_version {
+ V_DEFAULT = 0,
+ V487 = 1,
+ V520 = 2,
+};
+
struct idtcm;

struct idtcm_channel {
@@ -134,6 +140,7 @@ struct idtcm_channel {
u16 tod_write;
u16 tod_n;
u16 hw_dpll_n;
+ u8 sync_src;
enum pll_mode pll_mode;
u8 pll;
u16 output_mask;
@@ -145,7 +152,7 @@ struct idtcm {
u8 page_offset;
u8 tod_mask;
char version[16];
- u8 deprecated;
+ enum fw_version fw_ver;

/* Overhead calculation for adjtime */
u8 calculate_overhead_flag;
--
2.7.4

2021-09-14 13:33:16

by patchwork-bot+netdevbpf

[permalink] [raw]
Subject: Re: [PATCH net 1/3] ptp: ptp_clockmatrix: Remove idtcm_enable_tod_sync()

Hello:

This series was applied to netdev/net-next.git (refs/heads/master):

On Mon, 13 Sep 2021 16:12:32 -0400 you wrote:
> From: Min Li <[email protected]>
>
> Not need since TCS firmware file will configure it properlly.
>
> Signed-off-by: Min Li <[email protected]>
> ---
> drivers/ptp/ptp_clockmatrix.c | 229 +-----------------------------------------
> 1 file changed, 2 insertions(+), 227 deletions(-)

Here is the summary with links:
- [net,1/3] ptp: ptp_clockmatrix: Remove idtcm_enable_tod_sync()
https://git.kernel.org/netdev/net-next/c/c70aae139d39
- [net,2/3] ptp: ptp_clockmatrix: Add support for FW 5.2 (8A34005)
https://git.kernel.org/netdev/net-next/c/794c3dffacc1
- [net,3/3] ptp: ptp_clockmatrix: Add support for pll_mode=0 and manual ref switch of WF and WP
https://git.kernel.org/netdev/net-next/c/da9facf1c182

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html