/* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (C) 2024 Intel Corporation */ #ifndef _IDPF_PTP_H #define _IDPF_PTP_H #include /** * struct idpf_ptp_cmd - PTP command masks * @exec_cmd_mask: mask to trigger command execution * @shtime_enable_mask: mask to enable shadow time */ struct idpf_ptp_cmd { u32 exec_cmd_mask; u32 shtime_enable_mask; }; /* struct idpf_ptp_dev_clk_regs - PTP device registers * @dev_clk_ns_l: low part of the device clock register * @dev_clk_ns_h: high part of the device clock register * @phy_clk_ns_l: low part of the PHY clock register * @phy_clk_ns_h: high part of the PHY clock register * @incval_l: low part of the increment value register * @incval_h: high part of the increment value register * @shadj_l: low part of the shadow adjust register * @shadj_h: high part of the shadow adjust register * @phy_incval_l: low part of the PHY increment value register * @phy_incval_h: high part of the PHY increment value register * @phy_shadj_l: low part of the PHY shadow adjust register * @phy_shadj_h: high part of the PHY shadow adjust register * @cmd: PTP command register * @phy_cmd: PHY command register * @cmd_sync: PTP command synchronization register */ struct idpf_ptp_dev_clk_regs { /* Main clock */ void __iomem *dev_clk_ns_l; void __iomem *dev_clk_ns_h; /* PHY timer */ void __iomem *phy_clk_ns_l; void __iomem *phy_clk_ns_h; /* Main timer adjustments */ void __iomem *incval_l; void __iomem *incval_h; void __iomem *shadj_l; void __iomem *shadj_h; /* PHY timer adjustments */ void __iomem *phy_incval_l; void __iomem *phy_incval_h; void __iomem *phy_shadj_l; void __iomem *phy_shadj_h; /* Command */ void __iomem *cmd; void __iomem *phy_cmd; void __iomem *cmd_sync; }; /** * enum idpf_ptp_access - the type of access to PTP operations * @IDPF_PTP_NONE: no access * @IDPF_PTP_DIRECT: direct access through BAR registers * @IDPF_PTP_MAILBOX: access through mailbox messages */ enum idpf_ptp_access { IDPF_PTP_NONE = 0, IDPF_PTP_DIRECT, IDPF_PTP_MAILBOX, }; /** * struct idpf_ptp_secondary_mbx - PTP secondary mailbox * @peer_mbx_q_id: PTP mailbox queue ID * @peer_id: Peer ID for PTP Device Control daemon * @valid: indicates whether secondary mailblox is supported by the Control * Plane */ struct idpf_ptp_secondary_mbx { u16 peer_mbx_q_id; u16 peer_id; bool valid:1; }; /** * enum idpf_ptp_tx_tstamp_state - Tx timestamp states * @IDPF_PTP_FREE: Tx timestamp index free to use * @IDPF_PTP_REQUEST: Tx timestamp index set to the Tx descriptor * @IDPF_PTP_READ_VALUE: Tx timestamp value ready to be read */ enum idpf_ptp_tx_tstamp_state { IDPF_PTP_FREE, IDPF_PTP_REQUEST, IDPF_PTP_READ_VALUE, }; /** * struct idpf_ptp_tx_tstamp_status - Parameters to track Tx timestamp * @skb: the pointer to the SKB that received the completion tag * @state: the state of the Tx timestamp */ struct idpf_ptp_tx_tstamp_status { struct sk_buff *skb; enum idpf_ptp_tx_tstamp_state state; }; /** * struct idpf_ptp_tx_tstamp - Parameters for Tx timestamping * @list_member: the list member structure * @tx_latch_reg_offset_l: Tx tstamp latch low register offset * @tx_latch_reg_offset_h: Tx tstamp latch high register offset * @skb: the pointer to the SKB for this timestamp request * @tstamp: the Tx tstamp value * @idx: the index of the Tx tstamp */ struct idpf_ptp_tx_tstamp { struct list_head list_member; u32 tx_latch_reg_offset_l; u32 tx_latch_reg_offset_h; struct sk_buff *skb; u64 tstamp; u32 idx; }; /** * struct idpf_ptp_vport_tx_tstamp_caps - Tx timestamp capabilities * @vport_id: the vport id * @num_entries: the number of negotiated Tx timestamp entries * @tstamp_ns_lo_bit: first bit for nanosecond part of the timestamp * @latches_lock: the lock to the lists of free/used timestamp indexes * @status_lock: the lock to the status tracker * @access: indicates an access to Tx timestamp * @latches_free: the list of the free Tx timestamps latches * @latches_in_use: the list of the used Tx timestamps latches * @tx_tstamp_status: Tx tstamp status tracker */ struct idpf_ptp_vport_tx_tstamp_caps { u32 vport_id; u16 num_entries; u16 tstamp_ns_lo_bit; spinlock_t latches_lock; spinlock_t status_lock; bool access:1; struct list_head latches_free; struct list_head latches_in_use; struct idpf_ptp_tx_tstamp_status tx_tstamp_status[]; }; /** * struct idpf_ptp - PTP parameters * @info: structure defining PTP hardware capabilities * @clock: pointer to registered PTP clock device * @adapter: back pointer to the adapter * @base_incval: base increment value of the PTP clock * @max_adj: maximum adjustment of the PTP clock * @cmd: HW specific command masks * @cached_phc_time: a cached copy of the PHC time for timestamp extension * @cached_phc_jiffies: jiffies when cached_phc_time was last updated * @dev_clk_regs: the set of registers to access the device clock * @caps: PTP capabilities negotiated with the Control Plane * @get_dev_clk_time_access: access type for getting the device clock time * @set_dev_clk_time_access: access type for setting the device clock time * @adj_dev_clk_time_access: access type for the adjusting the device clock * @tx_tstamp_access: access type for the Tx timestamp value read * @rsv: reserved bits * @secondary_mbx: parameters for using dedicated PTP mailbox * @read_dev_clk_lock: spinlock protecting access to the device clock read * operation executed by the HW latch */ struct idpf_ptp { struct ptp_clock_info info; struct ptp_clock *clock; struct idpf_adapter *adapter; u64 base_incval; u64 max_adj; struct idpf_ptp_cmd cmd; u64 cached_phc_time; unsigned long cached_phc_jiffies; struct idpf_ptp_dev_clk_regs dev_clk_regs; u32 caps; enum idpf_ptp_access get_dev_clk_time_access:2; enum idpf_ptp_access set_dev_clk_time_access:2; enum idpf_ptp_access adj_dev_clk_time_access:2; enum idpf_ptp_access tx_tstamp_access:2; u8 rsv; struct idpf_ptp_secondary_mbx secondary_mbx; spinlock_t read_dev_clk_lock; }; /** * idpf_ptp_info_to_adapter - get driver adapter struct from ptp_clock_info * @info: pointer to ptp_clock_info struct * * Return: pointer to the corresponding adapter struct */ static inline struct idpf_adapter * idpf_ptp_info_to_adapter(const struct ptp_clock_info *info) { const struct idpf_ptp *ptp = container_of_const(info, struct idpf_ptp, info); return ptp->adapter; } /** * struct idpf_ptp_dev_timers - System time and device time values * @sys_time_ns: system time value expressed in nanoseconds * @dev_clk_time_ns: device clock time value expressed in nanoseconds */ struct idpf_ptp_dev_timers { u64 sys_time_ns; u64 dev_clk_time_ns; }; /** * idpf_ptp_is_vport_tx_tstamp_ena - Verify the Tx timestamping enablement for * a given vport. * @vport: Virtual port structure * * Tx timestamp capabilities are negotiated with the Control Plane only if the * device clock value can be read, Tx timestamp access type is different than * NONE, and the PTP clock for the adapter is created. When all those conditions * are satisfied, Tx timestamp feature is enabled and tx_tstamp_caps is * allocated and fulfilled. * * Return: true if the Tx timestamping is enabled, false otherwise. */ static inline bool idpf_ptp_is_vport_tx_tstamp_ena(struct idpf_vport *vport) { if (!vport->tx_tstamp_caps) return false; else return true; } /** * idpf_ptp_is_vport_rx_tstamp_ena - Verify the Rx timestamping enablement for * a given vport. * @vport: Virtual port structure * * Rx timestamp feature is enabled if the PTP clock for the adapter is created * and it is possible to read the value of the device clock. The second * assumption comes from the need to extend the Rx timestamp value to 64 bit * based on the current device clock time. * * Return: true if the Rx timestamping is enabled, false otherwise. */ static inline bool idpf_ptp_is_vport_rx_tstamp_ena(struct idpf_vport *vport) { if (!vport->adapter->ptp || vport->adapter->ptp->get_dev_clk_time_access == IDPF_PTP_NONE) return false; else return true; } #if IS_ENABLED(CONFIG_PTP_1588_CLOCK) int idpf_ptp_init(struct idpf_adapter *adapter); void idpf_ptp_release(struct idpf_adapter *adapter); int idpf_ptp_get_caps(struct idpf_adapter *adapter); void idpf_ptp_get_features_access(const struct idpf_adapter *adapter); bool idpf_ptp_get_txq_tstamp_capability(struct idpf_tx_queue *txq); int idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter, struct idpf_ptp_dev_timers *dev_clk_time); int idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter, u64 time); int idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter, u64 incval); int idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter, s64 delta); int idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport); int idpf_ptp_get_tx_tstamp(struct idpf_vport *vport); int idpf_ptp_set_timestamp_mode(struct idpf_vport *vport, struct kernel_hwtstamp_config *config); u64 idpf_ptp_extend_ts(struct idpf_vport *vport, u64 in_tstamp); u64 idpf_ptp_tstamp_extend_32b_to_64b(u64 cached_phc_time, u32 in_timestamp); int idpf_ptp_request_ts(struct idpf_tx_queue *tx_q, struct sk_buff *skb, u32 *idx); void idpf_tstamp_task(struct work_struct *work); #else /* CONFIG_PTP_1588_CLOCK */ static inline int idpf_ptp_init(struct idpf_adapter *adapter) { return 0; } static inline void idpf_ptp_release(struct idpf_adapter *adapter) { } static inline int idpf_ptp_get_caps(struct idpf_adapter *adapter) { return -EOPNOTSUPP; } static inline void idpf_ptp_get_features_access(const struct idpf_adapter *adapter) { } static inline bool idpf_ptp_get_txq_tstamp_capability(struct idpf_tx_queue *txq) { return false; } static inline int idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter, struct idpf_ptp_dev_timers *dev_clk_time) { return -EOPNOTSUPP; } static inline int idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter, u64 time) { return -EOPNOTSUPP; } static inline int idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter, u64 incval) { return -EOPNOTSUPP; } static inline int idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter, s64 delta) { return -EOPNOTSUPP; } static inline int idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport) { return -EOPNOTSUPP; } static inline int idpf_ptp_get_tx_tstamp(struct idpf_vport *vport) { return -EOPNOTSUPP; } static inline int idpf_ptp_set_timestamp_mode(struct idpf_vport *vport, struct kernel_hwtstamp_config *config) { return -EOPNOTSUPP; } static inline u64 idpf_ptp_extend_ts(struct idpf_vport *vport, u32 in_tstamp) { return 0; } static inline u64 idpf_ptp_tstamp_extend_32b_to_64b(u64 cached_phc_time, u32 in_timestamp) { return 0; } static inline int idpf_ptp_request_ts(struct idpf_tx_queue *tx_q, struct sk_buff *skb, u32 *idx) { return -EOPNOTSUPP; } static inline void idpf_tstamp_task(struct work_struct *work) { } #endif /* CONFIG_PTP_1588_CLOCK */ #endif /* _IDPF_PTP_H */