diff --git a/dumux/nonlinear/newtonsolver.hh b/dumux/nonlinear/newtonsolver.hh
index aa7dfb5eb60fcd2142f6f2717565cc4fc2017bc4..ee493a2b21049f24e0759e716d30e9f6d388afdb 100644
--- a/dumux/nonlinear/newtonsolver.hh
+++ b/dumux/nonlinear/newtonsolver.hh
@@ -39,7 +39,6 @@
 
 #include <dumux/common/parameters.hh>
 #include <dumux/common/exceptions.hh>
-#include <dumux/common/timeloop.hh>
 #include <dumux/common/typetraits/vector.hh>
 #include <dumux/common/typetraits/isvalid.hh>
 #include <dumux/linear/linearsolveracceptsmultitypematrix.hh>
@@ -110,38 +109,6 @@ public:
         }
     }
 
-    /*!
-     * \brief Constructor for instationary problems
-     */
-    NewtonSolver(std::shared_ptr<Assembler> assembler,
-                 std::shared_ptr<LinearSolver> linearSolver,
-                 std::shared_ptr<TimeLoop<Scalar>> timeLoop,
-                 const Communication& comm = Dune::MPIHelper::getCollectiveCommunication(),
-                 const std::string& paramGroup = "")
-    : endIterMsgStream_(std::ostringstream::out)
-    , assembler_(assembler)
-    , linearSolver_(linearSolver)
-    , comm_(comm)
-    , timeLoop_(timeLoop)
-    , paramGroup_(paramGroup)
-    {
-        initParams_(paramGroup);
-
-        // set the linear system (matrix & residual) in the assembler
-        assembler_->setLinearSystem();
-
-        // set a different default for the linear solver residual reduction
-        // within the Newton the linear solver doesn't need to solve too exact
-        linearSolver_->setResidualReduction(getParamFromGroup<Scalar>(paramGroup, "LinearSolver.ResidualReduction", 1e-6));
-
-        // initialize the partial reassembler
-        if (enablePartialReassembly_)
-        {
-            partialReassembler_ = std::make_unique<Reassembler>(assembler_->fvGridGeometry());
-            distanceFromLastLinearization_.resize(assembler_->fvGridGeometry().numDofs(), 0);
-        }
-    }
-
     //! the communicator for parallel runs
     const Communication& comm() const
     { return comm_; }
@@ -198,137 +165,62 @@ public:
 
     /*!
      * \brief Run the newton method to solve a non-linear system.
-     *        The controller is responsible for all the strategic decisions.
+     *        Does time step control when the newton fails to converge
      */
