diff --git a/Marlin/src/core/macros.h b/Marlin/src/core/macros.h
index 3a10340559b2f7785766a0da18c233ea14941588..ecc51b2c70d465599eedcacaf8ee39c9e052e27f 100644
--- a/Marlin/src/core/macros.h
+++ b/Marlin/src/core/macros.h
@@ -244,8 +244,11 @@
 #define DECREMENT_(n) DEC_##n
 #define DECREMENT(n) DECREMENT_(n)
 
+// Feedrate
+typedef float feedRate_t;
 #define MMM_TO_MMS(MM_M) ((MM_M)/60.0f)
 #define MMS_TO_MMM(MM_S) ((MM_S)*60.0f)
+#define MMS_SCALED(V)    ((V) * 0.01f * feedrate_percentage)
 
 #define NOOP (void(0))
 
diff --git a/Marlin/src/feature/I2CPositionEncoder.cpp b/Marlin/src/feature/I2CPositionEncoder.cpp
index bc6b49bab283854738043551553f229608c2a545..1f73f1417b52dcd381d1c541ce6899609859cc17 100644
--- a/Marlin/src/feature/I2CPositionEncoder.cpp
+++ b/Marlin/src/feature/I2CPositionEncoder.cpp
@@ -329,8 +329,8 @@ bool I2CPositionEncoder::test_axis() {
   float startCoord[NUM_AXIS] = { 0 }, endCoord[NUM_AXIS] = { 0 };
 
   const float startPosition = soft_endstop[encoderAxis].min + 10,
-              endPosition = soft_endstop[encoderAxis].max - 10,
-              feedrate = FLOOR(MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY));
+              endPosition = soft_endstop[encoderAxis].max - 10;
+  const feedRate_t fr_mm_s = FLOOR(MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY));
 
   ec = false;
 
@@ -344,7 +344,7 @@ bool I2CPositionEncoder::test_axis() {
   planner.synchronize();
 
   planner.buffer_line(startCoord[X_AXIS], startCoord[Y_AXIS], startCoord[Z_AXIS],
-                      planner.get_axis_position_mm(E_AXIS), feedrate, 0);
+                      planner.get_axis_position_mm(E_AXIS), fr_mm_s, 0);
   planner.synchronize();
 
   // if the module isn't currently trusted, wait until it is (or until it should be if things are working)
@@ -356,7 +356,7 @@ bool I2CPositionEncoder::test_axis() {
 
   if (trusted) { // if trusted, commence test
     planner.buffer_line(endCoord[X_AXIS], endCoord[Y_AXIS], endCoord[Z_AXIS],
-                        planner.get_axis_position_mm(E_AXIS), feedrate, 0);
+                        planner.get_axis_position_mm(E_AXIS), fr_mm_s, 0);
     planner.synchronize();
   }
 
@@ -379,11 +379,9 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
         travelDistance, travelledDistance, total = 0,
         startCoord[NUM_AXIS] = { 0 }, endCoord[NUM_AXIS] = { 0 };
 
-  float feedrate;
-
   int32_t startCount, stopCount;
 
-  feedrate = MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY);
+  const feedRate_t fr_mm_s = MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY);
 
   bool oldec = ec;
   ec = false;
@@ -404,7 +402,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
 
   LOOP_L_N(i, iter) {
     planner.buffer_line(startCoord[X_AXIS], startCoord[Y_AXIS], startCoord[Z_AXIS],
-                        planner.get_axis_position_mm(E_AXIS), feedrate, 0);
+                        planner.get_axis_position_mm(E_AXIS), fr_mm_s, 0);
     planner.synchronize();
 
     delay(250);
@@ -413,7 +411,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
     //do_blocking_move_to(endCoord[X_AXIS],endCoord[Y_AXIS],endCoord[Z_AXIS]);
 
     planner.buffer_line(endCoord[X_AXIS], endCoord[Y_AXIS], endCoord[Z_AXIS],
-                        planner.get_axis_position_mm(E_AXIS), feedrate, 0);
+                        planner.get_axis_position_mm(E_AXIS), fr_mm_s, 0);
     planner.synchronize();
 
     //Read encoder distance
