}
 
 static void
-__ptp_ocp_adjtime_locked(struct ptp_ocp *bp, u64 adj_val)
+__ptp_ocp_adjtime_locked(struct ptp_ocp *bp, u32 adj_val)
 {
        u32 select, ctrl;
 
        iowrite32(OCP_SELECT_CLK_REG, &bp->reg->select);
 
        iowrite32(adj_val, &bp->reg->offset_ns);
-       iowrite32(adj_val & 0x7f, &bp->reg->offset_window_ns);
+       iowrite32(NSEC_PER_SEC, &bp->reg->offset_window_ns);
 
        ctrl = OCP_CTRL_ADJUST_OFFSET | OCP_CTRL_ENABLE;
        iowrite32(ctrl, &bp->reg->ctrl);
        iowrite32(select >> 16, &bp->reg->select);
 }
 
+static void
+ptp_ocp_adjtime_coarse(struct ptp_ocp *bp, u64 delta_ns)
+{
+       struct timespec64 ts;
+       unsigned long flags;
+       int err;
+
+       spin_lock_irqsave(&bp->lock, flags);
+       err = __ptp_ocp_gettime_locked(bp, &ts, NULL);
+       if (likely(!err)) {
+               timespec64_add_ns(&ts, delta_ns);
+               __ptp_ocp_settime_locked(bp, &ts);
+       }
+       spin_unlock_irqrestore(&bp->lock, flags);
+}
+
 static int
 ptp_ocp_adjtime(struct ptp_clock_info *ptp_info, s64 delta_ns)
 {
        unsigned long flags;
        u32 adj_ns, sign;
 
+       if (delta_ns > NSEC_PER_SEC || -delta_ns > NSEC_PER_SEC) {
+               ptp_ocp_adjtime_coarse(bp, delta_ns);
+               return 0;
+       }
+
        sign = delta_ns < 0 ? BIT(31) : 0;
        adj_ns = sign ? -delta_ns : delta_ns;