-    bool solve(SolutionVector& uCurrentIter, const std::unique_ptr<ConvergenceWriter>& convWriter = nullptr)
+    template<class TimeLoop>
+    void solve(SolutionVector& uCurrentIter, TimeLoop& timeLoop,
+               const std::unique_ptr<ConvergenceWriter>& convWriter = nullptr)
     {
-        try
-        {
-            // the given solution is the initial guess
-            SolutionVector uLastIter(uCurrentIter);
-            SolutionVector deltaU(uCurrentIter);
+        if (assembler_->isStationaryProblem())
+            DUNE_THROW(Dune::InvalidStateException, "Using time step control with stationary problem makes no sense!");
 
-            Dune::Timer assembleTimer(false);
-            Dune::Timer solveTimer(false);
-            Dune::Timer updateTimer(false);
+        // try solving the non-linear system
+        for (std::size_t i = 0; i <= maxTimeStepDivisions_; ++i)
+        {
+            // linearize & solve
+            const bool converged = solve_(uCurrentIter, convWriter);
 
-            if (enablePartialReassembly_)
-            {
-                partialReassembler_->resetColors();
-                std::fill(distanceFromLastLinearization_.begin(),
-                          distanceFromLastLinearization_.end(), 0.0);
-            }
-            newtonBegin(uCurrentIter);
+            if (converged)
+                return;
 
-            // execute the method as long as the controller thinks
-            // that we should do another iteration
-            while (newtonProceed(uCurrentIter, newtonConverged()))
+            else if (!converged && i < maxTimeStepDivisions_)
             {
-                // notify the controller that we're about to start
-                // a new timestep
-                newtonBeginStep(uCurrentIter);
-
-                // make the current solution to the old one
-                if (numSteps_ > 0)
-                    uLastIter = uCurrentIter;
+                // set solution to previous solution
+                uCurrentIter = assembler_->prevSol();
 
-                if (verbose_) {
-                    std::cout << "Assemble: r(x^k) = dS/dt + div F - q;   M = grad r"
-                              << std::flush;
-                }
+                // reset the grid variables to the previous solution
+                assembler_->gridVariables().resetTimeStep(uCurrentIter);
 
-                ///////////////
-                // assemble
-                ///////////////
+                if (verbose_)
+                    std::cout << "Newton solver did not converge with dt = "
+                              << timeLoop.timeStepSize() << " seconds. Retrying with time step of "
+                              << timeLoop.timeStepSize()/2 << " seconds\n";
 
-                // linearize the problem at the current solution
-                assembleTimer.start();
-                assembleLinearSystem(uCurrentIter);
-                assembleTimer.stop();
-
-                ///////////////
-                // linear solve
-                ///////////////
-
-                // Clear the current line using an ansi escape
-                // sequence.  for an explanation see
-                // http://en.wikipedia.org/wiki/ANSI_escape_code
-                const char clearRemainingLine[] = { 0x1b, '[', 'K', 0 };
-
-                if (verbose_) {
-                    std::cout << "\rSolve: M deltax^k = r";
-                    std::cout << clearRemainingLine
-                              << std::flush;
-                }
-
-                // solve the resulting linear equation system
-                solveTimer.start();
-
-                // set the delta vector to zero before solving the linear system!
-                deltaU = 0;
-
-                solveLinearSystem(deltaU);
-                solveTimer.stop();
-
-                ///////////////
-                // update
-                ///////////////
-                if (verbose_) {
-                    std::cout << "\rUpdate: x^(k+1) = x^k - deltax^k";
-                    std::cout << clearRemainingLine;
-                    std::cout.flush();
-                }
-
-                updateTimer.start();
-                // update the current solution (i.e. uOld) with the delta
-                // (i.e. u). The result is stored in u
-                newtonUpdate(uCurrentIter, uLastIter, deltaU);
-                updateTimer.stop();
-
-                // tell the controller that we're done with this iteration
-                newtonEndStep(uCurrentIter, uLastIter);
-
-                // if a convergence writer was specified compute residual and write output
-                if (convWriter)
-                {
-                    assembler_->assembleResidual(uCurrentIter);
-                    convWriter->write(uLastIter, deltaU, assembler_->residual());
-                }
+                // try again with dt = dt/2
+                timeLoop.setTimeStepSize(timeLoop.timeStepSize()/2);
             }
 
-            // tell controller we are done
-            newtonEnd();
-
-            // reset state if newton failed
-            if (!newtonConverged())
+            else
             {
-                newtonFail(uCurrentIter);
-                return false;
+                DUNE_THROW(NumericalProblem, "Newton solver didn't converge after "
+                                             << maxTimeStepDivisions_ << " time-step divisions. dt="
+                                             << timeLoop.timeStepSize() << '\n');
             }
-
-            // tell controller we converged successfully
-            newtonSucceed();
-
-            if (verbose_) {
-                const auto elapsedTot = assembleTimer.elapsed() + solveTimer.elapsed() + updateTimer.elapsed();
-                std::cout << "Assemble/solve/update time: "
-                          <<  assembleTimer.elapsed() << "(" << 100*assembleTimer.elapsed()/elapsedTot << "%)/"
-                          <<  solveTimer.elapsed() << "(" << 100*solveTimer.elapsed()/elapsedTot << "%)/"
-                          <<  updateTimer.elapsed() << "(" << 100*updateTimer.elapsed()/elapsedTot << "%)"
-                          << "\n";
-            }
-            return true;
-
-        }
-        catch (const NumericalProblem &e)
-        {
-            if (verbose_)
-                std::cout << "Newton: Caught exception: \"" << e.what() << "\"\n";
-            newtonFail(uCurrentIter);
-            return false;
         }
     }
 
+    /*!
+     * \brief Run the newton method to solve a non-linear system.
+     *        The controller is responsible for all the strategic decisions.
+     */
+    void solve(SolutionVector& uCurrentIter, const std::unique_ptr<ConvergenceWriter>& convWriter = nullptr)
+    {
+        const bool converged = solve_(uCurrentIter, convWriter);
+        if (!converged)
+            DUNE_THROW(NumericalProblem, "Newton solver didn't converge after "
+                                         << numSteps_ << " iterations.\n");
+    }
+
     /*!
      * \brief Called before the Newton method is applied to an
      *        non-linear system of equations.
@@ -626,29 +518,7 @@ public:
      * \brief Called if the Newton method broke down.
      * This method is called _after_ newtonEnd()
      */
-    virtual void newtonFail(SolutionVector& u)
-    {
-        if (!assembler_->isStationaryProblem())
-        {
-            // set solution to previous solution
-            u = assembler_->prevSol();
-
-            // reset the grid variables to the previous solution
-            assembler_->gridVariables().resetTimeStep(u);
-
-            if (verbose())
-            {
-                std::cout << "Newton solver did not converge with dt = "
-                          << timeLoop_->timeStepSize() << " seconds. Retrying with time step of "
-                          << timeLoop_->timeStepSize()/2 << " seconds\n";
-            }
-
-            // try again with dt = dt/2
-            timeLoop_->setTimeStepSize(timeLoop_->timeStepSize()/2);
-        }
-        else
-            DUNE_THROW(Dune::MathError, "Newton solver did not converge");
-    }
+    virtual void newtonFail(SolutionVector& u) {}
 
     /*!
      * \brief Called if the Newton method ended succcessfully
@@ -722,9 +592,6 @@ protected:
     Assembler& assembler()
     { return *assembler_; }
 
-    const TimeLoop<Scalar>& timeLoop() const
-    { return *timeLoop_; }
-
     //! optimal number of iterations we want to achieve
     int targetSteps_;
     //! maximum number of iterations we do before giving up
@@ -748,6 +615,140 @@ protected:
 
 private:
 
+    /*!
+     * \brief Run the newton method to solve a non-linear system.
+     *        The controller is responsible for all the strategic decisions.
+     */
+    bool solve_(SolutionVector& uCurrentIter, const std::unique_ptr<ConvergenceWriter>& convWriter = nullptr)
+    {
+        // the given solution is the initial guess
+        SolutionVector uLastIter(uCurrentIter);
+        SolutionVector deltaU(uCurrentIter);
+
+        Dune::Timer assembleTimer(false);
+        Dune::Timer solveTimer(false);
+        Dune::Timer updateTimer(false);
+
+        if (enablePartialReassembly_)
+        {
+            partialReassembler_->resetColors();
+            std::fill(distanceFromLastLinearization_.begin(),
+                      distanceFromLastLinearization_.end(), 0.0);
+        }
+
+        try
+        {
+            newtonBegin(uCurrentIter);
+
+            // execute the method as long as the controller thinks
+            // that we should do another iteration
+            while (newtonProceed(uCurrentIter, newtonConverged()))
+            {
+                // notify the controller that we're about to start
+                // a new timestep
+                newtonBeginStep(uCurrentIter);
+
+                // make the current solution to the old one
+                if (numSteps_ > 0)
+                    uLastIter = uCurrentIter;
+
+                if (verbose_) {
+                    std::cout << "Assemble: r(x^k) = dS/dt + div F - q;   M = grad r"
+                              << std::flush;
+                }
+
+                ///////////////
+                // assemble
+                ///////////////
+
+                // linearize the problem at the current solution
+                assembleTimer.start();
+                assembleLinearSystem(uCurrentIter);
+                assembleTimer.stop();
+
+                ///////////////
+                // linear solve
+                ///////////////
+
+                // Clear the current line using an ansi escape
+                // sequence.  for an explanation see
+                // http://en.wikipedia.org/wiki/ANSI_escape_code
+                const char clearRemainingLine[] = { 0x1b, '[', 'K', 0 };
+
+                if (verbose_) {
+                    std::cout << "\rSolve: M deltax^k = r";
+                    std::cout << clearRemainingLine
+                              << std::flush;
+                }
+
+                // solve the resulting linear equation system
+                solveTimer.start();
+
+                // set the delta vector to zero before solving the linear system!
+                deltaU = 0;
+
+                solveLinearSystem(deltaU);
+                solveTimer.stop();
+
+                ///////////////
+                // update
+                ///////////////
+                if (verbose_) {
+                    std::cout << "\rUpdate: x^(k+1) = x^k - deltax^k";
+                    std::cout << clearRemainingLine;
+                    std::cout.flush();
+                }
+
+                updateTimer.start();
+                // update the current solution (i.e. uOld) with the delta
+                // (i.e. u). The result is stored in u
+                newtonUpdate(uCurrentIter, uLastIter, deltaU);
+                updateTimer.stop();
+
+                // tell the controller that we're done with this iteration
+                newtonEndStep(uCurrentIter, uLastIter);
+
+                // if a convergence writer was specified compute residual and write output
+                if (convWriter)
+                {
+                    assembler_->assembleResidual(uCurrentIter);
+                    convWriter->write(uLastIter, deltaU, assembler_->residual());
+                }
+            }
+
+            // tell controller we are done
+            newtonEnd();
+
+            // reset state if newton failed
+            if (!newtonConverged())
+            {
+                newtonFail(uCurrentIter);
+                return false;
+            }
+
+            // tell controller we converged successfully
+            newtonSucceed();
+
+            if (verbose_) {
+                const auto elapsedTot = assembleTimer.elapsed() + solveTimer.elapsed() + updateTimer.elapsed();
+                std::cout << "Assemble/solve/update time: "
+                          <<  assembleTimer.elapsed() << "(" << 100*assembleTimer.elapsed()/elapsedTot << "%)/"
+                          <<  solveTimer.elapsed() << "(" << 100*solveTimer.elapsed()/elapsedTot << "%)/"
+                          <<  updateTimer.elapsed() << "(" << 100*updateTimer.elapsed()/elapsedTot << "%)"
+                          << "\n";
+            }
+            return true;
+
+        }
+        catch (const NumericalProblem &e)
+        {
+            if (verbose_)
+                std::cout << "Newton: Caught exception: \"" << e.what() << "\"\n";
+            newtonFail(uCurrentIter);
+            return false;
+        }
+    }
+
     //! assembleLinearSystem_ for assemblers that support partial reassembly
     template<class A = Assembler>
     auto assembleLinearSystem_(const SolutionVector& uCurrentIter)
@@ -1017,6 +1018,8 @@ private:
         reassemblyMaxThreshold_ = getParamFromGroup<Scalar>(group, "Newton.ReassemblyMaxThreshold", 1e2*shiftTolerance_);
         reassemblyShiftWeight_ = getParamFromGroup<Scalar>(group, "Newton.ReassemblyShiftWeight", 1e-3);
 
+        maxTimeStepDivisions_ = getParamFromGroup<std::size_t>(group, "Newton.MaxTimeStepDivisions", 10);
+
         verbose_ = comm_.rank() == 0;
         numSteps_ = 0;
     }
