#define ice_pf_to_dev(pf) (&((pf)->pdev->dev))
 
-#define ice_pf_src_tmr_owned(pf) ((pf)->hw.func_caps.ts_func_info.src_tmr_owned)
-
 enum ice_feature {
        ICE_F_DSCP,
        ICE_F_PHY_RCLK,
 }
 
 extern const struct xdp_metadata_ops ice_xdp_md_ops;
+
+/**
+ * ice_is_dual - Check if given config is multi-NAC
+ * @hw: pointer to HW structure
+ *
+ * Return: true if the device is running in mutli-NAC (Network
+ * Acceleration Complex) configuration variant, false otherwise
+ * (always false for non-E825 devices).
+ */
+static inline bool ice_is_dual(struct ice_hw *hw)
+{
+       return hw->mac_type == ICE_MAC_GENERIC_3K_E825 &&
+              (hw->dev_caps.nac_topo.mode & ICE_NAC_TOPO_DUAL_M);
+}
+
+/**
+ * ice_is_primary - Check if given device belongs to the primary complex
+ * @hw: pointer to HW structure
+ *
+ * Check if given PF/HW is running on primary complex in multi-NAC
+ * configuration.
+ *
+ * Return: true if the device is dual, false otherwise (always true
+ * for non-E825 devices).
+ */
+static inline bool ice_is_primary(struct ice_hw *hw)
+{
+       return hw->mac_type != ICE_MAC_GENERIC_3K_E825 ||
+              !ice_is_dual(hw) ||
+              (hw->dev_caps.nac_topo.mode & ICE_NAC_TOPO_PRIMARY_M);
+}
+
+/**
+ * ice_pf_src_tmr_owned - Check if a primary timer is owned by PF
+ * @pf: pointer to PF structure
+ *
+ * Return: true if PF owns primary timer, false otherwise.
+ */
+static inline bool ice_pf_src_tmr_owned(struct ice_pf *pf)
+{
+       return pf->hw.func_caps.ts_func_info.src_tmr_owned &&
+              ice_is_primary(&pf->hw);
+}
+
+/**
+ * ice_get_primary_hw - Get pointer to primary ice_hw structure
+ * @pf: pointer to PF structure
+ *
+ * Return: A pointer to ice_hw structure with access to timesync
+ * register space.
+ */
+static inline struct ice_hw *ice_get_primary_hw(struct ice_pf *pf)
+{
+       if (!pf->adapter->ctrl_pf)
+               return &pf->hw;
+       else
+               return &pf->adapter->ctrl_pf->hw;
+}
 #endif /* _ICE_H_ */
 
                }
        }
 
+       hw->lane_num = ice_get_phy_lane_number(hw);
+
        return 0;
 err_unroll_fltr_mgmt_struct:
        ice_cleanup_fltr_mgmt_struct(hw);
                        continue;
 
                if (hw->pf_id == lport) {
+                       if (hw->mac_type == ICE_MAC_GENERIC_3K_E825 &&
+                           ice_is_dual(hw) && !ice_is_primary(hw))
+                               lane += ICE_PORTS_PER_QUAD;
                        kfree(options);
                        return lane;
                }
-
                lport++;
        }
 
 
        u32 hi, lo, lo2;
        u8 tmr_idx;
 
+       if (!ice_is_primary(hw))
+               hw = ice_get_primary_hw(pf);
+
        tmr_idx = ice_get_ptp_src_clock_index(hw);
        guard(spinlock)(&pf->adapter->ptp_gltsyn_time_lock);
        /* Read the system timestamp pre PHC read */
                                   msecs_to_jiffies(err ? 10 : 500));
 }
 
+/**
+ * ice_ptp_prepare_rebuild_sec - Prepare second NAC for PTP reset or rebuild
+ * @pf: Board private structure
+ * @rebuild: rebuild if true, prepare if false
+ * @reset_type: the reset type being performed
+ */
+static void ice_ptp_prepare_rebuild_sec(struct ice_pf *pf, bool rebuild,
+                                       enum ice_reset_req reset_type)
+{
+       struct list_head *entry;
+
+       list_for_each(entry, &pf->adapter->ports.ports) {
+               struct ice_ptp_port *port = list_entry(entry,
+                                                      struct ice_ptp_port,
+                                                      list_node);
+               struct ice_pf *peer_pf = ptp_port_to_pf(port);
+
+               if (!ice_is_primary(&peer_pf->hw)) {
+                       if (rebuild)
+                               ice_ptp_rebuild(peer_pf, reset_type);
+                       else
+                               ice_ptp_prepare_for_reset(peer_pf, reset_type);
+               }
+       }
+}
+
 /**
  * ice_ptp_prepare_for_reset - Prepare PTP for reset
  * @pf: Board private structure
 void ice_ptp_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
 {
        struct ice_ptp *ptp = &pf->ptp;
+       struct ice_hw *hw = &pf->hw;
        u8 src_tmr;
 
        if (ptp->state != ICE_PTP_READY)
        if (reset_type == ICE_RESET_PFR)
                return;
 
+       if (ice_pf_src_tmr_owned(pf) && hw->mac_type == ICE_MAC_GENERIC_3K_E825)
+               ice_ptp_prepare_rebuild_sec(pf, false, reset_type);
+
        ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
 
        /* Disable periodic outputs */
        dev_err(ice_pf_to_dev(pf), "PTP reset failed %d\n", err);
 }
 
