brintos

brintos / linux-shallow public Read only

0
0
Text · 17.8 KiB · bcc96ee Raw
678 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Marvell PTP driver3 *4 * Copyright (C) 2020 Marvell.5 *6 */7 8#include <linux/bitfield.h>9#include <linux/device.h>10#include <linux/module.h>11#include <linux/pci.h>12#include <linux/hrtimer.h>13#include <linux/ktime.h>14 15#include "mbox.h"16#include "ptp.h"17#include "rvu.h"18 19#define DRV_NAME				"Marvell PTP Driver"20 21#define PCI_DEVID_OCTEONTX2_PTP			0xA00C22#define PCI_SUBSYS_DEVID_OCTX2_98xx_PTP		0xB10023#define PCI_SUBSYS_DEVID_OCTX2_96XX_PTP		0xB20024#define PCI_SUBSYS_DEVID_OCTX2_95XX_PTP		0xB30025#define PCI_SUBSYS_DEVID_OCTX2_95XXN_PTP	0xB40026#define PCI_SUBSYS_DEVID_OCTX2_95MM_PTP		0xB50027#define PCI_SUBSYS_DEVID_OCTX2_95XXO_PTP	0xB60028#define PCI_DEVID_OCTEONTX2_RST			0xA08529#define PCI_DEVID_CN10K_PTP			0xA09E30#define PCI_SUBSYS_DEVID_CN10K_A_PTP		0xB90031#define PCI_SUBSYS_DEVID_CNF10K_A_PTP		0xBA0032#define PCI_SUBSYS_DEVID_CNF10K_B_PTP		0xBC0033 34#define PCI_PTP_BAR_NO				035 36#define PTP_CLOCK_CFG				0xF00ULL37#define PTP_CLOCK_CFG_PTP_EN			BIT_ULL(0)38#define PTP_CLOCK_CFG_EXT_CLK_EN		BIT_ULL(1)39#define PTP_CLOCK_CFG_EXT_CLK_IN_MASK		GENMASK_ULL(7, 2)40#define PTP_CLOCK_CFG_TSTMP_EDGE		BIT_ULL(9)41#define PTP_CLOCK_CFG_TSTMP_EN			BIT_ULL(8)42#define PTP_CLOCK_CFG_TSTMP_IN_MASK		GENMASK_ULL(15, 10)43#define PTP_CLOCK_CFG_ATOMIC_OP_MASK		GENMASK_ULL(28, 26)44#define PTP_CLOCK_CFG_PPS_EN			BIT_ULL(30)45#define PTP_CLOCK_CFG_PPS_INV			BIT_ULL(31)46 47#define PTP_PPS_HI_INCR				0xF60ULL48#define PTP_PPS_LO_INCR				0xF68ULL49#define PTP_PPS_THRESH_LO			0xF50ULL50#define PTP_PPS_THRESH_HI			0xF58ULL51 52#define PTP_CLOCK_LO				0xF08ULL53#define PTP_CLOCK_HI				0xF10ULL54#define PTP_CLOCK_COMP				0xF18ULL55#define PTP_TIMESTAMP				0xF20ULL56#define PTP_CLOCK_SEC				0xFD0ULL57#define PTP_SEC_ROLLOVER			0xFD8ULL58/* Atomic update related CSRs */59#define PTP_FRNS_TIMESTAMP			0xFE0ULL60#define PTP_NXT_ROLLOVER_SET			0xFE8ULL61#define PTP_CURR_ROLLOVER_SET			0xFF0ULL62#define PTP_NANO_TIMESTAMP			0xFF8ULL63#define PTP_SEC_TIMESTAMP			0x1000ULL64 65#define CYCLE_MULT				100066 67#define is_rev_A0(ptp) (((ptp)->pdev->revision & 0x0F) == 0x0)68#define is_rev_A1(ptp) (((ptp)->pdev->revision & 0x0F) == 0x1)69 70/* PTP atomic update operation type */71enum atomic_opcode {72	ATOMIC_SET = 1,73	ATOMIC_INC = 3,74	ATOMIC_DEC = 475};76 77static struct ptp *first_ptp_block;78static const struct pci_device_id ptp_id_table[];79 80static bool is_ptp_dev_cnf10ka(struct ptp *ptp)81{82	return ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP;83}84 85static bool is_ptp_dev_cn10ka(struct ptp *ptp)86{87	return ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP;88}89 90static bool cn10k_ptp_errata(struct ptp *ptp)91{92	if ((is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) &&93	    (is_rev_A0(ptp) || is_rev_A1(ptp)))94		return true;95 96	return false;97}98 99static bool is_tstmp_atomic_update_supported(struct rvu *rvu)100{101	struct ptp *ptp = rvu->ptp;102 103	if (is_rvu_otx2(rvu))104		return false;105 106	/* On older silicon variants of CN10K, atomic update feature107	 * is not available.108	 */109	if ((is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) &&110	    (is_rev_A0(ptp) || is_rev_A1(ptp)))111		return false;112 113	return true;114}115 116static enum hrtimer_restart ptp_reset_thresh(struct hrtimer *hrtimer)117{118	struct ptp *ptp = container_of(hrtimer, struct ptp, hrtimer);119	ktime_t curr_ts = ktime_get();120	ktime_t delta_ns, period_ns;121	u64 ptp_clock_hi;122 123	/* calculate the elapsed time since last restart */124	delta_ns = ktime_to_ns(ktime_sub(curr_ts, ptp->last_ts));125 126	/* if the ptp clock value has crossed 0.5 seconds,127	 * its too late to update pps threshold value, so128	 * update threshold after 1 second.129	 */130	ptp_clock_hi = readq(ptp->reg_base + PTP_CLOCK_HI);131	if (ptp_clock_hi > 500000000) {132		period_ns = ktime_set(0, (NSEC_PER_SEC + 100 - ptp_clock_hi));133	} else {134		writeq(500000000, ptp->reg_base + PTP_PPS_THRESH_HI);135		period_ns = ktime_set(0, (NSEC_PER_SEC + 100 - delta_ns));136	}137 138	hrtimer_forward_now(hrtimer, period_ns);139	ptp->last_ts = curr_ts;140 141	return HRTIMER_RESTART;142}143 144static void ptp_hrtimer_start(struct ptp *ptp, ktime_t start_ns)145{146	ktime_t period_ns;147 148	period_ns = ktime_set(0, (NSEC_PER_SEC + 100 - start_ns));149	hrtimer_start(&ptp->hrtimer, period_ns, HRTIMER_MODE_REL);150	ptp->last_ts = ktime_get();151}152 153static u64 read_ptp_tstmp_sec_nsec(struct ptp *ptp)154{155	u64 sec, sec1, nsec;156	unsigned long flags;157 158	spin_lock_irqsave(&ptp->ptp_lock, flags);159	sec = readq(ptp->reg_base + PTP_CLOCK_SEC) & 0xFFFFFFFFUL;160	nsec = readq(ptp->reg_base + PTP_CLOCK_HI);161	sec1 = readq(ptp->reg_base + PTP_CLOCK_SEC) & 0xFFFFFFFFUL;162	/* check nsec rollover */163	if (sec1 > sec) {164		nsec = readq(ptp->reg_base + PTP_CLOCK_HI);165		sec = sec1;166	}167	spin_unlock_irqrestore(&ptp->ptp_lock, flags);168 169	return sec * NSEC_PER_SEC + nsec;170}171 172static u64 read_ptp_tstmp_nsec(struct ptp *ptp)173{174	return readq(ptp->reg_base + PTP_CLOCK_HI);175}176 177static u64 ptp_calc_adjusted_comp(u64 ptp_clock_freq)178{179	u64 comp, adj = 0, cycles_per_sec, ns_drift = 0;180	u32 ptp_clock_nsec, cycle_time;181	int cycle;182 183	/* Errata:184	 * Issue #1: At the time of 1 sec rollover of the nano-second counter,185	 * the nano-second counter is set to 0. However, it should be set to186	 * (existing counter_value - 10^9).187	 *188	 * Issue #2: The nano-second counter rolls over at 0x3B9A_C9FF.189	 * It should roll over at 0x3B9A_CA00.190	 */191 192	/* calculate ptp_clock_comp value */193	comp = ((u64)1000000000ULL << 32) / ptp_clock_freq;194	/* use CYCLE_MULT to avoid accuracy loss due to integer arithmetic */195	cycle_time = NSEC_PER_SEC * CYCLE_MULT / ptp_clock_freq;196	/* cycles per sec */197	cycles_per_sec = ptp_clock_freq;198 199	/* check whether ptp nanosecond counter rolls over early */200	cycle = cycles_per_sec - 1;201	ptp_clock_nsec = (cycle * comp) >> 32;202	while (ptp_clock_nsec < NSEC_PER_SEC) {203		if (ptp_clock_nsec == 0x3B9AC9FF)204			goto calc_adj_comp;205		cycle++;206		ptp_clock_nsec = (cycle * comp) >> 32;207	}208	/* compute nanoseconds lost per second when nsec counter rolls over */209	ns_drift = ptp_clock_nsec - NSEC_PER_SEC;210	/* calculate ptp_clock_comp adjustment */211	if (ns_drift > 0) {212		adj = comp * ns_drift;213		adj = adj / 1000000000ULL;214	}215	/* speed up the ptp clock to account for nanoseconds lost */216	comp += adj;217	return comp;218 219calc_adj_comp:220	/* slow down the ptp clock to not rollover early */221	adj = comp * cycle_time;222	adj = adj / 1000000000ULL;223	adj = adj / CYCLE_MULT;224	comp -= adj;225 226	return comp;227}228 229struct ptp *ptp_get(void)230{231	struct ptp *ptp = first_ptp_block;232 233	/* Check PTP block is present in hardware */234	if (!pci_dev_present(ptp_id_table))235		return ERR_PTR(-ENODEV);236	/* Check driver is bound to PTP block */237	if (!ptp)238		ptp = ERR_PTR(-EPROBE_DEFER);239	else if (!IS_ERR(ptp))240		pci_dev_get(ptp->pdev);241 242	return ptp;243}244 245void ptp_put(struct ptp *ptp)246{247	if (!ptp)248		return;249 250	pci_dev_put(ptp->pdev);251}252 253static void ptp_atomic_update(struct ptp *ptp, u64 timestamp)254{255	u64 regval, curr_rollover_set, nxt_rollover_set;256 257	/* First setup NSECs and SECs */258	writeq(timestamp, ptp->reg_base + PTP_NANO_TIMESTAMP);259	writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP);260	writeq(timestamp / NSEC_PER_SEC,261	       ptp->reg_base + PTP_SEC_TIMESTAMP);262 263	nxt_rollover_set = roundup(timestamp, NSEC_PER_SEC);264	curr_rollover_set = nxt_rollover_set - NSEC_PER_SEC;265	writeq(nxt_rollover_set, ptp->reg_base + PTP_NXT_ROLLOVER_SET);266	writeq(curr_rollover_set, ptp->reg_base + PTP_CURR_ROLLOVER_SET);267 268	/* Now, initiate atomic update */269	regval = readq(ptp->reg_base + PTP_CLOCK_CFG);270	regval &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK;271	regval |= (ATOMIC_SET << 26);272	writeq(regval, ptp->reg_base + PTP_CLOCK_CFG);273}274 275static void ptp_atomic_adjtime(struct ptp *ptp, s64 delta)276{277	bool neg_adj = false, atomic_inc_dec = false;278	u64 regval, ptp_clock_hi;279 280	if (delta < 0) {281		delta = -delta;282		neg_adj = true;283	}284 285	/* use atomic inc/dec when delta < 1 second */286	if (delta < NSEC_PER_SEC)287		atomic_inc_dec = true;288 289	if (!atomic_inc_dec) {290		ptp_clock_hi = readq(ptp->reg_base + PTP_CLOCK_HI);291		if (neg_adj) {292			if (ptp_clock_hi > delta)293				ptp_clock_hi -= delta;294			else295				ptp_clock_hi = delta - ptp_clock_hi;296		} else {297			ptp_clock_hi += delta;298		}299		ptp_atomic_update(ptp, ptp_clock_hi);300	} else {301		writeq(delta, ptp->reg_base + PTP_NANO_TIMESTAMP);302		writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP);303 304		/* initiate atomic inc/dec */305		regval = readq(ptp->reg_base + PTP_CLOCK_CFG);306		regval &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK;307		regval |= neg_adj ? (ATOMIC_DEC << 26) : (ATOMIC_INC << 26);308		writeq(regval, ptp->reg_base + PTP_CLOCK_CFG);309	}310}311 312static int ptp_adjfine(struct ptp *ptp, long scaled_ppm)313{314	bool neg_adj = false;315	u32 freq, freq_adj;316	u64 comp, adj;317	s64 ppb;318 319	if (scaled_ppm < 0) {320		neg_adj = true;321		scaled_ppm = -scaled_ppm;322	}323 324	/* The hardware adds the clock compensation value to the PTP clock325	 * on every coprocessor clock cycle. Typical convention is that it326	 * represent number of nanosecond betwen each cycle. In this327	 * convention compensation value is in 64 bit fixed-point328	 * representation where upper 32 bits are number of nanoseconds329	 * and lower is fractions of nanosecond.330	 * The scaled_ppm represent the ratio in "parts per million" by which331	 * the compensation value should be corrected.332	 * To calculate new compenstation value we use 64bit fixed point333	 * arithmetic on following formula334	 * comp = tbase + tbase * scaled_ppm / (1M * 2^16)335	 * where tbase is the basic compensation value calculated336	 * initialy in the probe function.337	 */338	/* convert scaled_ppm to ppb */339	ppb = 1 + scaled_ppm;340	ppb *= 125;341	ppb >>= 13;342 343	if (cn10k_ptp_errata(ptp)) {344		/* calculate the new frequency based on ppb */345		freq_adj = (ptp->clock_rate * ppb) / 1000000000ULL;346		freq = neg_adj ? ptp->clock_rate + freq_adj : ptp->clock_rate - freq_adj;347		comp = ptp_calc_adjusted_comp(freq);348	} else {349		comp = ((u64)1000000000ull << 32) / ptp->clock_rate;350		adj = comp * ppb;351		adj = div_u64(adj, 1000000000ull);352		comp = neg_adj ? comp - adj : comp + adj;353	}354	writeq(comp, ptp->reg_base + PTP_CLOCK_COMP);355 356	return 0;357}358 359static int ptp_get_clock(struct ptp *ptp, u64 *clk)360{361	/* Return the current PTP clock */362	*clk = ptp->read_ptp_tstmp(ptp);363 364	return 0;365}366 367void ptp_start(struct rvu *rvu, u64 sclk, u32 ext_clk_freq, u32 extts)368{369	struct ptp *ptp = rvu->ptp;370	struct pci_dev *pdev;371	u64 clock_comp;372	u64 clock_cfg;373 374	if (!ptp)375		return;376 377	pdev = ptp->pdev;378 379	if (!sclk) {380		dev_err(&pdev->dev, "PTP input clock cannot be zero\n");381		return;382	}383 384	/* sclk is in MHz */385	ptp->clock_rate = sclk * 1000000;386 387	/* Program the seconds rollover value to 1 second */388	if (is_tstmp_atomic_update_supported(rvu)) {389		writeq(0, ptp->reg_base + PTP_NANO_TIMESTAMP);390		writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP);391		writeq(0, ptp->reg_base + PTP_SEC_TIMESTAMP);392		writeq(0, ptp->reg_base + PTP_CURR_ROLLOVER_SET);393		writeq(0x3b9aca00, ptp->reg_base + PTP_NXT_ROLLOVER_SET);394		writeq(0x3b9aca00, ptp->reg_base + PTP_SEC_ROLLOVER);395	}396 397	/* Enable PTP clock */398	clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);399 400	if (ext_clk_freq) {401		ptp->clock_rate = ext_clk_freq;402		/* Set GPIO as PTP clock source */403		clock_cfg &= ~PTP_CLOCK_CFG_EXT_CLK_IN_MASK;404		clock_cfg |= PTP_CLOCK_CFG_EXT_CLK_EN;405	}406 407	if (extts) {408		clock_cfg |= PTP_CLOCK_CFG_TSTMP_EDGE;409		/* Set GPIO as timestamping source */410		clock_cfg &= ~PTP_CLOCK_CFG_TSTMP_IN_MASK;411		clock_cfg |= PTP_CLOCK_CFG_TSTMP_EN;412	}413 414	clock_cfg |= PTP_CLOCK_CFG_PTP_EN;415	writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);416	clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);417	clock_cfg &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK;418	clock_cfg |= (ATOMIC_SET << 26);419	writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);420 421	if (cn10k_ptp_errata(ptp))422		clock_comp = ptp_calc_adjusted_comp(ptp->clock_rate);423	else424		clock_comp = ((u64)1000000000ull << 32) / ptp->clock_rate;425 426	/* Initial compensation value to start the nanosecs counter */427	writeq(clock_comp, ptp->reg_base + PTP_CLOCK_COMP);428}429 430static int ptp_get_tstmp(struct ptp *ptp, u64 *clk)431{432	u64 timestamp;433 434	if (is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) {435		timestamp = readq(ptp->reg_base + PTP_TIMESTAMP);436		*clk = (timestamp >> 32) * NSEC_PER_SEC + (timestamp & 0xFFFFFFFF);437	} else {438		*clk = readq(ptp->reg_base + PTP_TIMESTAMP);439	}440 441	return 0;442}443 444static int ptp_set_thresh(struct ptp *ptp, u64 thresh)445{446	if (!cn10k_ptp_errata(ptp))447		writeq(thresh, ptp->reg_base + PTP_PPS_THRESH_HI);448 449	return 0;450}451 452static int ptp_config_hrtimer(struct ptp *ptp, int on)453{454	u64 ptp_clock_hi;455 456	if (on) {457		ptp_clock_hi = readq(ptp->reg_base + PTP_CLOCK_HI);458		ptp_hrtimer_start(ptp, (ktime_t)ptp_clock_hi);459	} else {460		if (hrtimer_active(&ptp->hrtimer))461			hrtimer_cancel(&ptp->hrtimer);462	}463 464	return 0;465}466 467static int ptp_pps_on(struct ptp *ptp, int on, u64 period)468{469	u64 clock_cfg;470 471	clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);472	if (on) {473		if (cn10k_ptp_errata(ptp) && period != NSEC_PER_SEC) {474			dev_err(&ptp->pdev->dev, "Supports max period value as 1 second\n");475			return -EINVAL;476		}477 478		if (period > (8 * NSEC_PER_SEC)) {479			dev_err(&ptp->pdev->dev, "Supports max period as 8 seconds\n");480			return -EINVAL;481		}482 483		clock_cfg |= PTP_CLOCK_CFG_PPS_EN | PTP_CLOCK_CFG_PPS_INV;484		writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);485 486		writeq(0, ptp->reg_base + PTP_PPS_THRESH_HI);487		writeq(0, ptp->reg_base + PTP_PPS_THRESH_LO);488 489		/* Configure high/low phase time */490		period = period / 2;491		writeq(((u64)period << 32), ptp->reg_base + PTP_PPS_HI_INCR);492		writeq(((u64)period << 32), ptp->reg_base + PTP_PPS_LO_INCR);493	} else {494		clock_cfg &= ~(PTP_CLOCK_CFG_PPS_EN | PTP_CLOCK_CFG_PPS_INV);495		writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);496	}497 498	if (on && cn10k_ptp_errata(ptp)) {499		/* The ptp_clock_hi rollsover to zero once clock cycle before it500		 * reaches one second boundary. so, program the pps_lo_incr in501		 * such a way that the pps threshold value comparison at one502		 * second boundary will succeed and pps edge changes. After each503		 * one second boundary, the hrtimer handler will be invoked and504		 * reprograms the pps threshold value.505		 */506		ptp->clock_period = NSEC_PER_SEC / ptp->clock_rate;507		writeq((0x1dcd6500ULL - ptp->clock_period) << 32,508		       ptp->reg_base + PTP_PPS_LO_INCR);509	}510 511	if (cn10k_ptp_errata(ptp))512		ptp_config_hrtimer(ptp, on);513 514	return 0;515}516 517static int ptp_probe(struct pci_dev *pdev,518		     const struct pci_device_id *ent)519{520	struct ptp *ptp;521	int err;522 523	ptp = kzalloc(sizeof(*ptp), GFP_KERNEL);524	if (!ptp) {525		err = -ENOMEM;526		goto error;527	}528 529	ptp->pdev = pdev;530 531	err = pcim_enable_device(pdev);532	if (err)533		goto error_free;534 535	err = pcim_iomap_regions(pdev, 1 << PCI_PTP_BAR_NO, pci_name(pdev));536	if (err)537		goto error_free;538 539	ptp->reg_base = pcim_iomap_table(pdev)[PCI_PTP_BAR_NO];540 541	pci_set_drvdata(pdev, ptp);542	if (!first_ptp_block)543		first_ptp_block = ptp;544 545	spin_lock_init(&ptp->ptp_lock);546	if (cn10k_ptp_errata(ptp)) {547		ptp->read_ptp_tstmp = &read_ptp_tstmp_sec_nsec;548		hrtimer_init(&ptp->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);549		ptp->hrtimer.function = ptp_reset_thresh;550	} else {551		ptp->read_ptp_tstmp = &read_ptp_tstmp_nsec;552	}553 554	return 0;555 556error_free:557	kfree(ptp);558 559error:560	/* For `ptp_get()` we need to differentiate between the case561	 * when the core has not tried to probe this device and the case when562	 * the probe failed.  In the later case we keep the error in563	 * `dev->driver_data`.564	 */565	pci_set_drvdata(pdev, ERR_PTR(err));566	if (!first_ptp_block)567		first_ptp_block = ERR_PTR(err);568 569	return err;570}571 572static void ptp_remove(struct pci_dev *pdev)573{574	struct ptp *ptp = pci_get_drvdata(pdev);575	u64 clock_cfg;576 577	if (IS_ERR_OR_NULL(ptp))578		return;579 580	if (cn10k_ptp_errata(ptp) && hrtimer_active(&ptp->hrtimer))581		hrtimer_cancel(&ptp->hrtimer);582 583	/* Disable PTP clock */584	clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);585	clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;586	writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);587	kfree(ptp);588}589 590static const struct pci_device_id ptp_id_table[] = {591	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,592			 PCI_VENDOR_ID_CAVIUM,593			 PCI_SUBSYS_DEVID_OCTX2_98xx_PTP) },594	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,595			 PCI_VENDOR_ID_CAVIUM,596			 PCI_SUBSYS_DEVID_OCTX2_96XX_PTP) },597	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,598			 PCI_VENDOR_ID_CAVIUM,599			 PCI_SUBSYS_DEVID_OCTX2_95XX_PTP) },600	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,601			 PCI_VENDOR_ID_CAVIUM,602			 PCI_SUBSYS_DEVID_OCTX2_95XXN_PTP) },603	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,604			 PCI_VENDOR_ID_CAVIUM,605			 PCI_SUBSYS_DEVID_OCTX2_95MM_PTP) },606	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,607			 PCI_VENDOR_ID_CAVIUM,608			 PCI_SUBSYS_DEVID_OCTX2_95XXO_PTP) },609	{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_PTP) },610	{ 0, }611};612 613struct pci_driver ptp_driver = {614	.name = DRV_NAME,615	.id_table = ptp_id_table,616	.probe = ptp_probe,617	.remove = ptp_remove,618};619 620int rvu_mbox_handler_ptp_op(struct rvu *rvu, struct ptp_req *req,621			    struct ptp_rsp *rsp)622{623	int err = 0;624 625	/* This function is the PTP mailbox handler invoked when626	 * called by AF consumers/netdev drivers via mailbox mechanism.627	 * It is used by netdev driver to get the PTP clock and to set628	 * frequency adjustments. Since mailbox can be called without629	 * notion of whether the driver is bound to ptp device below630	 * validation is needed as first step.631	 */632	if (!rvu->ptp)633		return -ENODEV;634 635	switch (req->op) {636	case PTP_OP_ADJFINE:637		err = ptp_adjfine(rvu->ptp, req->scaled_ppm);638		break;639	case PTP_OP_GET_CLOCK:640		err = ptp_get_clock(rvu->ptp, &rsp->clk);641		break;642	case PTP_OP_GET_TSTMP:643		err = ptp_get_tstmp(rvu->ptp, &rsp->clk);644		break;645	case PTP_OP_SET_THRESH:646		err = ptp_set_thresh(rvu->ptp, req->thresh);647		break;648	case PTP_OP_PPS_ON:649		err = ptp_pps_on(rvu->ptp, req->pps_on, req->period);650		break;651	case PTP_OP_ADJTIME:652		ptp_atomic_adjtime(rvu->ptp, req->delta);653		break;654	case PTP_OP_SET_CLOCK:655		ptp_atomic_update(rvu->ptp, (u64)req->clk);656		break;657	default:658		err = -EINVAL;659		break;660	}661 662	return err;663}664 665int rvu_mbox_handler_ptp_get_cap(struct rvu *rvu, struct msg_req *req,666				 struct ptp_get_cap_rsp *rsp)667{668	if (!rvu->ptp)669		return -ENODEV;670 671	if (is_tstmp_atomic_update_supported(rvu))672		rsp->cap |= PTP_CAP_HW_ATOMIC_UPDATE;673	else674		rsp->cap &= ~BIT_ULL_MASK(0);675 676	return 0;677}678