diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs
index 3b0d2f1ca..a9487a9fd 100644
--- a/embassy-nrf/src/timer.rs
+++ b/embassy-nrf/src/timer.rs
@@ -6,15 +6,9 @@
 
 #![macro_use]
 
-use core::future::poll_fn;
-use core::marker::PhantomData;
-use core::task::Poll;
-
-use embassy_hal_common::drop::OnDrop;
 use embassy_hal_common::{into_ref, PeripheralRef};
-use embassy_sync::waitqueue::AtomicWaker;
 
-use crate::interrupt::{Interrupt, InterruptExt};
+use crate::interrupt::Interrupt;
 use crate::ppi::{Event, Task};
 use crate::{pac, Peripheral};
 
@@ -26,8 +20,6 @@ pub(crate) mod sealed {
         /// The number of CC registers this instance has.
         const CCS: usize;
         fn regs() -> &'static pac::timer0::RegisterBlock;
-        /// Storage for the waker for CC register `n`.
-        fn waker(n: usize) -> &'static AtomicWaker;
     }
     pub trait ExtendedInstance {}
 
@@ -50,12 +42,6 @@ macro_rules! impl_timer {
             fn regs() -> &'static pac::timer0::RegisterBlock {
                 unsafe { &*(pac::$pac_type::ptr() as *const pac::timer0::RegisterBlock) }
             }