-static bool ice_is_primary(struct ice_hw *hw)
-{
-       return hw->mac_type == ICE_MAC_GENERIC_3K_E825 && ice_is_dual(hw) ?
-                      !!(hw->dev_caps.nac_topo.mode & ICE_NAC_TOPO_PRIMARY_M) :
-                      true;
-}
-
 static int ice_ptp_setup_adapter(struct ice_pf *pf)
 {
        if (!ice_pf_src_tmr_owned(pf) || !ice_is_primary(&pf->hw))
 {
        struct ice_ptp *ptp = &pf->ptp;
        struct ice_hw *hw = &pf->hw;
-       int lane_num, err;
+       int err;
 
        ptp->state = ICE_PTP_INITIALIZING;
 
-       lane_num = ice_get_phy_lane_number(hw);
-       if (lane_num < 0) {
-               err = lane_num;
+       if (hw->lane_num < 0) {
+               err = hw->lane_num;
                goto err_exit;
        }
+       ptp->port.port_num = hw->lane_num;
 
-       ptp->port.port_num = (u8)lane_num;
        ice_ptp_init_hw(hw);
 
        ice_ptp_init_tx_interrupt_mode(pf);
 
  */
 void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
 {
+       struct ice_pf *pf = container_of(hw, struct ice_pf, hw);
        u32 cmd_val = ice_ptp_tmr_cmd_to_src_reg(hw, cmd);
 
+       if (!ice_is_primary(hw))
+               hw = ice_get_primary_hw(pf);
+
        wr32(hw, GLTSYN_CMD, cmd_val);
 }
 
 {
        struct ice_pf *pf = container_of(hw, struct ice_pf, hw);
 
+       if (!ice_is_primary(hw))
+               hw = ice_get_primary_hw(pf);
+
        guard(spinlock)(&pf->adapter->ptp_gltsyn_time_lock);
        wr32(hw, GLTSYN_CMD_SYNC, SYNC_EXEC_CMD);
        ice_flush(hw);
 static enum ice_sbq_dev_id ice_ptp_get_dest_dev_e825(struct ice_hw *hw,
                                                     u8 port)
 {
-       /* On a single complex E825, PHY 0 is always destination device phy_0
+       u8 curr_phy, tgt_phy;
+
+       tgt_phy = port >= hw->ptp.ports_per_phy;
+       curr_phy = hw->lane_num >= hw->ptp.ports_per_phy;
+       /* In the driver, lanes 4..7 are in fact 0..3 on a second PHY.
+        * On a single complex E825C, PHY 0 is always destination device phy_0
         * and PHY 1 is phy_0_peer.
+        * On dual complex E825C, device phy_0 points to PHY on a current
+        * complex and phy_0_peer to PHY on a different complex.
         */
-       if (port >= hw->ptp.ports_per_phy)
+       if ((!ice_is_dual(hw) && tgt_phy == 1) ||
+           (ice_is_dual(hw) && tgt_phy != curr_phy))
                return ice_sbq_dev_phy_0_peer;
        else
                return ice_sbq_dev_phy_0;
 static int ice_read_phy_and_phc_time_eth56g(struct ice_hw *hw, u8 port,
                                            u64 *phy_time, u64 *phc_time)
 {
+       struct ice_pf *pf = container_of(hw, struct ice_pf, hw);
        u64 tx_time, rx_time;
        u32 zo, lo;
        u8 tmr_idx;
        ice_ptp_exec_tmr_cmd(hw);
 
        /* Read the captured PHC time from the shadow time registers */
-       zo = rd32(hw, GLTSYN_SHTIME_0(tmr_idx));
-       lo = rd32(hw, GLTSYN_SHTIME_L(tmr_idx));
+       if (ice_is_primary(hw)) {
+               zo = rd32(hw, GLTSYN_SHTIME_0(tmr_idx));
+               lo = rd32(hw, GLTSYN_SHTIME_L(tmr_idx));
+       } else {
+               zo = rd32(ice_get_primary_hw(pf), GLTSYN_SHTIME_0(tmr_idx));
+               lo = rd32(ice_get_primary_hw(pf), GLTSYN_SHTIME_L(tmr_idx));
+       }
        *phc_time = (u64)lo << 32 | zo;
 
        /* Read the captured PHY time from the PHY shadow registers */
  */
 int ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port)
 {
+       struct ice_pf *pf = container_of(hw, struct ice_pf, hw);
        u32 lo, hi;
        u64 incval;
        u8 tmr_idx;
        if (err)
                return err;
 
-       lo = rd32(hw, GLTSYN_INCVAL_L(tmr_idx));
-       hi = rd32(hw, GLTSYN_INCVAL_H(tmr_idx));
+       if (ice_is_primary(hw)) {
+               lo = rd32(hw, GLTSYN_INCVAL_L(tmr_idx));
+               hi = rd32(hw, GLTSYN_INCVAL_H(tmr_idx));
+       } else {
+               lo = rd32(ice_get_primary_hw(pf), GLTSYN_INCVAL_L(tmr_idx));
+               hi = rd32(ice_get_primary_hw(pf), GLTSYN_INCVAL_H(tmr_idx));
+       }
        incval = (u64)hi << 32 | lo;
 
        err = ice_write_40b_ptp_reg_eth56g(hw, port, PHY_REG_TIMETUS_L, incval);
 
        }
 }
 
-static inline bool ice_is_dual(struct ice_hw *hw)
-{
-       return !!(hw->dev_caps.nac_topo.mode & ICE_NAC_TOPO_DUAL_M);
-}
-
 #define PFTSYN_SEM_BYTES       4
 
 #define ICE_PTP_CLOCK_INDEX_0  0x00
 
        u8 intrl_gran;
 
        struct ice_ptp_hw ptp;
+       s8 lane_num;
 
        /* Active package version (currently active) */
        struct ice_pkg_ver active_pkg_ver;