File Index
Files and directories
Sign in
FILE

bnxt_ptp.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c C
   1/* Broadcom NetXtreme-C/E network driver.
   2 *
   3 * Copyright (c) 2021 Broadcom Inc.
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation.
   8 */
   9#include <linux/kernel.h>
  10#include <linux/errno.h>
  11#include <linux/pci.h>
  12#include <linux/netdevice.h>
  13#include <linux/etherdevice.h>
  14#include <linux/net_tstamp.h>
  15#include <linux/timekeeping.h>
  16#include <linux/ptp_classify.h>
  17#include <linux/clocksource.h>
  18#include <linux/bnxt/hsi.h>
  19#include "bnxt.h"
  20#include "bnxt_hwrm.h"
  21#include "bnxt_ptp.h"
  22
  23static int bnxt_ptp_cfg_settime(struct bnxt *bp, u64 time)
  24{
  25	struct hwrm_func_ptp_cfg_input *req;
  26	int rc;
  27
  28	rc = hwrm_req_init(bp, req, HWRM_FUNC_PTP_CFG);
  29	if (rc)
  30		return rc;
  31
  32	req->enables = cpu_to_le16(FUNC_PTP_CFG_REQ_ENABLES_PTP_SET_TIME);
  33	req->ptp_set_time = cpu_to_le64(time);
  34	return hwrm_req_send(bp, req);
  35}
  36
  37int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id, u16 *hdr_off)
  38{
  39	unsigned int ptp_class;
  40	struct ptp_header *hdr;
  41
  42	ptp_class = ptp_classify_raw(skb);
  43
  44	switch (ptp_class & PTP_CLASS_VMASK) {
  45	case PTP_CLASS_V1:
  46	case PTP_CLASS_V2:
  47		hdr = ptp_parse_header(skb, ptp_class);
  48		if (!hdr)
  49			return -EINVAL;
  50
  51		*hdr_off = (u8 *)hdr - skb->data;
  52		*seq_id	 = ntohs(hdr->sequence_id);
  53		return 0;
  54	default:
  55		return -ERANGE;
  56	}
  57}
  58
  59static int bnxt_ptp_settime(struct ptp_clock_info *ptp_info,
  60			    const struct timespec64 *ts)
  61{
  62	struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
  63						ptp_info);
  64	u64 ns = timespec64_to_ns(ts);
  65	unsigned long flags;
  66
  67	if (BNXT_PTP_USE_RTC(ptp->bp))
  68		return bnxt_ptp_cfg_settime(ptp->bp, ns);
  69
  70	write_seqlock_irqsave(&ptp->ptp_lock, flags);
  71	timecounter_init(&ptp->tc, &ptp->cc, ns);
  72	write_sequnlock_irqrestore(&ptp->ptp_lock, flags);
  73	return 0;
  74}
  75
  76/* Caller holds ptp_lock */
  77static int __bnxt_refclk_read(struct bnxt *bp, struct ptp_system_timestamp *sts,
  78			      u64 *ns)
  79{
  80	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
  81	u32 high_before, high_now, low;
  82
  83	if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
  84		return -EIO;
  85
  86	high_before = readl(bp->bar0 + ptp->refclk_mapped_regs[1]);
  87	ptp_read_system_prets(sts);
  88	low = readl(bp->bar0 + ptp->refclk_mapped_regs[0]);
  89	ptp_read_system_postts(sts);
  90	high_now = readl(bp->bar0 + ptp->refclk_mapped_regs[1]);
  91	if (high_now != high_before) {
  92		ptp_read_system_prets(sts);
  93		low = readl(bp->bar0 + ptp->refclk_mapped_regs[0]);
  94		ptp_read_system_postts(sts);
  95	}
  96	*ns = ((u64)high_now << 32) | low;
  97
  98	return 0;
  99}
 100
 101static int bnxt_refclk_read(struct bnxt *bp, struct ptp_system_timestamp *sts,
 102			    u64 *ns)
 103{
 104	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 105	unsigned long flags;
 106	int rc;
 107
 108	/* We have to serialize reg access and FW reset */
 109	read_seqlock_excl_irqsave(&ptp->ptp_lock, flags);
 110	rc = __bnxt_refclk_read(bp, sts, ns);
 111	read_sequnlock_excl_irqrestore(&ptp->ptp_lock, flags);
 112	return rc;
 113}
 114
 115static int bnxt_refclk_read_low(struct bnxt *bp, struct ptp_system_timestamp *sts,
 116				u32 *low)
 117{
 118	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 119	unsigned long flags;
 120
 121	/* We have to serialize reg access and FW reset */
 122	read_seqlock_excl_irqsave(&ptp->ptp_lock, flags);
 123
 124	if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
 125		read_sequnlock_excl_irqrestore(&ptp->ptp_lock, flags);
 126		return -EIO;
 127	}
 128
 129	ptp_read_system_prets(sts);
 130	*low = readl(bp->bar0 + ptp->refclk_mapped_regs[0]);
 131	ptp_read_system_postts(sts);
 132
 133	read_sequnlock_excl_irqrestore(&ptp->ptp_lock, flags);
 134	return 0;
 135}
 136
 137static void bnxt_ptp_get_current_time(struct bnxt *bp)
 138{
 139	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 140
 141	if (!ptp)
 142		return;
 143	WRITE_ONCE(ptp->old_time, ptp->current_time >> BNXT_HI_TIMER_SHIFT);
 144	bnxt_refclk_read(bp, NULL, &ptp->current_time);
 145}
 146
 147static int bnxt_hwrm_port_ts_query(struct bnxt *bp, u32 flags, u64 *ts,
 148				   u32 txts_tmo, int slot)
 149{
 150	struct hwrm_port_ts_query_output *resp;
 151	struct hwrm_port_ts_query_input *req;
 152	int rc;
 153
 154	rc = hwrm_req_init(bp, req, HWRM_PORT_TS_QUERY);
 155	if (rc)
 156		return rc;
 157
 158	req->flags = cpu_to_le32(flags);
 159	if ((flags & PORT_TS_QUERY_REQ_FLAGS_PATH) ==
 160	    PORT_TS_QUERY_REQ_FLAGS_PATH_TX) {
 161		struct bnxt_ptp_tx_req *txts_req = &bp->ptp_cfg->txts_req[slot];
 162		u32 tmo_us = txts_tmo * 1000;
 163
 164		req->enables = cpu_to_le16(BNXT_PTP_QTS_TX_ENABLES);
 165		req->ptp_seq_id = cpu_to_le32(txts_req->tx_seqid);
 166		req->ptp_hdr_offset = cpu_to_le16(txts_req->tx_hdr_off);
 167		if (!tmo_us)
 168			tmo_us = BNXT_PTP_QTS_TIMEOUT;
 169		tmo_us = min(tmo_us, BNXT_PTP_QTS_MAX_TMO_US);
 170		req->ts_req_timeout = cpu_to_le16(tmo_us);
 171	}
 172	resp = hwrm_req_hold(bp, req);
 173
 174	rc = hwrm_req_send_silent(bp, req);
 175	if (!rc)
 176		*ts = le64_to_cpu(resp->ptp_msg_ts);
 177	hwrm_req_drop(bp, req);
 178	return rc;
 179}
 180
 181static int bnxt_ptp_gettimex(struct ptp_clock_info *ptp_info,
 182			     struct timespec64 *ts,
 183			     struct ptp_system_timestamp *sts)
 184{
 185	struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
 186						ptp_info);
 187	u64 ns, cycles;
 188	u32 low;
 189	int rc;
 190
 191	rc = bnxt_refclk_read_low(ptp->bp, sts, &low);
 192	if (rc)
 193		return rc;
 194
 195	cycles = bnxt_extend_cycles_32b_to_48b(ptp, low);
 196	ns = bnxt_timecounter_cyc2time(ptp, cycles);
 197	*ts = ns_to_timespec64(ns);
 198
 199	return 0;
 200}
 201
 202void bnxt_ptp_update_current_time(struct bnxt *bp)
 203{
 204	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 205
 206	bnxt_refclk_read(ptp->bp, NULL, &ptp->current_time);
 207	WRITE_ONCE(ptp->old_time, ptp->current_time >> BNXT_HI_TIMER_SHIFT);
 208}
 209
 210static int bnxt_ptp_adjphc(struct bnxt_ptp_cfg *ptp, s64 delta)
 211{
 212	struct hwrm_port_mac_cfg_input *req;
 213	int rc;
 214
 215	rc = hwrm_req_init(ptp->bp, req, HWRM_PORT_MAC_CFG);
 216	if (rc)
 217		return rc;
 218
 219	req->enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_PTP_ADJ_PHASE);
 220	req->ptp_adj_phase = cpu_to_le64(delta);
 221
 222	rc = hwrm_req_send(ptp->bp, req);
 223	if (rc) {
 224		netdev_err(ptp->bp->dev, "ptp adjphc failed. rc = %x\n", rc);
 225	} else {
 226		bnxt_ptp_update_current_time(ptp->bp);
 227	}
 228
 229	return rc;
 230}
 231
 232static int bnxt_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
 233{
 234	struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
 235						ptp_info);
 236	unsigned long flags;
 237
 238	if (BNXT_PTP_USE_RTC(ptp->bp))
 239		return bnxt_ptp_adjphc(ptp, delta);
 240
 241	write_seqlock_irqsave(&ptp->ptp_lock, flags);
 242	timecounter_adjtime(&ptp->tc, delta);
 243	write_sequnlock_irqrestore(&ptp->ptp_lock, flags);
 244	return 0;
 245}
 246
 247static int bnxt_ptp_adjfine_rtc(struct bnxt *bp, long scaled_ppm)
 248{
 249	s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
 250	struct hwrm_port_mac_cfg_input *req;
 251	int rc;
 252
 253	rc = hwrm_req_init(bp, req, HWRM_PORT_MAC_CFG);
 254	if (rc)
 255		return rc;
 256
 257	req->ptp_freq_adj_ppb = cpu_to_le32(ppb);
 258	req->enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_PTP_FREQ_ADJ_PPB);
 259	rc = hwrm_req_send(bp, req);
 260	if (rc)
 261		netdev_err(bp->dev,
 262			   "ptp adjfine failed. rc = %d\n", rc);
 263	return rc;
 264}
 265
 266static int bnxt_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm)
 267{
 268	struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
 269						ptp_info);
 270	struct bnxt *bp = ptp->bp;
 271	unsigned long flags;
 272
 273	if (!BNXT_MH(bp))
 274		return bnxt_ptp_adjfine_rtc(bp, scaled_ppm);
 275
 276	write_seqlock_irqsave(&ptp->ptp_lock, flags);
 277	timecounter_read(&ptp->tc);
 278	ptp->cc.mult = adjust_by_scaled_ppm(ptp->cmult, scaled_ppm);
 279	write_sequnlock_irqrestore(&ptp->ptp_lock, flags);
 280	return 0;
 281}
 282
 283void bnxt_ptp_pps_event(struct bnxt *bp, u32 data1, u32 data2)
 284{
 285	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 286	struct ptp_clock_event event;
 287	u64 ns, pps_ts;
 288
 289	pps_ts = EVENT_PPS_TS(data2, data1);
 290	ns = bnxt_timecounter_cyc2time(ptp, pps_ts);
 291
 292	switch (EVENT_DATA2_PPS_EVENT_TYPE(data2)) {
 293	case ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA2_EVENT_TYPE_INTERNAL:
 294		event.pps_times.ts_real = ns_to_timespec64(ns);
 295		event.type = PTP_CLOCK_PPSUSR;
 296		event.index = EVENT_DATA2_PPS_PIN_NUM(data2);
 297		break;
 298	case ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA2_EVENT_TYPE_EXTERNAL:
 299		event.timestamp = ns;
 300		event.type = PTP_CLOCK_EXTTS;
 301		event.index = EVENT_DATA2_PPS_PIN_NUM(data2);
 302		break;
 303	}
 304
 305	ptp_clock_event(bp->ptp_cfg->ptp_clock, &event);
 306}
 307
 308static int bnxt_ptp_cfg_pin(struct bnxt *bp, u8 pin, u8 usage)
 309{
 310	struct hwrm_func_ptp_pin_cfg_input *req;
 311	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 312	u8 state = usage != BNXT_PPS_PIN_NONE;
 313	u8 *pin_state, *pin_usg;
 314	u32 enables;
 315	int rc;
 316
 317	if (!TSIO_PIN_VALID(pin)) {
 318		netdev_err(ptp->bp->dev, "1PPS: Invalid pin. Check pin-function configuration\n");
 319		return -EOPNOTSUPP;
 320	}
 321
 322	rc = hwrm_req_init(ptp->bp, req, HWRM_FUNC_PTP_PIN_CFG);
 323	if (rc)
 324		return rc;
 325
 326	enables = (FUNC_PTP_PIN_CFG_REQ_ENABLES_PIN0_STATE |
 327		   FUNC_PTP_PIN_CFG_REQ_ENABLES_PIN0_USAGE) << (pin * 2);
 328	req->enables = cpu_to_le32(enables);
 329
 330	pin_state = &req->pin0_state;
 331	pin_usg = &req->pin0_usage;
 332
 333	*(pin_state + (pin * 2)) = state;
 334	*(pin_usg + (pin * 2)) = usage;
 335
 336	rc = hwrm_req_send(ptp->bp, req);
 337	if (rc)
 338		return rc;
 339
 340	ptp->pps_info.pins[pin].usage = usage;
 341	ptp->pps_info.pins[pin].state = state;
 342
 343	return 0;
 344}
 345
 346static int bnxt_ptp_cfg_event(struct bnxt *bp, u8 event)
 347{
 348	struct hwrm_func_ptp_cfg_input *req;
 349	int rc;
 350
 351	rc = hwrm_req_init(bp, req, HWRM_FUNC_PTP_CFG);
 352	if (rc)
 353		return rc;
 354
 355	req->enables = cpu_to_le16(FUNC_PTP_CFG_REQ_ENABLES_PTP_PPS_EVENT);
 356	req->ptp_pps_event = event;
 357	return hwrm_req_send(bp, req);
 358}
 359
 360int bnxt_ptp_cfg_tstamp_filters(struct bnxt *bp)
 361{
 362	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 363	struct hwrm_port_mac_cfg_input *req;
 364	int rc;
 365
 366	if (!ptp || !ptp->tstamp_filters)
 367		return -EIO;
 368
 369	rc = hwrm_req_init(bp, req, HWRM_PORT_MAC_CFG);
 370	if (rc)
 371		goto out;
 372
 373	if (!(bp->fw_cap & BNXT_FW_CAP_RX_ALL_PKT_TS) && (ptp->tstamp_filters &
 374	    (PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_ENABLE |
 375	     PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_DISABLE))) {
 376		ptp->tstamp_filters &= ~(PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_ENABLE |
 377					 PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_DISABLE);
 378		netdev_warn(bp->dev, "Unsupported FW for all RX pkts timestamp filter\n");
 379	}
 380
 381	req->flags = cpu_to_le32(ptp->tstamp_filters);
 382	req->enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_RX_TS_CAPTURE_PTP_MSG_TYPE);
 383	req->rx_ts_capture_ptp_msg_type = cpu_to_le16(ptp->rxctl);
 384
 385	rc = hwrm_req_send(bp, req);
 386	if (!rc) {
 387		bp->ptp_all_rx_tstamp = !!(ptp->tstamp_filters &
 388					   PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_ENABLE);
 389		return 0;
 390	}
 391	ptp->tstamp_filters = 0;
 392out:
 393	bp->ptp_all_rx_tstamp = 0;
 394	netdev_warn(bp->dev, "Failed to configure HW packet timestamp filters\n");
 395	return rc;
 396}
 397
 398void bnxt_ptp_reapply_pps(struct bnxt *bp)
 399{
 400	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 401	struct bnxt_pps *pps;
 402	u32 pin = 0;
 403	int rc;
 404
 405	if (!ptp || !(bp->fw_cap & BNXT_FW_CAP_PTP_PPS) ||
 406	    !(ptp->ptp_info.pin_config))
 407		return;
 408	pps = &ptp->pps_info;
 409	for (pin = 0; pin < BNXT_MAX_TSIO_PINS; pin++) {
 410		if (pps->pins[pin].state) {
 411			rc = bnxt_ptp_cfg_pin(bp, pin, pps->pins[pin].usage);
 412			if (!rc && pps->pins[pin].event)
 413				rc = bnxt_ptp_cfg_event(bp,
 414							pps->pins[pin].event);
 415			if (rc)
 416				netdev_err(bp->dev, "1PPS: Failed to configure pin%d\n",
 417					   pin);
 418		}
 419	}
 420}
 421
 422static int bnxt_get_target_cycles(struct bnxt_ptp_cfg *ptp, u64 target_ns,
 423				  u64 *cycles_delta)
 424{
 425	u64 cycles_now;
 426	u64 nsec_now, nsec_delta;
 427	int rc;
 428
 429	rc = bnxt_refclk_read(ptp->bp, NULL, &cycles_now);
 430	if (rc)
 431		return rc;
 432
 433	nsec_now = bnxt_timecounter_cyc2time(ptp, cycles_now);
 434
 435	nsec_delta = target_ns - nsec_now;
 436	*cycles_delta = div64_u64(nsec_delta << ptp->cc.shift, ptp->cc.mult);
 437	return 0;
 438}
 439
 440static int bnxt_ptp_perout_cfg(struct bnxt_ptp_cfg *ptp,
 441			       struct ptp_clock_request *rq)
 442{
 443	struct hwrm_func_ptp_cfg_input *req;
 444	struct bnxt *bp = ptp->bp;
 445	struct timespec64 ts;
 446	u64 target_ns, delta;
 447	u16 enables;
 448	int rc;
 449
 450	ts.tv_sec = rq->perout.start.sec;
 451	ts.tv_nsec = rq->perout.start.nsec;
 452	target_ns = timespec64_to_ns(&ts);
 453
 454	rc = bnxt_get_target_cycles(ptp, target_ns, &delta);
 455	if (rc)
 456		return rc;
 457
 458	rc = hwrm_req_init(bp, req, HWRM_FUNC_PTP_CFG);
 459	if (rc)
 460		return rc;
 461
 462	enables = FUNC_PTP_CFG_REQ_ENABLES_PTP_FREQ_ADJ_EXT_PERIOD |
 463		  FUNC_PTP_CFG_REQ_ENABLES_PTP_FREQ_ADJ_EXT_UP |
 464		  FUNC_PTP_CFG_REQ_ENABLES_PTP_FREQ_ADJ_EXT_PHASE;
 465	req->enables = cpu_to_le16(enables);
 466	req->ptp_pps_event = 0;
 467	req->ptp_freq_adj_dll_source = 0;
 468	req->ptp_freq_adj_dll_phase = 0;
 469	req->ptp_freq_adj_ext_period = cpu_to_le32(NSEC_PER_SEC);
 470	req->ptp_freq_adj_ext_up = 0;
 471	req->ptp_freq_adj_ext_phase_lower = cpu_to_le32(delta);
 472
 473	return hwrm_req_send(bp, req);
 474}
 475
 476static int bnxt_ptp_enable(struct ptp_clock_info *ptp_info,
 477			   struct ptp_clock_request *rq, int on)
 478{
 479	struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
 480						ptp_info);
 481	struct bnxt *bp = ptp->bp;
 482	int pin_id;
 483	int rc;
 484
 485	switch (rq->type) {
 486	case PTP_CLK_REQ_EXTTS:
 487		/* Configure an External PPS IN */
 488		pin_id = ptp_find_pin(ptp->ptp_clock, PTP_PF_EXTTS,
 489				      rq->extts.index);
 490		if (!TSIO_PIN_VALID(pin_id))
 491			return -EOPNOTSUPP;
 492		if (!on)
 493			break;
 494		rc = bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_PPS_IN);
 495		if (rc)
 496			return rc;
 497		rc = bnxt_ptp_cfg_event(bp, BNXT_PPS_EVENT_EXTERNAL);
 498		if (!rc)
 499			ptp->pps_info.pins[pin_id].event = BNXT_PPS_EVENT_EXTERNAL;
 500		return rc;
 501	case PTP_CLK_REQ_PEROUT:
 502		/* Configure a Periodic PPS OUT */
 503		pin_id = ptp_find_pin(ptp->ptp_clock, PTP_PF_PEROUT,
 504				      rq->perout.index);
 505		if (!TSIO_PIN_VALID(pin_id))
 506			return -EOPNOTSUPP;
 507		if (!on)
 508			break;
 509
 510		rc = bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_PPS_OUT);
 511		if (!rc)
 512			rc = bnxt_ptp_perout_cfg(ptp, rq);
 513
 514		return rc;
 515	case PTP_CLK_REQ_PPS:
 516		/* Configure PHC PPS IN */
 517		rc = bnxt_ptp_cfg_pin(bp, 0, BNXT_PPS_PIN_PPS_IN);
 518		if (rc)
 519			return rc;
 520		rc = bnxt_ptp_cfg_event(bp, BNXT_PPS_EVENT_INTERNAL);
 521		if (!rc)
 522			ptp->pps_info.pins[0].event = BNXT_PPS_EVENT_INTERNAL;
 523		return rc;
 524	default:
 525		netdev_err(ptp->bp->dev, "Unrecognized PIN function\n");
 526		return -EOPNOTSUPP;
 527	}
 528
 529	return bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_NONE);
 530}
 531
 532static int bnxt_hwrm_ptp_cfg(struct bnxt *bp)
 533{
 534	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 535	u32 flags = 0;
 536
 537	switch (ptp->rx_filter) {
 538	case HWTSTAMP_FILTER_ALL:
 539		flags = PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_ENABLE;
 540		break;
 541	case HWTSTAMP_FILTER_NONE:
 542		flags = PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_DISABLE;
 543		if (bp->fw_cap & BNXT_FW_CAP_RX_ALL_PKT_TS)
 544			flags |= PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_DISABLE;
 545		break;
 546	case HWTSTAMP_FILTER_PTP_V2_EVENT:
 547	case HWTSTAMP_FILTER_PTP_V2_SYNC:
 548	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
 549		flags = PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_ENABLE;
 550		break;
 551	}
 552
 553	if (ptp->tx_tstamp_en)
 554		flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_ENABLE;
 555	else
 556		flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_DISABLE;
 557
 558	ptp->tstamp_filters = flags;
 559
 560	return bnxt_ptp_cfg_tstamp_filters(bp);
 561}
 562
 563int bnxt_hwtstamp_set(struct net_device *dev,
 564		      struct kernel_hwtstamp_config *stmpconf,
 565		      struct netlink_ext_ack *extack)
 566{
 567	struct bnxt *bp = netdev_priv(dev);
 568	struct bnxt_ptp_cfg *ptp;
 569	u16 old_rxctl;
 570	int old_rx_filter, rc;
 571	u8 old_tx_tstamp_en;
 572
 573	ptp = bp->ptp_cfg;
 574	if (!ptp)
 575		return -EOPNOTSUPP;
 576
 577	if (stmpconf->tx_type != HWTSTAMP_TX_ON &&
 578	    stmpconf->tx_type != HWTSTAMP_TX_OFF)
 579		return -ERANGE;
 580
 581	old_rx_filter = ptp->rx_filter;
 582	old_rxctl = ptp->rxctl;
 583	old_tx_tstamp_en = ptp->tx_tstamp_en;
 584	switch (stmpconf->rx_filter) {
 585	case HWTSTAMP_FILTER_NONE:
 586		ptp->rxctl = 0;
 587		ptp->rx_filter = HWTSTAMP_FILTER_NONE;
 588		break;
 589	case HWTSTAMP_FILTER_ALL:
 590		if (bp->fw_cap & BNXT_FW_CAP_RX_ALL_PKT_TS) {
 591			ptp->rx_filter = HWTSTAMP_FILTER_ALL;
 592			break;
 593		}
 594		return -EOPNOTSUPP;
 595	case HWTSTAMP_FILTER_PTP_V2_EVENT:
 596	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
 597	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
 598		ptp->rxctl = BNXT_PTP_MSG_EVENTS;
 599		ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
 600		break;
 601	case HWTSTAMP_FILTER_PTP_V2_SYNC:
 602	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
 603	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
 604		ptp->rxctl = BNXT_PTP_MSG_SYNC;
 605		ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
 606		break;
 607	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
 608	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
 609	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
 610		ptp->rxctl = BNXT_PTP_MSG_DELAY_REQ;
 611		ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
 612		break;
 613	default:
 614		return -ERANGE;
 615	}
 616
 617	if (stmpconf->tx_type == HWTSTAMP_TX_ON)
 618		ptp->tx_tstamp_en = 1;
 619	else
 620		ptp->tx_tstamp_en = 0;
 621
 622	rc = bnxt_hwrm_ptp_cfg(bp);
 623	if (rc)
 624		goto ts_set_err;
 625
 626	stmpconf->rx_filter = ptp->rx_filter;
 627	return 0;
 628
 629ts_set_err:
 630	ptp->rx_filter = old_rx_filter;
 631	ptp->rxctl = old_rxctl;
 632	ptp->tx_tstamp_en = old_tx_tstamp_en;
 633	return rc;
 634}
 635
 636int bnxt_hwtstamp_get(struct net_device *dev,
 637		      struct kernel_hwtstamp_config *stmpconf)
 638{
 639	struct bnxt *bp = netdev_priv(dev);
 640	struct bnxt_ptp_cfg *ptp;
 641
 642	ptp = bp->ptp_cfg;
 643	if (!ptp)
 644		return -EOPNOTSUPP;
 645
 646	stmpconf->flags = 0;
 647	stmpconf->tx_type = ptp->tx_tstamp_en ? HWTSTAMP_TX_ON
 648					      : HWTSTAMP_TX_OFF;
 649
 650	stmpconf->rx_filter = ptp->rx_filter;
 651	return 0;
 652}
 653
 654static int bnxt_map_regs(struct bnxt *bp, u32 *reg_arr, int count, int reg_win)
 655{
 656	u32 reg_base = *reg_arr & BNXT_GRC_BASE_MASK;
 657	u32 win_off;
 658	int i;
 659
 660	for (i = 0; i < count; i++) {
 661		if ((reg_arr[i] & BNXT_GRC_BASE_MASK) != reg_base)
 662			return -ERANGE;
 663	}
 664	win_off = BNXT_GRCPF_REG_WINDOW_BASE_OUT + (reg_win - 1) * 4;
 665	writel(reg_base, bp->bar0 + win_off);
 666	return 0;
 667}
 668
 669static int bnxt_map_ptp_regs(struct bnxt *bp)
 670{
 671	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 672	u32 *reg_arr;
 673	int rc, i;
 674
 675	reg_arr = ptp->refclk_regs;
 676	if (BNXT_CHIP_P5(bp)) {
 677		rc = bnxt_map_regs(bp, reg_arr, 2, BNXT_PTP_GRC_WIN);
 678		if (rc)
 679			return rc;
 680		for (i = 0; i < 2; i++)
 681			ptp->refclk_mapped_regs[i] = BNXT_PTP_GRC_WIN_BASE +
 682				(ptp->refclk_regs[i] & BNXT_GRC_OFFSET_MASK);
 683		return 0;
 684	}
 685	if (bp->flags & BNXT_FLAG_CHIP_P7) {
 686		for (i = 0; i < 2; i++) {
 687			if (reg_arr[i] & BNXT_GRC_BASE_MASK)
 688				return -EINVAL;
 689			ptp->refclk_mapped_regs[i] = reg_arr[i];
 690		}
 691		return 0;
 692	}
 693	return -ENODEV;
 694}
 695
 696static void bnxt_unmap_ptp_regs(struct bnxt *bp)
 697{
 698	writel(0, bp->bar0 + BNXT_GRCPF_REG_WINDOW_BASE_OUT +
 699		  (BNXT_PTP_GRC_WIN - 1) * 4);
 700}
 701
 702static u64 bnxt_cc_read(struct cyclecounter *cc)
 703{
 704	struct bnxt_ptp_cfg *ptp = container_of(cc, struct bnxt_ptp_cfg, cc);
 705	u64 ns = 0;
 706
 707	__bnxt_refclk_read(ptp->bp, NULL, &ns);
 708	return ns;
 709}
 710
 711static int bnxt_stamp_tx_skb(struct bnxt *bp, int slot)
 712{
 713	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 714	struct skb_shared_hwtstamps timestamp;
 715	struct bnxt_ptp_tx_req *txts_req;
 716	unsigned long now = jiffies;
 717	u64 ts = 0, ns = 0;
 718	u32 tmo = 0;
 719	int rc;
 720
 721	txts_req = &ptp->txts_req[slot];
 722	/* make sure bnxt_get_tx_ts_p5() has updated abs_txts_tmo */
 723	smp_rmb();
 724	if (!time_after_eq(now, txts_req->abs_txts_tmo))
 725		tmo = jiffies_to_msecs(txts_req->abs_txts_tmo - now);
 726	rc = bnxt_hwrm_port_ts_query(bp, PORT_TS_QUERY_REQ_FLAGS_PATH_TX, &ts,
 727				     tmo, slot);
 728	if (!rc) {
 729		memset(&timestamp, 0, sizeof(timestamp));
 730		ns = bnxt_timecounter_cyc2time(ptp, ts);
 731		timestamp.hwtstamp = ns_to_ktime(ns);
 732		skb_tstamp_tx(txts_req->tx_skb, &timestamp);
 733		ptp->stats.ts_pkts++;
 734	} else {
 735		if (!time_after_eq(jiffies, txts_req->abs_txts_tmo))
 736			return -EAGAIN;
 737
 738		ptp->stats.ts_lost++;
 739		netdev_warn_once(bp->dev,
 740				 "TS query for TX timer failed rc = %x\n", rc);
 741	}
 742
 743	dev_kfree_skb_any(txts_req->tx_skb);
 744	txts_req->tx_skb = NULL;
 745
 746	return 0;
 747}
 748
 749static long bnxt_ptp_ts_aux_work(struct ptp_clock_info *ptp_info)
 750{
 751	struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
 752						ptp_info);
 753	unsigned long now = jiffies;
 754	struct bnxt *bp = ptp->bp;
 755	u16 cons = ptp->txts_cons;
 756	unsigned long flags;
 757	u32 num_requests;
 758	int rc = 0;
 759
 760	num_requests = BNXT_MAX_TX_TS - READ_ONCE(ptp->tx_avail);
 761	while (num_requests--) {
 762		if (IS_ERR(ptp->txts_req[cons].tx_skb))
 763			goto next_slot;
 764		if (!ptp->txts_req[cons].tx_skb)
 765			break;
 766		rc = bnxt_stamp_tx_skb(bp, cons);
 767		if (rc == -EAGAIN)
 768			break;
 769next_slot:
 770		BNXT_PTP_INC_TX_AVAIL(ptp);
 771		cons = NEXT_TXTS(cons);
 772	}
 773	ptp->txts_cons = cons;
 774
 775	if (!time_after_eq(now, ptp->next_period)) {
 776		if (rc == -EAGAIN)
 777			return 0;
 778		return ptp->next_period - now;
 779	}
 780
 781	bnxt_ptp_get_current_time(bp);
 782	ptp->next_period = now + HZ;
 783	if (time_after_eq(now, ptp->next_overflow_check)) {
 784		write_seqlock_irqsave(&ptp->ptp_lock, flags);
 785		timecounter_read(&ptp->tc);
 786		write_sequnlock_irqrestore(&ptp->ptp_lock, flags);
 787		ptp->next_overflow_check = now + BNXT_PHC_OVERFLOW_PERIOD;
 788	}
 789	if (rc == -EAGAIN)
 790		return 0;
 791	return HZ;
 792}
 793
 794void bnxt_ptp_free_txts_skbs(struct bnxt_ptp_cfg *ptp)
 795{
 796	struct bnxt_ptp_tx_req *txts_req;
 797	u16 cons = ptp->txts_cons;
 798
 799	/* make sure ptp aux worker finished with
 800	 * possible BNXT_STATE_OPEN set
 801	 */
 802	ptp_cancel_worker_sync(ptp->ptp_clock);
 803
 804	ptp->tx_avail = BNXT_MAX_TX_TS;
 805	while (cons != ptp->txts_prod) {
 806		txts_req = &ptp->txts_req[cons];
 807		if (!IS_ERR_OR_NULL(txts_req->tx_skb))
 808			dev_kfree_skb_any(txts_req->tx_skb);
 809		cons = NEXT_TXTS(cons);
 810	}
 811	ptp->txts_cons = cons;
 812	ptp_schedule_worker(ptp->ptp_clock, 0);
 813}
 814
 815int bnxt_ptp_get_txts_prod(struct bnxt_ptp_cfg *ptp, u16 *prod)
 816{
 817	spin_lock_bh(&ptp->ptp_tx_lock);
 818	if (ptp->tx_avail) {
 819		*prod = ptp->txts_prod;
 820		ptp->txts_prod = NEXT_TXTS(*prod);
 821		ptp->tx_avail--;
 822		spin_unlock_bh(&ptp->ptp_tx_lock);
 823		return 0;
 824	}
 825	spin_unlock_bh(&ptp->ptp_tx_lock);
 826	atomic64_inc(&ptp->stats.ts_err);
 827	return -ENOSPC;
 828}
 829
 830void bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb, u16 prod)
 831{
 832	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 833	struct bnxt_ptp_tx_req *txts_req;
 834
 835	txts_req = &ptp->txts_req[prod];
 836	txts_req->abs_txts_tmo = jiffies + msecs_to_jiffies(ptp->txts_tmo);
 837	/* make sure abs_txts_tmo is written first */
 838	smp_wmb();
 839	txts_req->tx_skb = skb;
 840	ptp_schedule_worker(ptp->ptp_clock, 0);
 841}
 842
 843int bnxt_get_rx_ts_p5(struct bnxt *bp, u64 *ts, u32 pkt_ts)
 844{
 845	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 846
 847	if (!ptp)
 848		return -ENODEV;
 849
 850	*ts = bnxt_extend_cycles_32b_to_48b(ptp, pkt_ts);
 851
 852	return 0;
 853}
 854
 855void bnxt_tx_ts_cmp(struct bnxt *bp, struct bnxt_napi *bnapi,
 856		    struct tx_ts_cmp *tscmp)
 857{
 858	struct skb_shared_hwtstamps timestamp = {};
 859	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 860	u32 opaque = tscmp->tx_ts_cmp_opaque;
 861	struct bnxt_tx_ring_info *txr;
 862	struct bnxt_sw_tx_bd *tx_buf;
 863	u64 ts, ns;
 864	u16 cons;
 865
 866	txr = bnapi->tx_ring[TX_OPAQUE_RING(opaque)];
 867	ts = BNXT_GET_TX_TS_48B_NS(tscmp);
 868	cons = TX_OPAQUE_IDX(opaque);
 869	tx_buf = &txr->tx_buf_ring[RING_TX(bp, cons)];
 870	if (tx_buf->is_ts_pkt) {
 871		if (BNXT_TX_TS_ERR(tscmp)) {
 872			netdev_err(bp->dev,
 873				   "timestamp completion error 0x%x 0x%x\n",
 874				   le32_to_cpu(tscmp->tx_ts_cmp_flags_type),
 875				   le32_to_cpu(tscmp->tx_ts_cmp_errors_v));
 876		} else {
 877			ns = bnxt_timecounter_cyc2time(ptp, ts);
 878			timestamp.hwtstamp = ns_to_ktime(ns);
 879			skb_tstamp_tx(tx_buf->skb, &timestamp);
 880		}
 881		tx_buf->is_ts_pkt = 0;
 882	}
 883}
 884
 885static const struct ptp_clock_info bnxt_ptp_caps = {
 886	.owner		= THIS_MODULE,
 887	.name		= "bnxt clock",
 888	.max_adj	= BNXT_MAX_PHC_DRIFT,
 889	.n_alarm	= 0,
 890	.n_ext_ts	= 0,
 891	.n_per_out	= 0,
 892	.n_pins		= 0,
 893	.pps		= 0,
 894	.adjfine	= bnxt_ptp_adjfine,
 895	.adjtime	= bnxt_ptp_adjtime,
 896	.do_aux_work	= bnxt_ptp_ts_aux_work,
 897	.gettimex64	= bnxt_ptp_gettimex,
 898	.settime64	= bnxt_ptp_settime,
 899	.enable		= bnxt_ptp_enable,
 900};
 901
 902static int bnxt_ptp_verify(struct ptp_clock_info *ptp_info, unsigned int pin,
 903			   enum ptp_pin_function func, unsigned int chan)
 904{
 905	struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
 906						ptp_info);
 907	/* Allow only PPS pin function configuration */
 908	if (ptp->pps_info.pins[pin].usage <= BNXT_PPS_PIN_PPS_OUT &&
 909	    func != PTP_PF_PHYSYNC)
 910		return 0;
 911	else
 912		return -EOPNOTSUPP;
 913}
 914
 915static int bnxt_ptp_pps_init(struct bnxt *bp)
 916{
 917	struct hwrm_func_ptp_pin_qcfg_output *resp;
 918	struct hwrm_func_ptp_pin_qcfg_input *req;
 919	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 920	struct ptp_clock_info *ptp_info;
 921	struct bnxt_pps *pps_info;
 922	u8 *pin_usg;
 923	u32 i, rc;
 924
 925	/* Query current/default PIN CFG */
 926	rc = hwrm_req_init(bp, req, HWRM_FUNC_PTP_PIN_QCFG);
 927	if (rc)
 928		return rc;
 929
 930	resp = hwrm_req_hold(bp, req);
 931	rc = hwrm_req_send(bp, req);
 932	if (rc || !resp->num_pins) {
 933		hwrm_req_drop(bp, req);
 934		return -EOPNOTSUPP;
 935	}
 936
 937	ptp_info = &ptp->ptp_info;
 938	pps_info = &ptp->pps_info;
 939	pps_info->num_pins = resp->num_pins;
 940	ptp_info->n_pins = pps_info->num_pins;
 941	ptp_info->pin_config = kcalloc(ptp_info->n_pins,
 942				       sizeof(*ptp_info->pin_config),
 943				       GFP_KERNEL);
 944	if (!ptp_info->pin_config) {
 945		hwrm_req_drop(bp, req);
 946		return -ENOMEM;
 947	}
 948
 949	/* Report the TSIO capability to kernel */
 950	pin_usg = &resp->pin0_usage;
 951	for (i = 0; i < pps_info->num_pins; i++, pin_usg++) {
 952		snprintf(ptp_info->pin_config[i].name,
 953			 sizeof(ptp_info->pin_config[i].name), "bnxt_pps%d", i);
 954		ptp_info->pin_config[i].index = i;
 955		if (*pin_usg == BNXT_PPS_PIN_PPS_IN)
 956			ptp_info->pin_config[i].func = PTP_PF_EXTTS;
 957		else if (*pin_usg == BNXT_PPS_PIN_PPS_OUT)
 958			ptp_info->pin_config[i].func = PTP_PF_PEROUT;
 959		else
 960			ptp_info->pin_config[i].func = PTP_PF_NONE;
 961
 962		pps_info->pins[i].usage = *pin_usg;
 963	}
 964	hwrm_req_drop(bp, req);
 965
 966	/* Only 1 each of ext_ts and per_out pins is available in HW */
 967	ptp_info->n_ext_ts = 1;
 968	ptp_info->n_per_out = 1;
 969	ptp_info->pps = 1;
 970	ptp_info->verify = bnxt_ptp_verify;
 971	ptp_info->supported_extts_flags = PTP_RISING_EDGE | PTP_STRICT_FLAGS;
 972	ptp_info->supported_perout_flags = PTP_PEROUT_DUTY_CYCLE;
 973
 974	return 0;
 975}
 976
 977static bool bnxt_pps_config_ok(struct bnxt *bp)
 978{
 979	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 980
 981	return !(bp->fw_cap & BNXT_FW_CAP_PTP_PPS) == !ptp->ptp_info.pin_config;
 982}
 983
 984static void bnxt_ptp_timecounter_init(struct bnxt *bp, bool init_tc)
 985{
 986	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 987	unsigned long flags;
 988
 989	if (!ptp->ptp_clock) {
 990		memset(&ptp->cc, 0, sizeof(ptp->cc));
 991		ptp->cc.read = bnxt_cc_read;
 992		ptp->cc.mask = CYCLECOUNTER_MASK(48);
 993		if (BNXT_MH(bp)) {
 994			/* Use timecounter based non-real time mode */
 995			ptp->cc.shift = BNXT_CYCLES_SHIFT;
 996			ptp->cc.mult = clocksource_khz2mult(BNXT_DEVCLK_FREQ, ptp->cc.shift);
 997			ptp->cmult = ptp->cc.mult;
 998		} else {
 999			ptp->cc.shift = 0;
1000			ptp->cc.mult = 1;
1001		}
1002		ptp->next_overflow_check = jiffies + BNXT_PHC_OVERFLOW_PERIOD;
1003	}
1004	if (init_tc) {
1005		write_seqlock_irqsave(&ptp->ptp_lock, flags);
1006		timecounter_init(&ptp->tc, &ptp->cc, ktime_to_ns(ktime_get_real()));
1007		write_sequnlock_irqrestore(&ptp->ptp_lock, flags);
1008	}
1009}
1010
1011/* Caller holds ptp_lock */
1012void bnxt_ptp_rtc_timecounter_init(struct bnxt_ptp_cfg *ptp, u64 ns)
1013{
1014	timecounter_init(&ptp->tc, &ptp->cc, ns);
1015	/* For RTC, cycle_last must be in sync with the timecounter value. */
1016	ptp->tc.cycle_last = ns & ptp->cc.mask;
1017}
1018
1019int bnxt_ptp_init_rtc(struct bnxt *bp, bool phc_cfg)
1020{
1021	struct timespec64 tsp;
1022	unsigned long flags;
1023	u64 ns;
1024	int rc;
1025
1026	if (!bp->ptp_cfg || !BNXT_PTP_USE_RTC(bp))
1027		return -ENODEV;
1028
1029	if (!phc_cfg) {
1030		ktime_get_real_ts64(&tsp);
1031		ns = timespec64_to_ns(&tsp);
1032		rc = bnxt_ptp_cfg_settime(bp, ns);
1033		if (rc)
1034			return rc;
1035	} else {
1036		rc = bnxt_hwrm_port_ts_query(bp, PORT_TS_QUERY_REQ_FLAGS_CURRENT_TIME,
1037					     &ns, 0, 0);
1038		if (rc)
1039			return rc;
1040	}
1041	write_seqlock_irqsave(&bp->ptp_cfg->ptp_lock, flags);
1042	bnxt_ptp_rtc_timecounter_init(bp->ptp_cfg, ns);
1043	write_sequnlock_irqrestore(&bp->ptp_cfg->ptp_lock, flags);
1044
1045	return 0;
1046}
1047
1048static void bnxt_ptp_free(struct bnxt *bp)
1049{
1050	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
1051
1052	if (ptp->ptp_clock) {
1053		ptp_clock_unregister(ptp->ptp_clock);
1054		ptp->ptp_clock = NULL;
1055	}
1056	kfree(ptp->ptp_info.pin_config);
1057	ptp->ptp_info.pin_config = NULL;
1058}
1059
1060int bnxt_ptp_init(struct bnxt *bp)
1061{
1062	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
1063	int rc;
1064
1065	if (!ptp)
1066		return 0;
1067
1068	rc = bnxt_map_ptp_regs(bp);
1069	if (rc)
1070		return rc;
1071
1072	if (ptp->ptp_clock && bnxt_pps_config_ok(bp))
1073		return 0;
1074
1075	bnxt_ptp_free(bp);
1076
1077	WRITE_ONCE(ptp->tx_avail, BNXT_MAX_TX_TS);
1078	seqlock_init(&ptp->ptp_lock);
1079	spin_lock_init(&ptp->ptp_tx_lock);
1080
1081	if (BNXT_PTP_USE_RTC(bp)) {
1082		bnxt_ptp_timecounter_init(bp, false);
1083		rc = bnxt_ptp_init_rtc(bp, ptp->rtc_configured);
1084		if (rc)
1085			goto out;
1086	} else {
1087		bnxt_ptp_timecounter_init(bp, true);
1088		bnxt_ptp_adjfine_rtc(bp, 0);
1089	}
1090	bnxt_hwrm_func_drv_rgtr(bp, NULL, 0, true);
1091
1092	ptp->ptp_info = bnxt_ptp_caps;
1093	if ((bp->fw_cap & BNXT_FW_CAP_PTP_PPS)) {
1094		if (bnxt_ptp_pps_init(bp))
1095			netdev_err(bp->dev, "1pps not initialized, continuing without 1pps support\n");
1096	}
1097	ptp->ptp_clock = ptp_clock_register(&ptp->ptp_info, &bp->pdev->dev);
1098	if (IS_ERR(ptp->ptp_clock)) {
1099		int err = PTR_ERR(ptp->ptp_clock);
1100
1101		ptp->ptp_clock = NULL;
1102		rc = err;
1103		goto out;
1104	}
1105
1106	ptp->stats.ts_pkts = 0;
1107	ptp->stats.ts_lost = 0;
1108	atomic64_set(&ptp->stats.ts_err, 0);
1109
1110	if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
1111		bnxt_refclk_read(bp, NULL, &ptp->current_time);
1112		WRITE_ONCE(ptp->old_time, ptp->current_time >> BNXT_HI_TIMER_SHIFT);
1113		ptp_schedule_worker(ptp->ptp_clock, 0);
1114	}
1115	ptp->txts_tmo = BNXT_PTP_DFLT_TX_TMO;
1116	return 0;
1117
1118out:
1119	bnxt_ptp_free(bp);
1120	bnxt_unmap_ptp_regs(bp);
1121	return rc;
1122}
1123
1124void bnxt_ptp_clear(struct bnxt *bp)
1125{
1126	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
1127
1128	if (!ptp)
1129		return;
1130
1131	if (ptp->ptp_clock)
1132		ptp_clock_unregister(ptp->ptp_clock);
1133
1134	ptp->ptp_clock = NULL;
1135	kfree(ptp->ptp_info.pin_config);
1136	ptp->ptp_info.pin_config = NULL;
1137
1138	bnxt_unmap_ptp_regs(bp);
1139}
~/ Read-only file preview.