@@ -1073,9 +1076,6 @@ private:
     //! The communication object
     Communication comm_;
 
-    //! The time loop for stationary simulations
-    std::shared_ptr<TimeLoop<Scalar>> timeLoop_;
-
     //! switches on/off verbosity
     bool verbose_;
 
@@ -1083,6 +1083,9 @@ private:
     Scalar reductionTolerance_;
     Scalar residualTolerance_;
 
+    // time step control
+    std::size_t maxTimeStepDivisions_;
+
     // further parameters
     bool useLineSearch_;
     bool useChop_;
diff --git a/test/porousmediumflow/1pnc/implicit/test_1p2c_fv.cc b/test/porousmediumflow/1pnc/implicit/test_1p2c_fv.cc
index 0109b9ccab82e954b06e47a3ede3965bd62bf6e8..9712deaf8ecf1a6f19ca420258dc19e153e48bed 100644
--- a/test/porousmediumflow/1pnc/implicit/test_1p2c_fv.cc
+++ b/test/porousmediumflow/1pnc/implicit/test_1p2c_fv.cc
@@ -107,7 +107,6 @@
      using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
      auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
      auto dt = getParam<Scalar>("TimeLoop.DtInitial");
-     auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
      auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
 
      // intialize the vtk output module
@@ -129,7 +128,7 @@
      auto linearSolver = std::make_shared<LinearSolver>();
 
      // the non-linear solver
