[PATCH net-next v6 5/6] ptp: clockmatrix: Fix caps.max_adj to reflect DPLL_MAX_FREQ_OFFSET[MAX_FFO]

Min Li
2023-11-30T18:47:16Z

Query MAX_FREQ_OFFSET register to set the proper limit.

Signed-off-by: Min Li <min.li.xe@renesas.com>
---
drivers/ptp/ptp_clockmatrix.c | 43 +++++++++++++++++++++++++-------
drivers/ptp/ptp_clockmatrix.h | 1 +
include/linux/mfd/idt8a340_reg.h | 1 +
3 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/drivers/ptp/ptp_clockmatrix.c b/drivers/ptp/ptp_clockmatrix.c
index 21f3a2c179f5..cd7b3110f8e4 100644
--- a/drivers/ptp/ptp_clockmatrix.c
+++ b/drivers/ptp/ptp_clockmatrix.c
@@ -1038,7 +1038,7 @@ static int _idtcm_adjtime_deprecated(struct idtcm_channel *channel, s64 delta)
s64 now;

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

@@ -1594,7 +1594,7 @@ static int do_phase_pull_in_sw(struct idtcm_channel *channel,
if (abs(delta_ns) < PHASE_PULL_IN_MIN_THRESHOLD_NS)
return 0;

- if (max_ffo_ppb == 0)
+ if (max_ffo_ppb == 0 || max_ffo_ppb > PHASE_PULL_IN_MAX_PPB)
max_ffo_ppb = PHASE_PULL_IN_MAX_PPB;

/* For most cases, keep phase pull-in duration 1 second */
@@ -1880,7 +1880,7 @@ static int idtcm_adjtime(struct ptp_clock_info *ptp, s64 delta)
mutex_lock(idtcm->lock);

if (abs(delta) < PHASE_PULL_IN_THRESHOLD_NS) {
- err = channel->do_phase_pull_in(channel, delta, 0);
+ err = channel->do_phase_pull_in(channel, delta, channel->caps.max_adj);
} else {
if (delta >= 0) {
ts = ns_to_timespec64(delta);
@@ -1927,9 +1927,6 @@ static int idtcm_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
if (channel->phase_pull_in == true)
return 0;

- if (scaled_ppm == channel->current_freq_scaled_ppm)
- return 0;
-
mutex_lock(idtcm->lock);
err = _idtcm_adjfine(channel, scaled_ppm);
mutex_unlock(idtcm->lock);
@@ -2054,7 +2051,7 @@ static struct ptp_pin_desc pin_config[MAX_TOD][MAX_REF_CLK];

static const struct ptp_clock_info idtcm_caps = {
.owner = THIS_MODULE,
- .max_adj = 244000,
+ .max_adj = MAX_FFO_PPB,
.n_per_out = 12,
.n_ext_ts = MAX_TOD,
.n_pins = MAX_REF_CLK,
@@ -2071,7 +2068,7 @@ static const struct ptp_clock_info idtcm_caps = {

static const struct ptp_clock_info idtcm_caps_deprecated = {
.owner = THIS_MODULE,
- .max_adj = 244000,
+ .max_adj = MAX_FFO_PPB,
.n_per_out = 12,
.n_ext_ts = MAX_TOD,
.n_pins = MAX_REF_CLK,
@@ -2242,6 +2239,25 @@ static int configure_channel_tod(struct idtcm_channel *channel, u32 index)
return 0;
}

+static int initialize_max_adj(struct idtcm_channel *channel)
+{
+ struct idtcm *idtcm = channel->idtcm;
+ u8 ffo_ppm;
+ int err;
+
+ err = idtcm_read(idtcm, channel->dpll_n, DPLL_MAX_FREQ_OFFSET,
+ &ffo_ppm, sizeof(ffo_ppm));
+ if (err)
+ return err;
+
+ if (ffo_ppm && ffo_ppm <= (MAX_FFO_PPB / 1000))
+ channel->caps.max_adj = ffo_ppm * 1000;
+ else
+ channel->caps.max_adj = MAX_FFO_PPB;
+
+ return 0;
+}
+
static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
{
struct idtcm_channel *channel;
@@ -2285,6 +2301,10 @@ static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
ppd->chan = index;
}

+ err = initialize_max_adj(channel);
+ if (err)
+ return err;
+
err = initialize_dco_operating_mode(channel);
if (err)
return err;
@@ -2437,8 +2457,13 @@ static int idtcm_probe(struct platform_device *pdev)

err = idtcm_load_firmware(idtcm, &pdev->dev);

- if (err)
+ if (err) {
+ if (err == -ENOENT) {
+ mutex_unlock(idtcm->lock);
+ return -EPROBE_DEFER;
+ }
dev_warn(idtcm->dev, "loading firmware failed with %d", err);
+ }

wait_for_chip_ready(idtcm);

diff --git a/drivers/ptp/ptp_clockmatrix.h b/drivers/ptp/ptp_clockmatrix.h
index ad39dc6decdf..31d90b1bf025 100644
--- a/drivers/ptp/ptp_clockmatrix.h
+++ b/drivers/ptp/ptp_clockmatrix.h
@@ -19,6 +19,7 @@
#define MAX_REF_CLK (16)

#define MAX_ABS_WRITE_PHASE_NANOSECONDS (107374182L)
+#define MAX_FFO_PPB (244000)

#define TOD_MASK_ADDR (0xFFA5)
#define DEFAULT_TOD_MASK (0x04)
diff --git a/include/linux/mfd/idt8a340_reg.h b/include/linux/mfd/idt8a340_reg.h
index b680a0eb5f68..13b36f4858b3 100644
--- a/include/linux/mfd/idt8a340_reg.h
+++ b/include/linux/mfd/idt8a340_reg.h
@@ -192,6 +192,7 @@
#define DPLL_CTRL_REG_0 0x0002
#define DPLL_CTRL_REG_1 0x0003
#define DPLL_CTRL_REG_2 0x0004
+#define DPLL_MAX_FREQ_OFFSET 0x0025
#define DPLL_WF_TIMER 0x002c
#define DPLL_WP_TIMER 0x002e
#define DPLL_TOD_SYNC_CFG 0x0031
--
2.39.2