brintos

brintos / linux-shallow public Read only

0
0
Text · 21.1 KiB · e14e149 Raw
1015 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * PTP hardware clock driver for the FemtoClock3 family of timing and4 * synchronization devices.5 *6 * Copyright (C) 2023 Integrated Device Technology, Inc., a Renesas Company.7 */8#include <linux/firmware.h>9#include <linux/platform_device.h>10#include <linux/module.h>11#include <linux/ptp_clock_kernel.h>12#include <linux/delay.h>13#include <linux/jiffies.h>14#include <linux/kernel.h>15#include <linux/timekeeping.h>16#include <linux/string.h>17#include <linux/of.h>18#include <linux/bitfield.h>19#include <linux/mfd/rsmu.h>20#include <linux/mfd/idtRC38xxx_reg.h>21#include <linux/unaligned.h>22 23#include "ptp_private.h"24#include "ptp_fc3.h"25 26MODULE_DESCRIPTION("Driver for IDT FemtoClock3(TM) family");27MODULE_AUTHOR("IDT support-1588 <IDT-support-1588@lm.renesas.com>");28MODULE_VERSION("1.0");29MODULE_LICENSE("GPL");30 31/*32 * The name of the firmware file to be loaded33 * over-rides any automatic selection34 */35static char *firmware;36module_param(firmware, charp, 0);37 38static s64 ns2counters(struct idtfc3 *idtfc3, s64 nsec, u32 *sub_ns)39{40	s64 sync;41	s32 rem;42 43	if (likely(nsec >= 0)) {44		sync = div_u64_rem(nsec, idtfc3->ns_per_sync, &rem);45		*sub_ns = rem;46	} else {47		sync = -div_u64_rem(-nsec - 1, idtfc3->ns_per_sync, &rem) - 1;48		*sub_ns = idtfc3->ns_per_sync - rem - 1;49	}50 51	return sync * idtfc3->ns_per_sync;52}53 54static s64 tdc_meas2offset(struct idtfc3 *idtfc3, u64 meas_read)55{56	s64 coarse, fine;57 58	fine = sign_extend64(FIELD_GET(FINE_MEAS_MASK, meas_read), 12);59	coarse = sign_extend64(FIELD_GET(COARSE_MEAS_MASK, meas_read), (39 - 13));60 61	fine = div64_s64(fine * NSEC_PER_SEC, idtfc3->tdc_apll_freq * 62LL);62	coarse = div64_s64(coarse * NSEC_PER_SEC, idtfc3->time_ref_freq);63 64	return coarse + fine;65}66 67static s64 tdc_offset2phase(struct idtfc3 *idtfc3, s64 offset_ns)68{69	if (offset_ns > idtfc3->ns_per_sync / 2)70		offset_ns -= idtfc3->ns_per_sync;71 72	return offset_ns * idtfc3->tdc_offset_sign;73}74 75static int idtfc3_set_lpf_mode(struct idtfc3 *idtfc3, u8 mode)76{77	int err;78 79	if (mode >= LPF_INVALID)80		return -EINVAL;81 82	if (idtfc3->lpf_mode == mode)83		return 0;84 85	err = regmap_bulk_write(idtfc3->regmap, LPF_MODE_CNFG, &mode, sizeof(mode));86	if (err)87		return err;88 89	idtfc3->lpf_mode = mode;90 91	return 0;92}93 94static int idtfc3_enable_lpf(struct idtfc3 *idtfc3, bool enable)95{96	u8 val;97	int err;98 99	err = regmap_bulk_read(idtfc3->regmap, LPF_CTRL, &val, sizeof(val));100	if (err)101		return err;102 103	if (enable == true)104		val |= LPF_EN;105	else106		val &= ~LPF_EN;107 108	return regmap_bulk_write(idtfc3->regmap, LPF_CTRL, &val, sizeof(val));109}110 111static int idtfc3_get_time_ref_freq(struct idtfc3 *idtfc3)112{113	int err;114	u8 buf[4];115	u8 time_ref_div;116	u8 time_clk_div;117 118	err = regmap_bulk_read(idtfc3->regmap, TIME_CLOCK_MEAS_DIV_CNFG, buf, sizeof(buf));119	if (err)120		return err;121	time_ref_div = FIELD_GET(TIME_REF_DIV_MASK, get_unaligned_le32(buf)) + 1;122 123	err = regmap_bulk_read(idtfc3->regmap, TIME_CLOCK_COUNT, buf, 1);124	if (err)125		return err;126	time_clk_div = (buf[0] & TIME_CLOCK_COUNT_MASK) + 1;127	idtfc3->time_ref_freq = idtfc3->hw_param.time_clk_freq *128				time_clk_div / time_ref_div;129 130	return 0;131}132 133static int idtfc3_get_tdc_offset_sign(struct idtfc3 *idtfc3)134{135	int err;136	u8 buf[4];137	u32 val;138	u8 sig1, sig2;139 140	err = regmap_bulk_read(idtfc3->regmap, TIME_CLOCK_TDC_FANOUT_CNFG, buf, sizeof(buf));141	if (err)142		return err;143 144	val = get_unaligned_le32(buf);145	if ((val & TIME_SYNC_TO_TDC_EN) != TIME_SYNC_TO_TDC_EN) {146		dev_err(idtfc3->dev, "TIME_SYNC_TO_TDC_EN is off !!!");147		return -EINVAL;148	}149 150	sig1 = FIELD_GET(SIG1_MUX_SEL_MASK, val);151	sig2 = FIELD_GET(SIG2_MUX_SEL_MASK, val);152 153	if ((sig1 == sig2) || ((sig1 != TIME_SYNC) && (sig2 != TIME_SYNC))) {154		dev_err(idtfc3->dev, "Invalid tdc_mux_sel sig1=%d sig2=%d", sig1, sig2);155		return -EINVAL;156	} else if (sig1 == TIME_SYNC) {157		idtfc3->tdc_offset_sign = 1;158	} else if (sig2 == TIME_SYNC) {159		idtfc3->tdc_offset_sign = -1;160	}161 162	return 0;163}164 165static int idtfc3_lpf_bw(struct idtfc3 *idtfc3, u8 shift, u8 mult)166{167	u8 val = FIELD_PREP(LPF_BW_SHIFT, shift) | FIELD_PREP(LPF_BW_MULT, mult);168 169	return regmap_bulk_write(idtfc3->regmap, LPF_BW_CNFG, &val, sizeof(val));170}171 172static int idtfc3_enable_tdc(struct idtfc3 *idtfc3, bool enable, u8 meas_mode)173{174	int err;175	u8 val = 0;176 177	/* Disable TDC first */178	err = regmap_bulk_write(idtfc3->regmap, TIME_CLOCK_MEAS_CTRL, &val, sizeof(val));179	if (err)180		return err;181 182	if (enable == false)183		return idtfc3_lpf_bw(idtfc3, LPF_BW_SHIFT_DEFAULT, LPF_BW_MULT_DEFAULT);184 185	if (meas_mode >= MEAS_MODE_INVALID)186		return -EINVAL;187 188	/* Change TDC meas mode */189	err = regmap_bulk_write(idtfc3->regmap, TIME_CLOCK_MEAS_CNFG,190				&meas_mode, sizeof(meas_mode));191	if (err)192		return err;193 194	/* Enable TDC */195	val = TDC_MEAS_EN;196	if (meas_mode == CONTINUOUS)197		val |= TDC_MEAS_START;198	err = regmap_bulk_write(idtfc3->regmap, TIME_CLOCK_MEAS_CTRL, &val, sizeof(val));199	if (err)200		return err;201 202	return idtfc3_lpf_bw(idtfc3, LPF_BW_SHIFT_1PPS, LPF_BW_MULT_DEFAULT);203}204 205static bool get_tdc_meas(struct idtfc3 *idtfc3, s64 *offset_ns)206{207	bool valid = false;208	u8 buf[9];209	u8 val;210	int err;211 212	while (true) {213		err = regmap_bulk_read(idtfc3->regmap, TDC_FIFO_STS,214				       &val, sizeof(val));215		if (err)216			return false;217 218		if (val & FIFO_EMPTY)219			break;220 221		err = regmap_bulk_read(idtfc3->regmap, TDC_FIFO_READ_REQ,222				       &buf, sizeof(buf));223		if (err)224			return false;225 226		valid = true;227	}228 229	if (valid)230		*offset_ns = tdc_meas2offset(idtfc3, get_unaligned_le64(&buf[1]));231 232	return valid;233}234 235static int check_tdc_fifo_overrun(struct idtfc3 *idtfc3)236{237	u8 val;238	int err;239 240	/* Check if FIFO is overrun */241	err = regmap_bulk_read(idtfc3->regmap, TDC_FIFO_STS, &val, sizeof(val));242	if (err)243		return err;244 245	if (!(val & FIFO_FULL))246		return 0;247 248	dev_warn(idtfc3->dev, "TDC FIFO overrun !!!");249 250	err = idtfc3_enable_tdc(idtfc3, true, CONTINUOUS);251	if (err)252		return err;253 254	return 0;255}256 257static int get_tdc_meas_continuous(struct idtfc3 *idtfc3)258{259	int err;260	s64 offset_ns;261	struct ptp_clock_event event;262 263	err = check_tdc_fifo_overrun(idtfc3);264	if (err)265		return err;266 267	if (get_tdc_meas(idtfc3, &offset_ns) && offset_ns >= 0) {268		event.index = 0;269		event.offset = tdc_offset2phase(idtfc3, offset_ns);270		event.type = PTP_CLOCK_EXTOFF;271		ptp_clock_event(idtfc3->ptp_clock, &event);272	}273 274	return 0;275}276 277static int idtfc3_read_subcounter(struct idtfc3 *idtfc3)278{279	u8 buf[5] = {0};280	int err;281 282	err = regmap_bulk_read(idtfc3->regmap, TOD_COUNTER_READ_REQ,283			       &buf, sizeof(buf));284	if (err)285		return err;286 287	/* sync_counter_value is [31:82] and sub_sync_counter_value is [0:30] */288	return get_unaligned_le32(&buf[1]) & SUB_SYNC_COUNTER_MASK;289}290 291static int idtfc3_tod_update_is_done(struct idtfc3 *idtfc3)292{293	int err;294	u8 req;295 296	err = read_poll_timeout_atomic(regmap_bulk_read, err, !req, USEC_PER_MSEC,297				       idtfc3->tc_write_timeout, true, idtfc3->regmap,298				       TOD_SYNC_LOAD_REQ_CTRL, &req, 1);299	if (err)300		dev_err(idtfc3->dev, "TOD counter write timeout !!!");301 302	return err;303}304 305static int idtfc3_write_subcounter(struct idtfc3 *idtfc3, u32 counter)306{307	u8 buf[18] = {0};308	int err;309 310	/* sync_counter_value is [31:82] and sub_sync_counter_value is [0:30] */311	put_unaligned_le32(counter & SUB_SYNC_COUNTER_MASK, &buf[0]);312 313	buf[16] = SUB_SYNC_LOAD_ENABLE | SYNC_LOAD_ENABLE;314	buf[17] = SYNC_LOAD_REQ;315 316	err = regmap_bulk_write(idtfc3->regmap, TOD_SYNC_LOAD_VAL_CTRL,317				&buf, sizeof(buf));318	if (err)319		return err;320 321	return idtfc3_tod_update_is_done(idtfc3);322}323 324static int idtfc3_timecounter_update(struct idtfc3 *idtfc3, u32 counter, s64 ns)325{326	int err;327 328	err = idtfc3_write_subcounter(idtfc3, counter);329	if (err)330		return err;331 332	/* Update time counter */333	idtfc3->ns = ns;334	idtfc3->last_counter = counter;335 336	return 0;337}338 339static int idtfc3_timecounter_read(struct idtfc3 *idtfc3)340{341	int now, delta;342 343	now = idtfc3_read_subcounter(idtfc3);344	if (now < 0)345		return now;346 347	/* calculate the delta since the last idtfc3_timecounter_read(): */348	if (now >= idtfc3->last_counter)349		delta = now - idtfc3->last_counter;350	else351		delta = idtfc3->sub_sync_count - idtfc3->last_counter + now;352 353	/* Update time counter */354	idtfc3->ns += delta * idtfc3->ns_per_counter;355	idtfc3->last_counter = now;356 357	return 0;358}359 360static int _idtfc3_gettime(struct idtfc3 *idtfc3, struct timespec64 *ts)361{362	int err;363 364	err = idtfc3_timecounter_read(idtfc3);365	if (err)366		return err;367 368	*ts = ns_to_timespec64(idtfc3->ns);369 370	return 0;371}372 373static int idtfc3_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)374{375	struct idtfc3 *idtfc3 = container_of(ptp, struct idtfc3, caps);376	int err;377 378	mutex_lock(idtfc3->lock);379	err = _idtfc3_gettime(idtfc3, ts);380	mutex_unlock(idtfc3->lock);381 382	return err;383}384 385static int _idtfc3_settime(struct idtfc3 *idtfc3, const struct timespec64 *ts)386{387	s64 offset_ns, now_ns;388	u32 counter, sub_ns;389	int now;390 391	if (timespec64_valid(ts) == false) {392		dev_err(idtfc3->dev, "%s: invalid timespec", __func__);393		return -EINVAL;394	}395 396	now = idtfc3_read_subcounter(idtfc3);397	if (now < 0)398		return now;399 400	offset_ns = (idtfc3->sub_sync_count - now) * idtfc3->ns_per_counter;401	now_ns = timespec64_to_ns(ts);402	(void)ns2counters(idtfc3, offset_ns + now_ns, &sub_ns);403 404	counter = sub_ns / idtfc3->ns_per_counter;405	return idtfc3_timecounter_update(idtfc3, counter, now_ns);406}407 408static int idtfc3_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts)409{410	struct idtfc3 *idtfc3 = container_of(ptp, struct idtfc3, caps);411	int err;412 413	mutex_lock(idtfc3->lock);414	err = _idtfc3_settime(idtfc3, ts);415	mutex_unlock(idtfc3->lock);416 417	return err;418}419 420static int _idtfc3_adjtime(struct idtfc3 *idtfc3, s64 delta)421{422	/*423	 * The TOD counter can be synchronously loaded with any value,424	 * to be loaded on the next Time Sync pulse425	 */426	s64 sync_ns;427	u32 sub_ns;428	u32 counter;429 430	if (idtfc3->ns + delta < 0) {431		dev_err(idtfc3->dev, "%lld ns adj is too large", delta);432		return -EINVAL;433	}434 435	sync_ns = ns2counters(idtfc3, delta + idtfc3->ns_per_sync, &sub_ns);436 437	counter = sub_ns / idtfc3->ns_per_counter;438	return idtfc3_timecounter_update(idtfc3, counter, idtfc3->ns + sync_ns +439									counter * idtfc3->ns_per_counter);440}441 442static int idtfc3_adjtime(struct ptp_clock_info *ptp, s64 delta)443{444	struct idtfc3 *idtfc3 = container_of(ptp, struct idtfc3, caps);445	int err;446 447	mutex_lock(idtfc3->lock);448	err = _idtfc3_adjtime(idtfc3, delta);449	mutex_unlock(idtfc3->lock);450 451	return err;452}453 454static int _idtfc3_adjphase(struct idtfc3 *idtfc3, s32 delta)455{456	u8 buf[8] = {0};457	int err;458	s64 pcw;459 460	err = idtfc3_set_lpf_mode(idtfc3, LPF_WP);461	if (err)462		return err;463 464	/*465	 * Phase Control Word unit is: 10^9 / (TDC_APLL_FREQ * 124)466	 *467	 *       delta * TDC_APLL_FREQ * 124468	 * PCW = ---------------------------469	 *                  10^9470	 *471	 */472	pcw = div_s64((s64)delta * idtfc3->tdc_apll_freq * 124, NSEC_PER_SEC);473 474	put_unaligned_le64(pcw, buf);475 476	return regmap_bulk_write(idtfc3->regmap, LPF_WR_PHASE_CTRL, buf, sizeof(buf));477}478 479static int idtfc3_adjphase(struct ptp_clock_info *ptp, s32 delta)480{481	struct idtfc3 *idtfc3 = container_of(ptp, struct idtfc3, caps);482	int err;483 484	mutex_lock(idtfc3->lock);485	err = _idtfc3_adjphase(idtfc3, delta);486	mutex_unlock(idtfc3->lock);487 488	return err;489}490 491static int _idtfc3_adjfine(struct idtfc3 *idtfc3, long scaled_ppm)492{493	u8 buf[8] = {0};494	int err;495	s64 fcw;496 497	err = idtfc3_set_lpf_mode(idtfc3, LPF_WF);498	if (err)499		return err;500 501	/*502	 * Frequency Control Word unit is: 2^-44 * 10^6 ppm503	 *504	 * adjfreq:505	 *       ppb * 2^44506	 * FCW = ----------507	 *          10^9508	 *509	 * adjfine:510	 *       ppm_16 * 2^28511	 * FCW = -------------512	 *           10^6513	 */514	fcw = scaled_ppm * BIT(28);515	fcw = div_s64(fcw, 1000000);516 517	put_unaligned_le64(fcw, buf);518 519	return regmap_bulk_write(idtfc3->regmap, LPF_WR_FREQ_CTRL, buf, sizeof(buf));520}521 522static int idtfc3_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)523{524	struct idtfc3 *idtfc3 = container_of(ptp, struct idtfc3, caps);525	int err;526 527	mutex_lock(idtfc3->lock);528	err = _idtfc3_adjfine(idtfc3, scaled_ppm);529	mutex_unlock(idtfc3->lock);530 531	return err;532}533 534static int idtfc3_enable(struct ptp_clock_info *ptp,535			 struct ptp_clock_request *rq, int on)536{537	struct idtfc3 *idtfc3 = container_of(ptp, struct idtfc3, caps);538	int err = -EOPNOTSUPP;539 540	mutex_lock(idtfc3->lock);541	switch (rq->type) {542	case PTP_CLK_REQ_PEROUT:543		if (!on)544			err = 0;545		/* Only accept a 1-PPS aligned to the second. */546		else if (rq->perout.start.nsec || rq->perout.period.sec != 1 ||547			 rq->perout.period.nsec)548			err = -ERANGE;549		else550			err = 0;551		break;552	case PTP_CLK_REQ_EXTTS:553		if (on) {554			/* Only accept requests for external phase offset */555			if ((rq->extts.flags & PTP_EXT_OFFSET) != (PTP_EXT_OFFSET))556				err = -EOPNOTSUPP;557			else558				err = idtfc3_enable_tdc(idtfc3, true, CONTINUOUS);559		} else {560			err = idtfc3_enable_tdc(idtfc3, false, MEAS_MODE_INVALID);561		}562		break;563	default:564		break;565	}566	mutex_unlock(idtfc3->lock);567 568	if (err)569		dev_err(idtfc3->dev, "Failed in %s with err %d!", __func__, err);570 571	return err;572}573 574static long idtfc3_aux_work(struct ptp_clock_info *ptp)575{576	struct idtfc3 *idtfc3 = container_of(ptp, struct idtfc3, caps);577	static int tdc_get;578 579	mutex_lock(idtfc3->lock);580	tdc_get %= TDC_GET_PERIOD;581	if ((tdc_get == 0) || (tdc_get == TDC_GET_PERIOD / 2))582		idtfc3_timecounter_read(idtfc3);583	get_tdc_meas_continuous(idtfc3);584	tdc_get++;585	mutex_unlock(idtfc3->lock);586 587	return idtfc3->tc_update_period;588}589 590static const struct ptp_clock_info idtfc3_caps = {591	.owner		= THIS_MODULE,592	.max_adj	= MAX_FFO_PPB,593	.n_per_out	= 1,594	.n_ext_ts	= 1,595	.adjphase	= &idtfc3_adjphase,596	.adjfine	= &idtfc3_adjfine,597	.adjtime	= &idtfc3_adjtime,598	.gettime64	= &idtfc3_gettime,599	.settime64	= &idtfc3_settime,600	.enable		= &idtfc3_enable,601	.do_aux_work	= &idtfc3_aux_work,602};603 604static int idtfc3_hw_calibrate(struct idtfc3 *idtfc3)605{606	int err = 0;607	u8 val;608 609	mdelay(10);610	/*611	 * Toggle TDC_DAC_RECAL_REQ:612	 * (1) set tdc_en to 1613	 * (2) set tdc_dac_recal_req to 0614	 * (3) set tdc_dac_recal_req to 1615	 */616	val = TDC_EN;617	err = regmap_bulk_write(idtfc3->regmap, TDC_CTRL,618				&val, sizeof(val));619	if (err)620		return err;621	val = TDC_EN | TDC_DAC_RECAL_REQ;622	err = regmap_bulk_write(idtfc3->regmap, TDC_CTRL,623				&val, sizeof(val));624	if (err)625		return err;626	mdelay(10);627 628	/*629	 * Toggle APLL_REINIT:630	 * (1) set apll_reinit to 0631	 * (2) set apll_reinit to 1632	 */633	val = 0;634	err = regmap_bulk_write(idtfc3->regmap, SOFT_RESET_CTRL,635				&val, sizeof(val));636	if (err)637		return err;638	val = APLL_REINIT;639	err = regmap_bulk_write(idtfc3->regmap, SOFT_RESET_CTRL,640				&val, sizeof(val));641	if (err)642		return err;643	mdelay(10);644 645	return err;646}647 648static int idtfc3_init_timecounter(struct idtfc3 *idtfc3)649{650	int err;651	u32 period_ms;652 653	period_ms = idtfc3->sub_sync_count * MSEC_PER_SEC /654			idtfc3->hw_param.time_clk_freq;655 656	idtfc3->tc_update_period = msecs_to_jiffies(period_ms / TDC_GET_PERIOD);657	idtfc3->tc_write_timeout = period_ms * USEC_PER_MSEC;658 659	err = idtfc3_timecounter_update(idtfc3, 0, 0);660	if (err)661		return err;662 663	err = idtfc3_timecounter_read(idtfc3);664	if (err)665		return err;666 667	ptp_schedule_worker(idtfc3->ptp_clock, idtfc3->tc_update_period);668 669	return 0;670}671 672static int idtfc3_get_tdc_apll_freq(struct idtfc3 *idtfc3)673{674	int err;675	u8 tdc_fb_div_int;676	u8 tdc_ref_div;677	struct idtfc3_hw_param *param = &idtfc3->hw_param;678 679	err = regmap_bulk_read(idtfc3->regmap, TDC_REF_DIV_CNFG,680				&tdc_ref_div, sizeof(tdc_ref_div));681	if (err)682		return err;683 684	err = regmap_bulk_read(idtfc3->regmap, TDC_FB_DIV_INT_CNFG,685				&tdc_fb_div_int, sizeof(tdc_fb_div_int));686	if (err)687		return err;688 689	tdc_fb_div_int &= TDC_FB_DIV_INT_MASK;690	tdc_ref_div &= TDC_REF_DIV_CONFIG_MASK;691 692	idtfc3->tdc_apll_freq = div_u64(param->xtal_freq * (u64)tdc_fb_div_int,693					1 << tdc_ref_div);694 695	return 0;696}697 698static int idtfc3_get_fod(struct idtfc3 *idtfc3)699{700	int err;701	u8 fod;702 703	err = regmap_bulk_read(idtfc3->regmap, TIME_CLOCK_SRC, &fod, sizeof(fod));704	if (err)705		return err;706 707	switch (fod) {708	case 0:709		idtfc3->fod_n = FOD_0;710		break;711	case 1:712		idtfc3->fod_n = FOD_1;713		break;714	case 2:715		idtfc3->fod_n = FOD_2;716		break;717	default:718		return -EINVAL;719	}720 721	return 0;722}723 724static int idtfc3_get_sync_count(struct idtfc3 *idtfc3)725{726	int err;727	u8 buf[4];728 729	err = regmap_bulk_read(idtfc3->regmap, SUB_SYNC_GEN_CNFG, buf, sizeof(buf));730	if (err)731		return err;732 733	idtfc3->sub_sync_count = (get_unaligned_le32(buf) & SUB_SYNC_COUNTER_MASK) + 1;734	idtfc3->ns_per_counter = NSEC_PER_SEC / idtfc3->hw_param.time_clk_freq;735	idtfc3->ns_per_sync = idtfc3->sub_sync_count * idtfc3->ns_per_counter;736 737	return 0;738}739 740static int idtfc3_setup_hw_param(struct idtfc3 *idtfc3)741{742	int err;743 744	err = idtfc3_get_fod(idtfc3);745	if (err)746		return err;747 748	err = idtfc3_get_sync_count(idtfc3);749	if (err)750		return err;751 752	err = idtfc3_get_time_ref_freq(idtfc3);753	if (err)754		return err;755 756	return idtfc3_get_tdc_apll_freq(idtfc3);757}758 759static int idtfc3_configure_hw(struct idtfc3 *idtfc3)760{761	int err = 0;762 763	err = idtfc3_hw_calibrate(idtfc3);764	if (err)765		return err;766 767	err = idtfc3_enable_lpf(idtfc3, true);768	if (err)769		return err;770 771	err = idtfc3_enable_tdc(idtfc3, false, MEAS_MODE_INVALID);772	if (err)773		return err;774 775	err = idtfc3_get_tdc_offset_sign(idtfc3);776	if (err)777		return err;778 779	return idtfc3_setup_hw_param(idtfc3);780}781 782static int idtfc3_set_overhead(struct idtfc3 *idtfc3)783{784	s64 current_ns = 0;785	s64 lowest_ns = 0;786	int err;787	u8 i;788	ktime_t start;789	ktime_t stop;790	ktime_t diff;791 792	char buf[18] = {0};793 794	for (i = 0; i < 5; i++) {795		start = ktime_get_raw();796 797		err = regmap_bulk_write(idtfc3->regmap, TOD_SYNC_LOAD_VAL_CTRL,798					&buf, sizeof(buf));799		if (err)800			return err;801 802		stop = ktime_get_raw();803 804		diff = ktime_sub(stop, start);805 806		current_ns = ktime_to_ns(diff);807 808		if (i == 0) {809			lowest_ns = current_ns;810		} else {811			if (current_ns < lowest_ns)812				lowest_ns = current_ns;813		}814	}815 816	idtfc3->tod_write_overhead = lowest_ns;817 818	return err;819}820 821static int idtfc3_enable_ptp(struct idtfc3 *idtfc3)822{823	int err;824 825	idtfc3->caps = idtfc3_caps;826	snprintf(idtfc3->caps.name, sizeof(idtfc3->caps.name), "IDT FC3W");827	idtfc3->ptp_clock = ptp_clock_register(&idtfc3->caps, NULL);828 829	if (IS_ERR(idtfc3->ptp_clock)) {830		err = PTR_ERR(idtfc3->ptp_clock);831		idtfc3->ptp_clock = NULL;832		return err;833	}834 835	err = idtfc3_set_overhead(idtfc3);836	if (err)837		return err;838 839	err = idtfc3_init_timecounter(idtfc3);840	if (err)841		return err;842 843	dev_info(idtfc3->dev, "TIME_SYNC_CHANNEL registered as ptp%d",844		 idtfc3->ptp_clock->index);845 846	return 0;847}848 849static int idtfc3_load_firmware(struct idtfc3 *idtfc3)850{851	char fname[128] = FW_FILENAME;852	const struct firmware *fw;853	struct idtfc3_fwrc *rec;854	u16 addr;855	u8 val;856	int err;857	s32 len;858 859	idtfc3_default_hw_param(&idtfc3->hw_param);860 861	if (firmware) /* module parameter */862		snprintf(fname, sizeof(fname), "%s", firmware);863 864	dev_info(idtfc3->dev, "requesting firmware '%s'\n", fname);865 866	err = request_firmware(&fw, fname, idtfc3->dev);867 868	if (err) {869		dev_err(idtfc3->dev,870			"requesting firmware failed with err %d!\n", err);871		return err;872	}873 874	dev_dbg(idtfc3->dev, "firmware size %zu bytes\n", fw->size);875 876	rec = (struct idtfc3_fwrc *)fw->data;877 878	for (len = fw->size; len > 0; len -= sizeof(*rec)) {879		if (rec->reserved) {880			dev_err(idtfc3->dev,881				"bad firmware, reserved field non-zero\n");882			err = -EINVAL;883		} else {884			val = rec->value;885			addr = rec->hiaddr << 8 | rec->loaddr;886 887			rec++;888 889			err = idtfc3_set_hw_param(&idtfc3->hw_param, addr, val);890		}891 892		if (err != -EINVAL) {893			err = 0;894 895			/* Max register */896			if (addr >= 0xE88)897				continue;898 899			err = regmap_bulk_write(idtfc3->regmap, addr,900						&val, sizeof(val));901		}902 903		if (err)904			goto out;905	}906 907	err = idtfc3_configure_hw(idtfc3);908out:909	release_firmware(fw);910	return err;911}912 913static int idtfc3_read_device_id(struct idtfc3 *idtfc3, u16 *device_id)914{915	int err;916	u8 buf[2] = {0};917 918	err = regmap_bulk_read(idtfc3->regmap, DEVICE_ID,919			       &buf, sizeof(buf));920	if (err) {921		dev_err(idtfc3->dev, "%s failed with %d", __func__, err);922		return err;923	}924 925	*device_id = get_unaligned_le16(buf);926 927	return 0;928}929 930static int idtfc3_check_device_compatibility(struct idtfc3 *idtfc3)931{932	int err;933	u16 device_id;934 935	err = idtfc3_read_device_id(idtfc3, &device_id);936	if (err)937		return err;938 939	if ((device_id & DEVICE_ID_MASK) == 0) {940		dev_err(idtfc3->dev, "invalid device");941		return -EINVAL;942	}943 944	return 0;945}946 947static int idtfc3_probe(struct platform_device *pdev)948{949	struct rsmu_ddata *ddata = dev_get_drvdata(pdev->dev.parent);950	struct idtfc3 *idtfc3;951	int err;952 953	idtfc3 = devm_kzalloc(&pdev->dev, sizeof(struct idtfc3), GFP_KERNEL);954 955	if (!idtfc3)956		return -ENOMEM;957 958	idtfc3->dev = &pdev->dev;959	idtfc3->mfd = pdev->dev.parent;960	idtfc3->lock = &ddata->lock;961	idtfc3->regmap = ddata->regmap;962 963	mutex_lock(idtfc3->lock);964 965	err = idtfc3_check_device_compatibility(idtfc3);966	if (err) {967		mutex_unlock(idtfc3->lock);968		return err;969	}970 971	err = idtfc3_load_firmware(idtfc3);972	if (err) {973		if (err == -ENOENT) {974			mutex_unlock(idtfc3->lock);975			return -EPROBE_DEFER;976		}977		dev_warn(idtfc3->dev, "loading firmware failed with %d", err);978	}979 980	err = idtfc3_enable_ptp(idtfc3);981	if (err) {982		dev_err(idtfc3->dev, "idtfc3_enable_ptp failed with %d", err);983		mutex_unlock(idtfc3->lock);984		return err;985	}986 987	mutex_unlock(idtfc3->lock);988 989	if (err) {990		ptp_clock_unregister(idtfc3->ptp_clock);991		return err;992	}993 994	platform_set_drvdata(pdev, idtfc3);995 996	return 0;997}998 999static void idtfc3_remove(struct platform_device *pdev)1000{1001	struct idtfc3 *idtfc3 = platform_get_drvdata(pdev);1002 1003	ptp_clock_unregister(idtfc3->ptp_clock);1004}1005 1006static struct platform_driver idtfc3_driver = {1007	.driver = {1008		.name = "rc38xxx-phc",1009	},1010	.probe = idtfc3_probe,1011	.remove_new = idtfc3_remove,1012};1013 1014module_platform_driver(idtfc3_driver);1015