-     NewtonSolver<Assembler, LinearSolver> nonLinearSolver(assembler, linearSolver, timeLoop);
+     NewtonSolver<Assembler, LinearSolver> nonLinearSolver(assembler, linearSolver);
 
      // time loop
      timeLoop->start(); do
@@ -137,24 +136,8 @@
          // set previous solution for storage evaluations
          assembler->setPreviousSolution(xOld);
 
-         // try solving the non-linear system
-         for (int i = 0; i < maxDivisions; ++i)
-         {
-             // linearize & solve
-             auto converged = nonLinearSolver.solve(x);
-
-             if (converged)
-                 break;
-
-             if (!converged && i == maxDivisions-1)
-                 DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-         }
+         // solve the non-linear system with time step control
+         nonLinearSolver.solve(x, *timeLoop);
 
          // make the new solution the old solution
          xOld = x;
diff --git a/test/porousmediumflow/2p/implicit/incompressible/test_2p_fv.cc b/test/porousmediumflow/2p/implicit/incompressible/test_2p_fv.cc
index 36fdc3307aa0042ce4c3f7b7dab36d22594bf99a..ad74e0d38dcb404a03cd090a422909e235c94c8d 100644
--- a/test/porousmediumflow/2p/implicit/incompressible/test_2p_fv.cc
+++ b/test/porousmediumflow/2p/implicit/incompressible/test_2p_fv.cc
@@ -134,7 +134,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -163,7 +162,7 @@ int main(int argc, char** argv) try
 
     // the non-linear solver
     using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
