162306a36Sopenharmony_ci/* Broadcom NetXtreme-C/E network driver. 262306a36Sopenharmony_ci * 362306a36Sopenharmony_ci * Copyright (c) 2021 Broadcom Inc. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 662306a36Sopenharmony_ci * it under the terms of the GNU General Public License as published by 762306a36Sopenharmony_ci * the Free Software Foundation. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/errno.h> 1162306a36Sopenharmony_ci#include <linux/pci.h> 1262306a36Sopenharmony_ci#include <linux/netdevice.h> 1362306a36Sopenharmony_ci#include <linux/etherdevice.h> 1462306a36Sopenharmony_ci#include <linux/net_tstamp.h> 1562306a36Sopenharmony_ci#include <linux/timekeeping.h> 1662306a36Sopenharmony_ci#include <linux/ptp_classify.h> 1762306a36Sopenharmony_ci#include <linux/clocksource.h> 1862306a36Sopenharmony_ci#include "bnxt_hsi.h" 1962306a36Sopenharmony_ci#include "bnxt.h" 2062306a36Sopenharmony_ci#include "bnxt_hwrm.h" 2162306a36Sopenharmony_ci#include "bnxt_ptp.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic int bnxt_ptp_cfg_settime(struct bnxt *bp, u64 time) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci struct hwrm_func_ptp_cfg_input *req; 2662306a36Sopenharmony_ci int rc; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci rc = hwrm_req_init(bp, req, HWRM_FUNC_PTP_CFG); 2962306a36Sopenharmony_ci if (rc) 3062306a36Sopenharmony_ci return rc; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci req->enables = cpu_to_le16(FUNC_PTP_CFG_REQ_ENABLES_PTP_SET_TIME); 3362306a36Sopenharmony_ci req->ptp_set_time = cpu_to_le64(time); 3462306a36Sopenharmony_ci return hwrm_req_send(bp, req); 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciint bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id, u16 *hdr_off) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci unsigned int ptp_class; 4062306a36Sopenharmony_ci struct ptp_header *hdr; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci ptp_class = ptp_classify_raw(skb); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci switch (ptp_class & PTP_CLASS_VMASK) { 4562306a36Sopenharmony_ci case PTP_CLASS_V1: 4662306a36Sopenharmony_ci case PTP_CLASS_V2: 4762306a36Sopenharmony_ci hdr = ptp_parse_header(skb, ptp_class); 4862306a36Sopenharmony_ci if (!hdr) 4962306a36Sopenharmony_ci return -EINVAL; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci *hdr_off = (u8 *)hdr - skb->data; 5262306a36Sopenharmony_ci *seq_id = ntohs(hdr->sequence_id); 5362306a36Sopenharmony_ci return 0; 5462306a36Sopenharmony_ci default: 5562306a36Sopenharmony_ci return -ERANGE; 5662306a36Sopenharmony_ci } 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistatic int bnxt_ptp_settime(struct ptp_clock_info *ptp_info, 6062306a36Sopenharmony_ci const struct timespec64 *ts) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg, 6362306a36Sopenharmony_ci ptp_info); 6462306a36Sopenharmony_ci u64 ns = timespec64_to_ns(ts); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci if (BNXT_PTP_USE_RTC(ptp->bp)) 6762306a36Sopenharmony_ci return bnxt_ptp_cfg_settime(ptp->bp, ns); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci spin_lock_bh(&ptp->ptp_lock); 7062306a36Sopenharmony_ci timecounter_init(&ptp->tc, &ptp->cc, ns); 7162306a36Sopenharmony_ci spin_unlock_bh(&ptp->ptp_lock); 7262306a36Sopenharmony_ci return 0; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/* Caller holds ptp_lock */ 7662306a36Sopenharmony_cistatic int bnxt_refclk_read(struct bnxt *bp, struct ptp_system_timestamp *sts, 7762306a36Sopenharmony_ci u64 *ns) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 8062306a36Sopenharmony_ci u32 high_before, high_now, low; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) 8362306a36Sopenharmony_ci return -EIO; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci high_before = readl(bp->bar0 + ptp->refclk_mapped_regs[1]); 8662306a36Sopenharmony_ci ptp_read_system_prets(sts); 8762306a36Sopenharmony_ci low = readl(bp->bar0 + ptp->refclk_mapped_regs[0]); 8862306a36Sopenharmony_ci ptp_read_system_postts(sts); 8962306a36Sopenharmony_ci high_now = readl(bp->bar0 + ptp->refclk_mapped_regs[1]); 9062306a36Sopenharmony_ci if (high_now != high_before) { 9162306a36Sopenharmony_ci ptp_read_system_prets(sts); 9262306a36Sopenharmony_ci low = readl(bp->bar0 + ptp->refclk_mapped_regs[0]); 9362306a36Sopenharmony_ci ptp_read_system_postts(sts); 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci *ns = ((u64)high_now << 32) | low; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci return 0; 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic void bnxt_ptp_get_current_time(struct bnxt *bp) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if (!ptp) 10562306a36Sopenharmony_ci return; 10662306a36Sopenharmony_ci spin_lock_bh(&ptp->ptp_lock); 10762306a36Sopenharmony_ci WRITE_ONCE(ptp->old_time, ptp->current_time); 10862306a36Sopenharmony_ci bnxt_refclk_read(bp, NULL, &ptp->current_time); 10962306a36Sopenharmony_ci spin_unlock_bh(&ptp->ptp_lock); 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic int bnxt_hwrm_port_ts_query(struct bnxt *bp, u32 flags, u64 *ts) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct hwrm_port_ts_query_output *resp; 11562306a36Sopenharmony_ci struct hwrm_port_ts_query_input *req; 11662306a36Sopenharmony_ci int rc; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci rc = hwrm_req_init(bp, req, HWRM_PORT_TS_QUERY); 11962306a36Sopenharmony_ci if (rc) 12062306a36Sopenharmony_ci return rc; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci req->flags = cpu_to_le32(flags); 12362306a36Sopenharmony_ci if ((flags & PORT_TS_QUERY_REQ_FLAGS_PATH) == 12462306a36Sopenharmony_ci PORT_TS_QUERY_REQ_FLAGS_PATH_TX) { 12562306a36Sopenharmony_ci req->enables = cpu_to_le16(BNXT_PTP_QTS_TX_ENABLES); 12662306a36Sopenharmony_ci req->ptp_seq_id = cpu_to_le32(bp->ptp_cfg->tx_seqid); 12762306a36Sopenharmony_ci req->ptp_hdr_offset = cpu_to_le16(bp->ptp_cfg->tx_hdr_off); 12862306a36Sopenharmony_ci req->ts_req_timeout = cpu_to_le16(BNXT_PTP_QTS_TIMEOUT); 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci resp = hwrm_req_hold(bp, req); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci rc = hwrm_req_send(bp, req); 13362306a36Sopenharmony_ci if (!rc) 13462306a36Sopenharmony_ci *ts = le64_to_cpu(resp->ptp_msg_ts); 13562306a36Sopenharmony_ci hwrm_req_drop(bp, req); 13662306a36Sopenharmony_ci return rc; 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic int bnxt_ptp_gettimex(struct ptp_clock_info *ptp_info, 14062306a36Sopenharmony_ci struct timespec64 *ts, 14162306a36Sopenharmony_ci struct ptp_system_timestamp *sts) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg, 14462306a36Sopenharmony_ci ptp_info); 14562306a36Sopenharmony_ci u64 ns, cycles; 14662306a36Sopenharmony_ci int rc; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci spin_lock_bh(&ptp->ptp_lock); 14962306a36Sopenharmony_ci rc = bnxt_refclk_read(ptp->bp, sts, &cycles); 15062306a36Sopenharmony_ci if (rc) { 15162306a36Sopenharmony_ci spin_unlock_bh(&ptp->ptp_lock); 15262306a36Sopenharmony_ci return rc; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci ns = timecounter_cyc2time(&ptp->tc, cycles); 15562306a36Sopenharmony_ci spin_unlock_bh(&ptp->ptp_lock); 15662306a36Sopenharmony_ci *ts = ns_to_timespec64(ns); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci return 0; 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci/* Caller holds ptp_lock */ 16262306a36Sopenharmony_civoid bnxt_ptp_update_current_time(struct bnxt *bp) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci bnxt_refclk_read(ptp->bp, NULL, &ptp->current_time); 16762306a36Sopenharmony_ci WRITE_ONCE(ptp->old_time, ptp->current_time); 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic int bnxt_ptp_adjphc(struct bnxt_ptp_cfg *ptp, s64 delta) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci struct hwrm_port_mac_cfg_input *req; 17362306a36Sopenharmony_ci int rc; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci rc = hwrm_req_init(ptp->bp, req, HWRM_PORT_MAC_CFG); 17662306a36Sopenharmony_ci if (rc) 17762306a36Sopenharmony_ci return rc; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci req->enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_PTP_ADJ_PHASE); 18062306a36Sopenharmony_ci req->ptp_adj_phase = cpu_to_le64(delta); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci rc = hwrm_req_send(ptp->bp, req); 18362306a36Sopenharmony_ci if (rc) { 18462306a36Sopenharmony_ci netdev_err(ptp->bp->dev, "ptp adjphc failed. rc = %x\n", rc); 18562306a36Sopenharmony_ci } else { 18662306a36Sopenharmony_ci spin_lock_bh(&ptp->ptp_lock); 18762306a36Sopenharmony_ci bnxt_ptp_update_current_time(ptp->bp); 18862306a36Sopenharmony_ci spin_unlock_bh(&ptp->ptp_lock); 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return rc; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistatic int bnxt_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg, 19762306a36Sopenharmony_ci ptp_info); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci if (BNXT_PTP_USE_RTC(ptp->bp)) 20062306a36Sopenharmony_ci return bnxt_ptp_adjphc(ptp, delta); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci spin_lock_bh(&ptp->ptp_lock); 20362306a36Sopenharmony_ci timecounter_adjtime(&ptp->tc, delta); 20462306a36Sopenharmony_ci spin_unlock_bh(&ptp->ptp_lock); 20562306a36Sopenharmony_ci return 0; 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic int bnxt_ptp_adjfine_rtc(struct bnxt *bp, long scaled_ppm) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci s32 ppb = scaled_ppm_to_ppb(scaled_ppm); 21162306a36Sopenharmony_ci struct hwrm_port_mac_cfg_input *req; 21262306a36Sopenharmony_ci int rc; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci rc = hwrm_req_init(bp, req, HWRM_PORT_MAC_CFG); 21562306a36Sopenharmony_ci if (rc) 21662306a36Sopenharmony_ci return rc; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci req->ptp_freq_adj_ppb = cpu_to_le32(ppb); 21962306a36Sopenharmony_ci req->enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_PTP_FREQ_ADJ_PPB); 22062306a36Sopenharmony_ci rc = hwrm_req_send(bp, req); 22162306a36Sopenharmony_ci if (rc) 22262306a36Sopenharmony_ci netdev_err(bp->dev, 22362306a36Sopenharmony_ci "ptp adjfine failed. rc = %d\n", rc); 22462306a36Sopenharmony_ci return rc; 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic int bnxt_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg, 23062306a36Sopenharmony_ci ptp_info); 23162306a36Sopenharmony_ci struct bnxt *bp = ptp->bp; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci if (!BNXT_MH(bp)) 23462306a36Sopenharmony_ci return bnxt_ptp_adjfine_rtc(bp, scaled_ppm); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci spin_lock_bh(&ptp->ptp_lock); 23762306a36Sopenharmony_ci timecounter_read(&ptp->tc); 23862306a36Sopenharmony_ci ptp->cc.mult = adjust_by_scaled_ppm(ptp->cmult, scaled_ppm); 23962306a36Sopenharmony_ci spin_unlock_bh(&ptp->ptp_lock); 24062306a36Sopenharmony_ci return 0; 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_civoid bnxt_ptp_pps_event(struct bnxt *bp, u32 data1, u32 data2) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 24662306a36Sopenharmony_ci struct ptp_clock_event event; 24762306a36Sopenharmony_ci u64 ns, pps_ts; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci pps_ts = EVENT_PPS_TS(data2, data1); 25062306a36Sopenharmony_ci spin_lock_bh(&ptp->ptp_lock); 25162306a36Sopenharmony_ci ns = timecounter_cyc2time(&ptp->tc, pps_ts); 25262306a36Sopenharmony_ci spin_unlock_bh(&ptp->ptp_lock); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci switch (EVENT_DATA2_PPS_EVENT_TYPE(data2)) { 25562306a36Sopenharmony_ci case ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA2_EVENT_TYPE_INTERNAL: 25662306a36Sopenharmony_ci event.pps_times.ts_real = ns_to_timespec64(ns); 25762306a36Sopenharmony_ci event.type = PTP_CLOCK_PPSUSR; 25862306a36Sopenharmony_ci event.index = EVENT_DATA2_PPS_PIN_NUM(data2); 25962306a36Sopenharmony_ci break; 26062306a36Sopenharmony_ci case ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA2_EVENT_TYPE_EXTERNAL: 26162306a36Sopenharmony_ci event.timestamp = ns; 26262306a36Sopenharmony_ci event.type = PTP_CLOCK_EXTTS; 26362306a36Sopenharmony_ci event.index = EVENT_DATA2_PPS_PIN_NUM(data2); 26462306a36Sopenharmony_ci break; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci ptp_clock_event(bp->ptp_cfg->ptp_clock, &event); 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic int bnxt_ptp_cfg_pin(struct bnxt *bp, u8 pin, u8 usage) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci struct hwrm_func_ptp_pin_cfg_input *req; 27362306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 27462306a36Sopenharmony_ci u8 state = usage != BNXT_PPS_PIN_NONE; 27562306a36Sopenharmony_ci u8 *pin_state, *pin_usg; 27662306a36Sopenharmony_ci u32 enables; 27762306a36Sopenharmony_ci int rc; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci if (!TSIO_PIN_VALID(pin)) { 28062306a36Sopenharmony_ci netdev_err(ptp->bp->dev, "1PPS: Invalid pin. Check pin-function configuration\n"); 28162306a36Sopenharmony_ci return -EOPNOTSUPP; 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci rc = hwrm_req_init(ptp->bp, req, HWRM_FUNC_PTP_PIN_CFG); 28562306a36Sopenharmony_ci if (rc) 28662306a36Sopenharmony_ci return rc; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci enables = (FUNC_PTP_PIN_CFG_REQ_ENABLES_PIN0_STATE | 28962306a36Sopenharmony_ci FUNC_PTP_PIN_CFG_REQ_ENABLES_PIN0_USAGE) << (pin * 2); 29062306a36Sopenharmony_ci req->enables = cpu_to_le32(enables); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci pin_state = &req->pin0_state; 29362306a36Sopenharmony_ci pin_usg = &req->pin0_usage; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci *(pin_state + (pin * 2)) = state; 29662306a36Sopenharmony_ci *(pin_usg + (pin * 2)) = usage; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci rc = hwrm_req_send(ptp->bp, req); 29962306a36Sopenharmony_ci if (rc) 30062306a36Sopenharmony_ci return rc; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci ptp->pps_info.pins[pin].usage = usage; 30362306a36Sopenharmony_ci ptp->pps_info.pins[pin].state = state; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci return 0; 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic int bnxt_ptp_cfg_event(struct bnxt *bp, u8 event) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci struct hwrm_func_ptp_cfg_input *req; 31162306a36Sopenharmony_ci int rc; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci rc = hwrm_req_init(bp, req, HWRM_FUNC_PTP_CFG); 31462306a36Sopenharmony_ci if (rc) 31562306a36Sopenharmony_ci return rc; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci req->enables = cpu_to_le16(FUNC_PTP_CFG_REQ_ENABLES_PTP_PPS_EVENT); 31862306a36Sopenharmony_ci req->ptp_pps_event = event; 31962306a36Sopenharmony_ci return hwrm_req_send(bp, req); 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_civoid bnxt_ptp_cfg_tstamp_filters(struct bnxt *bp) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 32562306a36Sopenharmony_ci struct hwrm_port_mac_cfg_input *req; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci if (!ptp || !ptp->tstamp_filters) 32862306a36Sopenharmony_ci return; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci if (hwrm_req_init(bp, req, HWRM_PORT_MAC_CFG)) 33162306a36Sopenharmony_ci goto out; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci if (!(bp->fw_cap & BNXT_FW_CAP_RX_ALL_PKT_TS) && (ptp->tstamp_filters & 33462306a36Sopenharmony_ci (PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_ENABLE | 33562306a36Sopenharmony_ci PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_DISABLE))) { 33662306a36Sopenharmony_ci ptp->tstamp_filters &= ~(PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_ENABLE | 33762306a36Sopenharmony_ci PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_DISABLE); 33862306a36Sopenharmony_ci netdev_warn(bp->dev, "Unsupported FW for all RX pkts timestamp filter\n"); 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci req->flags = cpu_to_le32(ptp->tstamp_filters); 34262306a36Sopenharmony_ci req->enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_RX_TS_CAPTURE_PTP_MSG_TYPE); 34362306a36Sopenharmony_ci req->rx_ts_capture_ptp_msg_type = cpu_to_le16(ptp->rxctl); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci if (!hwrm_req_send(bp, req)) { 34662306a36Sopenharmony_ci bp->ptp_all_rx_tstamp = !!(ptp->tstamp_filters & 34762306a36Sopenharmony_ci PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_ENABLE); 34862306a36Sopenharmony_ci return; 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci ptp->tstamp_filters = 0; 35162306a36Sopenharmony_ciout: 35262306a36Sopenharmony_ci bp->ptp_all_rx_tstamp = 0; 35362306a36Sopenharmony_ci netdev_warn(bp->dev, "Failed to configure HW packet timestamp filters\n"); 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_civoid bnxt_ptp_reapply_pps(struct bnxt *bp) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 35962306a36Sopenharmony_ci struct bnxt_pps *pps; 36062306a36Sopenharmony_ci u32 pin = 0; 36162306a36Sopenharmony_ci int rc; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci if (!ptp || !(bp->fw_cap & BNXT_FW_CAP_PTP_PPS) || 36462306a36Sopenharmony_ci !(ptp->ptp_info.pin_config)) 36562306a36Sopenharmony_ci return; 36662306a36Sopenharmony_ci pps = &ptp->pps_info; 36762306a36Sopenharmony_ci for (pin = 0; pin < BNXT_MAX_TSIO_PINS; pin++) { 36862306a36Sopenharmony_ci if (pps->pins[pin].state) { 36962306a36Sopenharmony_ci rc = bnxt_ptp_cfg_pin(bp, pin, pps->pins[pin].usage); 37062306a36Sopenharmony_ci if (!rc && pps->pins[pin].event) 37162306a36Sopenharmony_ci rc = bnxt_ptp_cfg_event(bp, 37262306a36Sopenharmony_ci pps->pins[pin].event); 37362306a36Sopenharmony_ci if (rc) 37462306a36Sopenharmony_ci netdev_err(bp->dev, "1PPS: Failed to configure pin%d\n", 37562306a36Sopenharmony_ci pin); 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci} 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_cistatic int bnxt_get_target_cycles(struct bnxt_ptp_cfg *ptp, u64 target_ns, 38162306a36Sopenharmony_ci u64 *cycles_delta) 38262306a36Sopenharmony_ci{ 38362306a36Sopenharmony_ci u64 cycles_now; 38462306a36Sopenharmony_ci u64 nsec_now, nsec_delta; 38562306a36Sopenharmony_ci int rc; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci spin_lock_bh(&ptp->ptp_lock); 38862306a36Sopenharmony_ci rc = bnxt_refclk_read(ptp->bp, NULL, &cycles_now); 38962306a36Sopenharmony_ci if (rc) { 39062306a36Sopenharmony_ci spin_unlock_bh(&ptp->ptp_lock); 39162306a36Sopenharmony_ci return rc; 39262306a36Sopenharmony_ci } 39362306a36Sopenharmony_ci nsec_now = timecounter_cyc2time(&ptp->tc, cycles_now); 39462306a36Sopenharmony_ci spin_unlock_bh(&ptp->ptp_lock); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci nsec_delta = target_ns - nsec_now; 39762306a36Sopenharmony_ci *cycles_delta = div64_u64(nsec_delta << ptp->cc.shift, ptp->cc.mult); 39862306a36Sopenharmony_ci return 0; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cistatic int bnxt_ptp_perout_cfg(struct bnxt_ptp_cfg *ptp, 40262306a36Sopenharmony_ci struct ptp_clock_request *rq) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci struct hwrm_func_ptp_cfg_input *req; 40562306a36Sopenharmony_ci struct bnxt *bp = ptp->bp; 40662306a36Sopenharmony_ci struct timespec64 ts; 40762306a36Sopenharmony_ci u64 target_ns, delta; 40862306a36Sopenharmony_ci u16 enables; 40962306a36Sopenharmony_ci int rc; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci ts.tv_sec = rq->perout.start.sec; 41262306a36Sopenharmony_ci ts.tv_nsec = rq->perout.start.nsec; 41362306a36Sopenharmony_ci target_ns = timespec64_to_ns(&ts); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci rc = bnxt_get_target_cycles(ptp, target_ns, &delta); 41662306a36Sopenharmony_ci if (rc) 41762306a36Sopenharmony_ci return rc; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci rc = hwrm_req_init(bp, req, HWRM_FUNC_PTP_CFG); 42062306a36Sopenharmony_ci if (rc) 42162306a36Sopenharmony_ci return rc; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci enables = FUNC_PTP_CFG_REQ_ENABLES_PTP_FREQ_ADJ_EXT_PERIOD | 42462306a36Sopenharmony_ci FUNC_PTP_CFG_REQ_ENABLES_PTP_FREQ_ADJ_EXT_UP | 42562306a36Sopenharmony_ci FUNC_PTP_CFG_REQ_ENABLES_PTP_FREQ_ADJ_EXT_PHASE; 42662306a36Sopenharmony_ci req->enables = cpu_to_le16(enables); 42762306a36Sopenharmony_ci req->ptp_pps_event = 0; 42862306a36Sopenharmony_ci req->ptp_freq_adj_dll_source = 0; 42962306a36Sopenharmony_ci req->ptp_freq_adj_dll_phase = 0; 43062306a36Sopenharmony_ci req->ptp_freq_adj_ext_period = cpu_to_le32(NSEC_PER_SEC); 43162306a36Sopenharmony_ci req->ptp_freq_adj_ext_up = 0; 43262306a36Sopenharmony_ci req->ptp_freq_adj_ext_phase_lower = cpu_to_le32(delta); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci return hwrm_req_send(bp, req); 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic int bnxt_ptp_enable(struct ptp_clock_info *ptp_info, 43862306a36Sopenharmony_ci struct ptp_clock_request *rq, int on) 43962306a36Sopenharmony_ci{ 44062306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg, 44162306a36Sopenharmony_ci ptp_info); 44262306a36Sopenharmony_ci struct bnxt *bp = ptp->bp; 44362306a36Sopenharmony_ci int pin_id; 44462306a36Sopenharmony_ci int rc; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci switch (rq->type) { 44762306a36Sopenharmony_ci case PTP_CLK_REQ_EXTTS: 44862306a36Sopenharmony_ci /* Configure an External PPS IN */ 44962306a36Sopenharmony_ci pin_id = ptp_find_pin(ptp->ptp_clock, PTP_PF_EXTTS, 45062306a36Sopenharmony_ci rq->extts.index); 45162306a36Sopenharmony_ci if (!TSIO_PIN_VALID(pin_id)) 45262306a36Sopenharmony_ci return -EOPNOTSUPP; 45362306a36Sopenharmony_ci if (!on) 45462306a36Sopenharmony_ci break; 45562306a36Sopenharmony_ci rc = bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_PPS_IN); 45662306a36Sopenharmony_ci if (rc) 45762306a36Sopenharmony_ci return rc; 45862306a36Sopenharmony_ci rc = bnxt_ptp_cfg_event(bp, BNXT_PPS_EVENT_EXTERNAL); 45962306a36Sopenharmony_ci if (!rc) 46062306a36Sopenharmony_ci ptp->pps_info.pins[pin_id].event = BNXT_PPS_EVENT_EXTERNAL; 46162306a36Sopenharmony_ci return rc; 46262306a36Sopenharmony_ci case PTP_CLK_REQ_PEROUT: 46362306a36Sopenharmony_ci /* Configure a Periodic PPS OUT */ 46462306a36Sopenharmony_ci pin_id = ptp_find_pin(ptp->ptp_clock, PTP_PF_PEROUT, 46562306a36Sopenharmony_ci rq->perout.index); 46662306a36Sopenharmony_ci if (!TSIO_PIN_VALID(pin_id)) 46762306a36Sopenharmony_ci return -EOPNOTSUPP; 46862306a36Sopenharmony_ci if (!on) 46962306a36Sopenharmony_ci break; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci rc = bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_PPS_OUT); 47262306a36Sopenharmony_ci if (!rc) 47362306a36Sopenharmony_ci rc = bnxt_ptp_perout_cfg(ptp, rq); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci return rc; 47662306a36Sopenharmony_ci case PTP_CLK_REQ_PPS: 47762306a36Sopenharmony_ci /* Configure PHC PPS IN */ 47862306a36Sopenharmony_ci rc = bnxt_ptp_cfg_pin(bp, 0, BNXT_PPS_PIN_PPS_IN); 47962306a36Sopenharmony_ci if (rc) 48062306a36Sopenharmony_ci return rc; 48162306a36Sopenharmony_ci rc = bnxt_ptp_cfg_event(bp, BNXT_PPS_EVENT_INTERNAL); 48262306a36Sopenharmony_ci if (!rc) 48362306a36Sopenharmony_ci ptp->pps_info.pins[0].event = BNXT_PPS_EVENT_INTERNAL; 48462306a36Sopenharmony_ci return rc; 48562306a36Sopenharmony_ci default: 48662306a36Sopenharmony_ci netdev_err(ptp->bp->dev, "Unrecognized PIN function\n"); 48762306a36Sopenharmony_ci return -EOPNOTSUPP; 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci return bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_NONE); 49162306a36Sopenharmony_ci} 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_cistatic int bnxt_hwrm_ptp_cfg(struct bnxt *bp) 49462306a36Sopenharmony_ci{ 49562306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 49662306a36Sopenharmony_ci u32 flags = 0; 49762306a36Sopenharmony_ci int rc = 0; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci switch (ptp->rx_filter) { 50062306a36Sopenharmony_ci case HWTSTAMP_FILTER_ALL: 50162306a36Sopenharmony_ci flags = PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_ENABLE; 50262306a36Sopenharmony_ci break; 50362306a36Sopenharmony_ci case HWTSTAMP_FILTER_NONE: 50462306a36Sopenharmony_ci flags = PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_DISABLE; 50562306a36Sopenharmony_ci if (bp->fw_cap & BNXT_FW_CAP_RX_ALL_PKT_TS) 50662306a36Sopenharmony_ci flags |= PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_DISABLE; 50762306a36Sopenharmony_ci break; 50862306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_EVENT: 50962306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_SYNC: 51062306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 51162306a36Sopenharmony_ci flags = PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_ENABLE; 51262306a36Sopenharmony_ci break; 51362306a36Sopenharmony_ci } 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci if (ptp->tx_tstamp_en) 51662306a36Sopenharmony_ci flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_ENABLE; 51762306a36Sopenharmony_ci else 51862306a36Sopenharmony_ci flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_DISABLE; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci ptp->tstamp_filters = flags; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci if (netif_running(bp->dev)) { 52362306a36Sopenharmony_ci if (ptp->rx_filter == HWTSTAMP_FILTER_ALL) { 52462306a36Sopenharmony_ci bnxt_close_nic(bp, false, false); 52562306a36Sopenharmony_ci rc = bnxt_open_nic(bp, false, false); 52662306a36Sopenharmony_ci } else { 52762306a36Sopenharmony_ci bnxt_ptp_cfg_tstamp_filters(bp); 52862306a36Sopenharmony_ci } 52962306a36Sopenharmony_ci if (!rc && !ptp->tstamp_filters) 53062306a36Sopenharmony_ci rc = -EIO; 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci return rc; 53462306a36Sopenharmony_ci} 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ciint bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) 53762306a36Sopenharmony_ci{ 53862306a36Sopenharmony_ci struct bnxt *bp = netdev_priv(dev); 53962306a36Sopenharmony_ci struct hwtstamp_config stmpconf; 54062306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp; 54162306a36Sopenharmony_ci u16 old_rxctl; 54262306a36Sopenharmony_ci int old_rx_filter, rc; 54362306a36Sopenharmony_ci u8 old_tx_tstamp_en; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci ptp = bp->ptp_cfg; 54662306a36Sopenharmony_ci if (!ptp) 54762306a36Sopenharmony_ci return -EOPNOTSUPP; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf))) 55062306a36Sopenharmony_ci return -EFAULT; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci if (stmpconf.tx_type != HWTSTAMP_TX_ON && 55362306a36Sopenharmony_ci stmpconf.tx_type != HWTSTAMP_TX_OFF) 55462306a36Sopenharmony_ci return -ERANGE; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci old_rx_filter = ptp->rx_filter; 55762306a36Sopenharmony_ci old_rxctl = ptp->rxctl; 55862306a36Sopenharmony_ci old_tx_tstamp_en = ptp->tx_tstamp_en; 55962306a36Sopenharmony_ci switch (stmpconf.rx_filter) { 56062306a36Sopenharmony_ci case HWTSTAMP_FILTER_NONE: 56162306a36Sopenharmony_ci ptp->rxctl = 0; 56262306a36Sopenharmony_ci ptp->rx_filter = HWTSTAMP_FILTER_NONE; 56362306a36Sopenharmony_ci break; 56462306a36Sopenharmony_ci case HWTSTAMP_FILTER_ALL: 56562306a36Sopenharmony_ci if (bp->fw_cap & BNXT_FW_CAP_RX_ALL_PKT_TS) { 56662306a36Sopenharmony_ci ptp->rx_filter = HWTSTAMP_FILTER_ALL; 56762306a36Sopenharmony_ci break; 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci return -EOPNOTSUPP; 57062306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_EVENT: 57162306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 57262306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 57362306a36Sopenharmony_ci ptp->rxctl = BNXT_PTP_MSG_EVENTS; 57462306a36Sopenharmony_ci ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 57562306a36Sopenharmony_ci break; 57662306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_SYNC: 57762306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 57862306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 57962306a36Sopenharmony_ci ptp->rxctl = BNXT_PTP_MSG_SYNC; 58062306a36Sopenharmony_ci ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC; 58162306a36Sopenharmony_ci break; 58262306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 58362306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 58462306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: 58562306a36Sopenharmony_ci ptp->rxctl = BNXT_PTP_MSG_DELAY_REQ; 58662306a36Sopenharmony_ci ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ; 58762306a36Sopenharmony_ci break; 58862306a36Sopenharmony_ci default: 58962306a36Sopenharmony_ci return -ERANGE; 59062306a36Sopenharmony_ci } 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci if (stmpconf.tx_type == HWTSTAMP_TX_ON) 59362306a36Sopenharmony_ci ptp->tx_tstamp_en = 1; 59462306a36Sopenharmony_ci else 59562306a36Sopenharmony_ci ptp->tx_tstamp_en = 0; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci rc = bnxt_hwrm_ptp_cfg(bp); 59862306a36Sopenharmony_ci if (rc) 59962306a36Sopenharmony_ci goto ts_set_err; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci stmpconf.rx_filter = ptp->rx_filter; 60262306a36Sopenharmony_ci return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ? 60362306a36Sopenharmony_ci -EFAULT : 0; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_cits_set_err: 60662306a36Sopenharmony_ci ptp->rx_filter = old_rx_filter; 60762306a36Sopenharmony_ci ptp->rxctl = old_rxctl; 60862306a36Sopenharmony_ci ptp->tx_tstamp_en = old_tx_tstamp_en; 60962306a36Sopenharmony_ci return rc; 61062306a36Sopenharmony_ci} 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ciint bnxt_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) 61362306a36Sopenharmony_ci{ 61462306a36Sopenharmony_ci struct bnxt *bp = netdev_priv(dev); 61562306a36Sopenharmony_ci struct hwtstamp_config stmpconf; 61662306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci ptp = bp->ptp_cfg; 61962306a36Sopenharmony_ci if (!ptp) 62062306a36Sopenharmony_ci return -EOPNOTSUPP; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci stmpconf.flags = 0; 62362306a36Sopenharmony_ci stmpconf.tx_type = ptp->tx_tstamp_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci stmpconf.rx_filter = ptp->rx_filter; 62662306a36Sopenharmony_ci return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ? 62762306a36Sopenharmony_ci -EFAULT : 0; 62862306a36Sopenharmony_ci} 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_cistatic int bnxt_map_regs(struct bnxt *bp, u32 *reg_arr, int count, int reg_win) 63162306a36Sopenharmony_ci{ 63262306a36Sopenharmony_ci u32 reg_base = *reg_arr & BNXT_GRC_BASE_MASK; 63362306a36Sopenharmony_ci u32 win_off; 63462306a36Sopenharmony_ci int i; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci for (i = 0; i < count; i++) { 63762306a36Sopenharmony_ci if ((reg_arr[i] & BNXT_GRC_BASE_MASK) != reg_base) 63862306a36Sopenharmony_ci return -ERANGE; 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci win_off = BNXT_GRCPF_REG_WINDOW_BASE_OUT + (reg_win - 1) * 4; 64162306a36Sopenharmony_ci writel(reg_base, bp->bar0 + win_off); 64262306a36Sopenharmony_ci return 0; 64362306a36Sopenharmony_ci} 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cistatic int bnxt_map_ptp_regs(struct bnxt *bp) 64662306a36Sopenharmony_ci{ 64762306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 64862306a36Sopenharmony_ci u32 *reg_arr; 64962306a36Sopenharmony_ci int rc, i; 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci reg_arr = ptp->refclk_regs; 65262306a36Sopenharmony_ci if (bp->flags & BNXT_FLAG_CHIP_P5) { 65362306a36Sopenharmony_ci rc = bnxt_map_regs(bp, reg_arr, 2, BNXT_PTP_GRC_WIN); 65462306a36Sopenharmony_ci if (rc) 65562306a36Sopenharmony_ci return rc; 65662306a36Sopenharmony_ci for (i = 0; i < 2; i++) 65762306a36Sopenharmony_ci ptp->refclk_mapped_regs[i] = BNXT_PTP_GRC_WIN_BASE + 65862306a36Sopenharmony_ci (ptp->refclk_regs[i] & BNXT_GRC_OFFSET_MASK); 65962306a36Sopenharmony_ci return 0; 66062306a36Sopenharmony_ci } 66162306a36Sopenharmony_ci return -ENODEV; 66262306a36Sopenharmony_ci} 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_cistatic void bnxt_unmap_ptp_regs(struct bnxt *bp) 66562306a36Sopenharmony_ci{ 66662306a36Sopenharmony_ci writel(0, bp->bar0 + BNXT_GRCPF_REG_WINDOW_BASE_OUT + 66762306a36Sopenharmony_ci (BNXT_PTP_GRC_WIN - 1) * 4); 66862306a36Sopenharmony_ci} 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_cistatic u64 bnxt_cc_read(const struct cyclecounter *cc) 67162306a36Sopenharmony_ci{ 67262306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = container_of(cc, struct bnxt_ptp_cfg, cc); 67362306a36Sopenharmony_ci u64 ns = 0; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci bnxt_refclk_read(ptp->bp, NULL, &ns); 67662306a36Sopenharmony_ci return ns; 67762306a36Sopenharmony_ci} 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_cistatic void bnxt_stamp_tx_skb(struct bnxt *bp, struct sk_buff *skb) 68062306a36Sopenharmony_ci{ 68162306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 68262306a36Sopenharmony_ci struct skb_shared_hwtstamps timestamp; 68362306a36Sopenharmony_ci u64 ts = 0, ns = 0; 68462306a36Sopenharmony_ci int rc; 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci rc = bnxt_hwrm_port_ts_query(bp, PORT_TS_QUERY_REQ_FLAGS_PATH_TX, &ts); 68762306a36Sopenharmony_ci if (!rc) { 68862306a36Sopenharmony_ci memset(×tamp, 0, sizeof(timestamp)); 68962306a36Sopenharmony_ci spin_lock_bh(&ptp->ptp_lock); 69062306a36Sopenharmony_ci ns = timecounter_cyc2time(&ptp->tc, ts); 69162306a36Sopenharmony_ci spin_unlock_bh(&ptp->ptp_lock); 69262306a36Sopenharmony_ci timestamp.hwtstamp = ns_to_ktime(ns); 69362306a36Sopenharmony_ci skb_tstamp_tx(ptp->tx_skb, ×tamp); 69462306a36Sopenharmony_ci } else { 69562306a36Sopenharmony_ci netdev_err(bp->dev, "TS query for TX timer failed rc = %x\n", 69662306a36Sopenharmony_ci rc); 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci dev_kfree_skb_any(ptp->tx_skb); 70062306a36Sopenharmony_ci ptp->tx_skb = NULL; 70162306a36Sopenharmony_ci atomic_inc(&ptp->tx_avail); 70262306a36Sopenharmony_ci} 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_cistatic long bnxt_ptp_ts_aux_work(struct ptp_clock_info *ptp_info) 70562306a36Sopenharmony_ci{ 70662306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg, 70762306a36Sopenharmony_ci ptp_info); 70862306a36Sopenharmony_ci unsigned long now = jiffies; 70962306a36Sopenharmony_ci struct bnxt *bp = ptp->bp; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci if (ptp->tx_skb) 71262306a36Sopenharmony_ci bnxt_stamp_tx_skb(bp, ptp->tx_skb); 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci if (!time_after_eq(now, ptp->next_period)) 71562306a36Sopenharmony_ci return ptp->next_period - now; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci bnxt_ptp_get_current_time(bp); 71862306a36Sopenharmony_ci ptp->next_period = now + HZ; 71962306a36Sopenharmony_ci if (time_after_eq(now, ptp->next_overflow_check)) { 72062306a36Sopenharmony_ci spin_lock_bh(&ptp->ptp_lock); 72162306a36Sopenharmony_ci timecounter_read(&ptp->tc); 72262306a36Sopenharmony_ci spin_unlock_bh(&ptp->ptp_lock); 72362306a36Sopenharmony_ci ptp->next_overflow_check = now + BNXT_PHC_OVERFLOW_PERIOD; 72462306a36Sopenharmony_ci } 72562306a36Sopenharmony_ci return HZ; 72662306a36Sopenharmony_ci} 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ciint bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb) 72962306a36Sopenharmony_ci{ 73062306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci if (ptp->tx_skb) { 73362306a36Sopenharmony_ci netdev_err(bp->dev, "deferring skb:one SKB is still outstanding\n"); 73462306a36Sopenharmony_ci return -EBUSY; 73562306a36Sopenharmony_ci } 73662306a36Sopenharmony_ci ptp->tx_skb = skb; 73762306a36Sopenharmony_ci ptp_schedule_worker(ptp->ptp_clock, 0); 73862306a36Sopenharmony_ci return 0; 73962306a36Sopenharmony_ci} 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ciint bnxt_get_rx_ts_p5(struct bnxt *bp, u64 *ts, u32 pkt_ts) 74262306a36Sopenharmony_ci{ 74362306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 74462306a36Sopenharmony_ci u64 time; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci if (!ptp) 74762306a36Sopenharmony_ci return -ENODEV; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci BNXT_READ_TIME64(ptp, time, ptp->old_time); 75062306a36Sopenharmony_ci *ts = (time & BNXT_HI_TIMER_MASK) | pkt_ts; 75162306a36Sopenharmony_ci if (pkt_ts < (time & BNXT_LO_TIMER_MASK)) 75262306a36Sopenharmony_ci *ts += BNXT_LO_TIMER_MASK + 1; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci return 0; 75562306a36Sopenharmony_ci} 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_cistatic const struct ptp_clock_info bnxt_ptp_caps = { 75862306a36Sopenharmony_ci .owner = THIS_MODULE, 75962306a36Sopenharmony_ci .name = "bnxt clock", 76062306a36Sopenharmony_ci .max_adj = BNXT_MAX_PHC_DRIFT, 76162306a36Sopenharmony_ci .n_alarm = 0, 76262306a36Sopenharmony_ci .n_ext_ts = 0, 76362306a36Sopenharmony_ci .n_per_out = 0, 76462306a36Sopenharmony_ci .n_pins = 0, 76562306a36Sopenharmony_ci .pps = 0, 76662306a36Sopenharmony_ci .adjfine = bnxt_ptp_adjfine, 76762306a36Sopenharmony_ci .adjtime = bnxt_ptp_adjtime, 76862306a36Sopenharmony_ci .do_aux_work = bnxt_ptp_ts_aux_work, 76962306a36Sopenharmony_ci .gettimex64 = bnxt_ptp_gettimex, 77062306a36Sopenharmony_ci .settime64 = bnxt_ptp_settime, 77162306a36Sopenharmony_ci .enable = bnxt_ptp_enable, 77262306a36Sopenharmony_ci}; 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_cistatic int bnxt_ptp_verify(struct ptp_clock_info *ptp_info, unsigned int pin, 77562306a36Sopenharmony_ci enum ptp_pin_function func, unsigned int chan) 77662306a36Sopenharmony_ci{ 77762306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg, 77862306a36Sopenharmony_ci ptp_info); 77962306a36Sopenharmony_ci /* Allow only PPS pin function configuration */ 78062306a36Sopenharmony_ci if (ptp->pps_info.pins[pin].usage <= BNXT_PPS_PIN_PPS_OUT && 78162306a36Sopenharmony_ci func != PTP_PF_PHYSYNC) 78262306a36Sopenharmony_ci return 0; 78362306a36Sopenharmony_ci else 78462306a36Sopenharmony_ci return -EOPNOTSUPP; 78562306a36Sopenharmony_ci} 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_cistatic int bnxt_ptp_pps_init(struct bnxt *bp) 78862306a36Sopenharmony_ci{ 78962306a36Sopenharmony_ci struct hwrm_func_ptp_pin_qcfg_output *resp; 79062306a36Sopenharmony_ci struct hwrm_func_ptp_pin_qcfg_input *req; 79162306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 79262306a36Sopenharmony_ci struct ptp_clock_info *ptp_info; 79362306a36Sopenharmony_ci struct bnxt_pps *pps_info; 79462306a36Sopenharmony_ci u8 *pin_usg; 79562306a36Sopenharmony_ci u32 i, rc; 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci /* Query current/default PIN CFG */ 79862306a36Sopenharmony_ci rc = hwrm_req_init(bp, req, HWRM_FUNC_PTP_PIN_QCFG); 79962306a36Sopenharmony_ci if (rc) 80062306a36Sopenharmony_ci return rc; 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci resp = hwrm_req_hold(bp, req); 80362306a36Sopenharmony_ci rc = hwrm_req_send(bp, req); 80462306a36Sopenharmony_ci if (rc || !resp->num_pins) { 80562306a36Sopenharmony_ci hwrm_req_drop(bp, req); 80662306a36Sopenharmony_ci return -EOPNOTSUPP; 80762306a36Sopenharmony_ci } 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci ptp_info = &ptp->ptp_info; 81062306a36Sopenharmony_ci pps_info = &ptp->pps_info; 81162306a36Sopenharmony_ci pps_info->num_pins = resp->num_pins; 81262306a36Sopenharmony_ci ptp_info->n_pins = pps_info->num_pins; 81362306a36Sopenharmony_ci ptp_info->pin_config = kcalloc(ptp_info->n_pins, 81462306a36Sopenharmony_ci sizeof(*ptp_info->pin_config), 81562306a36Sopenharmony_ci GFP_KERNEL); 81662306a36Sopenharmony_ci if (!ptp_info->pin_config) { 81762306a36Sopenharmony_ci hwrm_req_drop(bp, req); 81862306a36Sopenharmony_ci return -ENOMEM; 81962306a36Sopenharmony_ci } 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci /* Report the TSIO capability to kernel */ 82262306a36Sopenharmony_ci pin_usg = &resp->pin0_usage; 82362306a36Sopenharmony_ci for (i = 0; i < pps_info->num_pins; i++, pin_usg++) { 82462306a36Sopenharmony_ci snprintf(ptp_info->pin_config[i].name, 82562306a36Sopenharmony_ci sizeof(ptp_info->pin_config[i].name), "bnxt_pps%d", i); 82662306a36Sopenharmony_ci ptp_info->pin_config[i].index = i; 82762306a36Sopenharmony_ci ptp_info->pin_config[i].chan = i; 82862306a36Sopenharmony_ci if (*pin_usg == BNXT_PPS_PIN_PPS_IN) 82962306a36Sopenharmony_ci ptp_info->pin_config[i].func = PTP_PF_EXTTS; 83062306a36Sopenharmony_ci else if (*pin_usg == BNXT_PPS_PIN_PPS_OUT) 83162306a36Sopenharmony_ci ptp_info->pin_config[i].func = PTP_PF_PEROUT; 83262306a36Sopenharmony_ci else 83362306a36Sopenharmony_ci ptp_info->pin_config[i].func = PTP_PF_NONE; 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci pps_info->pins[i].usage = *pin_usg; 83662306a36Sopenharmony_ci } 83762306a36Sopenharmony_ci hwrm_req_drop(bp, req); 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci /* Only 1 each of ext_ts and per_out pins is available in HW */ 84062306a36Sopenharmony_ci ptp_info->n_ext_ts = 1; 84162306a36Sopenharmony_ci ptp_info->n_per_out = 1; 84262306a36Sopenharmony_ci ptp_info->pps = 1; 84362306a36Sopenharmony_ci ptp_info->verify = bnxt_ptp_verify; 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci return 0; 84662306a36Sopenharmony_ci} 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_cistatic bool bnxt_pps_config_ok(struct bnxt *bp) 84962306a36Sopenharmony_ci{ 85062306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci return !(bp->fw_cap & BNXT_FW_CAP_PTP_PPS) == !ptp->ptp_info.pin_config; 85362306a36Sopenharmony_ci} 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_cistatic void bnxt_ptp_timecounter_init(struct bnxt *bp, bool init_tc) 85662306a36Sopenharmony_ci{ 85762306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci if (!ptp->ptp_clock) { 86062306a36Sopenharmony_ci memset(&ptp->cc, 0, sizeof(ptp->cc)); 86162306a36Sopenharmony_ci ptp->cc.read = bnxt_cc_read; 86262306a36Sopenharmony_ci ptp->cc.mask = CYCLECOUNTER_MASK(48); 86362306a36Sopenharmony_ci if (BNXT_MH(bp)) { 86462306a36Sopenharmony_ci /* Use timecounter based non-real time mode */ 86562306a36Sopenharmony_ci ptp->cc.shift = BNXT_CYCLES_SHIFT; 86662306a36Sopenharmony_ci ptp->cc.mult = clocksource_khz2mult(BNXT_DEVCLK_FREQ, ptp->cc.shift); 86762306a36Sopenharmony_ci ptp->cmult = ptp->cc.mult; 86862306a36Sopenharmony_ci } else { 86962306a36Sopenharmony_ci ptp->cc.shift = 0; 87062306a36Sopenharmony_ci ptp->cc.mult = 1; 87162306a36Sopenharmony_ci } 87262306a36Sopenharmony_ci ptp->next_overflow_check = jiffies + BNXT_PHC_OVERFLOW_PERIOD; 87362306a36Sopenharmony_ci } 87462306a36Sopenharmony_ci if (init_tc) 87562306a36Sopenharmony_ci timecounter_init(&ptp->tc, &ptp->cc, ktime_to_ns(ktime_get_real())); 87662306a36Sopenharmony_ci} 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci/* Caller holds ptp_lock */ 87962306a36Sopenharmony_civoid bnxt_ptp_rtc_timecounter_init(struct bnxt_ptp_cfg *ptp, u64 ns) 88062306a36Sopenharmony_ci{ 88162306a36Sopenharmony_ci timecounter_init(&ptp->tc, &ptp->cc, ns); 88262306a36Sopenharmony_ci /* For RTC, cycle_last must be in sync with the timecounter value. */ 88362306a36Sopenharmony_ci ptp->tc.cycle_last = ns & ptp->cc.mask; 88462306a36Sopenharmony_ci} 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ciint bnxt_ptp_init_rtc(struct bnxt *bp, bool phc_cfg) 88762306a36Sopenharmony_ci{ 88862306a36Sopenharmony_ci struct timespec64 tsp; 88962306a36Sopenharmony_ci u64 ns; 89062306a36Sopenharmony_ci int rc; 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci if (!bp->ptp_cfg || !BNXT_PTP_USE_RTC(bp)) 89362306a36Sopenharmony_ci return -ENODEV; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci if (!phc_cfg) { 89662306a36Sopenharmony_ci ktime_get_real_ts64(&tsp); 89762306a36Sopenharmony_ci ns = timespec64_to_ns(&tsp); 89862306a36Sopenharmony_ci rc = bnxt_ptp_cfg_settime(bp, ns); 89962306a36Sopenharmony_ci if (rc) 90062306a36Sopenharmony_ci return rc; 90162306a36Sopenharmony_ci } else { 90262306a36Sopenharmony_ci rc = bnxt_hwrm_port_ts_query(bp, PORT_TS_QUERY_REQ_FLAGS_CURRENT_TIME, &ns); 90362306a36Sopenharmony_ci if (rc) 90462306a36Sopenharmony_ci return rc; 90562306a36Sopenharmony_ci } 90662306a36Sopenharmony_ci spin_lock_bh(&bp->ptp_cfg->ptp_lock); 90762306a36Sopenharmony_ci bnxt_ptp_rtc_timecounter_init(bp->ptp_cfg, ns); 90862306a36Sopenharmony_ci spin_unlock_bh(&bp->ptp_cfg->ptp_lock); 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci return 0; 91162306a36Sopenharmony_ci} 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_cistatic void bnxt_ptp_free(struct bnxt *bp) 91462306a36Sopenharmony_ci{ 91562306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci if (ptp->ptp_clock) { 91862306a36Sopenharmony_ci ptp_clock_unregister(ptp->ptp_clock); 91962306a36Sopenharmony_ci ptp->ptp_clock = NULL; 92062306a36Sopenharmony_ci kfree(ptp->ptp_info.pin_config); 92162306a36Sopenharmony_ci ptp->ptp_info.pin_config = NULL; 92262306a36Sopenharmony_ci } 92362306a36Sopenharmony_ci} 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ciint bnxt_ptp_init(struct bnxt *bp, bool phc_cfg) 92662306a36Sopenharmony_ci{ 92762306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 92862306a36Sopenharmony_ci int rc; 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci if (!ptp) 93162306a36Sopenharmony_ci return 0; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci rc = bnxt_map_ptp_regs(bp); 93462306a36Sopenharmony_ci if (rc) 93562306a36Sopenharmony_ci return rc; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci if (ptp->ptp_clock && bnxt_pps_config_ok(bp)) 93862306a36Sopenharmony_ci return 0; 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci bnxt_ptp_free(bp); 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci atomic_set(&ptp->tx_avail, BNXT_MAX_TX_TS); 94362306a36Sopenharmony_ci spin_lock_init(&ptp->ptp_lock); 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci if (BNXT_PTP_USE_RTC(bp)) { 94662306a36Sopenharmony_ci bnxt_ptp_timecounter_init(bp, false); 94762306a36Sopenharmony_ci rc = bnxt_ptp_init_rtc(bp, phc_cfg); 94862306a36Sopenharmony_ci if (rc) 94962306a36Sopenharmony_ci goto out; 95062306a36Sopenharmony_ci } else { 95162306a36Sopenharmony_ci bnxt_ptp_timecounter_init(bp, true); 95262306a36Sopenharmony_ci bnxt_ptp_adjfine_rtc(bp, 0); 95362306a36Sopenharmony_ci } 95462306a36Sopenharmony_ci bnxt_hwrm_func_drv_rgtr(bp, NULL, 0, true); 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci ptp->ptp_info = bnxt_ptp_caps; 95762306a36Sopenharmony_ci if ((bp->fw_cap & BNXT_FW_CAP_PTP_PPS)) { 95862306a36Sopenharmony_ci if (bnxt_ptp_pps_init(bp)) 95962306a36Sopenharmony_ci netdev_err(bp->dev, "1pps not initialized, continuing without 1pps support\n"); 96062306a36Sopenharmony_ci } 96162306a36Sopenharmony_ci ptp->ptp_clock = ptp_clock_register(&ptp->ptp_info, &bp->pdev->dev); 96262306a36Sopenharmony_ci if (IS_ERR(ptp->ptp_clock)) { 96362306a36Sopenharmony_ci int err = PTR_ERR(ptp->ptp_clock); 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci ptp->ptp_clock = NULL; 96662306a36Sopenharmony_ci rc = err; 96762306a36Sopenharmony_ci goto out; 96862306a36Sopenharmony_ci } 96962306a36Sopenharmony_ci if (bp->flags & BNXT_FLAG_CHIP_P5) { 97062306a36Sopenharmony_ci spin_lock_bh(&ptp->ptp_lock); 97162306a36Sopenharmony_ci bnxt_refclk_read(bp, NULL, &ptp->current_time); 97262306a36Sopenharmony_ci WRITE_ONCE(ptp->old_time, ptp->current_time); 97362306a36Sopenharmony_ci spin_unlock_bh(&ptp->ptp_lock); 97462306a36Sopenharmony_ci ptp_schedule_worker(ptp->ptp_clock, 0); 97562306a36Sopenharmony_ci } 97662306a36Sopenharmony_ci return 0; 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ciout: 97962306a36Sopenharmony_ci bnxt_ptp_free(bp); 98062306a36Sopenharmony_ci bnxt_unmap_ptp_regs(bp); 98162306a36Sopenharmony_ci return rc; 98262306a36Sopenharmony_ci} 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_civoid bnxt_ptp_clear(struct bnxt *bp) 98562306a36Sopenharmony_ci{ 98662306a36Sopenharmony_ci struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci if (!ptp) 98962306a36Sopenharmony_ci return; 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci if (ptp->ptp_clock) 99262306a36Sopenharmony_ci ptp_clock_unregister(ptp->ptp_clock); 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci ptp->ptp_clock = NULL; 99562306a36Sopenharmony_ci kfree(ptp->ptp_info.pin_config); 99662306a36Sopenharmony_ci ptp->ptp_info.pin_config = NULL; 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci if (ptp->tx_skb) { 99962306a36Sopenharmony_ci dev_kfree_skb_any(ptp->tx_skb); 100062306a36Sopenharmony_ci ptp->tx_skb = NULL; 100162306a36Sopenharmony_ci } 100262306a36Sopenharmony_ci bnxt_unmap_ptp_regs(bp); 100362306a36Sopenharmony_ci} 1004