diff --git a/cpu/nrf52/include/periph_cpu.h b/cpu/nrf52/include/periph_cpu.h
index efa1689b03e0b7988a932f79b632ef20a405a2ef..ad96f21b63c046f3412acd77e01b98d5ce4993e2 100644
--- a/cpu/nrf52/include/periph_cpu.h
+++ b/cpu/nrf52/include/periph_cpu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2017 Freie Universität Berlin
+ * Copyright (C) 2015-2018 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
@@ -30,6 +30,11 @@ extern "C" {
  */
 #define CLOCK_CORECLOCK     (64000000U)
 
+/**
+ * @name    Peripheral clock speed (fixed to 16MHz for nRF52 based CPUs)
+ */
+#define PERIPH_CLOCK        (16000000U)
+
 /**
  * @brief   Redefine some peripheral names to unify them between nRF51 and 52
  * @{
@@ -108,6 +113,49 @@ typedef struct {
 #define PERIPH_I2C_NEED_WRITE_REG
 /** @} */
 
+/**
+ * @name    The PWM unit on the nRF52 supports 4 channels per device
+ */
+#define PWM_CHANNELS        (4U)
+
+/**
+ * @name    Generate PWM mode values
+ *
+ * To encode the PWM mode, we use two bit:
+ * - bit  0: select up or up-and-down counting
+ * - bit 15: select polarity
+ */
+#define PWM_MODE(ud, pol)   (ud | (pol << 15))
+
+/**
+ * @brief   Override the PWM mode definitions
+ * @{
+ */
+#define HAVE_PWM_MODE_T
+typedef enum {
+    PWM_LEFT       = PWM_MODE(0, 1),    /**< left aligned PWM */
+    PWM_RIGHT      = PWM_MODE(0, 0),    /**< right aligned PWM */
+    PWM_CENTER     = PWM_MODE(1, 1),    /**< not supported */
+    PWM_CENTER_INV = PWM_MODE(1, 0)     /**< not supported */
+} pwm_mode_t;
+/** @} */
+
+/**
+ * @brief   PWM configuration options
+ *
+ * Each device supports up to 4 channels. If you want to use less than 4
+ * channels, just set the unused pins to GPIO_UNDEF.
+ *
+ * @note    define unused pins only from right to left, so the defined channels
+ *          always start with channel 0 to x and the undefined ones are from x+1
+ *          to PWM_CHANNELS.
+ */
+typedef struct {
+    NRF_PWM_Type *dev;                  /**< PWM device descriptor */
+    uint32_t pin[PWM_CHANNELS];         /**< PWM out pins */
+} pwm_conf_t;
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpu/nrf52/periph/pwm.c b/cpu/nrf52/periph/pwm.c
new file mode 100644
index 0000000000000000000000000000000000000000..f66a423e9cbffc710587a67eada46de6765e86bd
--- /dev/null
+++ b/cpu/nrf52/periph/pwm.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2016-2018 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_nrf52
+ * @{
+ *
+ * @file
+ * @brief       Implementation of the peripheral PWM interface
+ *
+ * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
+ * @author      Semjon Kerner <semjon.kerner@fu-berlin.de>
+ *
+ * @}
+ */
+
+#include "periph/pwm.h"
+
+#define ENABLE_DEBUG    (0)
+#include "debug.h"
+
+/**
+ * @brief   Define masks to get the MODE register value and the polarity from
+ *          the given pwm_mode_t value
+ * @{
+ */
+#define POL_MASK        (0x8000)
+#define MAX_RES         (0x7fff)
+#define PIN_CNF_SET     (GPIO_PIN_CNF_DIR_Output | GPIO_PIN_CNF_INPUT_Msk)
+#define MAX_PRESCALER   (7U)
+
+/** @} */
+
+/**
+ * @brief   When calculating the actual frequency, we allow for a deviation of
+ *          ~15.5% (val +- (val / 8))
+ */
+#define F_DEV           (8)
+
+/**
+ * @brief   Allocate some memory for the PWM sequences
+ */
+static uint16_t pwm_seq[PWM_NUMOF][PWM_CHANNELS];
+
+static inline NRF_PWM_Type *dev(pwm_t pwm)
+{
+    return pwm_config[pwm].dev;
+}
+
+/**
+ * @note Center mode is not supported. Use left or right aligned PWM modes.
+ */
+uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res)
+{
+    /* check if given device is valid */
+    if ((pwm >= PWM_NUMOF) || (res > MAX_RES)) {
+        return 0;
+    }
+
+    /* check if pwm mode is supported */
+    if ((mode != PWM_RIGHT) && (mode != PWM_LEFT)) {
+        return 0;
+    }
+
+    /* make sure the device is stopped */
+    dev(pwm)->TASKS_STOP = 1;
+    dev(pwm)->ENABLE = 0;
+
+    /* calculate the needed frequency, for center modes we need double */
+    uint32_t real_clk;
+    uint32_t clk = (freq * res);
+    /* match to best fitting prescaler */
+    for (uint8_t i = 0; i < (MAX_PRESCALER + 1); i++) {
+        real_clk = (PERIPH_CLOCK >> i);
+        if (((real_clk - (real_clk / F_DEV)) < clk) &&
+            ((real_clk + (real_clk / F_DEV)) > clk)) {
+            dev(pwm)->PRESCALER = i;
+            break;
+        }
+        if (i == MAX_PRESCALER) {
+            return 0;
+        }
+    }
+    real_clk /= res;
+
+    /* pin configuration */
+    for (unsigned i = 0; i < PWM_CHANNELS; i++) {
+        if (pwm_config[pwm].pin[i] != GPIO_UNDEF) {
+            NRF_P0->PIN_CNF[pwm_config[pwm].pin[i]] = PIN_CNF_SET;
+        }
+        /* either left aligned pol or inverted duty cycle */
+        pwm_seq[pwm][i] = (POL_MASK & mode) ? POL_MASK : res;
+        dev(pwm)->PSEL.OUT[i] = pwm_config[pwm].pin[i];
+        DEBUG("set PIN[%i] to %i with 0x%x\n",
+              (int)i, (int)pwm_config[pwm].pin[i], pwm_seq[pwm][i]);
+    }
+
+    /* enable the device */
+    dev(pwm)->ENABLE = 1;
+
+    /* finally get the actual selected frequency */
+    DEBUG("set real f to %i\n", (int)real_clk);
+    dev(pwm)->COUNTERTOP = (res - 1);
+
+    /* select PWM mode */
+    dev(pwm)->MODE = PWM_MODE_UPDOWN_Up;
+    dev(pwm)->LOOP = PWM_LOOP_CNT_Disabled;
+    dev(pwm)->DECODER = PWM_DECODER_LOAD_Individual;
+
+    DEBUG("MODE: 0x%08x\n", (int)dev(pwm)->MODE);
+    DEBUG("LOOP: 0x%08x\n", (int)dev(pwm)->LOOP);
+    DEBUG("DECODER: 0x%08x\n", (int)dev(pwm)->DECODER);
+
+    /* setup the sequence */
+    dev(pwm)->SEQ[0].PTR = (uint32_t)pwm_seq[pwm];
+    dev(pwm)->SEQ[0].CNT = pwm_channels(pwm);
+    dev(pwm)->SEQ[0].REFRESH = 0;
+    dev(pwm)->SEQ[0].ENDDELAY = 0;
+
+    DEBUG("ptr: 0x%08x\n", (int)dev(pwm)->SEQ[0].PTR);
+    DEBUG("cnt: 0x%08x\n", (int)dev(pwm)->SEQ[0].CNT);
+    DEBUG("refresh: 0x%08x\n", (int)dev(pwm)->SEQ[0].REFRESH);
+    DEBUG("enddelay: 0x%08x\n", (int)dev(pwm)->SEQ[0].ENDDELAY);
+
+    /* start sequence */
+    dev(pwm)->TASKS_SEQSTART[0] = 1;
+
+    DEBUG("PWM started\n");
+
+    return real_clk;
+}
+
+uint8_t pwm_channels(pwm_t pwm)
+{
+    uint8_t channels = 0;
+
+    while ((channels < PWM_CHANNELS) &&
+           (pwm_config[pwm].pin[channels] != GPIO_UNDEF)) {
+        ++channels;
+    }
+
+    return channels;
+}
+
+void pwm_set(pwm_t pwm, uint8_t channel, uint16_t value)
+{
+    if ((channel >= PWM_CHANNELS) || (value > MAX_RES)) {
+        return;
+    }
+
+    /* left aligned */
+    if (pwm_seq[pwm][channel] & POL_MASK) {
+        pwm_seq[pwm][channel] = value | POL_MASK;
+    }
+    /* right aligned */
+    else {
+        pwm_seq[pwm][channel] = dev(pwm)->COUNTERTOP - value;
+    }
+
+    dev(pwm)->TASKS_SEQSTART[0] = 1;
+}
+
+void pwm_stop(pwm_t pwm)
+{
+    DEBUG("STOPPING PWM %i\n", (int)pwm);
+    dev(pwm)->TASKS_STOP = 1;
+    dev(pwm)->ENABLE = 0;
+}
+
+void pwm_start(pwm_t pwm)
+{
+    DEBUG("STARTING PWM %i\n", (int)pwm);
+    dev(pwm)->ENABLE = 1;
+    dev(pwm)->TASKS_SEQSTART[0] = 1;
+}
+
+void pwm_poweron(pwm_t pwm)
+{
+    pwm_start(pwm);
+}
+
+void pwm_poweroff(pwm_t pwm)
+{
+    pwm_stop(pwm);
+}
diff --git a/cpu/nrf5x_common/include/periph_cpu_common.h b/cpu/nrf5x_common/include/periph_cpu_common.h
index 608883c8e6a8f53379826f81b44b84b17edafa08..f452c90564124fa0acabd498518ecec76759f43b 100644
--- a/cpu/nrf5x_common/include/periph_cpu_common.h
+++ b/cpu/nrf5x_common/include/periph_cpu_common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2017 Freie Universität Berlin
+ * Copyright (C) 2015-2018 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
@@ -52,6 +52,11 @@ extern "C" {
 #define GPIO_PIN(x,y)       ((x & 0) | y)
 #endif
 
+/**
+ * @brief   Override GPIO_UNDEF value
+ */
+#define GPIO_UNDEF          (UINT_MAX)
+
 /**
  * @brief   Generate GPIO mode bitfields
  *