-    NewtonSolver nonLinearSolver(assembler, linearSolver, timeLoop);
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -171,24 +170,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
diff --git a/test/porousmediumflow/2p2c/implicit/test_2p2c_fv.cc b/test/porousmediumflow/2p2c/implicit/test_2p2c_fv.cc
index 48414c9f14d4142bacce3b9909f9894ff9bae0b1..efac6ec2c78eb6e0fcbd2a5e7eda5fae2950e080 100644
--- a/test/porousmediumflow/2p2c/implicit/test_2p2c_fv.cc
+++ b/test/porousmediumflow/2p2c/implicit/test_2p2c_fv.cc
@@ -103,7 +103,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -140,24 +139,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
diff --git a/test/porousmediumflow/richards/implicit/test_richardslens_fv.cc b/test/porousmediumflow/richards/implicit/test_richardslens_fv.cc
index c108a3c94e90da4bcdae6cdfbb6b736fa34e0519..9d260e610e4532a6cdc41a9902cce78c46d5f890 100644
--- a/test/porousmediumflow/richards/implicit/test_richardslens_fv.cc
+++ b/test/porousmediumflow/richards/implicit/test_richardslens_fv.cc
@@ -127,7 +127,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -156,7 +155,7 @@ int main(int argc, char** argv) try
 
     // the non-linear solver
     using NewtonSolver = Dumux::RichardsNewtonSolver<TypeTag, Assembler, LinearSolver>;
-    NewtonSolver nonLinearSolver(assembler, linearSolver, timeLoop);
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -164,24 +163,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;