return 0;
 }
 
+static int
+ice_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
+{
+       struct ice_pf *pf = ice_netdev_to_pf(dev);
+
+       /* only report timestamping if PTP is enabled */
+       if (!test_bit(ICE_FLAG_PTP, pf->flags))
+               return ethtool_op_get_ts_info(dev, info);
+
+       info->so_timestamping = SOF_TIMESTAMPING_SOFTWARE;
+
+       info->phc_index = ice_get_ptp_clock_index(pf);
+
+       info->tx_types = BIT(HWTSTAMP_TX_OFF);
+
+       info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
+
+       return 0;
+}
+
 /**
  * ice_get_max_txq - return the maximum number of Tx queues for in a PF
  * @pf: PF structure
        .set_rxfh               = ice_set_rxfh,
        .get_channels           = ice_get_channels,
        .set_channels           = ice_set_channels,
-       .get_ts_info            = ethtool_op_get_ts_info,
+       .get_ts_info            = ice_get_ts_info,
        .get_per_queue_coalesce = ice_get_per_q_coalesce,
        .set_per_queue_coalesce = ice_set_per_q_coalesce,
        .get_fecparam           = ice_get_fecparam,
 
 #include "ice.h"
 #include "ice_lib.h"
 
+/**
+ * ice_get_ptp_clock_index - Get the PTP clock index
+ * @pf: the PF pointer
+ *
+ * Determine the clock index of the PTP clock associated with this device. If
+ * this is the PF controlling the clock, just use the local access to the
+ * clock device pointer.
+ *
+ * Otherwise, read from the driver shared parameters to determine the clock
+ * index value.
+ *
+ * Returns: the index of the PTP clock associated with this device, or -1 if
+ * there is no associated clock.
+ */
+int ice_get_ptp_clock_index(struct ice_pf *pf)
+{
+       struct device *dev = ice_pf_to_dev(pf);
+       enum ice_aqc_driver_params param_idx;
+       struct ice_hw *hw = &pf->hw;
+       u8 tmr_idx;
+       u32 value;
+       int err;
+
+       /* Use the ptp_clock structure if we're the main PF */
+       if (pf->ptp.clock)
+               return ptp_clock_index(pf->ptp.clock);
+
+       tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc;
+       if (!tmr_idx)
+               param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0;
+       else
+               param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1;
+
+       err = ice_aq_get_driver_param(hw, param_idx, &value, NULL);
+       if (err) {
+               dev_err(dev, "Failed to read PTP clock index parameter, err %d aq_err %s\n",
+                       err, ice_aq_str(hw->adminq.sq_last_status));
+               return -1;
+       }
+
+       /* The PTP clock index is an integer, and will be between 0 and
+        * INT_MAX. The highest bit of the driver shared parameter is used to
+        * indicate whether or not the currently stored clock index is valid.
+        */
+       if (!(value & PTP_SHARED_CLK_IDX_VALID))
+               return -1;
+
+       return value & ~PTP_SHARED_CLK_IDX_VALID;
+}
+
+/**
+ * ice_set_ptp_clock_index - Set the PTP clock index
+ * @pf: the PF pointer
+ *
+ * Set the PTP clock index for this device into the shared driver parameters,
+ * so that other PFs associated with this device can read it.
+ *
+ * If the PF is unable to store the clock index, it will log an error, but
+ * will continue operating PTP.
+ */
+static void ice_set_ptp_clock_index(struct ice_pf *pf)
+{
+       struct device *dev = ice_pf_to_dev(pf);
+       enum ice_aqc_driver_params param_idx;
+       struct ice_hw *hw = &pf->hw;
+       u8 tmr_idx;
+       u32 value;
+       int err;
+
+       if (!pf->ptp.clock)
+               return;
+
+       tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc;
+       if (!tmr_idx)
+               param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0;
+       else
+               param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1;
+
+       value = (u32)ptp_clock_index(pf->ptp.clock);
+       if (value > INT_MAX) {
+               dev_err(dev, "PTP Clock index is too large to store\n");
+               return;
+       }
+       value |= PTP_SHARED_CLK_IDX_VALID;
+
+       err = ice_aq_set_driver_param(hw, param_idx, value, NULL);
+       if (err) {
+               dev_err(dev, "Failed to set PTP clock index parameter, err %d aq_err %s\n",
+                       err, ice_aq_str(hw->adminq.sq_last_status));
+       }
+}
+
+/**
+ * ice_clear_ptp_clock_index - Clear the PTP clock index
+ * @pf: the PF pointer
+ *
+ * Clear the PTP clock index for this device. Must be called when
+ * unregistering the PTP clock, in order to ensure other PFs stop reporting
+ * a clock object that no longer exists.
+ */
+static void ice_clear_ptp_clock_index(struct ice_pf *pf)
+{
+       struct device *dev = ice_pf_to_dev(pf);
+       enum ice_aqc_driver_params param_idx;
+       struct ice_hw *hw = &pf->hw;
+       u8 tmr_idx;
+       int err;
+
+       /* Do not clear the index if we don't own the timer */
+       if (!hw->func_caps.ts_func_info.src_tmr_owned)
+               return;
+
+       tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc;
+       if (!tmr_idx)
+               param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0;
+       else
+               param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1;
+
+       err = ice_aq_set_driver_param(hw, param_idx, 0, NULL);
+       if (err) {
+               dev_dbg(dev, "Failed to clear PTP clock index parameter, err %d aq_err %s\n",
+                       err, ice_aq_str(hw->adminq.sq_last_status));
+       }
+}
+
 /**
  * ice_ptp_read_src_clk_reg - Read the source clock register
  * @pf: Board private structure
        if (err)
                goto err_clk;
 
+       /* Store the PTP clock index for other PFs */
+       ice_set_ptp_clock_index(pf);
+
        return 0;
 
 err_clk:
        if (!pf->ptp.clock)
                return;
 
+       ice_clear_ptp_clock_index(pf);
        ptp_clock_unregister(pf->ptp.clock);
        pf->ptp.clock = NULL;