diff --git a/Marlin/src/feature/bedlevel/abl/abl.cpp b/Marlin/src/feature/bedlevel/abl/abl.cpp
index 9e7fc0d6743e2195eb0360862b212c9e841a0e0e..d1857af11294eb6c2e242d5cb41009c6e7b043dd 100644
--- a/Marlin/src/feature/bedlevel/abl/abl.cpp
+++ b/Marlin/src/feature/bedlevel/abl/abl.cpp
@@ -360,7 +360,7 @@ float bilinear_z_offset(const float raw[XYZ]) {
    * Prepare a bilinear-leveled linear move on Cartesian,
    * splitting the move where it crosses grid borders.
    */
-  void bilinear_line_to_destination(const float fr_mm_s, uint16_t x_splits, uint16_t y_splits) {
+  void bilinear_line_to_destination(const feedRate_t scaled_fr_mm_s, uint16_t x_splits, uint16_t y_splits) {
     // Get current and destination cells for this line
     int cx1 = CELL_INDEX(X, current_position[X_AXIS]),
         cy1 = CELL_INDEX(Y, current_position[Y_AXIS]),
@@ -373,8 +373,8 @@ float bilinear_z_offset(const float raw[XYZ]) {
 
     // Start and end in the same cell? No split needed.
     if (cx1 == cx2 && cy1 == cy2) {
-      buffer_line_to_destination(fr_mm_s);
       set_current_from_destination();
+      line_to_current_position(scaled_fr_mm_s);
       return;
     }
 
@@ -405,8 +405,8 @@ float bilinear_z_offset(const float raw[XYZ]) {
     else {
       // Must already have been split on these border(s)
       // This should be a rare case.
-      buffer_line_to_destination(fr_mm_s);
       set_current_from_destination();
+      line_to_current_position(scaled_fr_mm_s);
       return;
     }
 
@@ -414,11 +414,11 @@ float bilinear_z_offset(const float raw[XYZ]) {
     destination[E_AXIS] = LINE_SEGMENT_END(E);
 
     // Do the split and look for more borders
-    bilinear_line_to_destination(fr_mm_s, x_splits, y_splits);
+    bilinear_line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
 
     // Restore destination from stack
     COPY(destination, end);
-    bilinear_line_to_destination(fr_mm_s, x_splits, y_splits);
+    bilinear_line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
   }
 
 #endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES
diff --git a/Marlin/src/feature/bedlevel/abl/abl.h b/Marlin/src/feature/bedlevel/abl/abl.h
index 2ba834480f56f068102c4c8dc861661f4bf53ac9..71c7d836326a269157e7cacbba237909e2836c4d 100644
--- a/Marlin/src/feature/bedlevel/abl/abl.h
+++ b/Marlin/src/feature/bedlevel/abl/abl.h
@@ -37,7 +37,7 @@ void refresh_bed_level();
 #endif
 
 #if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
-  void bilinear_line_to_destination(const float fr_mm_s, uint16_t x_splits=0xFFFF, uint16_t y_splits=0xFFFF);
+  void bilinear_line_to_destination(const feedRate_t &scaled_fr_mm_s, uint16_t x_splits=0xFFFF, uint16_t y_splits=0xFFFF);
 #endif
 
 #define _GET_MESH_X(I) (bilinear_start[X_AXIS] + (I) * bilinear_grid_spacing[X_AXIS])
diff --git a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp
index 6a9deaed9bba792c2ea401235be2f0f0e1dee9cb..b3a1a13529dadf8b26712010bd3ec9339a5a7d99 100644
--- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp
+++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp
@@ -64,7 +64,7 @@
      * Prepare a mesh-leveled linear move in a Cartesian setup,
      * splitting the move where it crosses mesh borders.
      */
-    void mesh_bed_leveling::line_to_destination(const float fr_mm_s, uint8_t x_splits, uint8_t y_splits) {
+    void mesh_bed_leveling::line_to_destination(const feedRate_t &scaled_fr_mm_s, uint8_t x_splits, uint8_t y_splits) {
       // Get current and destination cells for this line
       int cx1 = cell_index_x(current_position[X_AXIS]),
           cy1 = cell_index_y(current_position[Y_AXIS]),
@@ -77,7 +77,7 @@
 
       // Start and end in the same cell? No split needed.
       if (cx1 == cx2 && cy1 == cy2) {
-        line_to_destination(fr_mm_s);
+        line_to_destination(scaled_fr_mm_s);
         set_current_from_destination();
         return;
       }
@@ -109,7 +109,7 @@
       else {
         // Must already have been split on these border(s)
         // This should be a rare case.
-        line_to_destination(fr_mm_s);
+        line_to_destination(scaled_fr_mm_s);
         set_current_from_destination();
         return;
       }
@@ -118,11 +118,11 @@
       destination[E_AXIS] = MBL_SEGMENT_END(E);
 
       // Do the split and look for more borders
-      line_to_destination(fr_mm_s, x_splits, y_splits);
+      line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
 
       // Restore destination from stack
       COPY(destination, end);
-      line_to_destination(fr_mm_s, x_splits, y_splits);
+      line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
     }
 
   #endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES
diff --git a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h
index 4885cd825dc269fbee220eb3c2000d86bfad4783..def380399eb262ebd6f1d48d3667ceee5bb0b664 100644
--- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h
+++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h
@@ -116,7 +116,7 @@ public:
   }
 
   #if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
-    static void line_to_destination(const float fr_mm_s, uint8_t x_splits=0xFF, uint8_t y_splits=0xFF);
+    static void line_to_destination(const feedRate_t &scaled_fr_mm_s, uint8_t x_splits=0xFF, uint8_t y_splits=0xFF);
   #endif
 };
 
diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.h b/Marlin/src/feature/bedlevel/ubl/ubl.h
index 5183dc8485bbcfc512e828d5b92186646c9ee374..6897217c38434594235f55728fe8f03e98759ff3 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl.h
+++ b/Marlin/src/feature/bedlevel/ubl/ubl.h
@@ -285,9 +285,9 @@ class unified_bed_leveling {
     }
 
     #if UBL_SEGMENTED
-      static bool prepare_segmented_line_to(const float (&rtarget)[XYZE], const float &feedrate);
+      static bool line_to_destination_segmented(const feedRate_t &scaled_fr_mm_s);
     #else
-      static void line_to_destination_cartesian(const float &fr, const uint8_t e);
+      static void line_to_destination_cartesian(const feedRate_t &scaled_fr_mm_s, const uint8_t e);
     #endif
 
     static inline bool mesh_is_valid() {
diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp
index 105aee1c77225ba82370d154bf8b62dbe272ed39..fcce41169a321a5721616f0602ca4ecc8cb6b7a9 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp
+++ b/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp
@@ -43,7 +43,7 @@
 
 #if !UBL_SEGMENTED
 
-  void unified_bed_leveling::line_to_destination_cartesian(const float &feed_rate, const uint8_t extruder) {
+  void unified_bed_leveling::line_to_destination_cartesian(const feedRate_t &scaled_fr_mm_s, const uint8_t extruder) {
     /**
      * Much of the nozzle movement will be within the same cell. So we will do as little computation
      * as possible to determine if this is the case. If this move is within the same cell, we will
@@ -79,9 +79,8 @@
             + UBL_Z_RAISE_WHEN_OFF_MESH
           #endif
         ;
-        planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + z_raise, end[E_AXIS], feed_rate, extruder);
+        planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + z_raise, end[E_AXIS], scaled_fr_mm_s, extruder);
         set_current_from_destination();
-
         return;
       }
 
@@ -103,8 +102,7 @@
 
       // Undefined parts of the Mesh in z_values[][] are NAN.
       // Replace NAN corrections with 0.0 to prevent NAN propagation.
-      planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + (isnan(z0) ? 0.0 : z0), end[E_AXIS], feed_rate, extruder);
-
+      planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + (isnan(z0) ? 0.0 : z0), end[E_AXIS], scaled_fr_mm_s, extruder);
       set_current_from_destination();
       return;
     }
@@ -194,7 +192,7 @@
             z_position = end[Z_AXIS];
           }
 
-          planner.buffer_segment(rx, ry, z_position + z0, e_position, feed_rate, extruder);
+          planner.buffer_segment(rx, ry, z_position + z0, e_position, scaled_fr_mm_s, extruder);
         } //else printf("FIRST MOVE PRUNED  ");
       }
 
@@ -242,7 +240,7 @@
             z_position = end[Z_AXIS];
           }
 
-          if (!planner.buffer_segment(rx, ry, z_position + z0, e_position, feed_rate, extruder))
+          if (!planner.buffer_segment(rx, ry, z_position + z0, e_position, scaled_fr_mm_s, extruder))
             break;
         } //else printf("FIRST MOVE PRUNED  ");
       }
@@ -297,7 +295,7 @@
           e_position = end[E_AXIS];
           z_position = end[Z_AXIS];
         }
-        if (!planner.buffer_segment(rx, next_mesh_line_y, z_position + z0, e_position, feed_rate, extruder))
+        if (!planner.buffer_segment(rx, next_mesh_line_y, z_position + z0, e_position, scaled_fr_mm_s, extruder))
           break;
         current_yi += dyi;
         yi_cnt--;
@@ -321,7 +319,7 @@
           z_position = end[Z_AXIS];
         }
 
-        if (!planner.buffer_segment(next_mesh_line_x, ry, z_position + z0, e_position, feed_rate, extruder))
+        if (!planner.buffer_segment(next_mesh_line_x, ry, z_position + z0, e_position, scaled_fr_mm_s, extruder))
           break;
         current_xi += dxi;
         xi_cnt--;
@@ -356,25 +354,25 @@
    * Returns true if did NOT move, false if moved (requires current_position update).
    */
 
-  bool _O2 unified_bed_leveling::prepare_segmented_line_to(const float (&rtarget)[XYZE], const float &feedrate) {
+  bool _O2 unified_bed_leveling::line_to_destination_segmented(const feedRate_t &scaled_fr_mm_s) {
 
-    if (!position_is_reachable(rtarget[X_AXIS], rtarget[Y_AXIS]))  // fail if moving outside reachable boundary
+    if (!position_is_reachable(destination[X_AXIS], destination[Y_AXIS]))  // fail if moving outside reachable boundary
       return true; // did not move, so current_position still accurate
 
     const float total[XYZE] = {
-      rtarget[X_AXIS] - current_position[X_AXIS],
-      rtarget[Y_AXIS] - current_position[Y_AXIS],
-      rtarget[Z_AXIS] - current_position[Z_AXIS],
-      rtarget[E_AXIS] - current_position[E_AXIS]
+      destination[X_AXIS] - current_position[X_AXIS],
+      destination[Y_AXIS] - current_position[Y_AXIS],
+      destination[Z_AXIS] - current_position[Z_AXIS],
+      destination[E_AXIS] - current_position[E_AXIS]
     };
 
     const float cartesian_xy_mm = HYPOT(total[X_AXIS], total[Y_AXIS]);  // total horizontal xy distance
 
     #if IS_KINEMATIC
-      const float seconds = cartesian_xy_mm / feedrate;                                  // seconds to move xy distance at requested rate
-      uint16_t segments = LROUND(delta_segments_per_second * seconds),                  // preferred number of segments for distance @ feedrate
-               seglimit = LROUND(cartesian_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // number of segments at minimum segment length
-      NOMORE(segments, seglimit);                                                        // limit to minimum segment length (fewer segments)
+      const float seconds = cartesian_xy_mm / scaled_fr_mm_s;                             // Duration of XY move at requested rate
+      uint16_t segments = LROUND(delta_segments_per_second * seconds),                    // Preferred number of segments for distance @ feedrate
+               seglimit = LROUND(cartesian_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // Number of segments at minimum segment length
+      NOMORE(segments, seglimit);                                                         // Limit to minimum segment length (fewer segments)
     #else
       uint16_t segments = LROUND(cartesian_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // cartesian fixed segment length
     #endif
@@ -384,7 +382,7 @@
 
     const float segment_xyz_mm = HYPOT(cartesian_xy_mm, total[Z_AXIS]) * inv_segments;   // length of each segment
     #if ENABLED(SCARA_FEEDRATE_SCALING)
-      const float inv_duration = feedrate / segment_xyz_mm;
+      const float inv_duration = scaled_fr_mm_s / segment_xyz_mm;
     #endif
 
     const float diff[XYZE] = {
@@ -404,17 +402,17 @@
       current_position[E_AXIS]
     };
 
-    // Only compute leveling per segment if ubl active and target below z_fade_height.
-    if (!planner.leveling_active || !planner.leveling_active_at_z(rtarget[Z_AXIS])) {   // no mesh leveling
+    // Just do plain segmentation if UBL is inactive or the target is above the fade height
+    if (!planner.leveling_active || !planner.leveling_active_at_z(destination[Z_AXIS])) {
       while (--segments) {
         LOOP_XYZE(i) raw[i] += diff[i];
-        planner.buffer_line(raw, feedrate, active_extruder, segment_xyz_mm
+        planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm
           #if ENABLED(SCARA_FEEDRATE_SCALING)
             , inv_duration
           #endif
         );
       }
-      planner.buffer_line(rtarget, feedrate, active_extruder, segment_xyz_mm
+      planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, segment_xyz_mm
         #if ENABLED(SCARA_FEEDRATE_SCALING)
           , inv_duration
         #endif
@@ -425,7 +423,7 @@
     // Otherwise perform per-segment leveling
 
     #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
-      const float fade_scaling_factor = planner.fade_scaling_factor_for_z(rtarget[Z_AXIS]);
+      const float fade_scaling_factor = planner.fade_scaling_factor_for_z(destination[Z_AXIS]);
     #endif
 
     // increment to first segment destination
@@ -483,8 +481,7 @@
 
       for (;;) {  // for all segments within this mesh cell
 
-        if (--segments == 0)                      // if this is last segment, use rtarget for exact
-          COPY(raw, rtarget);
+        if (--segments == 0) COPY(raw, destination); // if this is last segment, use destination for exact
 
         const float z_cxcy = (z_cxy0 + z_cxym * cy) // interpolated mesh z height along cx at cy
           #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
@@ -494,7 +491,7 @@
 
         const float z = raw[Z_AXIS];
         raw[Z_AXIS] += z_cxcy;
-        planner.buffer_line(raw, feedrate, active_extruder, segment_xyz_mm
+        planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm
           #if ENABLED(SCARA_FEEDRATE_SCALING)
             , inv_duration
           #endif
diff --git a/Marlin/src/feature/fwretract.cpp b/Marlin/src/feature/fwretract.cpp
index dc9785c1d533160f494b130cd1471e76272fd7bc..b4302cb17ad9e22bbb5cc1e20d5afd74eea2e2f7 100644
--- a/Marlin/src/feature/fwretract.cpp
+++ b/Marlin/src/feature/fwretract.cpp
@@ -128,10 +128,7 @@ void FWRetract::retract(const bool retracting
     SERIAL_ECHOLNPAIR("current_hop ", current_hop);
   //*/
 
-  const float old_feedrate_mm_s = feedrate_mm_s,
-              unscale_e = RECIPROCAL(planner.e_factor[active_extruder]),
-              unscale_fr = 100.0 / feedrate_percentage, // Disable feedrate scaling for retract moves
-              base_retract = (
+  const float base_retract = (
                 (swapping ? settings.swap_retract_length : settings.retract_length)
                 #if ENABLED(RETRACT_SYNC_MIXING)
                   * (MIXING_STEPPERS)
@@ -146,53 +143,53 @@ void FWRetract::retract(const bool retracting
     mixer.T(MIXER_AUTORETRACT_TOOL);
   #endif
 
+  const feedRate_t fr_max_z = planner.settings.max_feedrate_mm_s[Z_AXIS];
   if (retracting) {
     // Retract by moving from a faux E position back to the current E position
-    feedrate_mm_s = (
-      settings.retract_feedrate_mm_s * unscale_fr
+    current_retract[active_extruder] = base_retract;
+    prepare_internal_move_to_destination(  // set_current_to_destination
+      settings.retract_feedrate_mm_s
       #if ENABLED(RETRACT_SYNC_MIXING)
         * (MIXING_STEPPERS)
       #endif
     );
-    current_retract[active_extruder] = base_retract * unscale_e;
-    prepare_move_to_destination();                        // set_current_to_destination
 
     // Is a Z hop set, and has the hop not yet been done?
-    if (settings.retract_zraise > 0.01 && !current_hop) {           // Apply hop only once
-      current_hop += settings.retract_zraise;                       // Add to the hop total (again, only once)
-      feedrate_mm_s = planner.settings.max_feedrate_mm_s[Z_AXIS] * unscale_fr;  // Maximum Z feedrate
-      prepare_move_to_destination();                      // Raise up, set_current_to_destination
+    if (!current_hop && settings.retract_zraise > 0.01f) {  // Apply hop only once
+      current_hop += settings.retract_zraise;               // Add to the hop total (again, only once)
+      // Raise up, set_current_to_destination. Maximum Z feedrate
+      prepare_internal_move_to_destination(fr_max_z);
     }
   }
   else {
     // If a hop was done and Z hasn't changed, undo the Z hop
     if (current_hop) {
-      current_hop = 0.0;
-      feedrate_mm_s = planner.settings.max_feedrate_mm_s[Z_AXIS] * unscale_fr;  // Z feedrate to max
-      prepare_move_to_destination();                      // Lower Z, set_current_to_destination
+      current_hop = 0;
+      // Lower Z, set_current_to_destination. Maximum Z feedrate
+      prepare_internal_move_to_destination(fr_max_z);
     }
 
     const float extra_recover = swapping ? settings.swap_retract_recover_extra : settings.retract_recover_extra;
-    if (extra_recover != 0.0) {
+    if (extra_recover) {
       current_position[E_AXIS] -= extra_recover;          // Adjust the current E position by the extra amount to recover
       sync_plan_position_e();                             // Sync the planner position so the extra amount is recovered
     }
 
-    current_retract[active_extruder] = 0.0;
-    feedrate_mm_s = (
-      (swapping ? settings.swap_retract_recover_feedrate_mm_s : settings.retract_recover_feedrate_mm_s) * unscale_fr
+    current_retract[active_extruder] = 0;
+
+    const feedRate_t fr_mm_s = (
+      (swapping ? settings.swap_retract_recover_feedrate_mm_s : settings.retract_recover_feedrate_mm_s)
       #if ENABLED(RETRACT_SYNC_MIXING)
         * (MIXING_STEPPERS)
       #endif
     );
-    prepare_move_to_destination();                        // Recover E, set_current_to_destination
+    prepare_internal_move_to_destination(fr_mm_s);        // Recover E, set_current_to_destination
   }
 
   #if ENABLED(RETRACT_SYNC_MIXING)
     mixer.T(old_mixing_tool);                             // Restore original mixing tool
   #endif
 
-  feedrate_mm_s = old_feedrate_mm_s;                      // Restore original feedrate
   retracted[active_extruder] = retracting;                // Active extruder now retracted / recovered
 
   // If swap retract/recover update the retracted_swap flag too
diff --git a/Marlin/src/feature/fwretract.h b/Marlin/src/feature/fwretract.h
index dacbec1fefcb839959777673fc2483206803aee2..374667513de2290d5a531ec726fed41880fb0a01 100644
--- a/Marlin/src/feature/fwretract.h
+++ b/Marlin/src/feature/fwretract.h
@@ -28,14 +28,14 @@
 #include "../inc/MarlinConfigPre.h"
 
 typedef struct {
-  float retract_length,                     // M207 S - G10 Retract length
-        retract_feedrate_mm_s,              // M207 F - G10 Retract feedrate
-        retract_zraise,                     // M207 Z - G10 Retract hop size
-        retract_recover_extra,              // M208 S - G11 Recover length
-        retract_recover_feedrate_mm_s,      // M208 F - G11 Recover feedrate
-        swap_retract_length,                // M207 W - G10 Swap Retract length
-        swap_retract_recover_extra,         // M208 W - G11 Swap Recover length
-        swap_retract_recover_feedrate_mm_s; // M208 R - G11 Swap Recover feedrate
+       float retract_length;                      // M207 S - G10 Retract length
+  feedRate_t retract_feedrate_mm_s;               // M207 F - G10 Retract feedrate
+       float retract_zraise,                      // M207 Z - G10 Retract hop size
+             retract_recover_extra;               // M208 S - G11 Recover length
+  feedRate_t retract_recover_feedrate_mm_s;       // M208 F - G11 Recover feedrate
+       float swap_retract_length,                 // M207 W - G10 Swap Retract length
+             swap_retract_recover_extra;          // M208 W - G11 Swap Recover length
+  feedRate_t swap_retract_recover_feedrate_mm_s;  // M208 R - G11 Swap Recover feedrate
 } fwretract_settings_t;
 
 #if ENABLED(FWRETRACT)
diff --git a/Marlin/src/feature/pause.cpp b/Marlin/src/feature/pause.cpp
index 8c014af96d053bdfcf624d9f2f78a37d25ad7bba..cf9f1838d408274cbdaa684a035cfb60561f9172 100644
--- a/Marlin/src/feature/pause.cpp
+++ b/Marlin/src/feature/pause.cpp
@@ -122,7 +122,7 @@ static bool ensure_safe_temperature(const PauseMode mode=PAUSE_MODE_SAME) {
   return thermalManager.wait_for_hotend(active_extruder);
 }
 
-void do_pause_e_move(const float &length, const float &fr_mm_s) {
+void do_pause_e_move(const float &length, const feedRate_t &fr_mm_s) {
   #if HAS_FILAMENT_SENSOR
     runout.reset();
   #endif
@@ -648,16 +648,16 @@ void resume_print(const float &slow_load_length/*=0*/, const float &fast_load_le
   #endif
 
   // If resume_position is negative
-  if (resume_position[E_AXIS] < 0) do_pause_e_move(resume_position[E_AXIS], PAUSE_PARK_RETRACT_FEEDRATE);
+  if (resume_position[E_AXIS] < 0) do_pause_e_move(resume_position[E_AXIS], feedRate_t(PAUSE_PARK_RETRACT_FEEDRATE));
 
   // Move XY to starting position, then Z
-  do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], NOZZLE_PARK_XY_FEEDRATE);
+  do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], feedRate_t(NOZZLE_PARK_XY_FEEDRATE));
 
   // Move Z_AXIS to saved position
-  do_blocking_move_to_z(resume_position[Z_AXIS], NOZZLE_PARK_Z_FEEDRATE);
+  do_blocking_move_to_z(resume_position[Z_AXIS], feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
 
   #if ADVANCED_PAUSE_RESUME_PRIME != 0
-    do_pause_e_move(ADVANCED_PAUSE_RESUME_PRIME, ADVANCED_PAUSE_PURGE_FEEDRATE);
+    do_pause_e_move(ADVANCED_PAUSE_RESUME_PRIME, feedRate_t(ADVANCED_PAUSE_PURGE_FEEDRATE));
   #endif
 
   // Now all extrusion positions are resumed and ready to be confirmed
diff --git a/Marlin/src/feature/pause.h b/Marlin/src/feature/pause.h
index 77cbe6b3f513e2fa5c4783d29f3b68a8895c52e8..deb19f46a8dc26efbe20c768e541b85c17196664 100644
--- a/Marlin/src/feature/pause.h
+++ b/Marlin/src/feature/pause.h
@@ -81,7 +81,7 @@ extern uint8_t did_pause_print;
   #define DXC_PASS
 #endif
 
-void do_pause_e_move(const float &length, const float &fr_mm_s);
+void do_pause_e_move(const float &length, const feedRate_t &fr_mm_s);
 
 bool pause_print(const float &retract, const point_t &park_point, const float &unload_length=0, const bool show_lcd=false DXC_PARAMS);
 
diff --git a/Marlin/src/feature/prusa_MMU2/mmu2.cpp b/Marlin/src/feature/prusa_MMU2/mmu2.cpp
index 37374d6e50e810651d8c720711f4a07ef8e1f66f..604138896d92ff638c5d4e0e42861708a7b0ecc2 100644
--- a/Marlin/src/feature/prusa_MMU2/mmu2.cpp
+++ b/Marlin/src/feature/prusa_MMU2/mmu2.cpp
@@ -102,8 +102,8 @@ char MMU2::rx_buffer[16], MMU2::tx_buffer[16];
 #if HAS_LCD_MENU && ENABLED(MMU2_MENUS)
 
   struct E_Step {
-    float extrude;    //!< extrude distance in mm
-    float feedRate;   //!< feed rate in mm/s
+    float extrude;        //!< extrude distance in mm
+    feedRate_t feedRate;  //!< feed rate in mm/s
   };
 
   static constexpr E_Step ramming_sequence[] PROGMEM = { MMU2_RAMMING_SEQUENCE };
@@ -606,10 +606,10 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
         BUZZ(200, 404);
 
         // Move XY to starting position, then Z
-        do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], NOZZLE_PARK_XY_FEEDRATE);
+        do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], feedRate_t(NOZZLE_PARK_XY_FEEDRATE));
 
         // Move Z_AXIS to saved position
-        do_blocking_move_to_z(resume_position[Z_AXIS], NOZZLE_PARK_Z_FEEDRATE);
+        do_blocking_move_to_z(resume_position[Z_AXIS], feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
       }
       else {
         BUZZ(200, 404);
@@ -783,15 +783,14 @@ void MMU2::filament_runout() {
     const E_Step* step = sequence;
 
     for (uint8_t i = 0; i < steps; i++) {
-      const float es = pgm_read_float(&(step->extrude)),
-                  fr = pgm_read_float(&(step->feedRate));
+      const float es = pgm_read_float(&(step->extrude));
+      const feedRate_t fr_mm_m = pgm_read_float(&(step->feedRate));
 
       DEBUG_ECHO_START();
-      DEBUG_ECHOLNPAIR("E step ", es, "/", fr);
+      DEBUG_ECHOLNPAIR("E step ", es, "/", fr_mm_m);
 
       current_position[E_AXIS] += es;
-      planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS],
-                          current_position[E_AXIS], MMM_TO_MMS(fr), active_extruder);
+      line_to_current_position(MMM_TO_MMS(fr_mm_m));
       planner.synchronize();
 
       step++;
diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp
index 1b8b5be5313e4d48eae82209550e0c6c7a8b2fe2..f98ffc88cb01d9dd1a9d5dfa7787e387239c0600 100644
--- a/Marlin/src/gcode/bedlevel/G26.cpp
+++ b/Marlin/src/gcode/bedlevel/G26.cpp
@@ -216,41 +216,32 @@ mesh_index_pair find_closest_circle_to_print(const float &X, const float &Y) {
   return return_val;
 }
 
-void G26_line_to_destination(const float &feed_rate) {
-  const float save_feedrate = feedrate_mm_s;
-  feedrate_mm_s = feed_rate;
-  prepare_move_to_destination();  // will ultimately call ubl.line_to_destination_cartesian or ubl.prepare_linear_move_to for UBL_SEGMENTED
-  feedrate_mm_s = save_feedrate;
-}
-
 void move_to(const float &rx, const float &ry, const float &z, const float &e_delta) {
-  float feed_value;
   static float last_z = -999.99;
 
   bool has_xy_component = (rx != current_position[X_AXIS] || ry != current_position[Y_AXIS]); // Check if X or Y is involved in the movement.
 
   if (z != last_z) {
     last_z = z;
-    feed_value = planner.settings.max_feedrate_mm_s[Z_AXIS]/(2.0);  // Base the feed rate off of the configured Z_AXIS feed rate
+    const feedRate_t feed_value = planner.settings.max_feedrate_mm_s[Z_AXIS] * 0.5f; // Use half of the Z_AXIS max feed rate
 
     destination[X_AXIS] = current_position[X_AXIS];
     destination[Y_AXIS] = current_position[Y_AXIS];
     destination[Z_AXIS] = z;                          // We know the last_z!=z or we wouldn't be in this block of code.
     destination[E_AXIS] = current_position[E_AXIS];
 
-    G26_line_to_destination(feed_value);
+    prepare_internal_move_to_destination(feed_value);
     set_destination_from_current();
   }
 
-  // Check if X or Y is involved in the movement.
-  // Yes: a 'normal' movement. No: a retract() or recover()
-  feed_value = has_xy_component ? G26_XY_FEEDRATE : planner.settings.max_feedrate_mm_s[E_AXIS] / 1.5;
+  // If X or Y is involved do a 'normal' move. Otherwise retract/recover/hop.
+  const feedRate_t feed_value = has_xy_component ? feedRate_t(G26_XY_FEEDRATE) : planner.settings.max_feedrate_mm_s[E_AXIS] * 0.666f;
 
   destination[X_AXIS] = rx;
   destination[Y_AXIS] = ry;
   destination[E_AXIS] += e_delta;
 
-  G26_line_to_destination(feed_value);
+  prepare_internal_move_to_destination(feed_value);
   set_destination_from_current();
 }
 
@@ -433,6 +424,7 @@ inline bool turn_on_heaters() {
  */
 inline bool prime_nozzle() {
 
+  const feedRate_t fr_slow_e = planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0f;
   #if HAS_LCD_MENU
     #if ENABLED(PREVENT_LENGTHY_EXTRUDE)
       float Total_Prime = 0.0;
@@ -455,7 +447,7 @@ inline bool prime_nozzle() {
           Total_Prime += 0.25;
           if (Total_Prime >= EXTRUDE_MAXLENGTH) return G26_ERR;
         #endif
-        G26_line_to_destination(planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0);
+        prepare_internal_move_to_destination(fr_slow_e);
         set_destination_from_current();
         planner.synchronize();    // Without this synchronize, the purge is more consistent,
                                   // but because the planner has a buffer, we won't be able
@@ -478,7 +470,7 @@ inline bool prime_nozzle() {
     #endif
     set_destination_from_current();
     destination[E_AXIS] += g26_prime_length;
-    G26_line_to_destination(planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0);
+    prepare_internal_move_to_destination(fr_slow_e);
     set_destination_from_current();
     retract_filament(destination);
   }
@@ -781,12 +773,13 @@ void GcodeSuite::G26() {
         move_to(sx, sy, g26_layer_height, 0.0); // Get to the starting point with no extrusion / un-Z bump
 
         recover_filament(destination);
-        const float save_feedrate = feedrate_mm_s;
-        feedrate_mm_s = PLANNER_XY_FEEDRATE() / 10.0;
 
+        const feedRate_t old_feedrate = feedrate_mm_s;
+        feedrate_mm_s = PLANNER_XY_FEEDRATE() * 0.1f;
         plan_arc(endpoint, arc_offset, false);  // Draw a counter-clockwise arc
-        feedrate_mm_s = save_feedrate;
+        feedrate_mm_s = old_feedrate;
         set_destination_from_current();
+
         #if HAS_LCD_MENU
           if (user_canceled()) goto LEAVE; // Check if the user wants to stop the Mesh Validation
         #endif
diff --git a/Marlin/src/gcode/bedlevel/G42.cpp b/Marlin/src/gcode/bedlevel/G42.cpp
index 7f0ed12a2565c5f18b65a2e20ff36c2118e0fd9a..55bc82317c3ac10e700c071d9416c149a1cdd607 100644
--- a/Marlin/src/gcode/bedlevel/G42.cpp
+++ b/Marlin/src/gcode/bedlevel/G42.cpp
@@ -45,8 +45,10 @@ void GcodeSuite::G42() {
     }
 
     set_destination_from_current();
+
     if (hasI) destination[X_AXIS] = _GET_MESH_X(ix);
     if (hasJ) destination[Y_AXIS] = _GET_MESH_Y(iy);
+
     #if HAS_BED_PROBE
       if (parser.boolval('P')) {
         if (hasI) destination[X_AXIS] -= probe_offset[X_AXIS];
@@ -54,14 +56,14 @@ void GcodeSuite::G42() {
       }
     #endif
 
-    const float fval = parser.linearval('F');
-    if (fval > 0.0) feedrate_mm_s = MMM_TO_MMS(fval);
+    const feedRate_t fval = parser.linearval('F'),
+                     fr_mm_s = fval > 0 ? MMM_TO_MMS(fval) : 0.0f;
 
     // SCARA kinematic has "safe" XY raw moves
     #if IS_SCARA
-      prepare_uninterpolated_move_to_destination();
+      prepare_internal_fast_move_to_destination(fr_mm_s);
     #else
-      prepare_move_to_destination();
+      prepare_internal_move_to_destination(fr_mm_s);
     #endif
   }
 }
diff --git a/Marlin/src/gcode/bedlevel/mbl/G29.cpp b/Marlin/src/gcode/bedlevel/mbl/G29.cpp
index b0f612442263886581762d8ca6109d2ab32f5f01..eee542a6f56dd3199f5b7750f5111b8d09f95c6b 100644
--- a/Marlin/src/gcode/bedlevel/mbl/G29.cpp
+++ b/Marlin/src/gcode/bedlevel/mbl/G29.cpp
@@ -143,8 +143,7 @@ void GcodeSuite::G29() {
 
         #if ENABLED(MESH_G28_REST_ORIGIN)
           current_position[Z_AXIS] = 0;
-          set_destination_from_current();
-          buffer_line_to_destination(homing_feedrate(Z_AXIS));
+          line_to_current_position(homing_feedrate(Z_AXIS));
           planner.synchronize();
         #endif
 
diff --git a/Marlin/src/gcode/calibrate/G425.cpp b/Marlin/src/gcode/calibrate/G425.cpp
index 93dbde669a74c40713f71af4c14f3fec07730493..5c4272346f91a2bacd597a692cc91078edaff2c1 100644
--- a/Marlin/src/gcode/calibrate/G425.cpp
+++ b/Marlin/src/gcode/calibrate/G425.cpp
@@ -171,17 +171,16 @@ inline bool read_calibration_pin() {
  *   fast         in - Fast vs. precise measurement
  */
 float measuring_movement(const AxisEnum axis, const int dir, const bool stop_state, const bool fast) {
-  const float step  =            fast ? 0.25                      : CALIBRATION_MEASUREMENT_RESOLUTION;
-  const float mms   = MMM_TO_MMS(fast ? CALIBRATION_FEEDRATE_FAST : CALIBRATION_FEEDRATE_SLOW);
-  const float limit =            fast ? 50                        : 5;
+  const float step     = fast ? 0.25 : CALIBRATION_MEASUREMENT_RESOLUTION;
+  const feedRate_t mms = fast ? MMM_TO_MMS(CALIBRATION_FEEDRATE_FAST) : MMM_TO_MMS(CALIBRATION_FEEDRATE_SLOW);
+  const float limit    = fast ? 50 : 5;
 
   set_destination_from_current();
   for (float travel = 0; travel < limit; travel += step) {
     destination[axis] += dir * step;
     do_blocking_move_to(destination, mms);
     planner.synchronize();
-    if (read_calibration_pin() == stop_state)
-      break;
+    if (read_calibration_pin() == stop_state) break;
   }
   return destination[axis];
 }
diff --git a/Marlin/src/gcode/feature/L6470/M916-918.cpp b/Marlin/src/gcode/feature/L6470/M916-918.cpp
index b756c6cf88e54cf2b6af10fd6beaf02c31b77a8e..3b62a0f45efcde4a0ea03c19cba75ac3964294dd 100644
--- a/Marlin/src/gcode/feature/L6470/M916-918.cpp
+++ b/Marlin/src/gcode/feature/L6470/M916-918.cpp
@@ -32,7 +32,7 @@
 #define DEBUG_OUT ENABLED(L6470_CHITCHAT)
 #include "../../../core/debug_out.h"
 
-static void jiggle_axis(const char axis_char, const float &min, const float &max, const float &rate) {
+static void jiggle_axis(const char axis_char, const float &min, const float &max, const feedRate_t &fr_mm_m) {
   char gcode_string[30], str1[11], str2[11];
 
   // Turn the motor(s) both directions
@@ -84,7 +84,7 @@ void GcodeSuite::M916() {
   uint8_t driver_count = 1;
   float position_max;
   float position_min;
-  float final_feedrate;
+  feedRate_t final_fr_mm_m;
   uint8_t kval_hold;
   uint8_t ocd_th_val = 0;
   uint8_t stall_th_val = 0;
@@ -93,10 +93,10 @@ void GcodeSuite::M916() {
 
   uint8_t j;   // general purpose counter
 
-  if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
+  if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_fr_mm_m, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
     return;  // quit if invalid user input
 
-  DEBUG_ECHOLNPAIR("feedrate = ", final_feedrate);
+  DEBUG_ECHOLNPAIR("feedrate = ", final_fr_mm_m);
 
   planner.synchronize();                  // Wait for moves to finish
 
@@ -115,7 +115,7 @@ void GcodeSuite::M916() {
       L6470.set_param(axis_index[j], L6470_KVAL_HOLD, kval_hold);
 
     // Turn the motor(s) both directions
-    jiggle_axis(axis_mon[0][0], position_min, position_max, final_feedrate);
+    jiggle_axis(axis_mon[0][0], position_min, position_max, final_fr_mm_m);
 
     status_composite = 0;    // clear out the old bits
 
@@ -190,7 +190,7 @@ void GcodeSuite::M917() {
   uint8_t driver_count = 1;
   float position_max;
   float position_min;
-  float final_feedrate;
+  feedRate_t final_fr_mm_m;
   uint8_t kval_hold;
   uint8_t ocd_th_val = 0;
   uint8_t stall_th_val = 0;
@@ -199,10 +199,10 @@ void GcodeSuite::M917() {
 
   uint8_t j;   // general purpose counter
 
-  if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
+  if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_fr_mm_m, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
     return;  // quit if invalid user input
 
-  DEBUG_ECHOLNPAIR("feedrate = ", final_feedrate);
+  DEBUG_ECHOLNPAIR("feedrate = ", final_fr_mm_m);
 
   planner.synchronize();                // Wait for moves to finish
   for (j = 0; j < driver_count; j++)
@@ -225,7 +225,7 @@ void GcodeSuite::M917() {
     DEBUG_ECHOPAIR("STALL threshold : ", (stall_th_val + 1) * 31.25);
     DEBUG_ECHOLNPAIR("   OCD threshold : ", (ocd_th_val + 1) * 375);
 
-    jiggle_axis(axis_mon[0][0], position_min, position_max, final_feedrate);
+    jiggle_axis(axis_mon[0][0], position_min, position_max, final_fr_mm_m);
 
     status_composite = 0;    // clear out the old bits
 
@@ -452,7 +452,7 @@ void GcodeSuite::M918() {
   uint16_t axis_status[3];
   uint8_t driver_count = 1;
   float position_max, position_min;
-  float final_feedrate;
+  feedRate_t final_fr_mm_m;
   uint8_t kval_hold;
   uint8_t ocd_th_val = 0;
   uint8_t stall_th_val = 0;
@@ -461,7 +461,7 @@ void GcodeSuite::M918() {
 
   uint8_t j;   // general purpose counter
 
-  if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
+  if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_fr_mm_m, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
     return;  // quit if invalid user input
 
   uint8_t m_steps = parser.byteval('M');
@@ -489,10 +489,7 @@ void GcodeSuite::M918() {
   for (j = 0; j < driver_count; j++)
     L6470.set_param(axis_index[j], L6470_STEP_MODE, m_bits);   // set microsteps
 
-  DEBUG_ECHOLNPAIR("target (maximum) feedrate = ",final_feedrate);
-
-  float feedrate_inc = final_feedrate / 10, // start at 1/10 of max & go up by 1/10 per step)
-        current_feedrate = 0;
+  DEBUG_ECHOLNPAIR("target (maximum) feedrate = ", final_fr_mm_m);
 
   planner.synchronize();                  // Wait for moves to finish
 
@@ -502,18 +499,19 @@ void GcodeSuite::M918() {
   uint16_t status_composite = 0;
   DEBUG_ECHOLNPGM(".\n.\n.");             // Make the feedrate prints easier to see
 
-  do {
-    current_feedrate += feedrate_inc;
-    DEBUG_ECHOLNPAIR("...feedrate = ", current_feedrate);
+  constexpr uint8_t iterations = 10;
+  for (uint8_t i = 1; i <= iterations; i++) {
+    const feedRate_t fr_mm_m = i * final_fr_mm_m / iterations;
+    DEBUG_ECHOLNPAIR("...feedrate = ", fr_mm_m);
 
-    jiggle_axis(axis_mon[0][0], position_min, position_max, current_feedrate);
+    jiggle_axis(axis_mon[0][0], position_min, position_max, fr_mm_m);
 
     for (j = 0; j < driver_count; j++) {
       axis_status[j] = (~L6470.get_status(axis_index[j])) & 0x0800;    // bits of interest are all active low
       status_composite |= axis_status[j];
     }
     if (status_composite) break;       // quit if any errors flags are raised
-  } while (current_feedrate < final_feedrate * 0.99);
+  }
 
   DEBUG_ECHOPGM("Completed with errors");
   if (status_composite) {
diff --git a/Marlin/src/gcode/feature/camera/M240.cpp b/Marlin/src/gcode/feature/camera/M240.cpp
index b4234cb823e8a33c9799c60881bfd982dee8d4bc..3144126fe5c869e9965da960b6cdc2087eaf0a53 100644
--- a/Marlin/src/gcode/feature/camera/M240.cpp
+++ b/Marlin/src/gcode/feature/camera/M240.cpp
@@ -43,7 +43,7 @@
   #endif
 
   #ifdef PHOTO_RETRACT_MM
-    inline void e_move_m240(const float length, const float fr_mm_s) {
+    inline void e_move_m240(const float length, const feedRate_t &fr_mm_s) {
       if (length && thermalManager.hotEnoughToExtrude(active_extruder)) {
         #if ENABLED(ADVANCED_PAUSE_FEATURE)
           do_pause_e_move(length, fr_mm_s);
@@ -104,7 +104,8 @@ void GcodeSuite::M240() {
     };
 
     #ifdef PHOTO_RETRACT_MM
-      constexpr float rfr = (MMS_TO_MMM(
+      const float rval = parser.seenval('R') ? parser.value_linear_units() : _PHOTO_RETRACT_MM;
+      feedRate_t sval = (
         #if ENABLED(ADVANCED_PAUSE_FEATURE)
           PAUSE_PARK_RETRACT_FEEDRATE
         #elif ENABLED(FWRETRACT)
@@ -112,13 +113,12 @@ void GcodeSuite::M240() {
         #else
           45
         #endif
-      ));
-      const float rval = parser.seenval('R') ? parser.value_linear_units() : _PHOTO_RETRACT_MM,
-                  sval = parser.seenval('S') ? MMM_TO_MMS(parser.value_feedrate()) : rfr;
+      );
+      if (parser.seenval('S')) sval = parser.value_feedrate();
       e_move_m240(-rval, sval);
     #endif
 
-    float fr_mm_s = MMM_TO_MMS(parser.linearval('F'));
+    feedRate_t fr_mm_s = MMM_TO_MMS(parser.linearval('F'));
     if (fr_mm_s) NOLESS(fr_mm_s, 10.0f);
 
     constexpr float photo_position[XYZ] = PHOTO_POSITION;
diff --git a/Marlin/src/gcode/feature/pause/M701_M702.cpp b/Marlin/src/gcode/feature/pause/M701_M702.cpp
index 109db545a44c7462a256018d42593f409028b9a1..6add2ebfaec26db3ffecfdfa9166629fe5ed0bce 100644
--- a/Marlin/src/gcode/feature/pause/M701_M702.cpp
+++ b/Marlin/src/gcode/feature/pause/M701_M702.cpp
@@ -97,7 +97,7 @@ void GcodeSuite::M701() {
 
   // Lift Z axis
   if (park_point.z > 0)
-    do_blocking_move_to_z(_MIN(current_position[Z_AXIS] + park_point.z, Z_MAX_POS), NOZZLE_PARK_Z_FEEDRATE);
+    do_blocking_move_to_z(_MIN(current_position[Z_AXIS] + park_point.z, Z_MAX_POS), feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
 
   // Load filament
   #if ENABLED(PRUSA_MMU2)
@@ -116,7 +116,7 @@ void GcodeSuite::M701() {
 
   // Restore Z axis
   if (park_point.z > 0)
-    do_blocking_move_to_z(_MAX(current_position[Z_AXIS] - park_point.z, 0), NOZZLE_PARK_Z_FEEDRATE);
+    do_blocking_move_to_z(_MAX(current_position[Z_AXIS] - park_point.z, 0), feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
 
   #if EXTRUDERS > 1 && DISABLED(PRUSA_MMU2)
     // Restore toolhead if it was changed
@@ -196,7 +196,7 @@ void GcodeSuite::M702() {
 
   // Lift Z axis
   if (park_point.z > 0)
-    do_blocking_move_to_z(_MIN(current_position[Z_AXIS] + park_point.z, Z_MAX_POS), NOZZLE_PARK_Z_FEEDRATE);
+    do_blocking_move_to_z(_MIN(current_position[Z_AXIS] + park_point.z, Z_MAX_POS), feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
 
   // Unload filament
   #if ENABLED(PRUSA_MMU2)
@@ -226,7 +226,7 @@ void GcodeSuite::M702() {
 
   // Restore Z axis
   if (park_point.z > 0)
-    do_blocking_move_to_z(_MAX(current_position[Z_AXIS] - park_point.z, 0), NOZZLE_PARK_Z_FEEDRATE);
+    do_blocking_move_to_z(_MAX(current_position[Z_AXIS] - park_point.z, 0), feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
 
   #if EXTRUDERS > 1 && DISABLED(PRUSA_MMU2)
     // Restore toolhead if it was changed
diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp
index 61b75753e7a451990ce7b55a03a37db07a5c7e20..f542f842ce21860f4190ab6e204887da60cf77dd 100644
--- a/Marlin/src/gcode/gcode.cpp
+++ b/Marlin/src/gcode/gcode.cpp
@@ -129,7 +129,7 @@ void GcodeSuite::get_destination_from_command() {
   #endif
 
   if (parser.linearval('F') > 0)
-    feedrate_mm_s = MMM_TO_MMS(parser.value_feedrate());
+    feedrate_mm_s = parser.value_feedrate();
 
   #if ENABLED(PRINTCOUNTER)
     if (!DEBUGGING(DRYRUN))
diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h
index 2282da57ae6dbba31a2a39d387e72248f7ca5c30..f871d6d216a59c6e642c954f21502f5de0508cd1 100644
--- a/Marlin/src/gcode/gcode.h
+++ b/Marlin/src/gcode/gcode.h
@@ -370,7 +370,7 @@ private:
 
   static void G0_G1(
     #if IS_SCARA || defined(G0_FEEDRATE)
-      bool fast_move=false
+      const bool fast_move=false
     #endif
   );
 
diff --git a/Marlin/src/gcode/motion/G0_G1.cpp b/Marlin/src/gcode/motion/G0_G1.cpp
index 82f9bdd67d37b4e5eacffa257c169f3659cab809..fed70f553e17acb3ed71598e254b394f6a6e4f38 100644
--- a/Marlin/src/gcode/motion/G0_G1.cpp
+++ b/Marlin/src/gcode/motion/G0_G1.cpp
@@ -38,7 +38,7 @@
 extern float destination[XYZE];
 
 #if ENABLED(VARIABLE_G0_FEEDRATE)
-  float saved_g0_feedrate_mm_s = MMM_TO_MMS(G0_FEEDRATE);
+  feedRate_t fast_move_feedrate = MMM_TO_MMS(G0_FEEDRATE);
 #endif
 
 /**
@@ -46,7 +46,7 @@ extern float destination[XYZE];
  */
 void GcodeSuite::G0_G1(
   #if IS_SCARA || defined(G0_FEEDRATE)
-    bool fast_move/*=false*/
+    const bool fast_move/*=false*/
   #endif
 ) {
 
@@ -60,23 +60,23 @@ void GcodeSuite::G0_G1(
   ) {
 
     #ifdef G0_FEEDRATE
-      float saved_feedrate_mm_s;
+      feedRate_t old_feedrate;
       #if ENABLED(VARIABLE_G0_FEEDRATE)
         if (fast_move) {
-          saved_feedrate_mm_s = feedrate_mm_s;      // Back up the (old) motion mode feedrate
-          feedrate_mm_s = saved_g0_feedrate_mm_s;   // Get G0 feedrate from last usage
+          old_feedrate = feedrate_mm_s;             // Back up the (old) motion mode feedrate
+          feedrate_mm_s = fast_move_feedrate;       // Get G0 feedrate from last usage
         }
       #endif
     #endif
 
-    get_destination_from_command(); // For X Y Z E F
+    get_destination_from_command();                 // Process X Y Z E F parameters
 
     #ifdef G0_FEEDRATE
       if (fast_move) {
         #if ENABLED(VARIABLE_G0_FEEDRATE)
-          saved_g0_feedrate_mm_s = feedrate_mm_s;   // Save feedrate for the next G0
+          fast_move_feedrate = feedrate_mm_s;       // Save feedrate for the next G0
         #else
-          saved_feedrate_mm_s = feedrate_mm_s;      // Back up the (new) motion mode feedrate
+          old_feedrate = feedrate_mm_s;             // Back up the (new) motion mode feedrate
           feedrate_mm_s = MMM_TO_MMS(G0_FEEDRATE);  // Get the fixed G0 feedrate
         #endif
       }
@@ -100,14 +100,14 @@ void GcodeSuite::G0_G1(
     #endif // FWRETRACT
 
     #if IS_SCARA
-      fast_move ? prepare_uninterpolated_move_to_destination() : prepare_move_to_destination();
+      fast_move ? prepare_fast_move_to_destination() : prepare_move_to_destination();
     #else
       prepare_move_to_destination();
     #endif
 
     #ifdef G0_FEEDRATE
       // Restore the motion mode feedrate
-      if (fast_move) feedrate_mm_s = saved_feedrate_mm_s;
+      if (fast_move) feedrate_mm_s = old_feedrate;
     #endif
 
     #if ENABLED(NANODLP_Z_SYNC)
diff --git a/Marlin/src/gcode/motion/G2_G3.cpp b/Marlin/src/gcode/motion/G2_G3.cpp
index 09762a995c8e88f873491c3aed944d051306ee2b..2a713a9f4170754bb0558a6efa52446da311881d 100644
--- a/Marlin/src/gcode/motion/G2_G3.cpp
+++ b/Marlin/src/gcode/motion/G2_G3.cpp
@@ -146,10 +146,10 @@ void plan_arc(
   // Initialize the extruder axis
   raw[E_AXIS] = current_position[E_AXIS];
 
-  const float fr_mm_s = MMS_SCALED(feedrate_mm_s);
+  const feedRate_t scaled_fr_mm_s = MMS_SCALED(feedrate_mm_s);
 
   #if ENABLED(SCARA_FEEDRATE_SCALING)
-    const float inv_duration = fr_mm_s / MM_PER_ARC_SEGMENT;
+    const float inv_duration = scaled_fr_mm_s / MM_PER_ARC_SEGMENT;
   #endif
 
   millis_t next_idle_ms = millis() + 200UL;
@@ -206,7 +206,7 @@ void plan_arc(
       planner.apply_leveling(raw);
     #endif
 
-    if (!planner.buffer_line(raw, fr_mm_s, active_extruder, MM_PER_ARC_SEGMENT
+    if (!planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, MM_PER_ARC_SEGMENT
       #if ENABLED(SCARA_FEEDRATE_SCALING)
         , inv_duration
       #endif
@@ -226,7 +226,7 @@ void plan_arc(
     planner.apply_leveling(raw);
   #endif
 
-  planner.buffer_line(raw, fr_mm_s, active_extruder, MM_PER_ARC_SEGMENT
+  planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, MM_PER_ARC_SEGMENT
     #if ENABLED(SCARA_FEEDRATE_SCALING)
       , inv_duration
     #endif
diff --git a/Marlin/src/gcode/parser.h b/Marlin/src/gcode/parser.h
index 4f5128bb9c3db65c9286f0b1d4936b8c35df4a6f..a4fd629b1626d4239c1eb6485f9973f59bebc681 100644
--- a/Marlin/src/gcode/parser.h
+++ b/Marlin/src/gcode/parser.h
@@ -364,7 +364,7 @@ public:
 
   #endif // !TEMPERATURE_UNITS_SUPPORT
 
-  static inline float value_feedrate() { return value_linear_units(); }
+  static inline feedRate_t value_feedrate() { return MMM_TO_MMS(value_linear_units()); }
 
   void unknown_command_error();
 
diff --git a/Marlin/src/lcd/extensible_ui/lib/lulzbot/screens/bio_status_screen.cpp b/Marlin/src/lcd/extensible_ui/lib/lulzbot/screens/bio_status_screen.cpp
index bd32d3a8fff7f28ba294209e7e88b6b951b091a5..17d9eefbcae97d32f6d9e49975a81dd1c487e6b7 100644
--- a/Marlin/src/lcd/extensible_ui/lib/lulzbot/screens/bio_status_screen.cpp
+++ b/Marlin/src/lcd/extensible_ui/lib/lulzbot/screens/bio_status_screen.cpp
@@ -289,7 +289,7 @@ bool StatusScreen::onTouchEnd(uint8_t tag) {
 
 bool StatusScreen::onTouchHeld(uint8_t tag) {
   if (tag >= 1 && tag <= 4 && !jog_xy) return false;
-  const float s  = min_speed  + (fine_motion ? 0 : (max_speed  - min_speed)  * sq(increment));
+  const float s = min_speed + (fine_motion ? 0 : (max_speed - min_speed) * sq(increment));
   switch (tag) {
     case 1: jog(-s,  0,  0); break;
     case 2: jog( s,  0,  0); break;
@@ -301,7 +301,7 @@ bool StatusScreen::onTouchHeld(uint8_t tag) {
     case 8:
     {
       if (ExtUI::isMoving()) return false;
-      const float feedrate  =  emin_speed + (fine_motion ? 0 : (emax_speed - emin_speed) * sq(increment));
+      const feedRate_t feedrate = emin_speed + (fine_motion ? 0 : (emax_speed - emin_speed) * sq(increment));
       const float increment = 0.25 * feedrate * (tag == 7 ? -1 : 1);
       MoveAxisScreen::setManualFeedrate(E0, feedrate);
       UI_INCREMENT(AxisPosition_mm, E0);
diff --git a/Marlin/src/lcd/extensible_ui/ui_api.cpp b/Marlin/src/lcd/extensible_ui/ui_api.cpp
index 4affcb6d7de9637da4cd4357649d6ca002b39bca..0b80def5c9ec83bfca7d81e3416da63032bf0a68 100644
--- a/Marlin/src/lcd/extensible_ui/ui_api.cpp
+++ b/Marlin/src/lcd/extensible_ui/ui_api.cpp
@@ -338,6 +338,8 @@ namespace ExtUI {
     return pos;
   }
 
+  constexpr feedRate_t manual_feedrate_mm_m[XYZE] = MANUAL_FEEDRATE;
+
   void setAxisPosition_mm(const float position, const axis_t axis) {
     // Start with no limits to movement
     float min = current_position[axis] - 1000,
@@ -382,23 +384,15 @@ namespace ExtUI {
       }
     #endif
 
-    constexpr float manual_feedrate[XYZE] = MANUAL_FEEDRATE;
-    setFeedrate_mm_s(MMM_TO_MMS(manual_feedrate[axis]));
-
-    set_destination_from_current();
-    destination[axis] = constrain(position, min, max);
-    prepare_move_to_destination();
+    current_position[axis] = constrain(position, min, max);
+    line_to_current_position(MMM_TO_MMS(manual_feedrate_mm_m[axis]));
   }
 
   void setAxisPosition_mm(const float position, const extruder_t extruder) {
     setActiveTool(extruder, true);
 
-    constexpr float manual_feedrate[XYZE] = MANUAL_FEEDRATE;
-    setFeedrate_mm_s(MMM_TO_MMS(manual_feedrate[E_AXIS]));
-
-    set_destination_from_current();
-    destination[E_AXIS] = position;
-    prepare_move_to_destination();
+    current_position[E_AXIS] = position;
+    line_to_current_position(MMM_TO_MMS(manual_feedrate_mm_m[E_AXIS]));
   }
 
   void setActiveTool(const extruder_t extruder, bool no_move) {
@@ -581,20 +575,20 @@ namespace ExtUI {
     planner.settings.axis_steps_per_mm[E_AXIS_N(axis - E0)] = value;
   }
 
-  float getAxisMaxFeedrate_mm_s(const axis_t axis) {
+  feedRate_t getAxisMaxFeedrate_mm_s(const axis_t axis) {
     return planner.settings.max_feedrate_mm_s[axis];
   }
 
-  float getAxisMaxFeedrate_mm_s(const extruder_t extruder) {
+  feedRate_t getAxisMaxFeedrate_mm_s(const extruder_t extruder) {
     UNUSED_E(extruder);
     return planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)];
   }
 
-  void setAxisMaxFeedrate_mm_s(const float value, const axis_t axis) {
+  void setAxisMaxFeedrate_mm_s(const feedRate_t value, const axis_t axis) {
     planner.settings.max_feedrate_mm_s[axis] = value;
   }
 
-  void setAxisMaxFeedrate_mm_s(const float value, const extruder_t extruder) {
+  void setAxisMaxFeedrate_mm_s(const feedRate_t value, const extruder_t extruder) {
     UNUSED_E(extruder);
     planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)] = value;
   }
@@ -670,15 +664,15 @@ namespace ExtUI {
     }
   #endif
 
-  float getFeedrate_mm_s()                            { return feedrate_mm_s; }
-  float getMinFeedrate_mm_s()                         { return planner.settings.min_feedrate_mm_s; }
-  float getMinTravelFeedrate_mm_s()                   { return planner.settings.min_travel_feedrate_mm_s; }
+  feedRate_t getFeedrate_mm_s()                       { return feedrate_mm_s; }
+  feedRate_t getMinFeedrate_mm_s()                    { return planner.settings.min_feedrate_mm_s; }
+  feedRate_t getMinTravelFeedrate_mm_s()              { return planner.settings.min_travel_feedrate_mm_s; }
   float getPrintingAcceleration_mm_s2()               { return planner.settings.acceleration; }
   float getRetractAcceleration_mm_s2()                { return planner.settings.retract_acceleration; }
   float getTravelAcceleration_mm_s2()                 { return planner.settings.travel_acceleration; }
-  void setFeedrate_mm_s(const float fr)               { feedrate_mm_s = fr; }
-  void setMinFeedrate_mm_s(const float fr)            { planner.settings.min_feedrate_mm_s = fr; }
-  void setMinTravelFeedrate_mm_s(const float fr)      { planner.settings.min_travel_feedrate_mm_s = fr; }
+  void setFeedrate_mm_s(const feedRate_t fr)          { feedrate_mm_s = fr; }
+  void setMinFeedrate_mm_s(const feedRate_t fr)       { planner.settings.min_feedrate_mm_s = fr; }
+  void setMinTravelFeedrate_mm_s(const feedRate_t fr) { planner.settings.min_travel_feedrate_mm_s = fr; }
   void setPrintingAcceleration_mm_s2(const float acc) { planner.settings.acceleration = acc; }
   void setRetractAcceleration_mm_s2(const float acc)  { planner.settings.retract_acceleration = acc; }
   void setTravelAcceleration_mm_s2(const float acc)   { planner.settings.travel_acceleration = acc; }
diff --git a/Marlin/src/lcd/extensible_ui/ui_api.h b/Marlin/src/lcd/extensible_ui/ui_api.h
index 60f17b62c7288058209ebf52e19f2512c3ca94ea..38cd19b579e4ab04cae7223a2509821499f371e6 100644
--- a/Marlin/src/lcd/extensible_ui/ui_api.h
+++ b/Marlin/src/lcd/extensible_ui/ui_api.h
@@ -116,12 +116,12 @@ namespace ExtUI {
   float getAxisPosition_mm(const extruder_t);
   float getAxisSteps_per_mm(const axis_t);
   float getAxisSteps_per_mm(const extruder_t);
-  float getAxisMaxFeedrate_mm_s(const axis_t);
-  float getAxisMaxFeedrate_mm_s(const extruder_t);
+  feedRate_t getAxisMaxFeedrate_mm_s(const axis_t);
+  feedRate_t getAxisMaxFeedrate_mm_s(const extruder_t);
   float getAxisMaxAcceleration_mm_s2(const axis_t);
   float getAxisMaxAcceleration_mm_s2(const extruder_t);
-  float getMinFeedrate_mm_s();
-  float getMinTravelFeedrate_mm_s();
+  feedRate_t getMinFeedrate_mm_s();
+  feedRate_t getMinTravelFeedrate_mm_s();
   float getPrintingAcceleration_mm_s2();
   float getRetractAcceleration_mm_s2();
   float getTravelAcceleration_mm_s2();
@@ -160,13 +160,13 @@ namespace ExtUI {
   void setAxisPosition_mm(const float, const extruder_t);
   void setAxisSteps_per_mm(const float, const axis_t);
   void setAxisSteps_per_mm(const float, const extruder_t);
-  void setAxisMaxFeedrate_mm_s(const float, const axis_t);
-  void setAxisMaxFeedrate_mm_s(const float, const extruder_t);
+  void setAxisMaxFeedrate_mm_s(const feedRate_t, const axis_t);
+  void setAxisMaxFeedrate_mm_s(const feedRate_t, const extruder_t);
   void setAxisMaxAcceleration_mm_s2(const float, const axis_t);
   void setAxisMaxAcceleration_mm_s2(const float, const extruder_t);
-  void setFeedrate_mm_s(const float);
-  void setMinFeedrate_mm_s(const float);
-  void setMinTravelFeedrate_mm_s(const float);
+  void setFeedrate_mm_s(const feedRate_t);
+  void setMinFeedrate_mm_s(const feedRate_t);
+  void setMinTravelFeedrate_mm_s(const feedRate_t);
   void setPrintingAcceleration_mm_s2(const float);
   void setRetractAcceleration_mm_s2(const float);
   void setTravelAcceleration_mm_s2(const float);
diff --git a/Marlin/src/lcd/menu/menu_ubl.cpp b/Marlin/src/lcd/menu/menu_ubl.cpp
index 79b0e1421e5f35036f976b35c5bd7a5ccde16bf0..2364a818aeb1b1a3e25376cd07b0f22d9391769a 100644
--- a/Marlin/src/lcd/menu/menu_ubl.cpp
+++ b/Marlin/src/lcd/menu/menu_ubl.cpp
@@ -430,21 +430,21 @@ void _lcd_ubl_map_lcd_edit_cmd() {
  * UBL LCD Map Movement
  */
 void ubl_map_move_to_xy() {
-  REMEMBER(fr, feedrate_mm_s, MMM_TO_MMS(XY_PROBE_SPEED));
+  const feedRate_t fr_mm_s = MMM_TO_MMS(XY_PROBE_SPEED);
 
-  set_destination_from_current();          // sync destination at the start
+  set_destination_from_current(); // sync destination at the start
 
   #if ENABLED(DELTA)
     if (current_position[Z_AXIS] > delta_clip_start_height) {
       destination[Z_AXIS] = delta_clip_start_height;
-      prepare_move_to_destination();
+      prepare_internal_move_to_destination(fr_mm_s);
     }
   #endif
 
   destination[X_AXIS] = pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]);
   destination[Y_AXIS] = pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]);
 
-  prepare_move_to_destination();
+  prepare_internal_move_to_destination(fr_mm_s);
 }
 
 /**
diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp
index 79f6baf4798ad721ba24e2604ded294494066ef6..390e0f17fad5a335d800ff368a23975c6a05c88e 100644
--- a/Marlin/src/lcd/ultralcd.cpp
+++ b/Marlin/src/lcd/ultralcd.cpp
@@ -662,11 +662,9 @@ void MarlinUI::quick_feedback(const bool clear_buttons/*=true*/) {
 
     if (manual_move_axis != (int8_t)NO_AXIS && ELAPSED(millis(), manual_move_start_time) && !planner.is_full()) {
 
+      const feedRate_t fr_mm_s = MMM_TO_MMS(manual_feedrate_mm_m[manual_move_axis]);
       #if IS_KINEMATIC
 
-        const float old_feedrate = feedrate_mm_s;
-        feedrate_mm_s = MMM_TO_MMS(manual_feedrate_mm_m[manual_move_axis]);
-
         #if EXTRUDERS > 1
           const int8_t old_extruder = active_extruder;
           if (manual_move_axis == E_AXIS) active_extruder = manual_move_e_index;
@@ -685,17 +683,16 @@ void MarlinUI::quick_feedback(const bool clear_buttons/*=true*/) {
         // previous invocation is being blocked. Modifications to manual_move_offset shouldn't be made while
         // processing_manual_move is true or the planner will get out of sync.
         processing_manual_move = true;
-        prepare_move_to_destination(); // will set current_position from destination
+        prepare_internal_move_to_destination(fr_mm_s);  // will set current_position from destination
         processing_manual_move = false;
 
-        feedrate_mm_s = old_feedrate;
         #if EXTRUDERS > 1
           active_extruder = old_extruder;
         #endif
 
       #else
 
-        planner.buffer_line(current_position, MMM_TO_MMS(manual_feedrate_mm_m[manual_move_axis]), manual_move_axis == E_AXIS ? manual_move_e_index : active_extruder);
+        planner.buffer_line(current_position, fr_mm_s, manual_move_axis == E_AXIS ? manual_move_e_index : active_extruder);
         manual_move_axis = (int8_t)NO_AXIS;
 
       #endif
diff --git a/Marlin/src/lcd/ultralcd.h b/Marlin/src/lcd/ultralcd.h
index 47f5806a2ff3f4336a84d9a0c156d02f9a00fbd6..f3dcb3a381ca179a277d03ab63285092f29689e4 100644
--- a/Marlin/src/lcd/ultralcd.h
+++ b/Marlin/src/lcd/ultralcd.h
@@ -90,7 +90,7 @@
     typedef void (*menuAction_t)();
 
     // Manual Movement
-    constexpr float manual_feedrate_mm_m[XYZE] = MANUAL_FEEDRATE;
+    constexpr feedRate_t manual_feedrate_mm_m[XYZE] = MANUAL_FEEDRATE;
     extern float move_menu_scale;
 
     #if ENABLED(ADVANCED_PAUSE_FEATURE)
diff --git a/Marlin/src/libs/nozzle.cpp b/Marlin/src/libs/nozzle.cpp
index 6a59c6d07b0999c3c62148ab4ea46968798278a7..829d46e1da9924bb84840a4a72af2f4602a2275f 100644
--- a/Marlin/src/libs/nozzle.cpp
+++ b/Marlin/src/libs/nozzle.cpp
@@ -186,7 +186,7 @@ Nozzle nozzle;
 #if ENABLED(NOZZLE_PARK_FEATURE)
 
   void Nozzle::park(const uint8_t z_action, const point_t &park/*=NOZZLE_PARK_POINT*/) {
-    constexpr float fr_xy = NOZZLE_PARK_XY_FEEDRATE, fr_z = NOZZLE_PARK_Z_FEEDRATE;
+    constexpr feedRate_t fr_xy = NOZZLE_PARK_XY_FEEDRATE, fr_z = NOZZLE_PARK_Z_FEEDRATE;
 
     switch (z_action) {
       case 1: // Go to Z-park height
diff --git a/Marlin/src/module/configuration_store.cpp b/Marlin/src/module/configuration_store.cpp
index ad3f6f4dcbc50ebfb6ea8985addb72c955d507c5..3d723909b08369a318ba5f06423929030a980a46 100644
--- a/Marlin/src/module/configuration_store.cpp
+++ b/Marlin/src/module/configuration_store.cpp
@@ -124,6 +124,11 @@ typedef struct {     bool X, Y, Z, X2, Y2, Z2, Z3, E0, E1, E2, E3, E4, E5; } tmc
 // Limit an index to an array size
 #define ALIM(I,ARR) _MIN(I, COUNT(ARR) - 1)
 
+// Defaults for reset / fill in on load
+static const uint32_t   _DMA[] PROGMEM = DEFAULT_MAX_ACCELERATION;
+static const float     _DASU[] PROGMEM = DEFAULT_AXIS_STEPS_PER_UNIT;
+static const feedRate_t _DMF[] PROGMEM = DEFAULT_MAX_FEEDRATE;
+
 /**
  * Current EEPROM Layout
  *
@@ -1289,21 +1294,19 @@ void MarlinSettings::postprocess() {
       {
         // Get only the number of E stepper parameters previously stored
         // Any steppers added later are set to their defaults
-        const uint32_t def1[] = DEFAULT_MAX_ACCELERATION;
-        const float def2[] = DEFAULT_AXIS_STEPS_PER_UNIT, def3[] = DEFAULT_MAX_FEEDRATE;
-
         uint32_t tmp1[XYZ + esteppers];
+        float tmp2[XYZ + esteppers];
+        feedRate_t tmp3[XYZ + esteppers];
         EEPROM_READ(tmp1);                         // max_acceleration_mm_per_s2
         EEPROM_READ(planner.settings.min_segment_time_us);
-
-        float tmp2[XYZ + esteppers], tmp3[XYZ + esteppers];
         EEPROM_READ(tmp2);                         // axis_steps_per_mm
         EEPROM_READ(tmp3);                         // max_feedrate_mm_s
+
         if (!validating) LOOP_XYZE_N(i) {
           const bool in = (i < esteppers + XYZ);
-          planner.settings.max_acceleration_mm_per_s2[i] = in ? tmp1[i] : def1[ALIM(i, def1)];
-          planner.settings.axis_steps_per_mm[i]          = in ? tmp2[i] : def2[ALIM(i, def2)];
-          planner.settings.max_feedrate_mm_s[i]          = in ? tmp3[i] : def3[ALIM(i, def3)];
+          planner.settings.max_acceleration_mm_per_s2[i] = in ? tmp1[i] : pgm_read_dword(&_DMA[ALIM(i, _DMA)]);
+          planner.settings.axis_steps_per_mm[i]          = in ? tmp2[i] : pgm_read_float(&_DASU[ALIM(i, _DASU)]);
+          planner.settings.max_feedrate_mm_s[i]          = in ? tmp3[i] : pgm_read_float(&_DMF[ALIM(i, _DMF)]);
         }
 
         EEPROM_READ(planner.settings.acceleration);
@@ -2205,20 +2208,18 @@ void MarlinSettings::postprocess() {
  * M502 - Reset Configuration
  */
 void MarlinSettings::reset() {
-  static const float tmp1[] PROGMEM = DEFAULT_AXIS_STEPS_PER_UNIT, tmp2[] PROGMEM = DEFAULT_MAX_FEEDRATE;
-  static const uint32_t tmp3[] PROGMEM = DEFAULT_MAX_ACCELERATION;
   LOOP_XYZE_N(i) {
-    planner.settings.axis_steps_per_mm[i]          = pgm_read_float(&tmp1[ALIM(i, tmp1)]);
-    planner.settings.max_feedrate_mm_s[i]          = pgm_read_float(&tmp2[ALIM(i, tmp2)]);
-    planner.settings.max_acceleration_mm_per_s2[i] = pgm_read_dword(&tmp3[ALIM(i, tmp3)]);
+    planner.settings.max_acceleration_mm_per_s2[i] = pgm_read_dword(&_DMA[ALIM(i, _DMA)]);
+    planner.settings.axis_steps_per_mm[i]          = pgm_read_float(&_DASU[ALIM(i, _DASU)]);
+    planner.settings.max_feedrate_mm_s[i]          = pgm_read_float(&_DMF[ALIM(i, _DMF)]);
   }
 
   planner.settings.min_segment_time_us = DEFAULT_MINSEGMENTTIME;
   planner.settings.acceleration = DEFAULT_ACCELERATION;
   planner.settings.retract_acceleration = DEFAULT_RETRACT_ACCELERATION;
   planner.settings.travel_acceleration = DEFAULT_TRAVEL_ACCELERATION;
-  planner.settings.min_feedrate_mm_s = DEFAULT_MINIMUMFEEDRATE;
-  planner.settings.min_travel_feedrate_mm_s = DEFAULT_MINTRAVELFEEDRATE;
+  planner.settings.min_feedrate_mm_s = feedRate_t(DEFAULT_MINIMUMFEEDRATE);
+  planner.settings.min_travel_feedrate_mm_s = feedRate_t(DEFAULT_MINTRAVELFEEDRATE);
 
   #if HAS_CLASSIC_JERK
     #ifndef DEFAULT_XJERK
@@ -3039,7 +3040,7 @@ void MarlinSettings::reset() {
       SERIAL_ECHOLNPAIR(
           "  M207 S", LINEAR_UNIT(fwretract.settings.retract_length)
         , " W", LINEAR_UNIT(fwretract.settings.swap_retract_length)
-        , " F", MMS_TO_MMM(LINEAR_UNIT(fwretract.settings.retract_feedrate_mm_s))
+        , " F", LINEAR_UNIT(MMS_TO_MMM(fwretract.settings.retract_feedrate_mm_s))
         , " Z", LINEAR_UNIT(fwretract.settings.retract_zraise)
       );
 
@@ -3048,7 +3049,7 @@ void MarlinSettings::reset() {
       SERIAL_ECHOLNPAIR(
           "  M208 S", LINEAR_UNIT(fwretract.settings.retract_recover_extra)
         , " W", LINEAR_UNIT(fwretract.settings.swap_retract_recover_extra)
-        , " F", MMS_TO_MMM(LINEAR_UNIT(fwretract.settings.retract_recover_feedrate_mm_s))
+        , " F", LINEAR_UNIT(MMS_TO_MMM(fwretract.settings.retract_recover_feedrate_mm_s))
       );
 
       #if ENABLED(FWRETRACT_AUTORETRACT)
diff --git a/Marlin/src/module/delta.cpp b/Marlin/src/module/delta.cpp
index 66973805de56e649cca1df37403c2b0af5d19ee4..b1b943b9448e95c03e1e1b8c13b55201c903312f 100644
--- a/Marlin/src/module/delta.cpp
+++ b/Marlin/src/module/delta.cpp
@@ -231,12 +231,12 @@ void home_delta() {
   #endif
 
   // Move all carriages together linearly until an endstop is hit.
-  destination[Z_AXIS] = (delta_height
+  current_position[Z_AXIS] = (delta_height + 10
     #if HAS_BED_PROBE
       - probe_offset[Z_AXIS]
     #endif
-    + 10);
-  buffer_line_to_destination(homing_feedrate(X_AXIS));
+  );
+  line_to_current_position(homing_feedrate(X_AXIS));
   planner.synchronize();
 
   // Re-enable stealthChop if used. Disable diag1 pin on driver.
diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp
index c27d87424e496791cb40198d534eb597286c62ce..928bb65ac07a96f1a0e316a6a78a475a1cda8b28 100644
--- a/Marlin/src/module/motion.cpp
+++ b/Marlin/src/module/motion.cpp
@@ -134,12 +134,11 @@ float destination[XYZE]; // = { 0 }
 // no other feedrate is specified. Overridden for special moves.
 // Set by the last G0 through G5 command's "F" parameter.
 // Functions that override this for custom moves *must always* restore it!
-float feedrate_mm_s = MMM_TO_MMS(1500.0f);
-
+feedRate_t feedrate_mm_s = MMM_TO_MMS(1500);
 int16_t feedrate_percentage = 100;
 
 // Homing feedrate is const progmem - compare to constexpr in the header
-const float homing_feedrate_mm_s[XYZ] PROGMEM = {
+const feedRate_t homing_feedrate_mm_s[XYZ] PROGMEM = {
   #if ENABLED(DELTA)
     MMM_TO_MMS(HOMING_FEEDRATE_Z), MMM_TO_MMS(HOMING_FEEDRATE_Z),
   #else
@@ -285,29 +284,21 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
  * Move the planner to the current position from wherever it last moved
  * (or from wherever it has been told it is located).
  */
-void line_to_current_position(const float &fr_mm_s/*=feedrate_mm_s*/) {
-  planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], fr_mm_s, active_extruder);
-}
-
-/**
- * Move the planner to the position stored in the destination array, which is
- * used by G0/G1/G2/G3/G5 and many other functions to set a destination.
- */
-void buffer_line_to_destination(const float fr_mm_s) {
-  planner.buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], fr_mm_s, active_extruder);
+void line_to_current_position(const feedRate_t &fr_mm_s/*=feedrate_mm_s*/) {
+  planner.buffer_line(current_position, fr_mm_s, active_extruder);
 }
 
 #if IS_KINEMATIC
 
   /**
-   * Calculate delta, start a line, and set current_position to destination
+   * Buffer a fast move without interpolation. Set current_position to destination
    */
-  void prepare_uninterpolated_move_to_destination(const float &fr_mm_s/*=0.0*/) {
-    if (DEBUGGING(LEVELING)) DEBUG_POS("prepare_uninterpolated_move_to_destination", destination);
+  void prepare_fast_move_to_destination(const feedRate_t &scaled_fr_mm_s/*=MMS_SCALED(feedrate_mm_s)*/) {
+    if (DEBUGGING(LEVELING)) DEBUG_POS("prepare_fast_move_to_destination", destination);
 
     #if UBL_SEGMENTED
-      // ubl segmented line will do z-only moves in single segment
-      ubl.prepare_segmented_line_to(destination, MMS_SCALED(fr_mm_s ? fr_mm_s : feedrate_mm_s));
+      // UBL segmented line will do Z-only moves in single segment
+      ubl.line_to_destination_segmented(scaled_fr_mm_s);
     #else
       if ( current_position[X_AXIS] == destination[X_AXIS]
         && current_position[Y_AXIS] == destination[Y_AXIS]
@@ -315,7 +306,7 @@ void buffer_line_to_destination(const float fr_mm_s) {
         && current_position[E_AXIS] == destination[E_AXIS]
       ) return;
 
-      planner.buffer_line(destination, MMS_SCALED(fr_mm_s ? fr_mm_s : feedrate_mm_s), active_extruder);
+      planner.buffer_line(destination, scaled_fr_mm_s, active_extruder);
     #endif
 
     set_current_from_destination();
@@ -323,14 +314,40 @@ void buffer_line_to_destination(const float fr_mm_s) {
 
 #endif // IS_KINEMATIC
 
+void _internal_move_to_destination(const feedRate_t &fr_mm_s/*=0.0f*/
+  #if IS_KINEMATIC
+    , const bool is_fast/*=false*/
+  #endif
+) {
+  const feedRate_t old_feedrate = feedrate_mm_s;
+  if (fr_mm_s) feedrate_mm_s = fr_mm_s;
+
+  const uint16_t old_pct = feedrate_percentage;
+  feedrate_percentage = 100;
+
+  const float old_fac = planner.e_factor[active_extruder];
+  planner.e_factor[active_extruder] = 1.0f;
+
+  #if IS_KINEMATIC
+    if (is_fast)
+      prepare_fast_move_to_destination();
+    else
+  #endif
+      prepare_move_to_destination();
+
+  feedrate_mm_s = old_feedrate;
+  feedrate_percentage = old_pct;
+  planner.e_factor[active_extruder] = old_fac;
+}
+
 /**
  * Plan a move to (X, Y, Z) and set the current_position
  */
-void do_blocking_move_to(const float rx, const float ry, const float rz, const float &fr_mm_s/*=0.0*/) {
+void do_blocking_move_to(const float rx, const float ry, const float rz, const feedRate_t &fr_mm_s/*=0.0*/) {
   if (DEBUGGING(LEVELING)) DEBUG_XYZ(">>> do_blocking_move_to", rx, ry, rz);
 
-  const float z_feedrate  = fr_mm_s ? fr_mm_s : homing_feedrate(Z_AXIS),
-              xy_feedrate = fr_mm_s ? fr_mm_s : XY_PROBE_FEEDRATE_MM_S;
+  const feedRate_t z_feedrate = fr_mm_s ? fr_mm_s : homing_feedrate(Z_AXIS),
+                  xy_feedrate = fr_mm_s ? fr_mm_s : feedRate_t(XY_PROBE_FEEDRATE_MM_S);
 
   #if ENABLED(DELTA)
 
@@ -344,33 +361,33 @@ void do_blocking_move_to(const float rx, const float ry, const float rz, const f
 
     // when in the danger zone
     if (current_position[Z_AXIS] > delta_clip_start_height) {
-      if (rz > delta_clip_start_height) {   // staying in the danger zone
-        destination[X_AXIS] = rx;           // move directly (uninterpolated)
+      if (rz > delta_clip_start_height) {                     // staying in the danger zone
+        destination[X_AXIS] = rx;                             // move directly (uninterpolated)
         destination[Y_AXIS] = ry;
         destination[Z_AXIS] = rz;
-        prepare_uninterpolated_move_to_destination(); // set_current_from_destination()
+        prepare_internal_fast_move_to_destination();          // set_current_from_destination()
         if (DEBUGGING(LEVELING)) DEBUG_POS("danger zone move", current_position);
         return;
       }
       destination[Z_AXIS] = delta_clip_start_height;
-      prepare_uninterpolated_move_to_destination(); // set_current_from_destination()
+      prepare_internal_fast_move_to_destination();            // set_current_from_destination()
       if (DEBUGGING(LEVELING)) DEBUG_POS("zone border move", current_position);
     }
 
-    if (rz > current_position[Z_AXIS]) {    // raising?
+    if (rz > current_position[Z_AXIS]) {                      // raising?
       destination[Z_AXIS] = rz;
-      prepare_uninterpolated_move_to_destination(z_feedrate);   // set_current_from_destination()
+      prepare_internal_fast_move_to_destination(z_feedrate);  // set_current_from_destination()
       if (DEBUGGING(LEVELING)) DEBUG_POS("z raise move", current_position);
     }
 
     destination[X_AXIS] = rx;
     destination[Y_AXIS] = ry;
-    prepare_move_to_destination();         // set_current_from_destination()
+    prepare_internal_move_to_destination();                   // set_current_from_destination()
     if (DEBUGGING(LEVELING)) DEBUG_POS("xy move", current_position);
 
-    if (rz < current_position[Z_AXIS]) {    // lowering?
+    if (rz < current_position[Z_AXIS]) {                      // lowering?
       destination[Z_AXIS] = rz;
-      prepare_uninterpolated_move_to_destination(z_feedrate);   // set_current_from_destination()
+      prepare_fast_move_to_destination(z_feedrate);           // set_current_from_destination()
       if (DEBUGGING(LEVELING)) DEBUG_POS("z lower move", current_position);
     }
 
@@ -383,17 +400,17 @@ void do_blocking_move_to(const float rx, const float ry, const float rz, const f
     // If Z needs to raise, do it before moving XY
     if (destination[Z_AXIS] < rz) {
       destination[Z_AXIS] = rz;
-      prepare_uninterpolated_move_to_destination(z_feedrate);
+      prepare_internal_fast_move_to_destination(z_feedrate);
     }
 
     destination[X_AXIS] = rx;
     destination[Y_AXIS] = ry;
-    prepare_uninterpolated_move_to_destination(xy_feedrate);
+    prepare_internal_fast_move_to_destination(xy_feedrate);
 
     // If Z needs to lower, do it after moving XY
     if (destination[Z_AXIS] > rz) {
       destination[Z_AXIS] = rz;
-      prepare_uninterpolated_move_to_destination(z_feedrate);
+      prepare_internal_fast_move_to_destination(z_feedrate);
     }
 
   #else
@@ -420,16 +437,16 @@ void do_blocking_move_to(const float rx, const float ry, const float rz, const f
 
   planner.synchronize();
 }
-void do_blocking_move_to_x(const float &rx, const float &fr_mm_s/*=0.0*/) {
+void do_blocking_move_to_x(const float &rx, const feedRate_t &fr_mm_s/*=0.0*/) {
   do_blocking_move_to(rx, current_position[Y_AXIS], current_position[Z_AXIS], fr_mm_s);
 }
-void do_blocking_move_to_y(const float &ry, const float &fr_mm_s/*=0.0*/) {
+void do_blocking_move_to_y(const float &ry, const feedRate_t &fr_mm_s/*=0.0*/) {
   do_blocking_move_to(current_position[X_AXIS], ry, current_position[Z_AXIS], fr_mm_s);
 }
-void do_blocking_move_to_z(const float &rz, const float &fr_mm_s/*=0.0*/) {
+void do_blocking_move_to_z(const float &rz, const feedRate_t &fr_mm_s/*=0.0*/) {
   do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], rz, fr_mm_s);
 }
-void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm_s/*=0.0*/) {
+void do_blocking_move_to_xy(const float &rx, const float &ry, const feedRate_t &fr_mm_s/*=0.0*/) {
   do_blocking_move_to(rx, ry, current_position[Z_AXIS], fr_mm_s);
 }
 
@@ -629,31 +646,31 @@ void restore_feedrate_and_scaling() {
    * small incremental moves for DELTA or SCARA.
    *
    * For Unified Bed Leveling (Delta or Segmented Cartesian)
-   * the ubl.prepare_segmented_line_to method replaces this.
+   * the ubl.line_to_destination_segmented method replaces this.
    *
    * For Auto Bed Leveling (Bilinear) with SEGMENT_LEVELED_MOVES
    * this is replaced by segmented_line_to_destination below.
    */
-  inline bool prepare_kinematic_move_to(const float (&rtarget)[XYZE]) {
+  inline bool line_to_destination_kinematic() {
 
     // Get the top feedrate of the move in the XY plane
-    const float _feedrate_mm_s = MMS_SCALED(feedrate_mm_s);
+    const float scaled_fr_mm_s = MMS_SCALED(feedrate_mm_s);
 
-    const float xdiff = rtarget[X_AXIS] - current_position[X_AXIS],
-                ydiff = rtarget[Y_AXIS] - current_position[Y_AXIS];
+    const float xdiff = destination[X_AXIS] - current_position[X_AXIS],
+                ydiff = destination[Y_AXIS] - current_position[Y_AXIS];
 
     // If the move is only in Z/E don't split up the move
     if (!xdiff && !ydiff) {
-      planner.buffer_line(rtarget, _feedrate_mm_s, active_extruder);
+      planner.buffer_line(destination, scaled_fr_mm_s, active_extruder);
       return false; // caller will update current_position
     }
 
     // Fail if attempting move outside printable radius
-    if (!position_is_reachable(rtarget[X_AXIS], rtarget[Y_AXIS])) return true;
+    if (!position_is_reachable(destination[X_AXIS], destination[Y_AXIS])) return true;
 
     // Remaining cartesian distances
-    const float zdiff = rtarget[Z_AXIS] - current_position[Z_AXIS],
-                ediff = rtarget[E_AXIS] - current_position[E_AXIS];
+    const float zdiff = destination[Z_AXIS] - current_position[Z_AXIS],
+                ediff = destination[E_AXIS] - current_position[E_AXIS];
 
     // Get the linear distance in XYZ
     float cartesian_mm = SQRT(sq(xdiff) + sq(ydiff) + sq(zdiff));
@@ -665,7 +682,7 @@ void restore_feedrate_and_scaling() {
     if (UNEAR_ZERO(cartesian_mm)) return true;
 
     // Minimum number of seconds to move the given distance
-    const float seconds = cartesian_mm / _feedrate_mm_s;
+    const float seconds = cartesian_mm / scaled_fr_mm_s;
 
     // The number of segments-per-second times the duration
     // gives the number of segments
@@ -690,7 +707,7 @@ void restore_feedrate_and_scaling() {
                 cartesian_segment_mm = cartesian_mm * inv_segments;
 
     #if ENABLED(SCARA_FEEDRATE_SCALING)
-      const float inv_duration = _feedrate_mm_s / cartesian_segment_mm;
+      const float inv_duration = scaled_fr_mm_s / cartesian_segment_mm;
     #endif
 
     /*
@@ -717,7 +734,7 @@ void restore_feedrate_and_scaling() {
 
       LOOP_XYZE(i) raw[i] += segment_distance[i];
 
-      if (!planner.buffer_line(raw, _feedrate_mm_s, active_extruder, cartesian_segment_mm
+      if (!planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, cartesian_segment_mm
         #if ENABLED(SCARA_FEEDRATE_SCALING)
           , inv_duration
         #endif
@@ -726,7 +743,7 @@ void restore_feedrate_and_scaling() {
     }
 
     // Ensure last segment arrives at target location.
-    planner.buffer_line(rtarget, _feedrate_mm_s, active_extruder, cartesian_segment_mm
+    planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, cartesian_segment_mm
       #if ENABLED(SCARA_FEEDRATE_SCALING)
         , inv_duration
       #endif
@@ -746,7 +763,7 @@ void restore_feedrate_and_scaling() {
      * small incremental moves. This allows the planner to
      * apply more detailed bed leveling to the full move.
      */
-    inline void segmented_line_to_destination(const float &fr_mm_s, const float segment_size=LEVELED_SEGMENT_LENGTH) {
+    inline void segmented_line_to_destination(const feedRate_t &fr_mm_s, const float segment_size=LEVELED_SEGMENT_LENGTH) {
 
       const float xdiff = destination[X_AXIS] - current_position[X_AXIS],
                   ydiff = destination[Y_AXIS] - current_position[Y_AXIS];
@@ -784,7 +801,7 @@ void restore_feedrate_and_scaling() {
                   };
 
       #if ENABLED(SCARA_FEEDRATE_SCALING)
-        const float inv_duration = _feedrate_mm_s / cartesian_segment_mm;
+        const float inv_duration = scaled_fr_mm_s / cartesian_segment_mm;
       #endif
 
       // SERIAL_ECHOPAIR("mm=", cartesian_mm);
@@ -832,13 +849,14 @@ void restore_feedrate_and_scaling() {
    * Returns true if current_position[] was set to destination[]
    */
   inline bool prepare_move_to_destination_cartesian() {
+    const float scaled_fr_mm_s = MMS_SCALED(feedrate_mm_s);
     #if HAS_MESH
       if (planner.leveling_active && planner.leveling_active_at_z(destination[Z_AXIS])) {
         #if ENABLED(AUTO_BED_LEVELING_UBL)
-          ubl.line_to_destination_cartesian(MMS_SCALED(feedrate_mm_s), active_extruder);  // UBL's motion routine needs to know about
-          return true;                                                                    // all moves, including Z-only moves.
+          ubl.line_to_destination_cartesian(scaled_fr_mm_s, active_extruder); // UBL's motion routine needs to know about
+          return true;                                                        // all moves, including Z-only moves.
         #elif ENABLED(SEGMENT_LEVELED_MOVES)
-          segmented_line_to_destination(MMS_SCALED(feedrate_mm_s));
+          segmented_line_to_destination(scaled_fr_mm_s);
           return false; // caller will update current_position
         #else
           /**
@@ -847,9 +865,9 @@ void restore_feedrate_and_scaling() {
            */
           if (current_position[X_AXIS] != destination[X_AXIS] || current_position[Y_AXIS] != destination[Y_AXIS]) {
             #if ENABLED(MESH_BED_LEVELING)
-              mbl.line_to_destination(MMS_SCALED(feedrate_mm_s));
+              mbl.line_to_destination(scaled_fr_mm_s);
             #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
-              bilinear_line_to_destination(MMS_SCALED(feedrate_mm_s));
+              bilinear_line_to_destination(scaled_fr_mm_s);
             #endif
             return true;
           }
@@ -857,7 +875,7 @@ void restore_feedrate_and_scaling() {
       }
     #endif // HAS_MESH
 
-    buffer_line_to_destination(MMS_SCALED(feedrate_mm_s));
+    planner.buffer_line(destination, scaled_fr_mm_s, active_extruder);
     return false; // caller will update current_position
   }
 
@@ -971,6 +989,8 @@ void restore_feedrate_and_scaling() {
  *
  * Make sure current_position[E] and destination[E] are good
  * before calling or cold/lengthy extrusion may get missed.
+ *
+ * Before exit, current_position is set to destination.
  */
 void prepare_move_to_destination() {
   apply_motion_limits(destination);
@@ -1014,14 +1034,13 @@ void prepare_move_to_destination() {
 
   if (
     #if UBL_SEGMENTED
-      //ubl.prepare_segmented_line_to(destination, MMS_SCALED(feedrate_mm_s))   // This doesn't seem to work correctly on UBL.
-      #if IS_KINEMATIC                                                          // Use Kinematic / Cartesian cases as a workaround for now.
-        ubl.prepare_segmented_line_to(destination, MMS_SCALED(feedrate_mm_s))
+      #if IS_KINEMATIC // UBL using Kinematic / Cartesian cases as a workaround for now.
+        ubl.line_to_destination_segmented(MMS_SCALED(feedrate_mm_s))
       #else
         prepare_move_to_destination_cartesian()
       #endif
     #elif IS_KINEMATIC
-      prepare_kinematic_move_to(destination)
+      line_to_destination_kinematic()
     #else
       prepare_move_to_destination_cartesian()
     #endif
@@ -1065,7 +1084,7 @@ bool axis_unhomed_error(uint8_t axis_bits/*=0x07*/) {
 /**
  * Homing bump feedrate (mm/s)
  */
-float get_homing_bump_feedrate(const AxisEnum axis) {
+feedRate_t get_homing_bump_feedrate(const AxisEnum axis) {
   #if HOMING_Z_WITH_PROBE
     if (axis == Z_AXIS) return MMM_TO_MMS(Z_PROBE_SPEED_SLOW);
   #endif
@@ -1075,7 +1094,7 @@ float get_homing_bump_feedrate(const AxisEnum axis) {
     hbd = 10;
     SERIAL_ECHO_MSG("Warning: Homing Bump Divisor < 1");
   }
-  return homing_feedrate(axis) / hbd;
+  return homing_feedrate(axis) / float(hbd);
 }
 
 #if ENABLED(SENSORLESS_HOMING)
@@ -1221,7 +1240,7 @@ float get_homing_bump_feedrate(const AxisEnum axis) {
 /**
  * Home an individual linear axis
  */
-void do_homing_move(const AxisEnum axis, const float distance, const float fr_mm_s=0.0) {
+void do_homing_move(const AxisEnum axis, const float distance, const feedRate_t fr_mm_s=0.0) {
 
   if (DEBUGGING(LEVELING)) {
     DEBUG_ECHOPAIR(">>> do_homing_move(", axis_codes[axis], ", ", distance, ", ");
@@ -1266,12 +1285,13 @@ void do_homing_move(const AxisEnum axis, const float distance, const float fr_mm
     #endif
   }
 
+  const feedRate_t real_fr_mm_s = fr_mm_s ? fr_mm_s : homing_feedrate(axis);
   #if IS_SCARA
     // Tell the planner the axis is at 0
     current_position[axis] = 0;
     sync_plan_position();
     current_position[axis] = distance;
-    planner.buffer_line(current_position, fr_mm_s ? fr_mm_s : homing_feedrate(axis), active_extruder);
+    line_to_current_position(real_fr_mm_s);
   #else
     float target[ABCE] = { planner.get_axis_position_mm(A_AXIS), planner.get_axis_position_mm(B_AXIS), planner.get_axis_position_mm(C_AXIS), planner.get_axis_position_mm(E_AXIS) };
     target[axis] = 0;
@@ -1287,7 +1307,7 @@ void do_homing_move(const AxisEnum axis, const float distance, const float fr_mm
       #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
         , delta_mm_cart
       #endif
-      , fr_mm_s ? fr_mm_s : homing_feedrate(axis), active_extruder
+      , real_fr_mm_s, active_extruder
     );
   #endif
 
@@ -1507,7 +1527,7 @@ void homeaxis(const AxisEnum axis) {
     if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Move Away:");
     do_homing_move(axis, -bump
       #if HOMING_Z_WITH_PROBE
-        , axis == Z_AXIS ? MMM_TO_MMS(Z_PROBE_SPEED_FAST) : 0.0
+        , MMM_TO_MMS(axis == Z_AXIS ? Z_PROBE_SPEED_FAST : 0)
       #endif
     );
 
diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h
index b3d79a7a0ee3f0a69c21c1ba2302c9ee5318cd6c..9c465a1d5954e40982c9d9c0192afaf410a68add 100644
--- a/Marlin/src/module/motion.h
+++ b/Marlin/src/module/motion.h
@@ -85,17 +85,16 @@ extern float cartes[XYZ];
  * Feed rates are often configured with mm/m
  * but the planner and stepper like mm/s units.
  */
-extern const float homing_feedrate_mm_s[XYZ];
-FORCE_INLINE float homing_feedrate(const AxisEnum a) { return pgm_read_float(&homing_feedrate_mm_s[a]); }
-float get_homing_bump_feedrate(const AxisEnum axis);
+extern const feedRate_t homing_feedrate_mm_s[XYZ];
+FORCE_INLINE feedRate_t homing_feedrate(const AxisEnum a) { return pgm_read_float(&homing_feedrate_mm_s[a]); }
+feedRate_t get_homing_bump_feedrate(const AxisEnum axis);
 
-extern float feedrate_mm_s;
+extern feedRate_t feedrate_mm_s;
 
 /**
- * Feedrate scaling and conversion
+ * Feedrate scaling
  */
 extern int16_t feedrate_percentage;
-#define MMS_SCALED(MM_S) ((MM_S)*feedrate_percentage*0.01f)
 
 // The active extruder (tool). Set with T<extruder> command.
 #if EXTRUDERS > 1
@@ -172,34 +171,42 @@ void sync_plan_position_e();
  * Move the planner to the current position from wherever it last moved
  * (or from wherever it has been told it is located).
  */
-void line_to_current_position(const float &fr_mm_s=feedrate_mm_s);
+void line_to_current_position(const feedRate_t &fr_mm_s=feedrate_mm_s);
 
-/**
- * Move the planner to the position stored in the destination array, which is
- * used by G0/G1/G2/G3/G5 and many other functions to set a destination.
- */
-void buffer_line_to_destination(const float fr_mm_s);
+void prepare_move_to_destination();
+
+void _internal_move_to_destination(const feedRate_t &fr_mm_s=0.0f
+  #if IS_KINEMATIC
+    , const bool is_fast=false
+  #endif
+);
+
+inline void prepare_internal_move_to_destination(const feedRate_t &fr_mm_s=0.0f) {
+  _internal_move_to_destination(fr_mm_s);
+}
 
 #if IS_KINEMATIC
-  void prepare_uninterpolated_move_to_destination(const float &fr_mm_s=0);
-#endif
+  void prepare_fast_move_to_destination(const feedRate_t &scaled_fr_mm_s=MMS_SCALED(feedrate_mm_s));
 
-void prepare_move_to_destination();
+  inline void prepare_internal_fast_move_to_destination(const feedRate_t &fr_mm_s=0.0f) {
+    _internal_move_to_destination(fr_mm_s, true);
+  }
+#endif
 
 /**
  * Blocking movement and shorthand functions
  */
-void do_blocking_move_to(const float rx, const float ry, const float rz, const float &fr_mm_s=0);
-void do_blocking_move_to_x(const float &rx, const float &fr_mm_s=0);
-void do_blocking_move_to_y(const float &ry, const float &fr_mm_s=0);
-void do_blocking_move_to_z(const float &rz, const float &fr_mm_s=0);
-void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm_s=0);
+void do_blocking_move_to(const float rx, const float ry, const float rz, const feedRate_t &fr_mm_s=0.0f);
+void do_blocking_move_to_x(const float &rx, const feedRate_t &fr_mm_s=0.0f);
+void do_blocking_move_to_y(const float &ry, const feedRate_t &fr_mm_s=0.0f);
+void do_blocking_move_to_z(const float &rz, const feedRate_t &fr_mm_s=0.0f);
+void do_blocking_move_to_xy(const float &rx, const float &ry, const feedRate_t &fr_mm_s=0.0f);
 
-FORCE_INLINE void do_blocking_move_to(const float (&raw)[XYZ], const float &fr_mm_s=0) {
+FORCE_INLINE void do_blocking_move_to(const float (&raw)[XYZ], const feedRate_t &fr_mm_s=0) {
   do_blocking_move_to(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], fr_mm_s);
 }
 
-FORCE_INLINE void do_blocking_move_to(const float (&raw)[XYZE], const float &fr_mm_s=0) {
+FORCE_INLINE void do_blocking_move_to(const float (&raw)[XYZE], const feedRate_t &fr_mm_s=0) {
   do_blocking_move_to(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], fr_mm_s);
 }
 
diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp
index 13e411b9b88d0c97e53e6e6397f9ca6aeee81119..2715221f329f095d8c9fe577ce27a5f8bd011b7c 100644
--- a/Marlin/src/module/planner.cpp
+++ b/Marlin/src/module/planner.cpp
@@ -1570,7 +1570,7 @@ bool Planner::_buffer_steps(const int32_t (&target)[XYZE]
   #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
     , const float (&delta_mm_cart)[XYZE]
   #endif
-  , float fr_mm_s, const uint8_t extruder, const float &millimeters
+  , feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters
 ) {
 
   // If we are cleaning, do not accept queuing of movements
@@ -1634,7 +1634,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
   #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
     , const float (&delta_mm_cart)[XYZE]
   #endif
-  , float fr_mm_s, const uint8_t extruder, const float &millimeters/*=0.0*/
+  , feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters/*=0.0*/
 ) {
 
   const int32_t da = target[A_AXIS] - position[A_AXIS],
@@ -2091,7 +2091,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
     #else
       const float delta_mm_i = delta_mm[i];
     #endif
-    const float cs = ABS(current_speed[i] = delta_mm_i * inverse_secs);
+    const feedRate_t cs = ABS(current_speed[i] = delta_mm_i * inverse_secs);
     #if ENABLED(DISTINCT_E_FACTORS)
       if (i == E_AXIS) i += extruder;
     #endif
@@ -2569,7 +2569,7 @@ bool Planner::buffer_segment(const float &a, const float &b, const float &c, con
   #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
     , const float (&delta_mm_cart)[XYZE]
   #endif
-  , const float &fr_mm_s, const uint8_t extruder, const float &millimeters/*=0.0*/
+  , const feedRate_t &fr_mm_s, const uint8_t extruder, const float &millimeters/*=0.0*/
 ) {
 
   // If we are cleaning, do not accept queuing of movements
@@ -2651,9 +2651,8 @@ bool Planner::buffer_segment(const float &a, const float &b, const float &c, con
 
 /**
  * Add a new linear movement to the buffer.
- * The target is cartesian, it's translated to delta/scara if
- * needed.
- *
+ * The target is cartesian. It's translated to
+ * delta/scara if needed.
  *
  *  rx,ry,rz,e   - target position in mm or degrees
  *  fr_mm_s      - (target) speed of the move (mm/s)
@@ -2661,7 +2660,7 @@ bool Planner::buffer_segment(const float &a, const float &b, const float &c, con
  *  millimeters  - the length of the movement, if known
  *  inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
  */
-bool Planner::buffer_line(const float &rx, const float &ry, const float &rz, const float &e, const float &fr_mm_s, const uint8_t extruder, const float millimeters
+bool Planner::buffer_line(const float &rx, const float &ry, const float &rz, const float &e, const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters
   #if ENABLED(SCARA_FEEDRATE_SCALING)
     , const float &inv_duration
   #endif
@@ -2690,10 +2689,10 @@ bool Planner::buffer_line(const float &rx, const float &ry, const float &rz, con
     #if ENABLED(SCARA_FEEDRATE_SCALING)
       // For SCARA scale the feed rate from mm/s to degrees/s
       // i.e., Complete the angular vector in the given time.
-      const float duration_recip = inv_duration ? inv_duration : fr_mm_s / mm,
-                  feedrate = HYPOT(delta[A_AXIS] - position_float[A_AXIS], delta[B_AXIS] - position_float[B_AXIS]) * duration_recip;
+      const float duration_recip = inv_duration ? inv_duration : fr_mm_s / mm;
+      const feedRate_t feedrate = HYPOT(delta[A_AXIS] - position_float[A_AXIS], delta[B_AXIS] - position_float[B_AXIS]) * duration_recip;
     #else
-      const float feedrate = fr_mm_s;
+      const feedRate_t feedrate = fr_mm_s;
     #endif
     if (buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS]
       #if ENABLED(JUNCTION_DEVIATION)
diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h
index 79efe349a17232b9c43cae932a04310ee0dc345e..2f3ee471d63cb01e522981d1b8f07c8a244c4c21 100644
--- a/Marlin/src/module/planner.h
+++ b/Marlin/src/module/planner.h
@@ -170,15 +170,15 @@ typedef struct block_t {
 #define BLOCK_MOD(n) ((n)&(BLOCK_BUFFER_SIZE-1))
 
 typedef struct {
-  uint32_t max_acceleration_mm_per_s2[XYZE_N],  // (mm/s^2) M201 XYZE
-           min_segment_time_us;                 // (µs) M205 B
-  float axis_steps_per_mm[XYZE_N],              // (steps) M92 XYZE - Steps per millimeter
-        max_feedrate_mm_s[XYZE_N],              // (mm/s) M203 XYZE - Max speeds
-        acceleration,                           // (mm/s^2) M204 S - Normal acceleration. DEFAULT ACCELERATION for all printing moves.
-        retract_acceleration,                   // (mm/s^2) M204 R - Retract acceleration. Filament pull-back and push-forward while standing still in the other axes
-        travel_acceleration,                    // (mm/s^2) M204 T - Travel acceleration. DEFAULT ACCELERATION for all NON printing moves.
-        min_feedrate_mm_s,                      // (mm/s) M205 S - Minimum linear feedrate
-        min_travel_feedrate_mm_s;               // (mm/s) M205 T - Minimum travel feedrate
+   uint32_t max_acceleration_mm_per_s2[XYZE_N], // (mm/s^2) M201 XYZE
+            min_segment_time_us;                // (µs) M205 B
+      float axis_steps_per_mm[XYZE_N];          // (steps) M92 XYZE - Steps per millimeter
+ feedRate_t max_feedrate_mm_s[XYZE_N];          // (mm/s) M203 XYZE - Max speeds
+      float acceleration,                       // (mm/s^2) M204 S - Normal acceleration. DEFAULT ACCELERATION for all printing moves.
+            retract_acceleration,               // (mm/s^2) M204 R - Retract acceleration. Filament pull-back and push-forward while standing still in the other axes
+            travel_acceleration;                // (mm/s^2) M204 T - Travel acceleration. DEFAULT ACCELERATION for all NON printing moves.
+ feedRate_t min_feedrate_mm_s,                  // (mm/s) M205 S - Minimum linear feedrate
+            min_travel_feedrate_mm_s;           // (mm/s) M205 T - Minimum travel feedrate
 } planner_settings_t;
 
 #if DISABLED(SKEW_CORRECTION)
@@ -585,7 +585,7 @@ class Planner {
       #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
         , const float (&delta_mm_cart)[XYZE]
       #endif
-      , float fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
+      , feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
     );
 
     /**
@@ -608,7 +608,7 @@ class Planner {
       #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
         , const float (&delta_mm_cart)[XYZE]
       #endif
-      , float fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
+      , feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
     );
 
     /**
@@ -621,7 +621,7 @@ class Planner {
     private:
 
       // Allow do_homing_move to access internal functions, such as buffer_segment.
-      friend void do_homing_move(const AxisEnum, const float, const float);
+      friend void do_homing_move(const AxisEnum, const float, const feedRate_t);
   #endif
 
     /**
@@ -640,14 +640,14 @@ class Planner {
       #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
         , const float (&delta_mm_cart)[XYZE]
       #endif
-      , const float &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
+      , const feedRate_t &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
     );
 
     FORCE_INLINE static bool buffer_segment(const float (&abce)[ABCE]
       #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
         , const float (&delta_mm_cart)[XYZE]
       #endif
-      , const float &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
+      , const feedRate_t &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
     ) {
       return buffer_segment(abce[A_AXIS], abce[B_AXIS], abce[C_AXIS], abce[E_AXIS]
         #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
@@ -660,9 +660,8 @@ class Planner {
 
     /**
      * Add a new linear movement to the buffer.
-     * The target is cartesian, it's translated to delta/scara if
-     * needed.
-     *
+     * The target is cartesian. It's translated to
+     * delta/scara if needed.
      *
      *  rx,ry,rz,e   - target position in mm or degrees
      *  fr_mm_s      - (target) speed of the move (mm/s)
@@ -670,13 +669,13 @@ class Planner {
      *  millimeters  - the length of the movement, if known
      *  inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
      */
-    static bool buffer_line(const float &rx, const float &ry, const float &rz, const float &e, const float &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
+    static bool buffer_line(const float &rx, const float &ry, const float &rz, const float &e, const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
       #if ENABLED(SCARA_FEEDRATE_SCALING)
         , const float &inv_duration=0.0
       #endif
     );
 
-    FORCE_INLINE static bool buffer_line(const float (&cart)[XYZE], const float &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
+    FORCE_INLINE static bool buffer_line(const float (&cart)[XYZE], const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
       #if ENABLED(SCARA_FEEDRATE_SCALING)
         , const float &inv_duration=0.0
       #endif
diff --git a/Marlin/src/module/planner_bezier.cpp b/Marlin/src/module/planner_bezier.cpp
index 71a99594f5b858f460cfc05fa429b573861cf79f..6e6746bce8c6023cffe0f925d4b304604eed262f 100644
--- a/Marlin/src/module/planner_bezier.cpp
+++ b/Marlin/src/module/planner_bezier.cpp
@@ -107,13 +107,18 @@ static inline float dist1(const float &x1, const float &y1, const float &x2, con
  * the mitigation offered by MIN_STEP and the small computational
  * power available on Arduino, I think it is not wise to implement it.
  */
-void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS], const float offset[4], float fr_mm_s, uint8_t extruder) {
+void cubic_b_spline(
+  const float position[NUM_AXIS],   // current position
+  const float target[NUM_AXIS],     // target position
+  const float (&offset)[4],         // a pair of offsets
+  const feedRate_t &scaled_fr_mm_s, // mm/s scaled by feedrate %
+  const uint8_t extruder
+) {
   // Absolute first and second control points are recovered.
   const float first0 = position[X_AXIS] + offset[0],
               first1 = position[Y_AXIS] + offset[1],
               second0 = target[X_AXIS] + offset[2],
               second1 = target[Y_AXIS] + offset[3];
-  float t = 0;
 
   float bez_target[4];
   bez_target[X_AXIS] = position[X_AXIS];
@@ -122,7 +127,7 @@ void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS]
 
   millis_t next_idle_ms = millis() + 200UL;
 
-  while (t < 1) {
+  for (float t = 0; t < 1;) {
 
     thermalManager.manage_heater();
     millis_t now = millis();
@@ -197,7 +202,7 @@ void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS]
       const float (&pos)[XYZE] = bez_target;
     #endif
 
-    if (!planner.buffer_line(pos, fr_mm_s, active_extruder, step))
+    if (!planner.buffer_line(pos, scaled_fr_mm_s, active_extruder, step))
       break;
   }
 }
diff --git a/Marlin/src/module/planner_bezier.h b/Marlin/src/module/planner_bezier.h
index 492bf51146aa4d811e7aa051e14352aa9bc21f49..5e959dd0f39420921cb99f5dad4bc116c0aef50d 100644
--- a/Marlin/src/module/planner_bezier.h
+++ b/Marlin/src/module/planner_bezier.h
@@ -32,9 +32,9 @@
 #include "../core/macros.h"
 
 void cubic_b_spline(
-              const float position[NUM_AXIS], // current position
-              const float target[NUM_AXIS],   // target position
-              const float offset[4],          // a pair of offsets
-              float fr_mm_s,
-              uint8_t extruder
-            );
+  const float position[NUM_AXIS],   // current position
+  const float target[NUM_AXIS],     // target position
+  const float (&offset)[4],         // a pair of offsets
+  const feedRate_t &scaled_fr_mm_s, // mm/s scaled by feedrate %
+  const uint8_t extruder
+);
diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp
index 830f6d4c0df3b09cfdad44a1391343f675536b46..ce0d84e41bf217a9c417ae7d858e85437a4d4dc8 100644
--- a/Marlin/src/module/probe.cpp
+++ b/Marlin/src/module/probe.cpp
@@ -446,7 +446,7 @@ bool set_probe_deployed(const bool deploy) {
   const char msg_wait_for_bed_heating[25] PROGMEM = "Wait for bed heating...\n";
 #endif
 
-static bool do_probe_move(const float z, const float fr_mm_s) {
+static bool do_probe_move(const float z, const feedRate_t fr_mm_s) {
   if (DEBUGGING(LEVELING)) DEBUG_POS(">>> do_probe_move", current_position);
 
   #if HAS_HEATED_BED && ENABLED(WAIT_FOR_BED_HEATER)
diff --git a/Marlin/src/module/tool_change.h b/Marlin/src/module/tool_change.h
index 754c72009609becfc2b6839d6b4740ee934114a5..42b96e2c6ad56dec69005254b1b6e1baf3e14e46 100644
--- a/Marlin/src/module/tool_change.h
+++ b/Marlin/src/module/tool_change.h
@@ -71,12 +71,12 @@
 #elif ENABLED(MAGNETIC_PARKING_EXTRUDER)
 
   typedef struct MPESettings {
-    float parking_xpos[2],      // M951 L R
-          grab_distance,        // M951 I
-          slow_feedrate,        // M951 J
-          fast_feedrate,        // M951 H
-          travel_distance,      // M951 D
-          compensation_factor;  // M951 C
+      float parking_xpos[2],      // M951 L R
+            grab_distance;        // M951 I
+ feedRate_t slow_feedrate,        // M951 J
+            fast_feedrate;        // M951 H
+      float travel_distance,      // M951 D
+            compensation_factor;  // M951 C
   } mpe_settings_t;
 
   extern mpe_settings_t mpe_settings;