diff --git a/repos/os/src/drivers/timer/epit/epit.h b/repos/os/src/drivers/timer/epit/epit.h
new file mode 100644
index 0000000000..26cdceb5b5
--- /dev/null
+++ b/repos/os/src/drivers/timer/epit/epit.h
@@ -0,0 +1,195 @@
+/*
+ * \brief  Driver base for the Enhanced Periodic Interrupt Timer (Freescale)
+ * \author Norman Feske
+ * \author Martin Stein
+ * \author Stefan Kalkowski
+ * \date   2012-10-25
+ */
+
+/*
+ * Copyright (C) 2012-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _EPIT_H_
+#define _EPIT_H_
+
+/* Genode includes */
+#include <util/mmio.h>
+
+namespace Genode { class Epit_base; }
+
+
+class Genode::Epit_base : public Mmio
+{
+	protected:
+
+		enum { TICS_PER_MS = 66000 };
+
+		/**
+		 * Control register
+		 */
+		struct Cr : Register<0x0, 32>
+		{
+			struct En : Bitfield<0, 1> { };       /* enable timer */
+
+			struct En_mod : Bitfield<1, 1>        /* reload on enable */
+			{
+				enum { RELOAD = 1 };
+			};
+
+			struct Oci_en : Bitfield<2, 1> { };   /* interrupt on compare */
+
+			struct Rld : Bitfield<3, 1>           /* reload or roll-over */
+			{
+				enum { RELOAD_FROM_LR = 1 };
+			};
+
+			struct Prescaler : Bitfield<4, 12>    /* clock input divisor */
+			{
+				enum { DIVIDE_BY_1 = 0 };
+			};
+
+			struct Swr     : Bitfield<16, 1> { }; /* software reset bit */
+			struct Iovw    : Bitfield<17, 1> { }; /* enable overwrite */
+			struct Dbg_en  : Bitfield<18, 1> { }; /* enable in debug mode */
+			struct Wait_en : Bitfield<19, 1> { }; /* enable in wait mode */
+			struct Doz_en  : Bitfield<20, 1> { }; /* enable in doze mode */
+			struct Stop_en : Bitfield<21, 1> { }; /* enable in stop mode */
+
+			struct Om : Bitfield<22, 2>           /* mode of the output pin */
+			{
+				enum { DISCONNECTED = 0 };
+			};
+
+			struct Clk_src : Bitfield<24, 2>      /* select clock input */
+			{
+				enum { HIGH_FREQ_REF_CLK = 2 };
+			};
+
+			/**
+			 * Register value that configures the timer for a one-shot run
+			 */
+			static access_t prepare_one_shot()
+			{
+				return En::bits(0) |
+				       En_mod::bits(En_mod::RELOAD) |
+				       Oci_en::bits(1) |
+				       Rld::bits(Rld::RELOAD_FROM_LR) |
+				       Prescaler::bits(Prescaler::DIVIDE_BY_1) |
+				       Swr::bits(0) |
+				       Iovw::bits(0) |
+				       Dbg_en::bits(0) |
+				       Wait_en::bits(0) |
+				       Doz_en::bits(0) |
+				       Stop_en::bits(0) |
+				       Om::bits(Om::DISCONNECTED) |
+				       Clk_src::bits(Clk_src::HIGH_FREQ_REF_CLK);
+			}
+		};
+
+		/**
+		 * Status register
+		 */
+		struct Sr : Register<0x4, 32>
+		{
+			struct Ocif : Bitfield<0, 1> { }; /* IRQ status, write 1 clears */
+		};
+
+		struct Lr   : Register<0x8,  32> { }; /* load value register */
+		struct Cmpr : Register<0xc,  32> { }; /* compare value register */
+		struct Cnt  : Register<0x10, 32> { }; /* counter register */
+
+		/**
+		 * Disable timer and clear its interrupt output
+		 */
+		void _reset()
+		{
+			/* wait until ongoing reset operations are finished */
+			while (read<Cr::Swr>()) ;
+
+			/* disable timer */
+			write<Cr::En>(0);
+
+			/* clear interrupt */
+			write<Sr::Ocif>(1);
+		}
+
+		void _start_one_shot(unsigned const tics)
+		{
+			/* stop timer */
+			_reset();
+
+			/* configure timer for a one-shot */
+			write<Cr>(Cr::prepare_one_shot());
+			write<Lr>(tics);
+			write<Cmpr>(0);
+
+			/* start timer */
+			write<Cr::En>(1);
+		}
+
+	public:
+
+		/**
+		 * Constructor
+		 */
+		Epit_base(addr_t base) : Mmio(base) { _reset(); }
+
+		/**
+		 * Start single timeout run
+		 *
+		 * \param tics  delay of timer interrupt
+		 */
+		void start_one_shot(unsigned const tics)
+		{
+			_start_one_shot(tics);
+		}
+
+		/**
+		 * Stop the timer from a one-shot run
+		 *
+		 * \return  last native timer value of the one-shot run
+		 */
+		unsigned stop_one_shot(bool &wrap)
+		{
+			/* disable timer */
+			write<Cr::En>(0);
+			return value(wrap);
+		}
+
+		/**
+		 * Translate microseconds to a native timer value
+		 */
+		unsigned us_to_tics(unsigned const us) const
+		{
+			return (1ULL * us * TICS_PER_MS) / 1000;
+		}
+
+		/**
+		 * Translate native timer value to microseconds
+		 */
+		unsigned tics_to_us(unsigned const tics) const
+		{
+			return (1ULL * tics * 1000) / TICS_PER_MS;
+		}
+
+		/**
+		 * Return current native timer value
+		 */
+		unsigned value(bool &wrapped) const
+		{
+			unsigned cnt = read<Cnt>();
+			wrapped = (bool)read<Sr::Ocif>();
+			return wrapped ? read<Cnt>() : cnt;
+		}
+
+		/**
+		 * Current maximum programmed timeout value
+		 */
+		unsigned current_max_value() const { return read<Lr>(); }
+};
+
+#endif /* _EPIT_H_ */
diff --git a/repos/os/src/drivers/timer/epit/time_source.cc b/repos/os/src/drivers/timer/epit/time_source.cc
new file mode 100644
index 0000000000..f486eeecc2
--- /dev/null
+++ b/repos/os/src/drivers/timer/epit/time_source.cc
@@ -0,0 +1,66 @@
+/*
+ * \brief  Time source that uses the Enhanced Periodic Interrupt Timer (Freescale)
+ * \author Norman Feske
+ * \author Martin Stein
+ * \author Stefan Kalkowski
+ * \author Alexander Boettcher
+ * \date   2009-06-16
+ */
+
+/*
+ * Copyright (C) 2009-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+/* local includes */
+#include <time_source.h>
+
+using namespace Genode;
+
+Microseconds Timer::Time_source::max_timeout() const {
+	return Microseconds(_epit.tics_to_us(~0U)); }
+
+void Timer::Time_source::schedule_timeout(Microseconds     duration,
+                                          Timeout_handler &handler)
+{
+	/* make swift current time steady */
+	Duration const time = curr_time();
+	_curr_time_us = time.trunc_to_plain_us().value;
+
+	/*
+	 * Program max timeout in case of duration 0 to avoid lost of accuracy
+	 * due to wraps when value is chosen too small. Send instead a signal
+	 * manually at end of this method.
+	 */
+	unsigned const tics = _epit.us_to_tics(duration.value ? duration.value
+	                                                      : max_timeout().value);
+
+	_handler = &handler;
+
+	_timer_irq.ack_irq();
+
+	_epit.start_one_shot(tics);
+
+	/* trigger for a timeout 0 immediately the signal */
+	if (!duration.value)
+		Signal_transmitter(_signal_handler).submit();
+}
+
+
+Duration Timer::Time_source::curr_time()
+{
+	/* read EPIT status */
+	bool           wrapped   = false;
+	unsigned const max_value = _epit.current_max_value();
+	unsigned const tic_value = _epit.value(wrapped);
+	unsigned       passed_tics = 0;
+
+	if (wrapped)
+		passed_tics += max_value;
+
+	passed_tics += max_value - tic_value;
+
+	return Duration(Microseconds(_curr_time_us + _epit.tics_to_us(passed_tics)));
+}
diff --git a/repos/os/src/drivers/timer/epit/time_source.h b/repos/os/src/drivers/timer/epit/time_source.h
new file mode 100644
index 0000000000..2dd9c49bad
--- /dev/null
+++ b/repos/os/src/drivers/timer/epit/time_source.h
@@ -0,0 +1,60 @@
+/*
+ * \brief  Time source that uses the Enhanced Periodic Interrupt Timer (Freescale)
+ * \author Norman Feske
+ * \author Martin Stein
+ * \author Stefan Kalkowski
+ * \date   2009-06-16
+ */
+
+/*
+ * Copyright (C) 2009-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef _TIME_SOURCE_H_
+#define _TIME_SOURCE_H_
+
+/* Genode includes */
+#include <base/attached_io_mem_dataspace.h>
+#include <irq_session/connection.h>
+#include <os/duration.h>
+
+/* local includes */
+#include <signalled_time_source.h>
+
+#include "epit.h"
+
+namespace Timer {
+
+	using Microseconds = Genode::Microseconds;
+	using Duration     = Genode::Duration;
+	class Time_source;
+}
+
+
+class Timer::Time_source : public Genode::Signalled_time_source
+{
+	private:
+
+		Genode::Attached_io_mem_dataspace _io_mem;
+		Genode::Irq_connection            _timer_irq;
+		Genode::Epit_base                 _epit;
+		unsigned long long mutable        _curr_time_us { 0 };
+
+	public:
+
+		Time_source(Genode::Env &env);
+
+
+		/*************************
+		 ** Genode::Time_source **
+		 *************************/
+
+		Duration curr_time() override;
+		void schedule_timeout(Microseconds duration, Timeout_handler &handler) override;
+		Microseconds max_timeout() const override;
+};
+
+#endif /* _TIME_SOURCE_H_ */
diff --git a/repos/os/src/drivers/timer/epit/wand_quad/target.mk b/repos/os/src/drivers/timer/epit/wand_quad/target.mk
new file mode 100644
index 0000000000..310f832ab7
--- /dev/null
+++ b/repos/os/src/drivers/timer/epit/wand_quad/target.mk
@@ -0,0 +1,9 @@
+TARGET   = wand_quad_timer_drv
+REQUIRES = wand_quad
+INC_DIR += $(REP_DIR)/src/drivers/timer/epit
+SRC_CC  += time_source.cc
+SRC_CC  += timer.cc
+
+include $(REP_DIR)/src/drivers/timer/target.inc
+
+vpath time_source.cc $(REP_DIR)/src/drivers/timer/epit
diff --git a/repos/os/src/drivers/timer/epit/wand_quad/timer.cc b/repos/os/src/drivers/timer/epit/wand_quad/timer.cc
new file mode 100644
index 0000000000..bf645232bb
--- /dev/null
+++ b/repos/os/src/drivers/timer/epit/wand_quad/timer.cc
@@ -0,0 +1,33 @@
+/*
+ * \brief  Time source for Wandboard Quad i.MX6
+ * \author Norman Feske
+ * \author Martin Stein
+ * \author Stefan Kalkowski
+ * \author Alexander Boettcher
+ * \date   2009-06-16
+ */
+
+/*
+ * Copyright (C) 2009-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+/* base include */
+#include <drivers/defs/wand_quad.h>
+
+/* local include */
+#include <time_source.h>
+
+using namespace Genode;
+
+Timer::Time_source::Time_source(Env &env)
+:
+	Signalled_time_source(env),
+	_io_mem(env, Wand_quad::EPIT_2_MMIO_BASE, Wand_quad::EPIT_2_MMIO_SIZE),
+	_timer_irq(env, Wand_quad::EPIT_2_IRQ),
+	_epit(reinterpret_cast<addr_t>(_io_mem.local_addr<addr_t>()))
+{
+	_timer_irq.sigh(_signal_handler);
+}