diff --git a/drivers/ptp/ptp_clockmatrix.c b/drivers/ptp/ptp_clockmatrix.c index 21f3a2c179f59b..cd7b3110f8e485 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 ad39dc6decdf7e..31d90b1bf02526 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 b680a0eb5f6889..13b36f4858b3db 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