Lines Matching +full:ns +full:- +full:firmware
1 // SPDX-License-Identifier: GPL-2.0+
8 #include <linux/firmware.h>
27 MODULE_AUTHOR("IDT support-1588 <IDT-support-1588@lm.renesas.com>");
32 * The name of the firmware file to be loaded
33 * over-rides any automatic selection
35 static char *firmware; variable
36 module_param(firmware, charp, 0);
44 sync = div_u64_rem(nsec, idtfc3->ns_per_sync, &rem); in ns2counters()
47 sync = -div_u64_rem(-nsec - 1, idtfc3->ns_per_sync, &rem) - 1; in ns2counters()
48 *sub_ns = idtfc3->ns_per_sync - rem - 1; in ns2counters()
51 return sync * idtfc3->ns_per_sync; in ns2counters()
59 coarse = sign_extend64(FIELD_GET(COARSE_MEAS_MASK, meas_read), (39 - 13)); in tdc_meas2offset()
61 fine = div64_s64(fine * NSEC_PER_SEC, idtfc3->tdc_apll_freq * 62LL); in tdc_meas2offset()
62 coarse = div64_s64(coarse * NSEC_PER_SEC, idtfc3->time_ref_freq); in tdc_meas2offset()
69 if (offset_ns > idtfc3->ns_per_sync / 2) in tdc_offset2phase()
70 offset_ns -= idtfc3->ns_per_sync; in tdc_offset2phase()
72 return offset_ns * idtfc3->tdc_offset_sign; in tdc_offset2phase()
80 return -EINVAL; in idtfc3_set_lpf_mode()
82 if (idtfc3->lpf_mode == mode) in idtfc3_set_lpf_mode()
85 err = regmap_bulk_write(idtfc3->regmap, LPF_MODE_CNFG, &mode, sizeof(mode)); in idtfc3_set_lpf_mode()
89 idtfc3->lpf_mode = mode; in idtfc3_set_lpf_mode()
99 err = regmap_bulk_read(idtfc3->regmap, LPF_CTRL, &val, sizeof(val)); in idtfc3_enable_lpf()
108 return regmap_bulk_write(idtfc3->regmap, LPF_CTRL, &val, sizeof(val)); in idtfc3_enable_lpf()
118 err = regmap_bulk_read(idtfc3->regmap, TIME_CLOCK_MEAS_DIV_CNFG, buf, sizeof(buf)); in idtfc3_get_time_ref_freq()
123 err = regmap_bulk_read(idtfc3->regmap, TIME_CLOCK_COUNT, buf, 1); in idtfc3_get_time_ref_freq()
127 idtfc3->time_ref_freq = idtfc3->hw_param.time_clk_freq * in idtfc3_get_time_ref_freq()
140 err = regmap_bulk_read(idtfc3->regmap, TIME_CLOCK_TDC_FANOUT_CNFG, buf, sizeof(buf)); in idtfc3_get_tdc_offset_sign()
146 dev_err(idtfc3->dev, "TIME_SYNC_TO_TDC_EN is off !!!"); in idtfc3_get_tdc_offset_sign()
147 return -EINVAL; in idtfc3_get_tdc_offset_sign()
154 dev_err(idtfc3->dev, "Invalid tdc_mux_sel sig1=%d sig2=%d", sig1, sig2); in idtfc3_get_tdc_offset_sign()
155 return -EINVAL; in idtfc3_get_tdc_offset_sign()
157 idtfc3->tdc_offset_sign = 1; in idtfc3_get_tdc_offset_sign()
159 idtfc3->tdc_offset_sign = -1; in idtfc3_get_tdc_offset_sign()
169 return regmap_bulk_write(idtfc3->regmap, LPF_BW_CNFG, &val, sizeof(val)); in idtfc3_lpf_bw()
178 err = regmap_bulk_write(idtfc3->regmap, TIME_CLOCK_MEAS_CTRL, &val, sizeof(val)); in idtfc3_enable_tdc()
186 return -EINVAL; in idtfc3_enable_tdc()
189 err = regmap_bulk_write(idtfc3->regmap, TIME_CLOCK_MEAS_CNFG, in idtfc3_enable_tdc()
198 err = regmap_bulk_write(idtfc3->regmap, TIME_CLOCK_MEAS_CTRL, &val, sizeof(val)); in idtfc3_enable_tdc()
213 err = regmap_bulk_read(idtfc3->regmap, TDC_FIFO_STS, in get_tdc_meas()
221 err = regmap_bulk_read(idtfc3->regmap, TDC_FIFO_READ_REQ, in get_tdc_meas()
241 err = regmap_bulk_read(idtfc3->regmap, TDC_FIFO_STS, &val, sizeof(val)); in check_tdc_fifo_overrun()
248 dev_warn(idtfc3->dev, "TDC FIFO overrun !!!"); in check_tdc_fifo_overrun()
271 ptp_clock_event(idtfc3->ptp_clock, &event); in get_tdc_meas_continuous()
282 err = regmap_bulk_read(idtfc3->regmap, TOD_COUNTER_READ_REQ, in idtfc3_read_subcounter()
297 idtfc3->tc_write_timeout, true, idtfc3->regmap, in idtfc3_tod_update_is_done()
300 dev_err(idtfc3->dev, "TOD counter write timeout !!!"); in idtfc3_tod_update_is_done()
316 err = regmap_bulk_write(idtfc3->regmap, TOD_SYNC_LOAD_VAL_CTRL, in idtfc3_write_subcounter()
324 static int idtfc3_timecounter_update(struct idtfc3 *idtfc3, u32 counter, s64 ns) in idtfc3_timecounter_update() argument
333 idtfc3->ns = ns; in idtfc3_timecounter_update()
334 idtfc3->last_counter = counter; in idtfc3_timecounter_update()
348 if (now >= idtfc3->last_counter) in idtfc3_timecounter_read()
349 delta = now - idtfc3->last_counter; in idtfc3_timecounter_read()
351 delta = idtfc3->sub_sync_count - idtfc3->last_counter + now; in idtfc3_timecounter_read()
354 idtfc3->ns += delta * idtfc3->ns_per_counter; in idtfc3_timecounter_read()
355 idtfc3->last_counter = now; in idtfc3_timecounter_read()
368 *ts = ns_to_timespec64(idtfc3->ns); in _idtfc3_gettime()
378 mutex_lock(idtfc3->lock); in idtfc3_gettime()
380 mutex_unlock(idtfc3->lock); in idtfc3_gettime()
392 dev_err(idtfc3->dev, "%s: invalid timespec", __func__); in _idtfc3_settime()
393 return -EINVAL; in _idtfc3_settime()
400 offset_ns = (idtfc3->sub_sync_count - now) * idtfc3->ns_per_counter; in _idtfc3_settime()
404 counter = sub_ns / idtfc3->ns_per_counter; in _idtfc3_settime()
413 mutex_lock(idtfc3->lock); in idtfc3_settime()
415 mutex_unlock(idtfc3->lock); in idtfc3_settime()
430 if (idtfc3->ns + delta < 0) { in _idtfc3_adjtime()
431 dev_err(idtfc3->dev, "%lld ns adj is too large", delta); in _idtfc3_adjtime()
432 return -EINVAL; in _idtfc3_adjtime()
435 sync_ns = ns2counters(idtfc3, delta + idtfc3->ns_per_sync, &sub_ns); in _idtfc3_adjtime()
437 counter = sub_ns / idtfc3->ns_per_counter; in _idtfc3_adjtime()
438 return idtfc3_timecounter_update(idtfc3, counter, idtfc3->ns + sync_ns + in _idtfc3_adjtime()
439 counter * idtfc3->ns_per_counter); in _idtfc3_adjtime()
447 mutex_lock(idtfc3->lock); in idtfc3_adjtime()
449 mutex_unlock(idtfc3->lock); in idtfc3_adjtime()
468 * PCW = --------------------------- in _idtfc3_adjphase()
472 pcw = div_s64((s64)delta * idtfc3->tdc_apll_freq * 124, NSEC_PER_SEC); in _idtfc3_adjphase()
476 return regmap_bulk_write(idtfc3->regmap, LPF_WR_PHASE_CTRL, buf, sizeof(buf)); in _idtfc3_adjphase()
484 mutex_lock(idtfc3->lock); in idtfc3_adjphase()
486 mutex_unlock(idtfc3->lock); in idtfc3_adjphase()
502 * Frequency Control Word unit is: 2^-44 * 10^6 ppm in _idtfc3_adjfine()
506 * FCW = ---------- in _idtfc3_adjfine()
511 * FCW = ------------- in _idtfc3_adjfine()
519 return regmap_bulk_write(idtfc3->regmap, LPF_WR_FREQ_CTRL, buf, sizeof(buf)); in _idtfc3_adjfine()
527 mutex_lock(idtfc3->lock); in idtfc3_adjfine()
529 mutex_unlock(idtfc3->lock); in idtfc3_adjfine()
538 int err = -EOPNOTSUPP; in idtfc3_enable()
540 mutex_lock(idtfc3->lock); in idtfc3_enable()
541 switch (rq->type) { in idtfc3_enable()
545 /* Only accept a 1-PPS aligned to the second. */ in idtfc3_enable()
546 else if (rq->perout.start.nsec || rq->perout.period.sec != 1 || in idtfc3_enable()
547 rq->perout.period.nsec) in idtfc3_enable()
548 err = -ERANGE; in idtfc3_enable()
555 if ((rq->extts.flags & PTP_EXT_OFFSET) != (PTP_EXT_OFFSET)) in idtfc3_enable()
556 err = -EOPNOTSUPP; in idtfc3_enable()
566 mutex_unlock(idtfc3->lock); in idtfc3_enable()
569 dev_err(idtfc3->dev, "Failed in %s with err %d!", __func__, err); in idtfc3_enable()
579 mutex_lock(idtfc3->lock); in idtfc3_aux_work()
585 mutex_unlock(idtfc3->lock); in idtfc3_aux_work()
587 return idtfc3->tc_update_period; in idtfc3_aux_work()
617 err = regmap_bulk_write(idtfc3->regmap, TDC_CTRL, in idtfc3_hw_calibrate()
622 err = regmap_bulk_write(idtfc3->regmap, TDC_CTRL, in idtfc3_hw_calibrate()
634 err = regmap_bulk_write(idtfc3->regmap, SOFT_RESET_CTRL, in idtfc3_hw_calibrate()
639 err = regmap_bulk_write(idtfc3->regmap, SOFT_RESET_CTRL, in idtfc3_hw_calibrate()
653 period_ms = idtfc3->sub_sync_count * MSEC_PER_SEC / in idtfc3_init_timecounter()
654 idtfc3->hw_param.time_clk_freq; in idtfc3_init_timecounter()
656 idtfc3->tc_update_period = msecs_to_jiffies(period_ms / TDC_GET_PERIOD); in idtfc3_init_timecounter()
657 idtfc3->tc_write_timeout = period_ms * USEC_PER_MSEC; in idtfc3_init_timecounter()
667 ptp_schedule_worker(idtfc3->ptp_clock, idtfc3->tc_update_period); in idtfc3_init_timecounter()
677 struct idtfc3_hw_param *param = &idtfc3->hw_param; in idtfc3_get_tdc_apll_freq()
679 err = regmap_bulk_read(idtfc3->regmap, TDC_REF_DIV_CNFG, in idtfc3_get_tdc_apll_freq()
684 err = regmap_bulk_read(idtfc3->regmap, TDC_FB_DIV_INT_CNFG, in idtfc3_get_tdc_apll_freq()
692 idtfc3->tdc_apll_freq = div_u64(param->xtal_freq * (u64)tdc_fb_div_int, in idtfc3_get_tdc_apll_freq()
703 err = regmap_bulk_read(idtfc3->regmap, TIME_CLOCK_SRC, &fod, sizeof(fod)); in idtfc3_get_fod()
709 idtfc3->fod_n = FOD_0; in idtfc3_get_fod()
712 idtfc3->fod_n = FOD_1; in idtfc3_get_fod()
715 idtfc3->fod_n = FOD_2; in idtfc3_get_fod()
718 return -EINVAL; in idtfc3_get_fod()
729 err = regmap_bulk_read(idtfc3->regmap, SUB_SYNC_GEN_CNFG, buf, sizeof(buf)); in idtfc3_get_sync_count()
733 idtfc3->sub_sync_count = (get_unaligned_le32(buf) & SUB_SYNC_COUNTER_MASK) + 1; in idtfc3_get_sync_count()
734 idtfc3->ns_per_counter = NSEC_PER_SEC / idtfc3->hw_param.time_clk_freq; in idtfc3_get_sync_count()
735 idtfc3->ns_per_sync = idtfc3->sub_sync_count * idtfc3->ns_per_counter; in idtfc3_get_sync_count()
797 err = regmap_bulk_write(idtfc3->regmap, TOD_SYNC_LOAD_VAL_CTRL, in idtfc3_set_overhead()
816 idtfc3->tod_write_overhead = lowest_ns; in idtfc3_set_overhead()
825 idtfc3->caps = idtfc3_caps; in idtfc3_enable_ptp()
826 snprintf(idtfc3->caps.name, sizeof(idtfc3->caps.name), "IDT FC3W"); in idtfc3_enable_ptp()
827 idtfc3->ptp_clock = ptp_clock_register(&idtfc3->caps, NULL); in idtfc3_enable_ptp()
829 if (IS_ERR(idtfc3->ptp_clock)) { in idtfc3_enable_ptp()
830 err = PTR_ERR(idtfc3->ptp_clock); in idtfc3_enable_ptp()
831 idtfc3->ptp_clock = NULL; in idtfc3_enable_ptp()
843 dev_info(idtfc3->dev, "TIME_SYNC_CHANNEL registered as ptp%d", in idtfc3_enable_ptp()
844 idtfc3->ptp_clock->index); in idtfc3_enable_ptp()
852 const struct firmware *fw; in idtfc3_load_firmware()
859 idtfc3_default_hw_param(&idtfc3->hw_param); in idtfc3_load_firmware()
861 if (firmware) /* module parameter */ in idtfc3_load_firmware()
862 snprintf(fname, sizeof(fname), "%s", firmware); in idtfc3_load_firmware()
864 dev_info(idtfc3->dev, "requesting firmware '%s'\n", fname); in idtfc3_load_firmware()
866 err = request_firmware(&fw, fname, idtfc3->dev); in idtfc3_load_firmware()
869 dev_err(idtfc3->dev, in idtfc3_load_firmware()
870 "requesting firmware failed with err %d!\n", err); in idtfc3_load_firmware()
874 dev_dbg(idtfc3->dev, "firmware size %zu bytes\n", fw->size); in idtfc3_load_firmware()
876 rec = (struct idtfc3_fwrc *)fw->data; in idtfc3_load_firmware()
878 for (len = fw->size; len > 0; len -= sizeof(*rec)) { in idtfc3_load_firmware()
879 if (rec->reserved) { in idtfc3_load_firmware()
880 dev_err(idtfc3->dev, in idtfc3_load_firmware()
881 "bad firmware, reserved field non-zero\n"); in idtfc3_load_firmware()
882 err = -EINVAL; in idtfc3_load_firmware()
884 val = rec->value; in idtfc3_load_firmware()
885 addr = rec->hiaddr << 8 | rec->loaddr; in idtfc3_load_firmware()
889 err = idtfc3_set_hw_param(&idtfc3->hw_param, addr, val); in idtfc3_load_firmware()
892 if (err != -EINVAL) { in idtfc3_load_firmware()
899 err = regmap_bulk_write(idtfc3->regmap, addr, in idtfc3_load_firmware()
918 err = regmap_bulk_read(idtfc3->regmap, DEVICE_ID, in idtfc3_read_device_id()
921 dev_err(idtfc3->dev, "%s failed with %d", __func__, err); in idtfc3_read_device_id()
940 dev_err(idtfc3->dev, "invalid device"); in idtfc3_check_device_compatibility()
941 return -EINVAL; in idtfc3_check_device_compatibility()
949 struct rsmu_ddata *ddata = dev_get_drvdata(pdev->dev.parent); in idtfc3_probe()
953 idtfc3 = devm_kzalloc(&pdev->dev, sizeof(struct idtfc3), GFP_KERNEL); in idtfc3_probe()
956 return -ENOMEM; in idtfc3_probe()
958 idtfc3->dev = &pdev->dev; in idtfc3_probe()
959 idtfc3->mfd = pdev->dev.parent; in idtfc3_probe()
960 idtfc3->lock = &ddata->lock; in idtfc3_probe()
961 idtfc3->regmap = ddata->regmap; in idtfc3_probe()
963 mutex_lock(idtfc3->lock); in idtfc3_probe()
967 mutex_unlock(idtfc3->lock); in idtfc3_probe()
973 if (err == -ENOENT) { in idtfc3_probe()
974 mutex_unlock(idtfc3->lock); in idtfc3_probe()
975 return -EPROBE_DEFER; in idtfc3_probe()
977 dev_warn(idtfc3->dev, "loading firmware failed with %d", err); in idtfc3_probe()
982 dev_err(idtfc3->dev, "idtfc3_enable_ptp failed with %d", err); in idtfc3_probe()
983 mutex_unlock(idtfc3->lock); in idtfc3_probe()
987 mutex_unlock(idtfc3->lock); in idtfc3_probe()
990 ptp_clock_unregister(idtfc3->ptp_clock); in idtfc3_probe()
1003 ptp_clock_unregister(idtfc3->ptp_clock); in idtfc3_remove()
1008 .name = "rc38xxx-phc",