diff --git a/boards/avsextrem/Makefile.features b/boards/avsextrem/Makefile.features
index d88a55619b1cbf4e68235d6180e0503187f0b8e2..a73d270b881cfb9e07978a0d7aec3f591f3fb796 100644
--- a/boards/avsextrem/Makefile.features
+++ b/boards/avsextrem/Makefile.features
@@ -1,4 +1,5 @@
 FEATURES_PROVIDED += periph_gpio
 FEATURES_PROVIDED += periph_rtc
 FEATURES_PROVIDED += periph_spi
+FEATURES_PROVIDED += periph_timer
 FEATURES_MCU_GROUP = arm7
diff --git a/boards/avsextrem/include/board.h b/boards/avsextrem/include/board.h
index 579f83824f7eda660aa4935d709a5e7c888c362c..3f74a5c9db308d50c4f973d0765ab81a7faeb2cd 100644
--- a/boards/avsextrem/include/board.h
+++ b/boards/avsextrem/include/board.h
@@ -56,6 +56,11 @@ extern "C" {
 #define STDIO_RX_BUFSIZE    (64U)
 /** @} */
 
+/**
+ * @brief Deprecated HW_TIMER definition (to be removed)
+ */
+#define HW_TIMER             TIMER_DEV(0)
+
 /**
  * @brief Initialize the board's clock system
  */
diff --git a/boards/avsextrem/include/periph_conf.h b/boards/avsextrem/include/periph_conf.h
index 72e7c89a9f2d9fe7448718b79cbe7f2d7d80db1f..2dc1dc76a9ad5a931ab43d3deef814741b2a15e2 100644
--- a/boards/avsextrem/include/periph_conf.h
+++ b/boards/avsextrem/include/periph_conf.h
@@ -25,6 +25,22 @@
 extern "C" {
 #endif
 
+/**
+ * @brief   Clock configuration
+ * @{
+ */
+#define CLOCK_CORECLOCK     (72000000U)         /* this board runs with 72MHz */
+
+#define CLOCK_PCLK          (CLOCK_CORECLOCK)
+/** @} */
+
+/**
+ * @brief   Timer configuration, select a number from 1 to 4
+ * @{
+ */
+#define TIMER_NUMOF         (1U)
+/** @} */
+
 /**
  * @brief PWM device and pinout configuration
  */
diff --git a/boards/msba2-common/lpc2387-timer3.c b/boards/msba2-common/lpc2387-timer3.c
deleted file mode 100644
index 7cbf9e0c8e559c6c3c4f4635049e0a7aee1868ea..0000000000000000000000000000000000000000
--- a/boards/msba2-common/lpc2387-timer3.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2014 INRIA
- *
- * This file is subject to the terms and conditions of the GNU Lesser
- * General Public License v2.1. See the file LICENSE in the top level
- * directory for more details.
- */
-
-/**
- * @ingroup msba2
- * @{
- */
-
-/**
- * @file
- * @brief       msba2 benchmark functions
- *
- * @author      Heiko Will <heiko.will@fu-berlin.de>
- * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
- * @author      Kaspar Schleiser <kaspar@schleiser.de>
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include "lpc2387.h"
-
-void  benchmark_init(void)
-{
-    PCLKSEL1 = (PCLKSEL1 & ~(BIT14|BIT15)) | (1 << 14); // CCLK to PCLK divider
-    PCONP |= PCTIM3;
-    T3TCR = 0;                                          // disable timer
-    T3MCR = 0;                                          // disable interrupt
-    T3CCR = 0;                                          // capture is disabled.
-    T3EMR = 0;                                          // no external match output.
-    T3PR = 0;                                           // set prescaler
-    T3TC = 0;                                           // reset counter
-}
-
-void  benchmark_reset_start(void)
-{
-    T3TCR = 0;                                              // disable timer
-    T3TC = 0;                                               // reset counter
-    T3TCR = BIT0;
-}
-
-unsigned int  benchmark_read_stop(void)
-{
-    T3TCR = 0;                                              // disable timer
-    return T3TC;
-}
diff --git a/boards/msba2/Makefile.features b/boards/msba2/Makefile.features
index f1261a22a43435a04f4ee974424e11fb83609f1d..420a36e116c06f9fbacd89a559539afb1ed7d619 100644
--- a/boards/msba2/Makefile.features
+++ b/boards/msba2/Makefile.features
@@ -2,6 +2,7 @@ FEATURES_PROVIDED += periph_gpio
 FEATURES_PROVIDED += periph_pwm
 FEATURES_PROVIDED += periph_rtc
 FEATURES_PROVIDED += periph_spi
+FEATURES_PROVIDED += periph_timer
 FEATURES_PROVIDED += cpp
 FEATURES_PROVIDED += config
 FEATURES_MCU_GROUP = arm7
diff --git a/boards/msba2/include/board.h b/boards/msba2/include/board.h
index 8b9d6e09b6ff268733e5c341e7b750f79415a60f..2b1102d0c0057f39fd0c88a1dab2cb3bc70d8b9e 100644
--- a/boards/msba2/include/board.h
+++ b/boards/msba2/include/board.h
@@ -53,6 +53,11 @@ extern "C" {
 #define STDIO_RX_BUFSIZE    (64U)
 /** @} */
 
+/**
+ * @brief Deprecated HW_TIMER definition (to be removed)
+ */
+#define HW_TIMER             TIMER_DEV(0)
+
 /**
  * @brief initialize the board's clock system
  */
diff --git a/boards/msba2/include/periph_conf.h b/boards/msba2/include/periph_conf.h
index d5c61c1d792154aa16f4a2941b7d5751a57845f1..8789c55a7859cc8d5b4dddcf99de606dfdbb22ca 100644
--- a/boards/msba2/include/periph_conf.h
+++ b/boards/msba2/include/periph_conf.h
@@ -25,6 +25,22 @@
 extern "C" {
 #endif
 
+/**
+ * @brief   Clock configuration
+ * @{
+ */
+#define CLOCK_CORECLOCK     (72000000U)         /* the msba2 runs with 72MHz */
+
+#define CLOCK_PCLK          (CLOCK_CORECLOCK)
+/** @} */
+
+/**
+ * @brief   Timer configuration, select a number from 1 to 4
+ * @{
+ */
+#define TIMER_NUMOF         (1U)
+/** @} */
+
 /**
  * @brief PWM device and pinout configuration
  */
diff --git a/boards/pttu/Makefile.features b/boards/pttu/Makefile.features
index d88a55619b1cbf4e68235d6180e0503187f0b8e2..a73d270b881cfb9e07978a0d7aec3f591f3fb796 100644
--- a/boards/pttu/Makefile.features
+++ b/boards/pttu/Makefile.features
@@ -1,4 +1,5 @@
 FEATURES_PROVIDED += periph_gpio
 FEATURES_PROVIDED += periph_rtc
 FEATURES_PROVIDED += periph_spi
+FEATURES_PROVIDED += periph_timer
 FEATURES_MCU_GROUP = arm7
diff --git a/boards/pttu/include/board.h b/boards/pttu/include/board.h
index 76e7b7c706c5accdb0590e487b8ab1db114b57af..e9efae4775d1e492cdf71f6ae45c87bae4c4b46a 100644
--- a/boards/pttu/include/board.h
+++ b/boards/pttu/include/board.h
@@ -59,6 +59,11 @@ void bl_init_clks(void);
 #define STDIO_RX_BUFSIZE    (64U)
 /** @} */
 
+/**
+ * @brief Deprecated HW_TIMER definition (to be removed)
+ */
+#define HW_TIMER             TIMER_DEV(0)
+
 /**
  * @name dummy-defines for LEDs
  * @{
diff --git a/boards/pttu/include/periph_conf.h b/boards/pttu/include/periph_conf.h
index 1998dd03a72743a52429a0a8bdfb3dd32e8d2f76..bc66266dc4458a4be2373771662ffaa295c460b3 100644
--- a/boards/pttu/include/periph_conf.h
+++ b/boards/pttu/include/periph_conf.h
@@ -25,6 +25,22 @@
 extern "C" {
 #endif
 
+/**
+ * @brief   Clock configuration
+ * @{
+ */
+#define CLOCK_CORECLOCK     (72000000U)         /* the msba2 runs with 72MHz */
+
+#define CLOCK_PCLK          (CLOCK_CORECLOCK)
+/** @} */
+
+/**
+ * @brief   Timer configuration, select a number from 1 to 4
+ * @{
+ */
+#define TIMER_NUMOF         (1U)
+/** @} */
+
 /**
  * @brief PWM device and pinout configuration
  */
diff --git a/cpu/lpc2387/Makefile.include b/cpu/lpc2387/Makefile.include
index 438dbb2c882ce33e3c8d674ff01ed6764fea329f..5af6269d11916d39ef8e62475692e7aed658ff0a 100644
--- a/cpu/lpc2387/Makefile.include
+++ b/cpu/lpc2387/Makefile.include
@@ -2,4 +2,4 @@ INCLUDES += -I$(RIOTCPU)/lpc2387/include
 
 include $(RIOTCPU)/arm7_common/Makefile.include
 
-USEMODULE += arm7_common periph periph_common bitfield newlib
+USEMODULE += arm7_common periph periph_common bitfield newlib hwtimer_compat
diff --git a/cpu/lpc2387/hwtimer_cpu.c b/cpu/lpc2387/hwtimer_cpu.c
deleted file mode 100644
index cd137a2cac0dda47e849ac2ee8bb2e498fd1da11..0000000000000000000000000000000000000000
--- a/cpu/lpc2387/hwtimer_cpu.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2014 INRIA
- *
- * This file is subject to the terms and conditions of the GNU Lesser
- * General Public License v2.1. See the file LICENSE in the top level
- * directory for more details.
- */
-
-/**
- * @ingroup cpu
- * @file
- * @internal
- * @brief       ARM kernel timer CPU dependent functions implementation
- *
- * @author      Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
- * @author      Heiko Will <hwill@inf.fu-berlin.de>
- * @author      Oliver Hahm <oliver.hahm@inria.fr>
- *
- */
-
-#include "cpu.h"
-#include "bitarithm.h"
-#include "hwtimer_cpu.h"
-#include "arch/hwtimer_arch.h"
-#include "irq.h"
-
-#define VULP(x) ((volatile unsigned long*) (x))
-
-/* High level interrupt handler */
-static void (*int_handler)(int);
-
-/* Timer 0-3 interrupt handler */
-static void timer_irq(void) __attribute__((interrupt("IRQ")));
-
-inline static unsigned long get_base_address(short timer)
-{
-    return (volatile unsigned long)(TMR0_BASE_ADDR + (timer / 8) * 0x6C000 + (timer / 4 - (timer / 8) * 2) * 0x4000);
-}
-
-static void timer_irq(void)
-{
-    short timer = 0;
-
-    if (T0IR) {
-        timer = 0;
-    }
-    else if (T1IR) {
-        timer = 4;
-    }
-    else if (T2IR) {
-        timer = 8;
-    }
-
-    volatile unsigned long base = get_base_address(timer);
-
-    if (*VULP(base + TXIR) & BIT0) {
-        *VULP(base + TXMCR) &= ~BIT0;
-        *VULP(base + TXIR) = BIT0;
-        int_handler(timer);
-    }
-
-    if (*VULP(base + TXIR) & BIT1) {
-        *VULP(base + TXMCR) &= ~BIT3;
-        *VULP(base + TXIR) = BIT1;
-        int_handler(timer + 1);
-    }
-
-    if (*VULP(base + TXIR) & BIT2) {
-        *VULP(base + TXMCR) &= ~BIT6;
-        *VULP(base + TXIR) = BIT2;
-        int_handler(timer + 2);
-    }
-
-    if (*VULP(base + TXIR) & BIT3) {
-        *VULP(base + TXMCR) &= ~BIT9;
-        *VULP(base + TXIR) = BIT3;
-        int_handler(timer + 3);
-    }
-
-    VICVectAddr = 0;    /* acknowledge interrupt (if using VIC IRQ) */
-}
-
-static void timer0_init(uint32_t cpsr)
-{
-    PCONP |= PCTIM0;        /* power up timer */
-    T0TCR = 2;              /* disable and reset timer */
-    T0MCR = 0;              /* disable compare */
-    T0CCR = 0;              /* capture is disabled */
-    T0EMR = 0;              /* no external match output */
-    T0PR = cpsr;            /* set prescaler */
-    install_irq(TIMER0_INT, &timer_irq, 1);
-    T0TCR = 1;              /* reset counter */
-}
-
-static void timer1_init(uint32_t cpsr)
-{
-    PCONP |= PCTIM1;        /* power up timer */
-    T1TCR = 2;              /* disable and reset timer */
-    T1MCR = 0;              /* disable compare */
-    T1CCR = 0;              /* capture is disabled */
-    T1EMR = 0;              /* no external match output */
-    T1PR = cpsr;            /* set prescaler */
-    install_irq(TIMER1_INT, &timer_irq, 1);
-    T1TCR = 1;              /* reset counter */
-}
-
-static void timer2_init(uint32_t cpsr)
-{
-    PCONP |= PCTIM2;        /* power up timer */
-    T2TCR = 2;              /* disable and reset timer */
-    T2MCR = 0;              /* disable compare */
-    T2CCR = 0;              /* capture is disabled */
-    T2EMR = 0;              /* no external match output */
-    T2PR = cpsr;            /* set prescaler */
-    install_irq(TIMER2_INT, &timer_irq, 1);
-    T2TCR = 1;              /* reset counter */
-}
-
-void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu)
-{
-    uint32_t cpsr;
-    int_handler = handler;
-    cpu_clock_scale(fcpu, HWTIMER_SPEED, &cpsr);
-    timer0_init(cpsr);
-    timer1_init(cpsr);
-    timer2_init(cpsr);
-}
-
-/*---------------------------------------------------------------------------*/
-
-void hwtimer_arch_enable_interrupt(void)
-{
-    VICIntEnable = 1 << TIMER0_INT; /* Enable Interrupt */
-    VICIntEnable = 1 << TIMER1_INT; /* Enable Interrupt */
-    VICIntEnable = 1 << TIMER2_INT; /* Enable Interrupt */
-}
-
-/*---------------------------------------------------------------------------*/
-
-void hwtimer_arch_disable_interrupt(void)
-{
-    VICIntEnClr = 1 << TIMER0_INT;  /* Disable Interrupt */
-    VICIntEnClr = 1 << TIMER1_INT;  /* Disable Interrupt */
-    VICIntEnClr = 1 << TIMER2_INT;  /* Disable Interrupt */
-}
-
-/*---------------------------------------------------------------------------*/
-
-void hwtimer_arch_set(unsigned long offset, short timer)
-{
-    /* Calculate base address of timer register */
-    /* Timer 0-3 are matched to TIMER0 */
-    /* Timer 4-7 are matched to TIMER1 */
-    /* Timer 8-11 are matched to TIMER2 */
-    volatile unsigned long base = get_base_address(timer);
-    /* Calculate match register address of corresponding timer */
-    timer %= 4;
-    unsigned long cpsr = disableIRQ();
-    volatile unsigned long *addr = VULP(base + TXMR0 + 4 * timer);
-    /* Calculate match register value */
-    unsigned long value = *VULP(base + TXTC) + offset;
-    *addr = value;                                  /* set match register */
-    *VULP(base + TXIR) = 0x01 << timer;             /* reset interrupt register value for corresponding match register */
-    *VULP(base + TXMCR) &= ~(7 << (3 * timer));     /* Clear all bits */
-    *VULP(base + TXMCR) |= (MR0I << (3 * timer));   /* enable interrupt for match register */
-    restoreIRQ(cpsr);
-}
-
-void hwtimer_arch_set_absolute(unsigned long value, short timer)
-{
-    /* Calculate base address of timer register */
-    /* Timer 0-3 are matched to TIMER0 */
-    /* Timer 4-7 are matched to TIMER1 */
-    /* Timer 8-11 are matched to TIMER2 */
-    volatile unsigned long base = get_base_address(timer);
-    /* Calculate match register address of corresponding timer */
-    timer %= 4;
-    volatile unsigned long *addr = VULP(base + TXMR0 + 4 * timer);
-    /* Calculate match register value */
-    *addr = value;                                  /* set match register */
-    *VULP(base + TXIR) = 0x01 << timer;             /* reset interrupt register value for corresponding match register */
-    *VULP(base + TXMCR) &= ~(7 << (3 * timer));     /* Clear all bits */
-    *VULP(base + TXMCR) |= (MR0I << (3 * timer));   /* enable interrupt for match register */
-}
-
-/*---------------------------------------------------------------------------*/
-
-void hwtimer_arch_unset(short timer)
-{
-    volatile unsigned long base = get_base_address(timer);
-    timer %= 4;
-    *VULP(base + TXMCR) &= ~(MR0I << (3 * timer));  /* disable interrupt for match register */
-    *VULP(base + TXIR) = 0x01 << timer;             /* reset interrupt register value for corresponding match register */
-}
-
-/*---------------------------------------------------------------------------*/
-
-unsigned long hwtimer_arch_now(void)
-{
-    return T0TC;
-}
-
-void hwtimer_arch_setcounter(unsigned int val)
-{
-    T0TC = val;
-}
diff --git a/cpu/lpc2387/include/lpc23xx.h b/cpu/lpc2387/include/lpc23xx.h
index b6de1a990f872c165b9cbae880d39ff328c1ce39..dac007043730aabba916c01e4ae169e6c656ad90 100644
--- a/cpu/lpc2387/include/lpc23xx.h
+++ b/cpu/lpc2387/include/lpc23xx.h
@@ -12,13 +12,20 @@
  *
 ******************************************************************************/
 
-#ifndef __LPC23xx_H
-#define __LPC23xx_H
+#ifndef LPC23XX_H
+#define LPC23XX_H
+
+#include <stdint.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+/**
+ * @brief   Type for 32-bit registers
+ */
+#define REG32       volatile uint32_t
+
 /* Vectored Interrupt Controller (VIC) */
 #define VIC_BASE_ADDR   0xFFFFF000
 #define VICIRQStatus   (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x000))
@@ -496,8 +503,27 @@ are for LPC24xx only. */
 
 #define EMC_STA_EXT_WAIT  (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x880))
 
+/**
+ * @brief   Generic timer register map
+ */
+typedef struct {
+    REG32   IR;             /**< interrupt register */
+    REG32   TCR;            /**< timer control register */
+    REG32   TC;             /**< timer counter */
+    REG32   PR;             /**< prescale register */
+    REG32   PC;             /**< prescale counter */
+    REG32   MCR;            /**< match control register */
+    REG32   MR[4];          /**< match registers 1-4 */
+    REG32   CCR;            /**< capture control register */
+    REG32   CR[4];          /**< capture register 1-4 */
+    REG32   EMR;            /**< external match register */
+    REG32   reserved[12];   /**< reserved */
+    REG32   CTCR;           /**< count control register */
+} lpc23xx_timer_t;
+
 /* Timer 0 */
 #define TMR0_BASE_ADDR      0xE0004000
+#define TMR0                ((lpc23xx_timer_t *)TMR0_BASE_ADDR)
 #define T0IR           (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x00))
 #define T0TCR          (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x04))
 #define T0TC           (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x08))
@@ -518,6 +544,7 @@ are for LPC24xx only. */
 
 /* Timer 1 */
 #define TMR1_BASE_ADDR      0xE0008000
+#define TMR1                ((lpc23xx_timer_t *)TMR1_BASE_ADDR)
 #define T1IR           (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x00))
 #define T1TCR          (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x04))
 #define T1TC           (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x08))
@@ -538,6 +565,7 @@ are for LPC24xx only. */
 
 /* Timer 2 */
 #define TMR2_BASE_ADDR      0xE0070000
+#define TMR2                ((lpc23xx_timer_t *)TMR2_BASE_ADDR)
 #define T2IR           (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x00))
 #define T2TCR          (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x04))
 #define T2TC           (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x08))
@@ -558,6 +586,7 @@ are for LPC24xx only. */
 
 /* Timer 3 */
 #define TMR3_BASE_ADDR      0xE0074000
+#define TMR3                ((lpc23xx_timer_t *)TMR3_BASE_ADDR)
 #define T3IR           (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x00))
 #define T3TCR          (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x04))
 #define T3TC           (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x08))
@@ -1134,4 +1163,4 @@ with the spec. update in USB Device Section. */
 }
 #endif
 
-#endif  // __LPC23xx_H
+#endif  /* LPC23XX_H */
diff --git a/cpu/lpc2387/include/periph_cpu.h b/cpu/lpc2387/include/periph_cpu.h
index 47a07255fd301ec0c771158f304fcc917d2e02d7..8fccc27687ed8b5725dae9602f3861c2f6860902 100644
--- a/cpu/lpc2387/include/periph_cpu.h
+++ b/cpu/lpc2387/include/periph_cpu.h
@@ -71,7 +71,12 @@ typedef enum {
 } gpio_flank_t;
 
 /**
- * @brief declare needed generic SPI functions
+ * @brief   Number of available timer channels
+ */
+#define TIMER_CHAN_NUMOF        (4U)
+
+/**
+ * @brief   Declare needed generic SPI functions
  * @{
  */
 #define PERIPH_SPI_NEEDS_TRANSFER_BYTES
diff --git a/cpu/lpc2387/periph/timer.c b/cpu/lpc2387/periph/timer.c
new file mode 100644
index 0000000000000000000000000000000000000000..6b1e783cb9160c9c891c632c1deea24df0b563ef
--- /dev/null
+++ b/cpu/lpc2387/periph/timer.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2015 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     cpu_lpc2387
+ * @{
+ *
+ * @file
+ * @brief       Implementation of the low-level timer driver for the LPC2387
+ *
+ * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
+ * @}
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include "periph_conf.h"
+#include "periph_cpu.h"
+#include "periph/timer.h"
+
+/**
+ * @brief   Check the board config to make sure we do not exceed max number of
+ *          timers
+ */
+#if TIMER_NUMOF > 3
+#error "ERROR in timer configuration: too many timers defined"
+#endif
+
+/**
+ * @brief   Interrupt context information for configured timers
+ */
+static timer_isr_ctx_t isr_ctx[TIMER_NUMOF];
+
+/**
+ * @brief   Forward declarations for interrupt functions
+ * @{
+ */
+void tim_isr_0(void);
+void tim_isr_1(void);
+void tim_isr_2(void);
+void tim_isr_3(void);
+/** @} */
+
+/**
+ * @brief   Get the base pointer of a timer
+ */
+static inline lpc23xx_timer_t *get_dev(tim_t tim)
+{
+    switch (tim) {
+        case 0:
+            return TMR0;
+#if TIMER_NUMOF > 1
+        case 1:
+            return TMR1;
+#endif
+#if TIMER_NUMOF > 2
+        case 2:
+            return TMR2;
+#endif
+#if TIMER_NUMOF > 3
+        case 3:
+            return TMR3;
+#endif
+        default:
+            return NULL;
+    }
+}
+
+static inline void pwr_clk_and_isr(tim_t tim)
+{
+    switch (tim) {
+        case 0:
+            PCONP |= (1 << 1);
+            PCLKSEL0 &= ~(0x03 << 2);
+            PCLKSEL0 |=  (0x01 << 2);
+            install_irq(TIMER0_INT, &tim_isr_0, 1);
+            break;
+#if TIMER_NUMOF > 1
+        case 1:
+            PCONP |= (1 << 2);
+            PCLKSEL0 &= ~(0x03 << 4);
+            PCLKSEL0 |=  (0x01 << 4);
+            install_irq(TIMER1_INT, &tim_isr_1, 1);
+            break;
+#endif
+#if TIMER_NUMOF > 2
+        case 2:
+            PCONP |= (1 << 22);
+            PCLKSEL1 &= ~(0x03 << 12);
+            PCLKSEL1 |=  (0x01 << 12);
+            install_irq(TIMER2_INT, &tim_isr_2, 1);
+            break;
+#endif
+#if TIMER_NUMOF > 3
+        case 3:
+            PCONP |= (1 << 23);
+            PCLKSEL1 &= ~(0x03 << 14);
+            PCLKSEL1 |=  (0x01 << 14);
+            install_irq(TIMER3_INT, &tim_isr_3, 1);
+            break;
+#endif
+    }
+}
+
+int timer_init(tim_t tim, unsigned int us_per_tick, void (*callback)(int))
+{
+    /* get the timers base register */
+    lpc23xx_timer_t *dev = get_dev(tim);
+
+    /* make sure the timer device is valid */
+    if (dev == NULL) {
+        return -1;
+    }
+
+    /* save the callback */
+    isr_ctx[tim].cb = callback;
+    /* enable power, config periph clock and install ISR vector */
+    pwr_clk_and_isr(tim);
+    /* reset timer configuration (sets the timer to timer mode) */
+    dev->TCR = 0;
+    dev->CTCR = 0;
+    /* configure the prescaler */
+    dev->PR = (us_per_tick * ((CLOCK_PCLK / 1000000) - 1));
+    /* enable timer */
+    dev->TCR = 1;
+    return 0;
+}
+
+int timer_set(tim_t tim, int channel, unsigned int timeout)
+{
+    unsigned int now = timer_read(tim);
+    return timer_set_absolute(tim, channel, (timeout + now));
+}
+
+int timer_set_absolute(tim_t tim, int channel, unsigned int value)
+{
+    if (tim >= TIMER_NUMOF || channel >= TIMER_CHAN_NUMOF) {
+        return -1;
+    }
+
+    lpc23xx_timer_t *dev = get_dev(tim);
+    dev->MR[channel] = value;
+    dev->MCR |= (1 << (channel * 3));
+    return 0;
+}
+
+int timer_clear(tim_t tim, int channel)
+{
+    if (tim >= TIMER_NUMOF || channel >= TIMER_CHAN_NUMOF) {
+        return -1;
+    }
+    get_dev(tim)->MCR &= ~(1 << (channel * 3));
+    return 0;
+}
+
+unsigned int timer_read(tim_t tim)
+{
+    return (unsigned int)(get_dev(tim)->TC);
+}
+
+void timer_start(tim_t tim)
+{
+    get_dev(tim)->TCR = 1;
+}
+
+void timer_stop(tim_t tim)
+{
+    get_dev(tim)->TCR = 0;
+}
+
+void timer_reset(tim_t tim)
+{
+    lpc23xx_timer_t *dev = get_dev(tim);
+    dev->TCR |= 2;
+    asm("nop");
+    dev->TCR &= ~(2);
+}
+
+void timer_irq_enable(tim_t tim)
+{
+    /* TODO */
+}
+
+void timer_irq_disable(tim_t tim)
+{
+    /* TODO */
+}
+
+static inline void isr_handler(lpc23xx_timer_t *dev, int tim_num)
+{
+    for (int i = 0; i < TIMER_CHAN_NUMOF; i++) {
+        if (dev->IR & (1 << i)) {
+            dev->IR |= (1 << i);
+            dev->MCR &= ~(1 << (i * 3));
+            isr_ctx[tim_num].cb(i);
+        }
+    }
+    /* we must not forget to acknowledge the handling of the interrupt */
+    VICVectAddr = 0;
+}
+
+void __attribute__((interrupt("IRQ"))) tim_isr_0(void)
+{
+    isr_handler(TMR0, 0);
+}
+
+#if TIMER_NUMOF > 1
+void __attribute__((interrupt("IRQ"))) tim_isr_1(void)
+{
+    isr_handler(TMR1, 1);
+}
+#endif
+
+#if TIMER_NUMOF > 2
+void __attribute__((interrupt("IRQ"))) tim_isr_2(void)
+{
+    isr_handler(TMR2, 2);
+}
+#endif
+
+#if TIMER_NUMOF > 3
+void __attribute__((interrupt("IRQ"))) tim_isr_3(void)
+{
+    isr_handler(TMR3, 3);
+}
+#endif