-            fn waker(n: usize) -> &'static ::embassy_sync::waitqueue::AtomicWaker {
-                use ::embassy_sync::waitqueue::AtomicWaker;
-                const NEW_AW: AtomicWaker = AtomicWaker::new();
-                static WAKERS: [AtomicWaker; $ccs] = [NEW_AW; $ccs];
-                &WAKERS[n]
-            }
         }
         impl crate::timer::Instance for peripherals::$type {
             type Interrupt = crate::interrupt::$irq;
@@ -99,59 +85,18 @@ pub enum Frequency {
 /// nRF Timer driver.
 ///
 /// The timer has an internal counter, which is incremented for every tick of the timer.
-/// The counter is 32-bit, so it wraps back to 0 at 4294967296.
+/// The counter is 32-bit, so it wraps back to 0 when it reaches 2^32.
 ///
 /// It has either 4 or 6 Capture/Compare registers, which can be used to capture the current state of the counter
 /// or trigger an event when the counter reaches a certain value.
 
-pub trait TimerType: sealed::TimerType {}
-
-/// Marker type indicating the timer driver can await expiration (it owns the timer interrupt).
-pub enum Awaitable {}
-
-/// Marker type indicating the timer driver cannot await expiration (it does not own the timer interrupt).
-pub enum NotAwaitable {}
-
-impl sealed::TimerType for Awaitable {}
-impl sealed::TimerType for NotAwaitable {}
-impl TimerType for Awaitable {}
-impl TimerType for NotAwaitable {}
-
 /// Timer driver.
-pub struct Timer<'d, T: Instance, I: TimerType = NotAwaitable> {
+pub struct Timer<'d, T: Instance> {
     _p: PeripheralRef<'d, T>,
-    _i: PhantomData<I>,
 }
 
-impl<'d, T: Instance> Timer<'d, T, Awaitable> {
-    /// Create a new async-capable timer driver.
-    pub fn new_awaitable(timer: impl Peripheral<P = T> + 'd, irq: impl Peripheral<P = T::Interrupt> + 'd) -> Self {
-        into_ref!(irq);
-
-        irq.set_handler(Self::on_interrupt);
-        irq.unpend();
-        irq.enable();
-
-        Self::new_inner(timer, false)
-    }
-
-    /// Create a new async-capable timer driver in counter mode.
-    pub fn new_awaitable_counter(
-        timer: impl Peripheral<P = T> + 'd,
-        irq: impl Peripheral<P = T::Interrupt> + 'd,
-    ) -> Self {
-        into_ref!(irq);
-
-        irq.set_handler(Self::on_interrupt);
-        irq.unpend();
-        irq.enable();
-
-        Self::new_inner(timer, true)
-    }
-}
-
-impl<'d, T: Instance> Timer<'d, T, NotAwaitable> {
-    /// Create a `Timer` driver without an interrupt, meaning `Cc::wait` won't work.
+impl<'d, T: Instance> Timer<'d, T> {
+    /// Create a new `Timer` driver.
     ///
     /// This can be useful for triggering tasks via PPI
     /// `Uarte` uses this internally.
@@ -159,28 +104,20 @@ impl<'d, T: Instance> Timer<'d, T, NotAwaitable> {
         Self::new_inner(timer, false)
     }
 
-    /// Create a `Timer` driver in counter mode without an interrupt, meaning `Cc::wait` won't work.
+    /// Create a new `Timer` driver in counter mode.
     ///
     /// This can be useful for triggering tasks via PPI
     /// `Uarte` uses this internally.
     pub fn new_counter(timer: impl Peripheral<P = T> + 'd) -> Self {
         Self::new_inner(timer, true)
     }
-}
 
-impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
-    /// Create a `Timer` without an interrupt, meaning `Cc::wait` won't work.
-    ///
-    /// This is used by the public constructors.
     fn new_inner(timer: impl Peripheral<P = T> + 'd, is_counter: bool) -> Self {
         into_ref!(timer);
 
         let regs = T::regs();
 
-        let mut this = Self {
-            _p: timer,
-            _i: PhantomData,
-        };
+        let mut this = Self { _p: timer };
 
         // Stop the timer before doing anything else,
         // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification.
@@ -272,31 +209,17 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
             .write(|w| unsafe { w.prescaler().bits(frequency as u8) })
     }
 
-    fn on_interrupt(_: *mut ()) {
-        let regs = T::regs();
-        for n in 0..T::CCS {
-            if regs.events_compare[n].read().bits() != 0 {
-                // Clear the interrupt, otherwise the interrupt will be repeatedly raised as soon as the interrupt handler exits.
-                // We can't clear the event, because it's used to poll whether the future is done or still pending.
-                regs.intenclr
-                    .modify(|r, w| unsafe { w.bits(r.bits() | (1 << (16 + n))) });
-                T::waker(n).wake();
-            }
-        }
-    }
-
     /// Returns this timer's `n`th CC register.
     ///
     /// # Panics
     /// Panics if `n` >= the number of CC registers this timer has (4 for a normal timer, 6 for an extended timer).
-    pub fn cc(&mut self, n: usize) -> Cc<T, I> {
+    pub fn cc(&mut self, n: usize) -> Cc<T> {
         if n >= T::CCS {
             panic!("Cannot get CC register {} of timer with {} CC registers.", n, T::CCS);
         }
         Cc {
             n,
             _p: self._p.reborrow(),
-            _i: PhantomData,
         }
     }
 }
@@ -308,49 +231,12 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
 ///
 /// The timer will fire the register's COMPARE event when its counter reaches the value stored in the register.
 /// When the register's CAPTURE task is triggered, the timer will store the current value of its counter in the register
-pub struct Cc<'d, T: Instance, I: TimerType = NotAwaitable> {
+pub struct Cc<'d, T: Instance> {
     n: usize,
     _p: PeripheralRef<'d, T>,
-    _i: PhantomData<I>,
 }
 
-impl<'d, T: Instance> Cc<'d, T, Awaitable> {
-    /// Wait until the timer's counter reaches the value stored in this register.
-    ///
-    /// This requires a mutable reference so that this task's waker cannot be overwritten by a second call to `wait`.
-    pub async fn wait(&mut self) {
-        let regs = T::regs();
-
-        // Enable the interrupt for this CC's COMPARE event.
-        regs.intenset
-            .modify(|r, w| unsafe { w.bits(r.bits() | (1 << (16 + self.n))) });
-
-        // Disable the interrupt if the future is dropped.
-        let on_drop = OnDrop::new(|| {
-            regs.intenclr
-                .modify(|r, w| unsafe { w.bits(r.bits() | (1 << (16 + self.n))) });
-        });
-
-        poll_fn(|cx| {
-            T::waker(self.n).register(cx.waker());
-
-            if regs.events_compare[self.n].read().bits() != 0 {
-                // Reset the register for next time
-                regs.events_compare[self.n].reset();
-                Poll::Ready(())
-            } else {
-                Poll::Pending
-            }
-        })
-        .await;
-
-        // The interrupt was already disabled in the interrupt handler, so there's no need to disable it again.
-        on_drop.defuse();
-    }
-}
-impl<'d, T: Instance> Cc<'d, T, NotAwaitable> {}
-
-impl<'d, T: Instance, I: TimerType> Cc<'d, T, I> {
+impl<'d, T: Instance> Cc<'d, T> {
     /// Get the current value stored in the register.
     pub fn read(&self) -> u32 {
         T::regs().cc[self.n].read().cc().bits()
diff --git a/examples/nrf52840/src/bin/awaitable_timer.rs b/examples/nrf52840/src/bin/awaitable_timer.rs
deleted file mode 100644
index b32af236c..000000000
--- a/examples/nrf52840/src/bin/awaitable_timer.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-#![no_std]
-#![no_main]
-#![feature(type_alias_impl_trait)]
-
-use defmt::info;
-use embassy_executor::Spawner;
-use embassy_nrf::interrupt;
-use embassy_nrf::timer::Timer;
-use {defmt_rtt as _, panic_probe as _};
-
-#[embassy_executor::main]
-async fn main(_spawner: Spawner) {
-    let p = embassy_nrf::init(Default::default());
-    let mut t = Timer::new_awaitable(p.TIMER0, interrupt::take!(TIMER0));
-    // default frequency is 1MHz, so this triggers every second
-    t.cc(0).write(1_000_000);
-    // clear the timer value on cc[0] compare match
-    t.cc(0).short_compare_clear();
-    t.start();
-
-    loop {
-        // wait for compare match
-        t.cc(0).wait().await;
-        info!("hardware timer tick");
-    }
-}