From cf32ff7f194134fbcbfe1e3151e5be1435049bc7 Mon Sep 17 00:00:00 2001
From: Johann Fischer <j.fischer@phytec.de>
Date: Fri, 20 May 2016 17:13:31 +0200
Subject: [PATCH] drivers/kw2xrf: adapt for the netdev2 interface

Adapt the kw2xrf driver for the netdev2 interface.
This patch also adds overwrites.h, the header provides overwrite
values for the kw2xrf PHY.
---
 drivers/Makefile.dep                   |    5 +-
 drivers/include/kw2xrf.h               |  140 +--
 drivers/kw2xrf/include/kw2xrf_getset.h |   70 ++
 drivers/kw2xrf/include/kw2xrf_intern.h |  129 +++
 drivers/kw2xrf/include/kw2xrf_netdev.h |   31 +
 drivers/kw2xrf/include/kw2xrf_reg.h    |  216 +++-
 drivers/kw2xrf/include/kw2xrf_spi.h    |   50 +-
 drivers/kw2xrf/include/kw2xrf_tm.h     |   47 +
 drivers/kw2xrf/include/overwrites.h    |  308 ++++++
 drivers/kw2xrf/kw2xrf.c                | 1311 ++----------------------
 drivers/kw2xrf/kw2xrf_getset.c         |  516 ++++++++++
 drivers/kw2xrf/kw2xrf_intern.c         |  230 +++++
 drivers/kw2xrf/kw2xrf_netdev.c         |  765 ++++++++++++++
 drivers/kw2xrf/kw2xrf_spi.c            |  112 +-
 drivers/kw2xrf/kw2xrf_tm.c             |  181 ++++
 sys/auto_init/netif/auto_init_kw2xrf.c |   24 +-
 16 files changed, 2783 insertions(+), 1352 deletions(-)
 create mode 100644 drivers/kw2xrf/include/kw2xrf_getset.h
 create mode 100644 drivers/kw2xrf/include/kw2xrf_intern.h
 create mode 100644 drivers/kw2xrf/include/kw2xrf_netdev.h
 create mode 100644 drivers/kw2xrf/include/kw2xrf_tm.h
 create mode 100644 drivers/kw2xrf/include/overwrites.h
 create mode 100644 drivers/kw2xrf/kw2xrf_getset.c
 create mode 100644 drivers/kw2xrf/kw2xrf_intern.c
 create mode 100644 drivers/kw2xrf/kw2xrf_netdev.c
 create mode 100644 drivers/kw2xrf/kw2xrf_tm.c

diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep
index 8bcb374a09..350907e237 100644
--- a/drivers/Makefile.dep
+++ b/drivers/Makefile.dep
@@ -116,8 +116,11 @@ endif
 ifneq (,$(filter kw2xrf,$(USEMODULE)))
   USEMODULE += ieee802154
   USEMODULE += netif
+  USEMODULE += netdev2_ieee802154
   ifneq (,$(filter gnrc_netdev_default,$(USEMODULE)))
-    USEMODULE += gnrc_nomac
+	# XXX: this can be modelled as a dependency for gnrc_netdev_default as soon
+	# as all drivers are ported to netdev2
+    USEMODULE += gnrc_netdev2
   endif
 endif
 
diff --git a/drivers/include/kw2xrf.h b/drivers/include/kw2xrf.h
index c7682ba1b7..1e328ad464 100644
--- a/drivers/include/kw2xrf.h
+++ b/drivers/include/kw2xrf.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Phytec Messtechnik GmbH
+ * Copyright (C) 2016 Phytec Messtechnik GmbH
  *
  * 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
@@ -8,12 +8,12 @@
 
 /**
  * @defgroup    drivers_kw2xrf kw2x radio-driver
- * @ingroup     drivers_netdev
- * @brief       Device driver for the Freescale KW2xD radio
+ * @ingroup     drivers_netdev_netdev2
+ * @brief       Device driver for the NXP CR20A and KW2xD radios
  * @{
  *
  * @file
- * @brief       Interface definition for the KW2xD device driver
+ * @brief       Interface definition for the kw2xrf driver
  *
  * @author      Johann Fischer <j.fischer@phytec.de>
  * @author      Jonas Remmert <j.remmert@phytec.de>
@@ -27,8 +27,9 @@
 #include "board.h"
 #include "periph/spi.h"
 #include "periph/gpio.h"
-#include "net/gnrc/netdev.h"
-#include "net/ieee802154.h"
+#include "net/netdev2.h"
+#include "net/netdev2/ieee802154.h"
+#include "net/gnrc/nettype.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -39,24 +40,15 @@ extern "C" {
  */
 #define KW2XRF_MAX_PKT_LENGTH         (IEEE802154_FRAME_LEN_MAX)
 
-/**
- * @brief   Default protocol for data that is coming in
- */
-#ifdef MODULE_GNRC_SIXLOWPAN
-#define KW2XRF_DEFAULT_PROTOCOL       GNRC_NETTYPE_SIXLOWPAN
-#else
-#define KW2XRF_DEFAULT_PROTOCOL       GNRC_NETTYPE_UNDEF
-#endif
-
 /**
  * @brief   Default short address used after initialization
  */
-#define KW2XRF_DEFAULT_SHORT_ADDR     (0x0002)
+#define KW2XRF_DEFAULT_SHORT_ADDR       (0x0042)
 
 /**
  * @brief   Default short address used after initialization
  */
-#define KW2XRF_DEFAULT_ADDR_LONG  (0x0000000000000000)
+#define KW2XRF_DEFAULT_ADDR_LONG        (0x0000000DEADCAB1E)
 
 /**
  * @brief   Default PAN ID used after initialization
@@ -72,6 +64,8 @@ extern "C" {
 #ifndef KW2XRF_DEFAULT_CHANNEL
 #define KW2XRF_DEFAULT_CHANNEL        (IEEE802154_DEFAULT_CHANNEL)
 #endif
+#define KW2XRF_MIN_CHANNEL              (11U)
+#define KW2XRF_MAX_CHANNEL              (26U)
 
 /**
  * @brief   Default TX_POWER in dbm used after initialization
@@ -81,79 +75,99 @@ extern "C" {
 /**
  * @brief   Maximum output power of the kw2x device in dBm
  */
-#define MKW2XDRF_OUTPUT_POWER_MAX      (8)
+#define MKW2XDRF_OUTPUT_POWER_MAX       (8)
 
 /**
  * @brief   Minimum output power of the kw2x device in dBm
  */
-#define MKW2XDRF_OUTPUT_POWER_MIN      (-35)
+#define MKW2XDRF_OUTPUT_POWER_MIN       (-35)
 
 /**
  * @brief   Internal device option flags
+ *
+ * `0x00ff` is reserved for general IEEE 802.15.4 flags
+ * (see @ref netdev2_ieee802154_t)
+ *
  * @{
  */
-#define KW2XRF_OPT_AUTOACK       (0x0001)  /**< auto ACKs active */
-#define KW2XRF_OPT_CSMA          (0x0002)  /**< CSMA active */
-#define KW2XRF_OPT_PROMISCUOUS   (0x0004)  /**< promiscuous mode active */
-#define KW2XRF_OPT_PRELOADING    (0x0008)  /**< preloading enabled */
-#define KW2XRF_OPT_TELL_TX_START (0x0010)  /**< notify MAC layer on TX start */
-#define KW2XRF_OPT_TELL_TX_END   (0x0020)  /**< notify MAC layer on TX finished */
-#define KW2XRF_OPT_TELL_RX_START (0x0040)  /**< notify MAC layer on RX start */
-#define KW2XRF_OPT_TELL_RX_END   (0x0080)  /**< notify MAC layer on RX finished */
-#define KW2XRF_OPT_RAWDUMP       (0x0100)  /**< pass RAW frame data to upper layer */
-#define KW2XRF_OPT_SRC_ADDR_LONG (0x0200)  /**< send data using long source address */
-#define KW2XRF_OPT_USE_SRC_PAN   (0x0400)  /**< do not compress source PAN ID */
+#define KW2XRF_OPT_SRC_ADDR_LONG    (NETDEV2_IEEE802154_SRC_MODE_LONG) /**< legacy define */
+#define KW2XRF_OPT_RAWDUMP          (NETDEV2_IEEE802154_RAW)           /**< legacy define */
+#define KW2XRF_OPT_ACK_REQ          (NETDEV2_IEEE802154_ACK_REQ)       /**< legacy define */
+
+#define KW2XRF_OPT_AUTOCCA          (0x0100)    /**< CCA befor TX active */
+#define KW2XRF_OPT_PROMISCUOUS      (0x0200)    /**< promiscuous mode
+                                                  *   active */
+#define KW2XRF_OPT_PRELOADING       (0x0400)    /**< preloading enabled */
+#define KW2XRF_OPT_TELL_TX_START    (0x0800)    /**< notify MAC layer on TX
+                                                  *   start */
+#define KW2XRF_OPT_TELL_TX_END      (0x1000)    /**< notify MAC layer on TX
+                                                  *   finished */
+#define KW2XRF_OPT_TELL_RX_START    (0x2000)    /**< notify MAC layer on RX
+                                                  *   start */
+#define KW2XRF_OPT_TELL_RX_END      (0x4000)    /**< notify MAC layer on RX
+                                                  *   finished */
+#define KW2XRF_OPT_AUTOACK          (0x8000)    /**< enable automatically ACK
+                                                  *   for incommint packet */
 /** @} */
 
 /**
- * @brief   kw2xrf device descriptor
+ * @brief struct holding all params needed for device initialization
+ */
+typedef struct kw2xrf_params {
+    spi_t spi;                          /**< SPI bus the device is connected to */
+    spi_speed_t spi_speed;              /**< SPI speed to use */
+    gpio_t cs_pin;                      /**< GPIO pin connected to chip select */
+    gpio_t int_pin;                     /**< GPIO pin connected to the interrupt pin */
+} kw2xrf_params_t;
+
+/**
+ * @brief   Device descriptor for KW2XRF radio devices
+ *
+ * @extends netdev2_ieee802154_t
  */
 typedef struct {
-    /* netdev fields */
-    gnrc_netdev_driver_t const *driver;   /**< Pointer to the devices interface */
-    gnrc_netdev_event_cb_t event_cb;      /**< Netdev event callback */
-    kernel_pid_t mac_pid;                 /**< The driver's thread's PID */
-    /* driver specific fields */
-    uint8_t buf[KW2XRF_MAX_PKT_LENGTH];   /**< Buffer for incoming or outgoing packets */
-    netopt_state_t state;                 /**< Variable to keep radio driver's state */
-    uint8_t seq_nr;                       /**< Next packets sequence number */
-    uint16_t radio_pan;                   /**< The PAN the radio device is using */
-    uint8_t radio_channel;                /**< The channel the radio device is using */
-    uint8_t addr_short[2];                /**< The short address the radio device is using */
-    uint8_t addr_long[8];                 /**< The long address the radio device is using */
-    uint16_t option;                      /**< Bit field to save enable/disable options */
-    int8_t tx_power;                      /**< The current tx-power setting of the device */
-    gnrc_nettype_t proto;                 /**< Protocol the interface speaks */
+    netdev2_ieee802154_t netdev;         /**< netdev2 parent struct */
+    /**
+     * @brief   device specific fields
+     * @{
+     */
+    kw2xrf_params_t params;             /**< parameters for initialization */
+    uint8_t buf[KW2XRF_MAX_PKT_LENGTH]; /**< Buffer for incoming or outgoing packets */
+    uint8_t state;                      /**< current state of the radio */
+    uint8_t tx_frame_len;               /**< length of the current TX frame */
+    uint8_t idle_state;                 /**< state to return to after sending */
+    uint8_t pending_tx;                 /**< keep track of pending TX calls
+                                             this is required to know when to
+                                             return to @ref kw2xrf_t::idle_state */
+    int16_t tx_power;                   /**< The current tx-power setting of the device */
+    /** @} */
 } kw2xrf_t;
 
+/**
+ * @brief   Setup an KW2XRF based device state
+ *
+ * @param[out] dev          device descriptor
+ * @param[in]  params       parameters for device initialization
+ */
+void kw2xrf_setup(kw2xrf_t *dev, const kw2xrf_params_t *params);
+
 /**
  * @brief   Initialize the given KW2XRF device
  * @param[out] dev          device descriptor
- * @param[in] spi           SPI bus the device is connected to
- * @param[in] spi_clk       SPI bus clock speed to use
- * @param[in] cs_pin        GPIO pin connected to chip select
- * @param[in] int_pin       GPIO pin connected to the interrupt pin
+ * @param[in] cb            irq callback
  *
  * @return                  0 on success
  * @return                  <0 on error
  */
-int kw2xrf_init(kw2xrf_t *dev, spi_t spi, spi_clk_t spi_clk,
-                    gpio_t cs_pin, gpio_t int_pin);
+int kw2xrf_init(kw2xrf_t *dev, gpio_cb_t cb);
 
 /**
- * @brief struct holding all params needed for device initialization
+ * @brief   Configure radio with default values
+ *
+ * @param[in] dev           device to reset
  */
-typedef struct kw2xrf_params {
-    spi_t spi;              /**< SPI bus the device is connected to */
-    spi_clk_t spi_speed;    /**< SPI speed to use */
-    gpio_t cs_pin;          /**< GPIO pin connected to chip select */
-    gpio_t int_pin;         /**< GPIO pin connected to the interrupt pin */
-} kw2xrf_params_t;
+void kw2xrf_reset_phy(kw2xrf_t *dev);
 
-/**
- * @brief Reference to the KW2XRF driver interface
- */
-extern const gnrc_netdev_driver_t kw2xrf_driver;
 
 #ifdef __cplusplus
 }
diff --git a/drivers/kw2xrf/include/kw2xrf_getset.h b/drivers/kw2xrf/include/kw2xrf_getset.h
new file mode 100644
index 0000000000..fbc219b368
--- /dev/null
+++ b/drivers/kw2xrf/include/kw2xrf_getset.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 Phytec Messtechnik GmbH
+ *
+ * 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
+ * @{
+ *
+ * @file
+ * @brief       get/set interfaces for kw2xrf driver
+ *
+ * @author      Johann Fischer <j.fischer@phytec.de>
+ */
+
+#include "kw2xrf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void kw2xrf_set_tx_power(kw2xrf_t *dev, int16_t txpower);
+
+uint16_t kw2xrf_get_txpower(kw2xrf_t *dev);
+
+uint8_t kw2xrf_get_channel(kw2xrf_t *dev);
+
+int kw2xrf_set_channel(kw2xrf_t *dev, uint8_t val);
+
+void kw2xrf_abort_sequence(kw2xrf_t *dev);
+
+void kw2xrf_set_idle_sequence(kw2xrf_t *dev);
+
+void kw2xrf_set_sequence(kw2xrf_t *dev, kw2xrf_physeq_t seq);
+
+void kw2xrf_set_pan(kw2xrf_t *dev, uint16_t pan);
+
+void kw2xrf_set_addr_short(kw2xrf_t *dev, uint16_t addr);
+
+void kw2xrf_set_addr_long(kw2xrf_t *dev, uint64_t addr);
+
+uint16_t kw2xrf_get_addr_short(kw2xrf_t *dev);
+
+uint64_t kw2xrf_get_addr_long(kw2xrf_t *dev);
+
+int8_t kw2xrf_get_cca_threshold(kw2xrf_t *dev);
+
+void kw2xrf_set_cca_threshold(kw2xrf_t *dev, int8_t value);
+
+void kw2xrf_set_cca_mode(kw2xrf_t *dev, uint8_t mode);
+
+uint8_t kw2xrf_get_cca_mode(kw2xrf_t *dev);
+
+uint32_t kw2xrf_get_rssi(uint32_t value);
+
+netopt_state_t kw2xrf_get_status(kw2xrf_t *dev);
+
+int kw2xrf_cca(kw2xrf_t *dev);
+
+void kw2xrf_set_rx_watermark(kw2xrf_t *dev, uint8_t value);
+
+void kw2xrf_set_option(kw2xrf_t *dev, uint16_t option, bool state);
+
+#ifdef __cplusplus
+}
+#endif
+/** @} */
diff --git a/drivers/kw2xrf/include/kw2xrf_intern.h b/drivers/kw2xrf/include/kw2xrf_intern.h
new file mode 100644
index 0000000000..600d37d5d0
--- /dev/null
+++ b/drivers/kw2xrf/include/kw2xrf_intern.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2016 Phytec Messtechnik GmbH
+ *
+ * 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
+ * @{
+ *
+ * @file
+ * @brief       Internal function interfaces for kw2xrf driver
+ *
+ * @author      Johann Fischer <j.fischer@phytec.de>
+ */
+
+#include <stdint.h>
+#include "kw2xrf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Power Modes */
+typedef enum {
+    KW2XRF_HIBERNATE = 0,
+    KW2XRF_DOZE,
+    KW2XRF_IDLE,
+    KW2XRF_AUTODOZE,
+} kw2xrf_powermode_t;
+
+inline void kw2xrf_set_dreg_bit(kw2xrf_t *dev, uint8_t reg, uint8_t bit)
+{
+    uint8_t tmp = kw2xrf_read_dreg(dev, reg);
+    tmp |= bit;
+    kw2xrf_write_dreg(dev, reg, tmp);
+}
+
+inline void kw2xrf_clear_dreg_bit(kw2xrf_t *dev, uint8_t reg, uint8_t bit)
+{
+    uint8_t tmp = kw2xrf_read_dreg(dev, reg);
+    tmp &= ~bit;
+    kw2xrf_write_dreg(dev, reg, tmp);
+}
+
+/** Enable any transceiver interrupt to assert IRQ_B */
+inline void kw2xrf_enable_irq_b(kw2xrf_t *dev)
+{
+    kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL4, MKW2XDM_PHY_CTRL4_TRCV_MSK);
+}
+
+/** Mask all transceiver interrupts to assert IRQ_B */
+inline void kw2xrf_mask_irq_b(kw2xrf_t *dev)
+{
+    kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL4, MKW2XDM_PHY_CTRL4_TRCV_MSK);
+}
+
+void kw2xrf_disable_interrupts(kw2xrf_t *dev);
+
+void kw2xrf_update_overwrites(kw2xrf_t *dev);
+
+void kw2xrf_set_out_clk(kw2xrf_t *dev);
+
+void kw2xrf_set_power_mode(kw2xrf_t *dev, kw2xrf_powermode_t pm);
+
+int kw2xrf_can_switch_to_idle(kw2xrf_t *dev);
+
+typedef enum kw2xrf_timer_timebase {
+    KW2XRF_TIMEBASE_500000HZ = 2,
+    KW2XRF_TIMEBASE_250000HZ,
+    KW2XRF_TIMEBASE_125000HZ,
+    KW2XRF_TIMEBASE_62500HZ,
+    KW2XRF_TIMEBASE_31250HZ,
+    KW2XRF_TIMEBASE_15625HZ,
+} kw2xrf_timer_timebase_t;
+
+/**
+ * Initialize the Event Timer Block (up counter)
+ * The Event Timer Block provides:
+ *   - Abort an RX and CCA sequence at pre-determined time
+ *   - Latches "timestamp" value during packet reception
+ *   - Initiates timer-triggered sequences
+ */
+void kw2xrf_timer_init(kw2xrf_t *dev, kw2xrf_timer_timebase_t tb);
+
+void kw2xrf_timer2_seq_start_on(kw2xrf_t *dev);
+
+void kw2xrf_timer2_seq_start_off(kw2xrf_t *dev);
+
+void kw2xrf_timer3_seq_abort_on(kw2xrf_t *dev);
+
+void kw2xrf_timer3_seq_abort_off(kw2xrf_t *dev);
+
+/**
+ * Use T2CMP or T2PRIMECMP to Trigger Transceiver Operations
+ */
+void kw2xrf_trigger_tx_ops_enable(kw2xrf_t *dev, uint32_t timeout);
+
+/**
+ * Disable Trigger for Transceiver Operations
+ *
+ */
+void kw2xrf_trigger_tx_ops_disable(kw2xrf_t *dev);
+
+/**
+ * Use T3CMP to Abort an RX operation
+ */
+void kw2xrf_abort_rx_ops_enable(kw2xrf_t *dev, uint32_t timeout);
+
+/**
+ * Disable Trigger to Abort an RX operation
+ */
+void kw2xrf_abort_rx_ops_disable(kw2xrf_t *dev);
+
+void kw2xrf_seq_timeout_on(kw2xrf_t *dev, uint32_t timeout);
+
+void kw2xrf_seq_timeout_off(kw2xrf_t *dev);
+
+/**
+ * Returns Timestamp of the actual received packet
+ */
+uint32_t kw2xrf_get_timestamp(kw2xrf_t *dev);
+
+#ifdef __cplusplus
+}
+#endif
+/** @} */
diff --git a/drivers/kw2xrf/include/kw2xrf_netdev.h b/drivers/kw2xrf/include/kw2xrf_netdev.h
new file mode 100644
index 0000000000..ebe42fd0dc
--- /dev/null
+++ b/drivers/kw2xrf/include/kw2xrf_netdev.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 Phytec Messtechnik GmbH
+ *
+ * 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
+ * @{
+ *
+ * @file
+ * @brief       Netdev interface for kw2xrf driver
+ *
+ * @author      Johann Fischer <j.fischer@phytec.de>
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief   Reference to the netdev device driver struct
+ */
+extern const netdev2_driver_t kw2xrf_driver;
+
+#ifdef __cplusplus
+}
+#endif
+/** @} */
diff --git a/drivers/kw2xrf/include/kw2xrf_reg.h b/drivers/kw2xrf/include/kw2xrf_reg.h
index 3fa1b0f7b4..1e572c8482 100644
--- a/drivers/kw2xrf/include/kw2xrf_reg.h
+++ b/drivers/kw2xrf/include/kw2xrf_reg.h
@@ -1,9 +1,43 @@
 /*
- * Copyright (C) 2015 Phytec Messtechnik GmbH
+ * Copyright (C) 2016 Phytec Messtechnik GmbH
  *
  * 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.
+ *
+ * The description of the registers was extracted from the
+ * Reference Manual MKW2xDxxxRM.pdf. After the release of MCR20A Device,
+ * it was extended by the undocumented registers from the file MCR20reg.h.
+ *
+ * Portions of this file are derived from material that is
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
  */
 
 /**
@@ -92,6 +126,24 @@ enum mkw2xdrf_dregister {
     MKW2XDM_SEQ_STATE = 0x24,           /**< Sequence Manager State */
     MKW2XDM_LQI_VALUE = 0x25,           /**< Link Quality Indicator */
     MKW2XDM_RSSI_CCA_CNT = 0x26,        /**< RSSI CCA CNT */
+    MKW2XDM_ASM_CTRL1 = 0x28,
+    MKW2XDM_ASM_CTRL2 = 0x29,
+    MKW2XDM_ASM_DATA_0 = 0x2A,
+    MKW2XDM_ASM_DATA_1 = 0x2B,
+    MKW2XDM_ASM_DATA_2 = 0x2C,
+    MKW2XDM_ASM_DATA_3 = 0x2D,
+    MKW2XDM_ASM_DATA_4 = 0x2E,
+    MKW2XDM_ASM_DATA_5 = 0x2F,
+    MKW2XDM_ASM_DATA_6 = 0x30,
+    MKW2XDM_ASM_DATA_7 = 0x31,
+    MKW2XDM_ASM_DATA_8 = 0x32,
+    MKW2XDM_ASM_DATA_9 = 0x33,
+    MKW2XDM_ASM_DATA_A = 0x34,
+    MKW2XDM_ASM_DATA_B = 0x35,
+    MKW2XDM_ASM_DATA_C = 0x36,
+    MKW2XDM_ASM_DATA_D = 0x37,
+    MKW2XDM_ASM_DATA_E = 0x38,
+    MKW2XDM_ASM_DATA_F = 0x39,
     MKW2XDM_OVERWRITE_VER = 0x3b,       /**< Overwrite Version Number */
     MKW2XDM_CLK_OUT_CTRL = 0x3c,        /**< CLK_OUT Control */
     MKW2XDM_PWR_MODES = 0x3d,           /**< Power Modes */
@@ -124,13 +176,16 @@ enum mkw2xdrf_dregister {
 #define MKW2XDM_IRQSTS3_TMR3IRQ                     (1 << 2)
 #define MKW2XDM_IRQSTS3_TMR2IRQ                     (1 << 1)
 #define MKW2XDM_IRQSTS3_TMR1IRQ                     (1 << 0)
+#define MKW2XDM_IRQSTS3_TMR_IRQ_MASK                0xfu
+#define MKW2XDM_IRQSTS3_TMR_IRQ_SHIFT               0x0u
+#define MKW2XDM_IRQSTS3_TMR_IRQ(x)                  (((uint8_t)(((uint8_t)(x))<<MKW2XDM_IRQSTS3_TMR_IRQ_SHIFT))&MKW2XDM_IRQSTS3_TMR_IRQ_MASK)
 
 #define MKW2XDM_PHY_CTRL1_TMRTRIGEN                 (1 << 7)
 #define MKW2XDM_PHY_CTRL1_SLOTTED                   (1 << 6)
 #define MKW2XDM_PHY_CTRL1_CCABFRTX                  (1 << 5)
 #define MKW2XDM_PHY_CTRL1_RXACKRQD                  (1 << 4)
 #define MKW2XDM_PHY_CTRL1_AUTOACK                   (1 << 3)
-#define MKW2XDM_PHY_CTRL1_XCVSEQ_MASK               0x03u
+#define MKW2XDM_PHY_CTRL1_XCVSEQ_MASK               0x07u
 #define MKW2XDM_PHY_CTRL1_XCVSEQ(x)                 (((uint8_t)(((uint8_t)(x))<<0))&MKW2XDM_PHY_CTRL1_XCVSEQ_MASK)
 
 #define MKW2XDM_PHY_CTRL2_CRC_MSK                   (1 << 7)
@@ -227,6 +282,7 @@ enum mkw2xdrf_iregister {
     MKW2XDMI_CCA_CTRL = 0x25,              /**< CCA Control */
     MKW2XDMI_CCA2_CORR_PEAKS = 0x26,       /**< Clear Channel Assessment 2 Threshold Peak Compare */
     MKW2XDMI_CCA2_THRESH = 0x27,           /**< Clear Channel Assessment 2 Threshold */
+    MKW2XDMI_TMR_PRESCALE = 0x28,          /**< Event Timer Time Base */
     MKW2XDMI_GPIO_DATA = 0x2a,             /**< GPIO Data */
     MKW2XDMI_GPIO_DIR = 0x2b,              /**< GPIO Direction Control */
     MKW2XDMI_GPIO_PUL_EN = 0x2c,           /**< GPIO Pullup Enable */
@@ -234,8 +290,110 @@ enum mkw2xdrf_iregister {
     MKW2XDMI_GPIO_DS = 0x2e,               /**< GPIO Drive Strength */
     MKW2XDMI_ANT_PAD_CTRL = 0x30,          /**< Antenna Control */
     MKW2XDMI_MISC_PAD_CTRL = 0x31,         /**< Miscellaneous Pad Control */
+    MKW2XDMI_BSM_CTRL = 0x32,
+    MKW2XDMI__RNG = 0x34,
+    MKW2XDMI_RX_BYTE_COUNT = 0x35,
+    MKW2XDMI_RX_WTR_MARK = 0x36,
+    MKW2XDMI_SOFT_RESET = 0x37,
+    MKW2XDMI_TXDELAY = 0x38,
+    MKW2XDMI_ACKDELAY = 0x39,
+    MKW2XDMI_SEQ_MGR_CTRL = 0x3A,
+    MKW2XDMI_SEQ_MGR_STS = 0x3B,
+    MKW2XDMI_SEQ_T_STS = 0x3C,
+    MKW2XDMI_ABORT_STS = 0x3D,
+    MKW2XDMI_CCCA_BUSY_CNT = 0x3E,
+    MKW2XDMI_SRC_ADDR_CHECKSUM1 = 0x3F,
+    MKW2XDMI_SRC_ADDR_CHECKSUM2 = 0x40,
+    MKW2XDMI_SRC_TBL_VALID1 = 0x41,
+    MKW2XDMI_SRC_TBL_VALID2 = 0x42,
+    MKW2XDMI_FILTERFAIL_CODE1 = 0x43,
+    MKW2XDMI_FILTERFAIL_CODE2 = 0x44,
+    MKW2XDMI_SLOT_PRELOAD = 0x45,
+    MKW2XDMI_CORR_VT = 0x47,
+    MKW2XDMI_SYNC_CTRL = 0x48,
+    MKW2XDMI_PN_LSB_0 = 0x49,
+    MKW2XDMI_PN_LSB_1 = 0x4A,
+    MKW2XDMI_PN_MSB_0 = 0x4B,
+    MKW2XDMI_PN_MSB_1 = 0x4C,
+    MKW2XDMI_CORR_NVAL = 0x4D,
+    MKW2XDMI_TX_MODE_CTRL = 0x4E,
+    MKW2XDMI_SNF_THR = 0x4F,
+    MKW2XDMI_FAD_THR = 0x50,
     MKW2XDMI_ANT_AGC_CTRL = 0x51,          /**< Antenna AGC and FAD Control */
+    MKW2XDMI_AGC_THR1 = 0x52,
+    MKW2XDMI_AGC_THR2 = 0x53,
+    MKW2XDMI_AGC_HYS = 0x54,
+    MKW2XDMI_AFC = 0x55,
     MKW2XDMI_LPPS_CTRL = 0x56,             /**< LPPS_CTRL */
+    MKW2XDMI_PHY_STS = 0x58,
+    MKW2XDMI_RX_MAX_CORR = 0x59,
+    MKW2XDMI_RX_MAX_PREAMBLE = 0x5A,
+    MKW2XDMI_RSSI = 0x5B,
+    MKW2XDMI_PLL_DIG_CTRL = 0x5E,
+    MKW2XDMI_VCO_CAL = 0x5F,
+    MKW2XDMI_VCO_BEST_DIFF = 0x60,
+    MKW2XDMI_VCO_BIAS = 0x61,
+    MKW2XDMI_KMOD_CTRL = 0x62,
+    MKW2XDMI_KMOD_CAL = 0x63,
+    MKW2XDMI_PA_CAL = 0x64,
+    MKW2XDMI_PA_PWRCAL = 0x65,
+    MKW2XDMI_ATT_RSSI1 = 0x66,
+    MKW2XDMI_ATT_RSSI2 = 0x67,
+    MKW2XDMI_RSSI_OFFSET = 0x68,
+    MKW2XDMI_RSSI_SLOPE = 0x69,
+    MKW2XDMI_RSSI_CAL1 = 0x6A,
+    MKW2XDMI_RSSI_CAL2 = 0x6B,
+    MKW2XDMI_XTAL_CTRL = 0x6E,
+    MKW2XDMI_XTAL_COMP_MIN = 0x6F,
+    MKW2XDMI_XTAL_COMP_MAX = 0x70,
+    MKW2XDMI_XTAL_GM = 0x71,
+    MKW2XDMI_LNA_TUNE = 0x74,
+    MKW2XDMI_LNA_AGCGAIN = 0x75,
+    MKW2XDMI_CHF_PMA_GAIN = 0x78,
+    MKW2XDMI_CHF_IBUF = 0x79,
+    MKW2XDMI_CHF_QBUF = 0x7A,
+    MKW2XDMI_CHF_IRIN = 0x7B,
+    MKW2XDMI_CHF_QRIN = 0x7C,
+    MKW2XDMI_CHF_IL = 0x7D,
+    MKW2XDMI_CHF_QL = 0x7E,
+    MKW2XDMI_CHF_CC1 = 0x7F,
+    MKW2XDMI_CHF_CCL = 0x80,
+    MKW2XDMI_CHF_CC2 = 0x81,
+    MKW2XDMI_CHF_IROUT = 0x82,
+    MKW2XDMI_CHF_QROUT = 0x83,
+    MKW2XDMI_RSSI_CTRL = 0x86,
+    MKW2XDMI_PA_BIAS = 0x89,
+    MKW2XDMI_PA_TUNING = 0x8A,
+    MKW2XDMI_PMC_HP_TRIM = 0x8D,
+    MKW2XDMI_VREGA_TRIM = 0x8E,
+    MKW2XDMI_VCO_CTRL1 = 0x91,
+    MKW2XDMI_VCO_CTRL2 = 0x92,
+    MKW2XDMI_ANA_SPARE_OUT1 = 0x95,
+    MKW2XDMI_ANA_SPARE_OUT2 = 0x96,
+    MKW2XDMI_ANA_SPARE_IN = 0x97,
+    MKW2XDMI_MISCELLANEOUS = 0x98,
+    MKW2XDMI_SEQ_MGR_OVRD0 = 0x9A,
+    MKW2XDMI_SEQ_MGR_OVRD1 = 0x9B,
+    MKW2XDMI_SEQ_MGR_OVRD2 = 0x9C,
+    MKW2XDMI_SEQ_MGR_OVRD3 = 0x9D,
+    MKW2XDMI_SEQ_MGR_OVRD4 = 0x9E,
+    MKW2XDMI_SEQ_MGR_OVRD5 = 0x9F,
+    MKW2XDMI_SEQ_MGR_OVRD6 = 0xA0,
+    MKW2XDMI_SEQ_MGR_OVRD7 = 0xA1,
+    MKW2XDMI_TESTMODE_CTRL = 0xA3,
+    MKW2XDMI_DTM_CTRL1= 0xA4,
+    MKW2XDMI_DTM_CTRL2= 0xA5,
+    MKW2XDMI_ATM_CTRL1= 0xA6,
+    MKW2XDMI_ATM_CTRL2= 0xA7,
+    MKW2XDMI_ATM_CTRL3= 0xA8,
+    MKW2XDMI_LIM_FE_TEST_CTRL = 0xAA,
+    MKW2XDMI_CHF_TEST_CTRL = 0xAB,
+    MKW2XDMI_VCO_TEST_CTRL = 0xAC,
+    MKW2XDMI_PLL_TEST_CTRL = 0xAD,
+    MKW2XDMI_PA_TEST_CTRL = 0xAE,
+    MKW2XDMI_PMC_TEST_CTRL = 0xAF,
+    MKW2XDMI_SCAN_DTM_PROTECT_1 = 0xFE,
+    MKW2XDMI_SCAN_DTM_PROTECT_0 = 0xFF,
 };
 
 #define MKW2XDMI_PART_ID_MANUF_ID_MASK                          0x60u
@@ -279,6 +437,10 @@ enum mkw2xdrf_iregister {
 #define MKW2XDMI_CCA2_CORR_PEAKS_CCA2_MIN_NUM_CORR_TH(x)       (((uint8_t)(((uint8_t)(x))<<MKW2XDMI_CCA2_CORR_PEAKS_CCA2_MIN_NUM_CORR_TH_SHIFT))&MKW2XDMI_CCA2_CORR_PEAKS_CCA2_MIN_NUM_CORR_TH_MASK)
 #define MKW2XDMI_CCA2_CORR_PEAKS_CCA2_NUM_CORR_PEAKS_MASK      0x0Fu
 
+#define MKW2XDMI_TMR_PRESCALE_MASK           0x7u
+#define MKW2XDMI_TMR_PRESCALE_SHIFT          0x0u
+#define MKW2XDMI_TMR_PRESCALE_SET(x)         (((uint8_t)(((uint8_t)(x))<<MKW2XDMI_TMR_PRESCALE_SHIFT))&MKW2XDMI_TMR_PRESCALE_MASK)
+
 #define MKW2XDMI_GPIO_DATA8                  (1 << 7)
 #define MKW2XDMI_GPIO_DATA7                  (1 << 6)
 #define MKW2XDMI_GPIO_DATA6                  (1 << 5)
@@ -348,6 +510,56 @@ enum mkw2xdrf_iregister {
 
 #define MKW2XDMI_LPPS_CTRL_LPPS_EN           (1 << 0)
 
+#define MKW2XDMI_SOFT_RESET_SOG_RST          (1 << 7)
+#define MKW2XDMI_SOFT_RESET_REGS_RST         (1 << 4)
+#define MKW2XDMI_SOFT_RESET_PLL_RST          (1 << 3)
+#define MKW2XDMI_SOFT_RESET_TX_RST           (1 << 2)
+#define MKW2XDMI_SOFT_RESET_RX_RST           (1 << 1)
+#define MKW2XDMI_SOFT_RESET_SEQ_MGR_RST      (1 << 0)
+
+#define MKW2XDMI_SEQ_MGR_CTRL_SEQ_STATE_CTRL_MASK       0x3
+#define MKW2XDMI_SEQ_MGR_CTRL_SEQ_STATE_CTRL_SHIFT      6
+#define MKW2XDMI_SEQ_MGR_CTRL_NO_RX_RECYCLE             (1 << 5)
+#define MKW2XDMI_SEQ_MGR_CTRL_LATCH_PREAMBLE            (1 << 4)
+#define MKW2XDMI_SEQ_MGR_CTRL_EVENT_TMR_DO_NOT_LATCH    (1 << 3)
+#define MKW2XDMI_SEQ_MGR_CTRL_CLR_NEW_SEQ_INHIBIT       (1 << 2)
+#define MKW2XDMI_SEQ_MGR_CTRL_PSM_LOCK_DIS              (1 << 1)
+#define MKW2XDMI_SEQ_MGR_CTRL_PLL_ABORT_OVRD            (1 << 0)
+
+#define MKW2XDMI_SEQ_MGR_STS_TMR2_SEQ_TRIG_ARMED        (1 << 7)
+#define MKW2XDMI_SEQ_MGR_STS_RX_MODE                    (1 << 6)
+#define MKW2XDMI_SEQ_MGR_STS_RX_TIMEOUT_PENDING         (1 << 5)
+#define MKW2XDMI_SEQ_MGR_STS_NEW_SEQ_INHIBIT            (1 << 4)
+#define MKW2XDMI_SEQ_MGR_STS_SEQ_IDLE                   (1 << 3)
+#define MKW2XDMI_SEQ_MGR_STS_XCVSEQ_ACTUAL_MASK         7
+
+#define MKW2XDMI_ABORT_STS_PLL_ABORTED                  (1 << 2)
+#define MKW2XDMI_ABORT_STS_TC3_ABORTED                  (1 << 1)
+#define MKW2XDMI_ABORT_STS_SW_ABORTED                   (1 << 0)
+
+#define MKW2XDMI_TESTMODE_CTRL_HOT_ANT                  (1 << 4)
+#define MKW2XDMI_TESTMODE_CTRL_IDEAL_RSSI_EN            (1 << 3)
+#define MKW2XDMI_TESTMODE_CTRL_IDEAL_PFC_EN             (1 << 2)
+#define MKW2XDMI_TESTMODE_CTRL_CONTINUOUS_EN            (1 << 1)
+#define MKW2XDMI_TESTMODE_CTRL_FPGA_EN                  (1 << 0)
+
+#define MKW2XDMI_DTM_CTRL1_ATM_LOCKED                   (1 << 7)
+#define MKW2XDMI_DTM_CTRL1_DTM_EN                       (1 << 6)
+#define MKW2XDMI_DTM_CTRL1_PAGE5                        (1 << 5)
+#define MKW2XDMI_DTM_CTRL1_PAGE4                        (1 << 4)
+#define MKW2XDMI_DTM_CTRL1_PAGE3                        (1 << 3)
+#define MKW2XDMI_DTM_CTRL1_PAGE2                        (1 << 2)
+#define MKW2XDMI_DTM_CTRL1_PAGE1                        (1 << 1)
+#define MKW2XDMI_DTM_CTRL1_PAGE0                        (1 << 0)
+
+#define MKW2XDMI_TX_MODE_CTRL_TX_INV                    (1 << 4)
+#define MKW2XDMI_TX_MODE_CTRL_BT_EN                     (1 << 3)
+#define MKW2XDMI_TX_MODE_CTRL_DTS2                      (1 << 2)
+#define MKW2XDMI_TX_MODE_CTRL_DTS1                      (1 << 1)
+#define MKW2XDMI_TX_MODE_CTRL_DTS0                      (1 << 0)
+#define MKW2XDMI_TX_MODE_CTRL_DTS_MASK                  7
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/drivers/kw2xrf/include/kw2xrf_spi.h b/drivers/kw2xrf/include/kw2xrf_spi.h
index a973a5510f..3cddd14723 100644
--- a/drivers/kw2xrf/include/kw2xrf_spi.h
+++ b/drivers/kw2xrf/include/kw2xrf_spi.h
@@ -29,85 +29,111 @@ extern "C" {
 
 /**
  * @brief SPI interface initialization
- * @param[in] spi           SPI bus the device is connected to
- * @param[in] spi_clk     SPI clock speed to use
- * @param[in] cs_pin        GPIO pin connected to chip select
+ * @param[in] dev device descriptor
  *
  * @return 0 on success
  * @return -1 on error
  */
-int kw2xrf_spi_init(spi_t spi, spi_clk_t spi_clk, spi_cs_t cs_pin);
+int kw2xrf_spi_init(kw2xrf_t *dev);
 
 /**
  * @brief Writes a byte to the kw2xrf register.
  *
+ * @param[in] dev device descriptor
  * @param[in] addr Address of the register to write.
  * @param[in] value The value to write in the register.
  */
-void kw2xrf_write_dreg(uint8_t addr, uint8_t value);
+void kw2xrf_write_dreg(kw2xrf_t *dev, uint8_t addr, uint8_t value);
 
 /**
  * @brief Reads a byte from the kw2xrf register.
  *
+ * @param[in] dev device descriptor
  * @param[in] addr Address of the register to read.
  * @return Value of the register.
  */
-uint8_t kw2xrf_read_dreg(uint8_t addr);
+uint8_t kw2xrf_read_dreg(kw2xrf_t *dev, uint8_t addr);
+
+/**
+ * @brief Writes to kw2xrf direct registers.
+ *
+ * @param[in] dev device descriptor
+ * @param[in] addr Address of the register to write into.
+ * @param[in] buf Value that shall be written.
+ * @param[in] length Length of the register.
+ */
+size_t kw2xrf_write_dregs(kw2xrf_t *dev, uint8_t addr, uint8_t *buf, uint8_t length);
+
+/**
+ * @brief Reads a byte from the kw2xrf indirect register.
+ *
+ * @param[in] dev device descriptor
+ * @param[in] addr Address of the register to read.
+ * @param[in] buf Buffer, where the content of the reg shall be written to.
+ * @param[in] length Length of the register.
+ */
+size_t kw2xrf_read_dregs(kw2xrf_t *dev, uint8_t addr, uint8_t *buf, uint8_t length);
 
 /**
  * @brief Writes to  a byte from the kw2xrf indirect register.
  *
+ * @param[in] dev device descriptor
  * @param[in] addr Address of the register to write into.
  * @param[in] value Value that shall be written.
  */
-void kw2xrf_write_ireg(uint8_t addr, uint8_t value);
+void kw2xrf_write_ireg(kw2xrf_t *dev, uint8_t addr, uint8_t value);
 
 /**
  * @brief Reads a byte from the kw2xrf indirect register.
  *
+ * @param[in] dev device descriptor
  * @param[in] addr Address of the register to read.
  *
  * @return value in the register
  */
-uint8_t kw2xrf_read_ireg(uint8_t addr);
+uint8_t kw2xrf_read_ireg(kw2xrf_t *dev, uint8_t addr);
 
 /**
  * @brief Writes to kw2xrf indirect registers.
  *
+ * @param[in] dev device descriptor
  * @param[in] addr Address of the register to write into.
  * @param[in] buf Value that shall be written.
  * @param[in] length Length of the register.
  */
-void kw2xrf_write_iregs(uint8_t addr, uint8_t *buf, uint8_t length);
+void kw2xrf_write_iregs(kw2xrf_t *dev, uint8_t addr, uint8_t *buf, uint8_t length);
 
 /**
  * @brief Reads a byte from the kw2xrf indirect register.
  *
+ * @param[in] dev device descriptor
  * @param[in] addr Address of the register to read.
  * @param[in] buf Buffer, where the content of the reg shall be written to.
  * @param[in] length Length of the register.
  */
-void kw2xrf_read_iregs(uint8_t addr, uint8_t *buf, uint8_t length);
+void kw2xrf_read_iregs(kw2xrf_t *dev, uint8_t addr, uint8_t *buf, uint8_t length);
 
 /**
  * @brief Writes multiple bytes to the kw2xrf fifo.
  *
+ * @param[in] dev device descriptor
  * @param[in] data A buffer with the value to write to the fifo.
  * @param[in] data_length The count of bytes which should be written.
  *
  * @return number of bytes written.
  */
-void kw2xrf_write_fifo(uint8_t *data, uint8_t data_length);
+void kw2xrf_write_fifo(kw2xrf_t *dev, uint8_t *data, uint8_t data_length);
 
 /**
  * @brief Reads multiple bytes from the kw2xrf fifo.
  *
+ * @param[in] dev device descriptor
  * @param[out] data A buffer to store the value of the fifo.
  * @param[in] data_length The count of bytes which should be read.
  *
  * @return number of bytes read.
  */
-void kw2xrf_read_fifo(uint8_t *data, uint8_t data_length);
+void kw2xrf_read_fifo(kw2xrf_t *dev, uint8_t *data, uint8_t data_length);
 
 #ifdef __cplusplus
 }
diff --git a/drivers/kw2xrf/include/kw2xrf_tm.h b/drivers/kw2xrf/include/kw2xrf_tm.h
new file mode 100644
index 0000000000..63cfb14e67
--- /dev/null
+++ b/drivers/kw2xrf/include/kw2xrf_tm.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 Phytec Messtechnik GmbH
+ *
+ * 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     tests_kw2xrf
+ * @{
+ *
+ * @file
+ * @brief       Testing interfaces for kw2xrf driver
+ *
+ * @author      Johann Fischer <j.fischer@phytec.de>
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef KW2XRF_TESTMODE
+
+#include "kw2xrf.h"
+#include "kw2xrf_reg.h"
+#include "kw2xrf_getset.h"
+#include "net/netopt.h"
+
+enum mkw2xrf_testmode {
+    KW2XRF_TM_CTX_PREAMBLE = NETOPT_RF_TESTMODE_CTX_PRBS9 + 1,
+    KW2XRF_TM_CTX_2MHZ,
+    KW2XRF_TM_CTX_200KHZ,
+    KW2XRF_TM_CTX_1MBPS_PRBS9,
+    KW2XRF_TM_CTX_EXT,
+    KW2XRF_TM_CTX_NM0,
+    KW2XRF_TM_CTX_NM1,
+};
+
+int kw2xrf_set_test_mode(kw2xrf_t *dev, uint8_t mode);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+/** @} */
diff --git a/drivers/kw2xrf/include/overwrites.h b/drivers/kw2xrf/include/overwrites.h
new file mode 100644
index 0000000000..26d7d5305b
--- /dev/null
+++ b/drivers/kw2xrf/include/overwrites.h
@@ -0,0 +1,308 @@
+/*!
+* Copyright (c) 2015, Freescale Semiconductor, Inc.
+* All rights reserved.
+*
+* \file MCR20Overwrites.h
+* Description: Overwrites header file for MCR20 Register values
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*
+* o Redistributions of source code must retain the above copyright notice, this list
+*   of conditions and the following disclaimer.
+*
+* o Redistributions in binary form must reproduce the above copyright notice, this
+*   list of conditions and the following disclaimer in the documentation and/or
+*   other materials provided with the distribution.
+*
+* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+*   contributors may be used to endorse or promote products derived from this
+*   software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef OVERWRITES_H_
+#define OVERWRITES_H_
+
+typedef struct overwrites_tag {
+    char address;
+    char data;
+} overwrites_t;
+
+
+/*****************************************************************************************************************/
+//         This file is created exclusively for use with the transceiver 2.0 silicon
+//         and is provided for the world to use. It contains a list of all
+//         known overwrite values. Overwrite values are non-default register
+//         values that configure the transceiver device to a more optimally performing
+//         posture. It is expected that low level software (i.e. PHY) will
+//         consume this file as a #include, and transfer the contents to the
+//         the indicated addresses in the transceiver's memory space. This file has
+//         at least one required entry, that being its own version current version
+//         number, to be stored at transceiver's location 0x3B the
+//         OVERWRITES_VERSION_NUMBER register. The RAM register is provided in
+//         the transceiver address space to assist in future debug efforts. The
+//         analyst may read this location (once device has been booted with
+//         mysterious software) and have a good indication of what register
+//         overwrites were performed (with all versions of the overwrites.h file
+//         being archived forever at the Compass location shown above.
+//
+//     The transceiver has an indirect register (IAR) space. Write access to this space
+//         requires 3 or more writes:
+//         1st) the first write is an index value to the indirect (write Bit7=0, register access Bit 6=0) + 0x3E
+//         2nd) IAR Register #0x00 - 0xFF.
+//     3rd) The data to write
+//         nth) Burst mode additional data if required.
+//
+//     Write access to direct space requires only a single address, data pair.
+
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x0C}, //version 0C: new value for ACKDELAY targeting 198us (23 May, 2013, Larry Roshak)
+{0x23, 0x17}  //PA_PWR new default Power Step is "23"
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents)
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3
+{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1
+{0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F}, //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F}, //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24}, //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24}, //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24}, //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24}, //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}, //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D}, //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D}, //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24}, //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24}, //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x64, 0x28}, //PA_CAL_DIS=1  Disabled PA calibration
+{0x52, 0x55}, //AGC_THR1 RSSI tune up
+{0x53, 0x2D}, //AGC_THR2 RSSI tune up
+{0x66, 0x5F}, //ATT_RSSI1 tune up
+{0x67, 0x8F}, //ATT_RSSI2 tune up
+{0x68, 0x61}, //RSSI_OFFSET
+{0x78, 0x03}, //CHF_PMAGAIN
+{0x22, 0x50}, //CCA1_THRESH
+{0x4D, 0x13}, //CORR_NVAL moved from 0x14 to 0x13 for 0.5 dB improved Rx Sensitivity
+{0x39, 0x3D}  //ACKDELAY new value targeting a delay of 198us (23 May, 2013, Larry Roshak)
+};
+
+
+/* begin of deprecated versions
+
+==VERSION 1==
+(version 1 is empty)
+
+==VERSION 2==
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}  //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents)
+};
+
+==VERSION 3==
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents)
+{0x91, 0xB3}, //VCO_CTRL1: override VCOALC_REF_TX to 3
+{0x92, 0x07}  //VCO_CTRL2: override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1
+};
+
+==VERSION 4==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x04}  //version 04 is the current version: update PA_COILTUNING default
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents)
+{0x91, 0xB3}, //VCO_CTRL1: override VCOALC_REF_TX to 3
+{0x92, 0x07}  //VCO_CTRL2: override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1
+{0x8A, 0x71}  //PA_TUNING: override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+};
+
+==VERSION 5==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x05}  //version 05: updates Channel Filter Register set (21 Dec 2012, on behalf of S. Soca)
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents)
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3
+{0x92, 0x07}  //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1
+{0x8A, 0x71}  //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F}  //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F}  //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24}  //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24}  //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24}  //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24}  //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24}  //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24}  //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}  //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D}  //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D}  //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+};
+
+==VERSION 6==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x06}  //version 06: disable PA calibration
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents)
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3
+{0x92, 0x07}  //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1
+{0x8A, 0x71}  //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F}  //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F}  //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24}  //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24}  //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24}  //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24}  //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24}  //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24}  //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}  //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D}  //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D}  //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x64, 0x28}  //PA_CAL_DIS=1  Disabled PA calibration
+};
+
+==VERSION 7==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x07}  //version 07: updated registers for ED/RSSI
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents)
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3
+{0x92, 0x07},  //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1
+{0x8A, 0x71},  //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F},  //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F},  //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24},  //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24},  //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24},  //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24},  //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24},  //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24},  //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}, //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D},  //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D},  //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x64, 0x28},  //PA_CAL_DIS=1  Disabled PA calibration
+{0x52, 0x73},  //AGC_THR1 RSSI tune up
+{0x53, 0x2D}, //AGC_THR2 RSSI tune up
+{0x66, 0x5F}, //ATT_RSSI1 tune up
+{0x67, 0x8F}, //ATT_RSSI2 tune up
+{0x68, 0x60}, //RSSI_OFFSET
+{0x69, 0x65}  //RSSI_SLOPE
+};
+
+
+==VERSION 8==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x08}  //version 08: updated registers for ED/RSSI
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents)
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3
+{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1
+{0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F}, //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F}, //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24}, //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24}, //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24}, //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24}, //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24}, //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24}, //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}, //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D}, //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D}, //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x64, 0x28}, //PA_CAL_DIS=1  Disabled PA calibration
+{0x52, 0x73}, //AGC_THR1 RSSI tune up
+{0x53, 0x2D}, //AGC_THR2 RSSI tune up
+{0x66, 0x5F}, //ATT_RSSI1 tune up
+{0x67, 0x8F}, //ATT_RSSI2 tune up
+{0x69, 0x65}  //RSSI_SLOPE
+{0x68, 0x61}, //RSSI_OFFSET
+{0x78, 0x03}  //CHF_PMAGAIN
+};
+
+
+==VERSION 9==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x09}  //version 09: updated registers for ED/RSSI and PowerStep
+{0x23, 0x17}  //PA_PWR new default value
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents)
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3
+{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1
+{0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F}, //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F}, //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24}, //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24}, //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24}, //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24}, //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}, //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D}, //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D}, //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24}, //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24}, //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x64, 0x28}, //PA_CAL_DIS=1  Disabled PA calibration
+{0x52, 0x55}, //AGC_THR1 RSSI tune up
+{0x53, 0x2D}, //AGC_THR2 RSSI tune up
+{0x66, 0x5F}, //ATT_RSSI1 tune up
+{0x67, 0x8F}, //ATT_RSSI2 tune up
+{0x68, 0x61}, //RSSI_OFFSET
+{0x78, 0x03}  //CHF_PMAGAIN
+};
+
+==VERSION A==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x0A}  //version 0A: updated registers for CCA
+{0x23, 0x17}  //PA_PWR new default Power Step is "23"
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents)
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3
+{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1
+{0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F}, //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F}, //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24}, //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24}, //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24}, //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24}, //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}, //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D}, //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D}, //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24}, //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24}, //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x64, 0x28}, //PA_CAL_DIS=1  Disabled PA calibration
+{0x52, 0x55}, //AGC_THR1 RSSI tune up
+{0x53, 0x2D}, //AGC_THR2 RSSI tune up
+{0x66, 0x5F}, //ATT_RSSI1 tune up
+{0x67, 0x8F}, //ATT_RSSI2 tune up
+{0x68, 0x61}, //RSSI_OFFSET
+{0x78, 0x03}  //CHF_PMAGAIN
+{0x22, 0x50}  //CCA1_THRESH
+};
+
+end of deprecated versions */
+
+
+#endif  //OVERWRITES_H_
diff --git a/drivers/kw2xrf/kw2xrf.c b/drivers/kw2xrf/kw2xrf.c
index fd2b41d9b7..b4fdbb859d 100644
--- a/drivers/kw2xrf/kw2xrf.c
+++ b/drivers/kw2xrf/kw2xrf.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 PHYTEC Messtechnik GmbH
+ * Copyright (C) 2016 PHYTEC Messtechnik GmbH
  *
  * 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
@@ -7,7 +7,7 @@
  */
 
 /**
- * @ingroup     kw2xrf
+ * @ingroup     drivers_kw2xrf
  * @{
  * @file
  * @brief       Basic functionality of kw2xrf driver
@@ -17,10 +17,9 @@
  * @author      Oliver Hahm <oliver.hahm@inria.fr>
  * @}
  */
-#include "panic.h"
-#include "kw2xrf.h"
-#include "kw2xrf_spi.h"
-#include "kw2xrf_reg.h"
+#include <stdint.h>
+#include <string.h>
+
 #include "mutex.h"
 #include "msg.h"
 #include "periph/gpio.h"
@@ -28,1262 +27,136 @@
 #include "net/gnrc.h"
 #include "net/ieee802154.h"
 
+#include "kw2xrf.h"
+#include "kw2xrf_spi.h"
+#include "kw2xrf_reg.h"
+#include "kw2xrf_netdev.h"
+#include "kw2xrf_getset.h"
+#include "kw2xrf_intern.h"
+
 #define ENABLE_DEBUG    (0)
 #include "debug.h"
 
-/**
- * @brief   Internal driver event type in case of an unexpected interrupt
- */
-#define ISR_EVENT_UNKNOWN      (0x0020)
-
-/* Modem_PA_PWR Register (PA Power Control) has a valid range from 3-31 */
-#define MKW2XDRF_PA_RANGE_MAX      31       /**< Maximum value of PA Power Control Register */
-#define MKW2XDRF_PA_RANGE_MIN      3        /**< Minimum value of PA Power Control Register */
-
-#define _MAX_MHR_OVERHEAD       (25)
-
-/* PLL integer lookup table */
-static const uint8_t pll_int_lt[16] = {
-    11, 11, 11, 11,
-    11, 11, 12, 12,
-    12, 12, 12, 12,
-    13, 13, 13, 13
-};
-
-/* PLL frequency fractional lookup table */
-static const uint16_t pll_frac_lt[16] = {
-    10240, 20480, 30720, 40960,
-    51200, 61440, 6144, 16384,
-    26624, 36864, 47104, 57344,
-    2048, 12288, 22528, 32768
-};
-
-static const uint8_t pow_lt[44] = {
-    3, 4, 4, 5,
-    6, 6, 7, 7,
-    8, 9, 9, 10,
-    11, 11, 12, 13,
-    13, 14, 14, 15,
-    16, 16, 17, 18,
-    18, 19, 20, 20,
-    21, 21, 22, 23,
-    23, 24, 25, 25,
-    26, 27, 27, 28,
-    28, 29, 30, 31
-};
-
-/* TODO: Implement this
-static const int level_lt[29] = {
-    -35, -34, -32, -31,
-    -29, -28, -26, -25,
-    -23, -22, -20, -19,
-    -17, -16, -14, -13,
-    -11, -10, -8, -7,
-    -5, -4, -2, -1,
-    1, 2, 4, 5,
-    7
-};
-*/
-
-static gpio_t kw2xrf_gpio_int;
-
-void kw2xrf_set_option(kw2xrf_t *dev, uint16_t option, bool state);
-
-int kw2xrf_set_tx_power(kw2xrf_t *dev, int8_t *val, size_t len)
-{
-    uint8_t level = pow_lt[val[0] - MKW2XDRF_OUTPUT_POWER_MIN];
-    kw2xrf_write_dreg(MKW2XDM_PA_PWR, MKW2XDM_PA_PWR(level));
-    return 2;
-}
-
-int kw2xrf_get_channel(kw2xrf_t *dev, uint8_t *val, size_t max)
-{
-    if (max < 2) {
-        return -EOVERFLOW;
-    }
-
-    uint8_t pll_int = kw2xrf_read_dreg(MKW2XDM_PLL_INT0);
-    uint16_t pll_frac = kw2xrf_read_dreg(MKW2XDM_PLL_FRAC0_LSB);
-    pll_frac |= ((uint16_t)kw2xrf_read_dreg(MKW2XDM_PLL_FRAC0_MSB) << 8);
-
-    for (int i = 0; i < 16; i++) {
-        if ((pll_frac_lt[i] == pll_frac) && (pll_int_lt[i] == pll_int)) {
-            val[0] = i + 11;
-            val[1] = 0;
-            return 2;
-        }
-    }
-
-    return -EINVAL;
-}
-
-int kw2xrf_get_sequence(void)
-{
-    int reg = 0;
-    reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL1);
-    reg &= MKW2XDM_PHY_CTRL1_XCVSEQ_MASK;
-    return reg;
-}
-
-void kw2xrf_set_sequence(kw2xrf_t *dev, kw2xrf_physeq_t seq)
-{
-    uint8_t reg = 0;
-
-    /* Only interrupt interruptable states */
-    uint8_t curr_seq = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL1);
-    curr_seq &= (MKW2XDM_PHY_CTRL1_XCVSEQ_MASK);
-
-    if ((curr_seq == XCVSEQ_RECEIVE) || (curr_seq == XCVSEQ_CONTINUOUS_CCA)) {
-        /* Clear all pending interrupts */
-        gpio_irq_disable(kw2xrf_gpio_int);
-
-        /* abort any ongoing sequence */
-        DEBUG("kw2xrf_tx: abort SEQ_STATE: %x\n", kw2xrf_read_dreg(MKW2XDM_SEQ_STATE));
-        reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL1);
-        reg &= ~(MKW2XDM_PHY_CTRL1_XCVSEQ_MASK);
-        kw2xrf_write_dreg(MKW2XDM_PHY_CTRL1, reg);
-
-        /* Mask all possible interrupts */
-        reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL3);
-        reg |= MKW2XDM_PHY_CTRL3_WAKE_MSK;
-        kw2xrf_write_dreg(MKW2XDM_PHY_CTRL3, reg);
-
-        kw2xrf_write_dreg(MKW2XDM_IRQSTS1, 0x7f);
-        kw2xrf_write_dreg(MKW2XDM_IRQSTS2, 0x03);
-        kw2xrf_write_dreg(MKW2XDM_IRQSTS3, 0xff);
-
-        gpio_irq_enable(kw2xrf_gpio_int);
-    }
-
-#ifdef DEVELHELP
-    uint16_t max_tries = 0;
-#endif
-
-    /* Wait for all other states finish */
-    while (kw2xrf_read_dreg(MKW2XDM_SEQ_STATE)) {
-#ifdef DEVELHELP
-        max_tries++;
-
-        /* At 10MHz SPI-Clock, 40000 should be in the magnitue of 0.1s */
-        if (max_tries == 40000) {
-            DEBUG("kw2xrf_error: device does not finish sequence\n");
-            core_panic(PANIC_GENERAL_ERROR, "kw2xrf_error: device does not finish sequence");
-        }
-
-#endif
-    }
-
-    /* For all sequences only enable SEQ-irq will be set when sequence completed */
-    reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL2);
-    reg &= ~(MKW2XDM_PHY_CTRL2_SEQMSK);
-    kw2xrf_write_dreg(MKW2XDM_PHY_CTRL2, reg);
-
-    /* Progrmm new sequence */
-    switch (seq) {
-        case XCVSEQ_IDLE:
-            dev->state = NETOPT_STATE_SLEEP;
-            break;
-
-        case XCVSEQ_RECEIVE:
-            dev->state = NETOPT_STATE_RX;
-            break;
-
-        case XCVSEQ_TRANSMIT:
-            dev->state = NETOPT_STATE_TX;
-            break;
-
-        case XCVSEQ_CCA:
-            dev->state = NETOPT_STATE_TX;
-            break;
-
-        case XCVSEQ_TX_RX:
-            dev->state = NETOPT_STATE_TX;
-            break;
-
-        case XCVSEQ_CONTINUOUS_CCA:
-            dev->state = NETOPT_STATE_TX;
-            break;
-
-        default:
-            DEBUG("kw2xrf: undefined state assigned to phy\n");
-            dev->state = NETOPT_STATE_IDLE;
-    }
-
-    /* Mapping of TX-sequences depending on AUTOACK flag */
-    /* TODO: This should only used in combination with
-     *       an CSMA-MAC layer. Currently not working
-     */
-    /*if ((seq == XCVSEQ_TRANSMIT) || (seq == XCVSEQ_TX_RX)) {
-        if ((dev->option) & KW2XRF_OPT_AUTOACK) {
-            seq = XCVSEQ_TX_RX;
-        }
-        else {
-            seq = XCVSEQ_TRANSMIT;
-        }
-    }*/
-
-    DEBUG("kw2xrf: Set sequence to %i\n", seq);
-    reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL1);
-    reg &= ~(MKW2XDM_PHY_CTRL1_XCVSEQ_MASK);
-    reg |= MKW2XDM_PHY_CTRL1_XCVSEQ(seq);
-    kw2xrf_write_dreg(MKW2XDM_PHY_CTRL1, reg);
-}
-
-int kw2xrf_set_channel(kw2xrf_t *dev, uint8_t *val, size_t len)
-{
-    /* Save old sequence to restore this state later */
-    uint8_t old_seq = kw2xrf_get_sequence();
-
-    if (old_seq) {
-        kw2xrf_set_sequence(dev, XCVSEQ_IDLE);
-    }
-
-    if ((val[0] < 11) || (val[0] > 26)) {
-        DEBUG("kw2xrf: Invalid channel %i set. Valid channels are 11 through 26\n", val[0]);
-        return -ENOTSUP;
-    }
-
-    if ((len != 2) || (val[1] != 0)) {
-        DEBUG("kw2xrf: set channel failed, len: %u, val[0]:%u\n", len, val[0]);
-        return -EINVAL;
-    }
-
-    /*
-     * Fc = 2405 + 5(k - 11) , k = 11,12,...,26
-     *
-     * Equation for PLL frequency, MKW2xD Reference Manual, p.255 :
-     * F = ((PLL_INT0 + 64) + (PLL_FRAC0/65536))32MHz
-     *
-     */
-    uint8_t tmp = val[0] - 11;
-    kw2xrf_write_dreg(MKW2XDM_PLL_INT0, MKW2XDM_PLL_INT0_VAL(pll_int_lt[tmp]));
-    kw2xrf_write_dreg(MKW2XDM_PLL_FRAC0_LSB, (uint8_t)pll_frac_lt[tmp]);
-    kw2xrf_write_dreg(MKW2XDM_PLL_FRAC0_MSB, (uint8_t)(pll_frac_lt[tmp] >> 8));
-
-    DEBUG("kw2xrf: set channel to %u\n", val[0]);
-
-    if (old_seq) {
-        kw2xrf_set_sequence(dev, old_seq);
-    }
-
-    return 2;
-}
-
-void kw2xrf_irq_handler(void *args)
-{
-    msg_t msg;
-    kw2xrf_t *dev = (kw2xrf_t *)args;
-
-    /* notify driver thread about the interrupt */
-    msg.type = GNRC_NETDEV_MSG_TYPE_EVENT;
-    msg_send_int(&msg, dev->mac_pid);
-}
-
-/* Set up interrupt sources, triggered by the radio-module */
-void kw2xrf_init_interrupts(kw2xrf_t *dev, gpio_t int_pin)
-{
-    /* Clear all pending interrupts */
-    kw2xrf_write_dreg(MKW2XDM_IRQSTS1, 0x7f);
-    kw2xrf_write_dreg(MKW2XDM_IRQSTS2, 0x03);
-    kw2xrf_write_dreg(MKW2XDM_IRQSTS3, 0xff);
-
-    /* Disable all interrups:
-     * Selectively enable only one interrupt source selectively in sequence manager.
-     * After reset state all interrupts are disabled, except WAKE_IRQ.
-     */
-    int reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL3);
-    reg |= MKW2XDM_PHY_CTRL3_WAKE_MSK;
-    kw2xrf_write_dreg(MKW2XDM_PHY_CTRL3, reg);
-
-    /* set up GPIO-pin used for IRQ */
-    gpio_init_int(int_pin, GPIO_IN, GPIO_FALLING, &kw2xrf_irq_handler, dev);
-}
-
-int kw2xrf_set_pan(kw2xrf_t *dev, uint16_t pan)
-{
-    dev->radio_pan = pan;
-
-    uint8_t val_ar[2];
-    val_ar[1] = (pan >> 8);
-    val_ar[0] = (uint8_t)pan;
-    kw2xrf_write_iregs(MKW2XDMI_MACPANID0_LSB, val_ar, 2);
-    return 2;
-}
-
-int kw2xrf_get_proto(kw2xrf_t *dev, uint8_t *val, size_t max)
-{
-    if (max < sizeof(gnrc_nettype_t)) {
-        return -EOVERFLOW;
-    }
-
-    memcpy(val, &(dev->proto), sizeof(gnrc_nettype_t));
-    return sizeof(gnrc_nettype_t);
-}
-
-int kw2xrf_set_proto(kw2xrf_t *dev, uint8_t *val, size_t len)
-{
-    if (len != sizeof(gnrc_nettype_t)) {
-        return -EINVAL;
-    }
-
-    memcpy(&(dev->proto), val, sizeof(gnrc_nettype_t));
-    return sizeof(gnrc_nettype_t);
-}
-
-int kw2xrf_on(kw2xrf_t *dev)
-{
-    uint8_t tmp;
-    /* check modem's crystal oscillator, CLK_OUT shall be 4MHz */
-    tmp = kw2xrf_read_dreg(MKW2XDM_CLK_OUT_CTRL);
-
-    if (tmp != 0x8Bu) {
-        return -1;
-    }
-
-    DEBUG("SEQ_STATE: %x\n", kw2xrf_read_dreg(MKW2XDM_SEQ_STATE));
-
-    /* enable RFon mode */
-    kw2xrf_write_dreg(MKW2XDM_PWR_MODES,
-                      (MKW2XDM_PWR_MODES_XTALEN | MKW2XDM_PWR_MODES_PMC_MODE));
-
-    /* abort any ongoing sequence */
-    kw2xrf_set_sequence(dev, XCVSEQ_IDLE);
-
-    dev->state = NETOPT_STATE_SLEEP;
-    return 0;
-}
-
-int kw2xrf_set_addr(kw2xrf_t *dev, uint16_t addr)
-{
-    uint8_t val_ar[2];
-    val_ar[0] = (addr >> 8);
-    val_ar[1] = (uint8_t)addr;
-    dev->addr_short[0] = val_ar[0];
-    dev->addr_short[1] = val_ar[1];
-#ifdef MODULE_SIXLOWPAN
-    /* https://tools.ietf.org/html/rfc4944#section-12 requires the first bit to
-     * 0 for unicast addresses */
-    dev->addr_short[1] &= 0x7F;
-#endif
-    kw2xrf_write_iregs(MKW2XDMI_MACSHORTADDRS0_LSB, val_ar,
-                       IEEE802154_SHORT_ADDRESS_LEN);
-
-    return sizeof(uint16_t);
-}
-
-int kw2xrf_set_addr_long(kw2xrf_t *dev, uint64_t addr)
-{
-    for (int i = 0; i < IEEE802154_LONG_ADDRESS_LEN; i++) {
-        dev->addr_long[i] = (addr >> ((IEEE802154_LONG_ADDRESS_LEN - 1 - i) * 8));
-    }
-
-    kw2xrf_write_iregs(MKW2XDMI_MACLONGADDRS0_0, (dev->addr_long),
-                       IEEE802154_LONG_ADDRESS_LEN);
-
-    return sizeof(uint64_t);
-}
-
-int kw2xrf_init(kw2xrf_t *dev, spi_t spi, spi_clk_t spi_clk,
-                gpio_t cs_pin, gpio_t int_pin)
-{
-    uint8_t reg = 0;
-    uint8_t tmp[2];
-    kw2xrf_gpio_int = int_pin;
 #if CPUID_LEN
 /* make sure that the buffer is always big enough to store a 64bit value */
-#   if CPUID_LEN < IEEE802154_LONG_ADDRESS_LEN
-    uint8_t cpuid[IEEE802154_LONG_ADDRESS_LEN];
-#   else
-    uint8_t cpuid[CPUID_LEN];
-#endif
-    uint16_t addr_short = 0;
-    eui64_t addr_long;
-#endif
-
-    /* check device parameters */
-    if (dev == NULL) {
-        return -ENODEV;
-    }
-
-    kw2xrf_spi_init(spi, spi_clk, cs_pin);
-
-    if (kw2xrf_on(dev) != 0) {
-        core_panic(PANIC_GENERAL_ERROR, "Could not start MKW2XD radio transceiver");
-    }
-
-    /* General initialization of interrupt sources.
-     * sets radio to idle mode with all interrupt masked
-     */
-    kw2xrf_init_interrupts(dev, kw2xrf_gpio_int);
-
-    /* set device driver */
-    dev->driver = &kw2xrf_driver;
-    /* set default option */
-    dev->proto = KW2XRF_DEFAULT_PROTOCOL;
-    dev->option = 0;
-
-#if CPUID_LEN
-    /* in case CPUID_LEN < 8, fill missing bytes with zeros */
-    memset(cpuid, 0, CPUID_LEN);
-
-    cpuid_get(cpuid);
-
-    /* generate short hardware address if CPUID_LEN > 0 */
-    for (int i = 0; i < CPUID_LEN; i++) {
-        /* XOR each even byte of the CPUID with LSB of short address
-           and each odd byte with MSB */
-        addr_short ^= (uint16_t)(cpuid[i] << ((i & 0x01) * 8));
-    }
-#if CPUID_LEN > IEEE802154_LONG_ADDRESS_LEN
-    for (int i = IEEE802154_LONG_ADDRESS_LEN; i < CPUID_LEN; i++) {
-        cpuid[i & 0x07] ^= cpuid[i];
-    }
-#endif
-    /* make sure we mark the address as non-multicast and not globally unique */
-    cpuid[0] &= ~(0x01);
-    cpuid[0] |= 0x02;
-    /* copy and set long address */
-    memcpy(&addr_long, cpuid, IEEE802154_LONG_ADDRESS_LEN);
-    kw2xrf_set_addr_long(dev, NTOHLL(addr_long.uint64.u64));
-    kw2xrf_set_addr(dev, addr_short);
+#if CPUID_LEN < IEEE802154_LONG_ADDRESS_LEN
+#define KW2XRF_ID_LEN   IEEE802154_LONG_ADDRESS_LEN
 #else
-    kw2xrf_set_addr_long(dev, KW2XRF_DEFAULT_SHORT_ADDR);
-    kw2xrf_set_addr(dev, KW2XRF_DEFAULT_ADDR_LONG);
+#define KW2XRF_ID_LEN   CPUID_LEN
+#endif
 #endif
 
-    /* set default TX-Power */
-    dev->tx_power = KW2XRF_DEFAULT_TX_POWER;
-    kw2xrf_set_tx_power(dev, &(dev->tx_power), sizeof(dev->tx_power));
-
-    /* set default channel */
-    dev->radio_channel = KW2XRF_DEFAULT_CHANNEL;
-    tmp[0] = dev->radio_channel;
-    tmp[1] = 0;
-    kw2xrf_set_channel(dev, tmp, 2);
-    /* set default PAN ID */
-    kw2xrf_set_pan(dev, KW2XRF_DEFAULT_PANID);
-
-    /* CCA Setup */
-    reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL4);
-    /* Set up CCA mode 1 (RSSI threshold) */
-    reg |= MKW2XDM_PHY_CTRL4_CCATYPE(1);
-    kw2xrf_write_dreg(MKW2XDM_PHY_CTRL4, reg);
-    DEBUG("kw2xrf: Initialized and set to channel %i and pan %i.\n",
-          KW2XRF_DEFAULT_CHANNEL, KW2XRF_DEFAULT_PANID);
-
-    kw2xrf_set_option(dev, KW2XRF_OPT_AUTOACK, true);
-    kw2xrf_set_option(dev, KW2XRF_OPT_CSMA, true);
-
-    /* Switch to Receive state per default after initialization */
-    kw2xrf_set_sequence(dev, XCVSEQ_RECEIVE);
-    return 0;
-}
-
-int kw2xrf_add_cb(gnrc_netdev_t *dev, gnrc_netdev_event_cb_t cb)
-{
-    if (dev == NULL) {
-        return -ENODEV;
-    }
-
-    if (dev->event_cb != NULL) {
-        return -ENOBUFS;
-    }
-
-    dev->event_cb = cb;
-    return 0;
-}
-
-int kw2xrf_rem_cb(gnrc_netdev_t *dev, gnrc_netdev_event_cb_t cb)
-{
-    if (dev == NULL) {
-        return -ENODEV;
-    }
-
-    if (dev->event_cb != cb) {
-        return -ENOENT;
-    }
-
-    dev->event_cb = NULL;
-    return 0;
-}
-
-uint16_t kw2xrf_get_addr_short(kw2xrf_t *dev)
-{
-    return (dev->addr_short[0] << 8) | dev->addr_short[1];
-}
-
-uint64_t kw2xrf_get_addr_long(kw2xrf_t *dev)
-{
-    uint64_t addr;
-    uint8_t *ap = (uint8_t *)(&addr);
-
-    for (int i = 0; i < IEEE802154_LONG_ADDRESS_LEN; i++) {
-        ap[i] = dev->addr_long[IEEE802154_LONG_ADDRESS_LEN - 1 - i];
-    }
-
-    return addr;
-}
-
-int8_t kw2xrf_get_cca_threshold(kw2xrf_t *dev)
-{
-    uint8_t tmp;
-    kw2xrf_read_iregs(MKW2XDMI_CCA1_THRESH, &tmp, 1);
-    /* KW2x register value represents absolute value in dBm
-     * default value: -75 dBm
-     */
-    return (-tmp);
-}
-
-void kw2xrf_set_cca_threshold(kw2xrf_t *dev, int8_t value)
-{
-    /* normalize to absolute value */
-    if (value < 0) {
-        value = -value;
-    }
-    kw2xrf_write_iregs(MKW2XDMI_CCA1_THRESH, (uint8_t*)&value, 1);
-}
-
-int kw2xrf_get(gnrc_netdev_t *netdev, netopt_t opt, void *value, size_t max_len)
-{
-    kw2xrf_t *dev = (kw2xrf_t *)netdev;
-
-    if (dev == NULL) {
-        return -ENODEV;
-    }
-
-    switch (opt) {
-        case NETOPT_ADDRESS:
-            if (max_len < sizeof(uint16_t)) {
-                return -EOVERFLOW;
-            }
-
-            *((uint16_t *)value) = kw2xrf_get_addr_short(dev);
-            return sizeof(uint16_t);
-
-        case NETOPT_ADDRESS_LONG:
-            if (max_len < sizeof(uint64_t)) {
-                return -EOVERFLOW;
-            }
-
-            *((uint64_t *)value) = kw2xrf_get_addr_long(dev);
-            return sizeof(uint64_t);
-
-        case NETOPT_ADDR_LEN:
-            if (max_len < sizeof(uint16_t)) {
-                return -EOVERFLOW;
-            }
-
-            *((uint16_t *)value) = 2;
-            return sizeof(uint16_t);
-
-        case NETOPT_SRC_LEN:
-            if (max_len < sizeof(uint16_t)) {
-                return -EOVERFLOW;
-            }
-
-            if (dev->option & KW2XRF_OPT_SRC_ADDR_LONG) {
-                *((uint16_t *)value) = IEEE802154_LONG_ADDRESS_LEN;
-            }
-            else {
-                *((uint16_t *)value) = IEEE802154_SHORT_ADDRESS_LEN;
-            }
-
-            return sizeof(uint16_t);
-
-        case NETOPT_NID:
-            if (max_len < sizeof(uint16_t)) {
-                return -EOVERFLOW;
-            }
-
-            *((uint16_t *)value) = dev->radio_pan;
-            return sizeof(uint16_t);
-
-        case NETOPT_IPV6_IID:
-            if (max_len < sizeof(eui64_t)) {
-                return -EOVERFLOW;
-            }
-            if (dev->option & KW2XRF_OPT_SRC_ADDR_LONG) {
-                uint64_t addr = kw2xrf_get_addr_long(dev);
-                ieee802154_get_iid(value, (uint8_t *)&addr, IEEE802154_LONG_ADDRESS_LEN);
-            }
-            else {
-                uint16_t addr = kw2xrf_get_addr_short(dev);
-                ieee802154_get_iid(value, (uint8_t *)&addr, IEEE802154_SHORT_ADDRESS_LEN);
-            }
-            return sizeof(eui64_t);
-
-        case NETOPT_CHANNEL:
-            return kw2xrf_get_channel(dev, (uint8_t *)value, max_len);
-
-        case NETOPT_PROTO:
-            return kw2xrf_get_proto(dev, (uint8_t *)value, max_len);
-
-        case NETOPT_STATE:
-            if (max_len < sizeof(netopt_state_t)) {
-                return -EOVERFLOW;
-            }
-
-            *(netopt_state_t *)value = *(netopt_state_t *) & (dev->state);
-            return 0;
-
-        case NETOPT_TX_POWER:
-            if (max_len < 1) {
-                return -EOVERFLOW;
-            }
-
-            *(int16_t *)value = dev->tx_power;
-            return 0;
-
-        case NETOPT_CCA_THRESHOLD:
-            if (max_len < sizeof(uint8_t)) {
-                return -EOVERFLOW;
-            } else {
-            *(int8_t *)value = kw2xrf_get_cca_threshold(dev);
-            }
-            return 0;
-
-        case NETOPT_MAX_PACKET_SIZE:
-            if (max_len < sizeof(int16_t)) {
-                return -EOVERFLOW;
-            }
-
-            *((uint16_t *)value) = KW2XRF_MAX_PKT_LENGTH - _MAX_MHR_OVERHEAD;
-            return sizeof(uint16_t);
-
-        case NETOPT_PRELOADING:
-            *((netopt_enable_t *)value) = !!(dev->option & KW2XRF_OPT_PRELOADING);
-            return sizeof(netopt_enable_t);
-
-        case NETOPT_AUTOACK:
-            *((netopt_enable_t *)value) = !!(dev->option & KW2XRF_OPT_AUTOACK);
-            return sizeof(netopt_enable_t);
-
-        case NETOPT_PROMISCUOUSMODE:
-            *((netopt_enable_t *)value) = !!(dev->option & KW2XRF_OPT_PROMISCUOUS);
-            return sizeof(netopt_enable_t);
-
-        case NETOPT_RAWMODE:
-            *((netopt_enable_t *)value) = !!(dev->option & KW2XRF_OPT_RAWDUMP);
-            return sizeof(netopt_enable_t);
-
-        default:
-            return -ENOTSUP;
-    }
-}
-
-void kw2xrf_set_option(kw2xrf_t *dev, uint16_t option, bool state)
-{
-    uint8_t reg;
-
-    DEBUG("set option %i to %i\n", option, state);
-
-    /* set option field */
-    if (state) {
-        dev->option |= option;
-
-        /* trigger option specific actions */
-        switch (option) {
-            case KW2XRF_OPT_CSMA:
-                DEBUG("[kw2xrf] opt: enabling CSMA mode\n");
-                reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL1);
-                reg |= MKW2XDM_PHY_CTRL1_CCABFRTX;
-                kw2xrf_write_dreg(MKW2XDM_PHY_CTRL1, reg);
-                break;
-
-            case KW2XRF_OPT_PROMISCUOUS:
-                DEBUG("[kw2xrf] opt: enabling PROMISCUOUS mode\n");
-                /* disable auto ACKs in promiscuous mode */
-                reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL1);
-                reg &= ~(MKW2XDM_PHY_CTRL1_AUTOACK);
-                kw2xrf_write_dreg(MKW2XDM_PHY_CTRL1, reg);
-                /* enable promiscuous mode */
-                reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL4);
-                reg |= MKW2XDM_PHY_CTRL4_PROMISCUOUS;
-                kw2xrf_write_dreg(MKW2XDM_PHY_CTRL4, reg);
-                break;
-
-            case KW2XRF_OPT_AUTOACK:
-                DEBUG("[kw2xrf] opt: enabling auto ACKs\n");
-                reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL1);
-                reg |= MKW2XDM_PHY_CTRL1_AUTOACK;
-                kw2xrf_write_dreg(MKW2XDM_PHY_CTRL1, reg);
-                break;
-
-            default:
-                /* do nothing */
-                break;
-        }
-    }
-    else {
-        dev->option &= ~(option);
-
-        /* trigger option specific actions */
-        switch (option) {
-            case KW2XRF_OPT_CSMA:
-                reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL1);
-                reg &= ~(MKW2XDM_PHY_CTRL1_CCABFRTX);
-                kw2xrf_write_dreg(MKW2XDM_PHY_CTRL1, reg);
-                break;
-
-            case KW2XRF_OPT_PROMISCUOUS:
-                /* disable promiscuous mode */
-                reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL4);
-                reg &= ~(MKW2XDM_PHY_CTRL4_PROMISCUOUS);
-                kw2xrf_write_dreg(MKW2XDM_PHY_CTRL4, reg);
-
-                /* re-enable AUTOACK only if the option is set */
-                if (dev->option & KW2XRF_OPT_AUTOACK) {
-                    reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL1);
-                    reg |= MKW2XDM_PHY_CTRL1_AUTOACK;
-                    kw2xrf_write_dreg(MKW2XDM_PHY_CTRL1, reg);
-                }
-
-                break;
-
-            case KW2XRF_OPT_AUTOACK:
-                reg = kw2xrf_read_dreg(MKW2XDM_PHY_CTRL1);
-                reg &= ~(MKW2XDM_PHY_CTRL1_AUTOACK);
-                kw2xrf_write_dreg(MKW2XDM_PHY_CTRL1, reg);
-                break;
-
-            default:
-                /* do nothing */
-                break;
-        }
-    }
-}
-
-int kw2xrf_set(gnrc_netdev_t *netdev, netopt_t opt, void *value, size_t value_len)
-{
-    kw2xrf_t *dev = (kw2xrf_t *)netdev;
-
-    if (dev == NULL) {
-        return -ENODEV;
-    }
-
-    switch (opt) {
-        case NETOPT_CHANNEL:
-            return kw2xrf_set_channel(dev, (uint8_t *)value, value_len);
-
-        case NETOPT_ADDRESS:
-            if (value_len > sizeof(uint16_t)) {
-                return -EOVERFLOW;
-            }
-
-            return kw2xrf_set_addr(dev, *((uint16_t *)value));
-
-        case NETOPT_ADDRESS_LONG:
-            if (value_len > sizeof(uint64_t)) {
-                return -EOVERFLOW;
-            }
-
-            return kw2xrf_set_addr_long(dev, *((uint64_t *)value));
-
-        case NETOPT_SRC_LEN:
-            if (value_len > sizeof(uint16_t)) {
-                return -EOVERFLOW;
-            }
-
-            if (*((uint16_t *)value) == IEEE802154_SHORT_ADDRESS_LEN) {
-                kw2xrf_set_option(dev, KW2XRF_OPT_SRC_ADDR_LONG,
-                                  false);
-            }
-            else if (*((uint16_t *)value) == IEEE802154_LONG_ADDRESS_LEN) {
-                kw2xrf_set_option(dev, KW2XRF_OPT_SRC_ADDR_LONG,
-                                  true);
-            }
-            else {
-                return -ENOTSUP;
-            }
-
-            return sizeof(uint16_t);
-
-        case NETOPT_NID:
-            if (value_len > sizeof(uint16_t)) {
-                return -EOVERFLOW;
-            }
-
-            return kw2xrf_set_pan(dev, *((uint16_t *)value));
-
-        case NETOPT_TX_POWER:
-            if (value_len < sizeof(uint16_t)) {
-                return -EOVERFLOW;
-            }
-            /* correct value if out of valid range */
-            if (*(int16_t *)value > MKW2XDRF_OUTPUT_POWER_MAX) {
-                *(int16_t *)value = MKW2XDRF_OUTPUT_POWER_MAX;
-            }
-            else if (*(int16_t *)value < MKW2XDRF_OUTPUT_POWER_MIN) {
-                *(int16_t *)value = MKW2XDRF_OUTPUT_POWER_MIN;
-            }
-            kw2xrf_set_tx_power(dev, (int8_t *)value, value_len);
-            dev->tx_power = *((uint16_t *)value);
-            return sizeof(uint16_t);
-
-        case NETOPT_CCA_THRESHOLD:
-            if (value_len < sizeof(uint8_t)) {
-                return -EOVERFLOW;
-            } else {
-                kw2xrf_set_cca_threshold(dev, *((int8_t*)value));
-            }
-            return sizeof(uint8_t);
-
-        case NETOPT_PROTO:
-            return kw2xrf_set_proto(dev, (uint8_t *)value, value_len);
-
-        case NETOPT_AUTOACK:
-            /* Set up HW generated automatic ACK after Receive */
-            kw2xrf_set_option(dev, KW2XRF_OPT_AUTOACK,
-                              ((bool *)value)[0]);
-            return sizeof(netopt_enable_t);
-
-        case NETOPT_PROMISCUOUSMODE:
-            kw2xrf_set_option(dev, KW2XRF_OPT_PROMISCUOUS,
-                              ((bool *)value)[0]);
-            return sizeof(netopt_enable_t);
-
-        case NETOPT_RAWMODE:
-            kw2xrf_set_option(dev, KW2XRF_OPT_RAWDUMP,
-                              ((bool *)value)[0]);
-            return sizeof(netopt_enable_t);
-
-        case NETOPT_PRELOADING:
-            kw2xrf_set_option(dev, KW2XRF_OPT_PRELOADING,
-                              ((bool *)value)[0]);
-            return sizeof(netopt_enable_t);
-
-        case NETOPT_AUTOCCA:
-            kw2xrf_set_option(dev, KW2XRF_OPT_CSMA,
-                              ((bool *)value)[0]);
-            return sizeof(netopt_enable_t);
-
-        case NETOPT_STATE:
-            if (*((netopt_state_t *)value) == NETOPT_STATE_TX) {
-                DEBUG("kw2xrf: Sending now.\n");
-                kw2xrf_set_sequence(dev, XCVSEQ_TRANSMIT);
-                return sizeof(netopt_state_t);
-            }
-            else if (*((netopt_state_t *)value) == NETOPT_STATE_SLEEP) {
-                kw2xrf_set_sequence(dev, XCVSEQ_IDLE);
-                return sizeof(netopt_state_t);
-            }
-            else if (*((netopt_state_t *)value) == NETOPT_STATE_IDLE) {
-                kw2xrf_set_sequence(dev, XCVSEQ_RECEIVE);
-                return sizeof(netopt_state_t);
-            }
-
-            /* TODO: Implement Off state here, when LPM functions are implemented */
-
-        default:
-            return -ENOTSUP;
-    }
-}
-
-/* TODO: generalize and move to ieee802154 */
-/* TODO: include security header implications */
-static size_t _get_frame_hdr_len(uint8_t *mhr)
-{
-    uint8_t tmp;
-    size_t len = 3;
-
-    /* figure out address sizes */
-    tmp = (mhr[1] & IEEE802154_FCF_DST_ADDR_MASK);
-
-    if (tmp == IEEE802154_FCF_DST_ADDR_SHORT) {
-        len += 4;
-    }
-    else if (tmp == IEEE802154_FCF_DST_ADDR_LONG) {
-        len += 10;
-    }
-    else if (tmp != IEEE802154_FCF_DST_ADDR_VOID) {
-        return 0;
-    }
-
-    tmp = (mhr[1] & IEEE802154_FCF_SRC_ADDR_MASK);
-
-    if (tmp == IEEE802154_FCF_SRC_ADDR_VOID) {
-        return len;
-    }
-    else {
-        if (!(mhr[0] & IEEE802154_FCF_PAN_COMP)) {
-            len += 2;
-        }
-
-        if (tmp == IEEE802154_FCF_SRC_ADDR_SHORT) {
-            return (len + IEEE802154_SHORT_ADDRESS_LEN);
-        }
-        else if (tmp == IEEE802154_FCF_SRC_ADDR_LONG) {
-            return (len + IEEE802154_LONG_ADDRESS_LEN);
-        }
-    }
-
-    return 0;
-}
-
-/* TODO: generalize and move to (gnrc_)ieee802154 */
-static gnrc_pktsnip_t *_make_netif_hdr(uint8_t *mhr)
+static void kw2xrf_set_address(kw2xrf_t *dev)
 {
-    uint8_t tmp;
-    uint8_t *addr;
-    uint8_t src_len, dst_len;
-    gnrc_pktsnip_t *snip;
-    gnrc_netif_hdr_t *hdr;
-
-    /* figure out address sizes */
-    tmp = mhr[1] & IEEE802154_FCF_SRC_ADDR_MASK;
-
-    if (tmp == IEEE802154_FCF_SRC_ADDR_SHORT) {
-        src_len = IEEE802154_SHORT_ADDRESS_LEN;
-    }
-    else if (tmp == IEEE802154_FCF_SRC_ADDR_LONG) {
-        src_len = IEEE802154_LONG_ADDRESS_LEN;
-    }
-    else if (tmp == 0) {
-        src_len = 0;
-    }
-    else {
-        return NULL;
-    }
-
-    tmp = mhr[1] & IEEE802154_FCF_DST_ADDR_MASK;
-
-    if (tmp == IEEE802154_FCF_DST_ADDR_SHORT) {
-        dst_len = IEEE802154_SHORT_ADDRESS_LEN;
-    }
-    else if (tmp == IEEE802154_FCF_DST_ADDR_LONG) {
-        dst_len = IEEE802154_LONG_ADDRESS_LEN;
-    }
-    else if (tmp == 0) {
-        dst_len = 0;
-    }
-    else {
-        return NULL;
-    }
-
-    /* allocate space for header */
-    snip = gnrc_pktbuf_add(NULL, NULL, sizeof(gnrc_netif_hdr_t) + src_len + dst_len,
-                           GNRC_NETTYPE_NETIF);
-
-    if (snip == NULL) {
-        return NULL;
-    }
-
-    /* fill header */
-    hdr = (gnrc_netif_hdr_t *)snip->data;
-    gnrc_netif_hdr_init(hdr, src_len, dst_len);
-
-    if (dst_len > 0) {
-        tmp = 5 + dst_len;
-        addr = gnrc_netif_hdr_get_dst_addr(hdr);
-
-        for (int i = 0; i < dst_len; i++) {
-            addr[i] = mhr[5 + (dst_len - i) - 1];
-        }
-    }
-    else {
-        tmp = 3;
-    }
+    eui64_t addr_long;
+    addr_long.uint64.u64 = KW2XRF_DEFAULT_ADDR_LONG;
+    uint16_t addr_short = KW2XRF_DEFAULT_SHORT_ADDR;
 
-    if (!(mhr[0] & IEEE802154_FCF_PAN_COMP)) {
-        tmp += 2;
-    }
+#if CPUID_LEN
+    if (CPUID_LEN) {
+        uint8_t cpuid[KW2XRF_ID_LEN];
+        /* in case CPUID_LEN < 8, fill missing bytes with zeros */
+        memset(cpuid, 0, CPUID_LEN);
 
-    if (src_len > 0) {
-        addr = gnrc_netif_hdr_get_src_addr(hdr);
+        cpuid_get(cpuid);
 
-        for (int i = 0; i < src_len; i++) {
-            addr[i] = mhr[tmp + (src_len - i) - 1];
+        /* generate short hardware address if CPUID_LEN > 0 */
+        for (int i = 0; i < CPUID_LEN; i++) {
+            /* XOR each even byte of the CPUID with LSB of short address
+               and each odd byte with MSB */
+            addr_short ^= (uint16_t)(cpuid[i] << ((i & 0x01) * 8));
         }
-    }
-
-    return snip;
-}
-
-void _receive_data(kw2xrf_t *dev)
-{
-    size_t pkt_len, hdr_len;
-    gnrc_pktsnip_t *hdr, *payload = NULL;
-    gnrc_netif_hdr_t *netif;
-
-    /* get size of the received packet */
-    pkt_len = kw2xrf_read_dreg(MKW2XDM_RX_FRM_LEN);
-
-    /* read PSDU */
-    kw2xrf_read_fifo(dev->buf, pkt_len + 1);
-
-    /* abort here already if no event callback is registered */
-    if (!dev->event_cb) {
-        return;
-    }
 
-    /* If RAW-mode is selected directly forward pkt, MAC does the rest */
-    if (dev->option & KW2XRF_OPT_RAWDUMP) {
-        payload = gnrc_pktbuf_add(NULL, NULL, pkt_len, GNRC_NETTYPE_UNDEF);
-
-        if (payload == NULL) {
-            DEBUG("kw2xf: error: unable to allocate RAW data\n");
-            return;
+        for (int i = IEEE802154_LONG_ADDRESS_LEN; i < CPUID_LEN; i++) {
+            cpuid[i & 0x07] ^= cpuid[i];
         }
 
-        payload->data = dev->buf;
-        dev->event_cb(NETDEV_EVENT_RX_COMPLETE, payload);
-        return;
-    }
-
-    /* get FCF field and compute 802.15.4 header length */
-    hdr_len = _get_frame_hdr_len(dev->buf);
-
-    if (hdr_len == 0) {
-        DEBUG("kw2xrf error: unable parse incoming frame header\n");
-        return;
-    }
-
-    /* read the rest of the header and parse the netif header from it */
-    hdr = _make_netif_hdr(dev->buf);
-
-    if (hdr == NULL) {
-        DEBUG("kw2xrf error: unable to allocate netif header\n");
-        return;
-    }
-
-    /* fill missing fields in netif header */
-    netif = (gnrc_netif_hdr_t *)hdr->data;
-    netif->if_pid = thread_getpid();
-    netif->lqi = dev->buf[pkt_len];
-    /* lqi and rssi are directly related to each other in the kw2x-device.
-     * The rssi-unit is dBm and in this case always negative, nevertheless a
-     * positive value is reported.
-     */
-    netif->rssi = -((netif->lqi) - 286.6) / 2.69333;
-
-    payload = gnrc_pktbuf_add(hdr, (void *) & (dev->buf[hdr_len]),
-                              pkt_len - hdr_len - 2, dev->proto);
-
-    if (payload == NULL) {
-        DEBUG("kw2xrf: ERROR allocating payload in packet buffer on RX\n");
-        gnrc_pktbuf_release(hdr);
-        return;
+        /* make sure we mark the address as non-multicast and not globally unique */
+        cpuid[0] &= ~(0x01);
+        cpuid[0] |= 0x02;
+        /* copy and set long address */
+        memcpy(&addr_long, cpuid, IEEE802154_LONG_ADDRESS_LEN);
     }
+#endif
 
-    dev->event_cb(NETDEV_EVENT_RX_COMPLETE, payload);
+    kw2xrf_set_addr_long(dev, addr_long.uint64.u64);
+    kw2xrf_set_addr_short(dev, addr_short);
 }
 
-void kw2xrf_isr_event(gnrc_netdev_t *netdev, uint32_t event_type)
+void kw2xrf_setup(kw2xrf_t *dev, const kw2xrf_params_t *params)
 {
-    kw2xrf_t *dev = (kw2xrf_t *)netdev;
-    uint8_t irqst1 = kw2xrf_read_dreg(MKW2XDM_IRQSTS1);
-    uint8_t irqst2 = kw2xrf_read_dreg(MKW2XDM_IRQSTS2);
+    netdev2_t *netdev = (netdev2_t *)dev;
 
-    if ((irqst1 & MKW2XDM_IRQSTS1_RXIRQ) && (irqst1 & MKW2XDM_IRQSTS1_SEQIRQ)) {
-        /* RX */
-        DEBUG("kw2xrf: RX Int\n");
-        _receive_data(dev);
-        kw2xrf_set_sequence(dev, XCVSEQ_RECEIVE);
-        kw2xrf_write_dreg(MKW2XDM_IRQSTS1, MKW2XDM_IRQSTS1_RXIRQ | MKW2XDM_IRQSTS1_SEQIRQ);
-    }
-    else if ((irqst1 & MKW2XDM_IRQSTS1_TXIRQ) && (irqst1 & MKW2XDM_IRQSTS1_SEQIRQ)) {
-        /* TX_Complete */
-        /* Device is automatically in Radio-idle state when TX is done */
-        kw2xrf_set_sequence(dev, XCVSEQ_RECEIVE);
-        DEBUG("kw2xrf: TX Complete\n");
-        kw2xrf_write_dreg(MKW2XDM_IRQSTS1, MKW2XDM_IRQSTS1_TXIRQ | MKW2XDM_IRQSTS1_SEQIRQ);
-    }
-    else if ((irqst1 & MKW2XDM_IRQSTS1_CCAIRQ) && (irqst1 & MKW2XDM_IRQSTS1_SEQIRQ)) {
-        /* TX_Started (CCA_done) */
-        if (irqst2 & MKW2XDM_IRQSTS2_CCA) {
-            DEBUG("kw2xrf: CCA done -> Channel busy\n");
-        }
-        else {
-            DEBUG("kw2xrf: CCA done -> Channel idle\n");
-        }
+    netdev->driver = &kw2xrf_driver;
+    /* initialize device descriptor */
+    memcpy(&dev->params, params, sizeof(kw2xrf_params_t));
+    dev->idle_state = XCVSEQ_RECEIVE;
+    dev->state = 0;
+    dev->pending_tx = 0;
 
-        kw2xrf_write_dreg(MKW2XDM_IRQSTS1, MKW2XDM_IRQSTS1_CCAIRQ | MKW2XDM_IRQSTS1_SEQIRQ);
-        kw2xrf_set_sequence(dev, XCVSEQ_RECEIVE);
-    }
-    else {
-        /* Unknown event */
-        /* Clear all interrupts to prevent ISR-loop */
-        kw2xrf_write_dreg(MKW2XDM_IRQSTS1, 0x7f);
-        kw2xrf_write_dreg(MKW2XDM_IRQSTS2, 0x03);
-        kw2xrf_write_dreg(MKW2XDM_IRQSTS3, 0xff);
-        DEBUG("kw2xrf_isr_event: unknown Interrupt\n");
-        kw2xrf_set_sequence(dev, XCVSEQ_RECEIVE);
-        return;
-    }
+    kw2xrf_spi_init(dev);
+    kw2xrf_set_power_mode(dev, KW2XRF_IDLE);
+    DEBUG("[kw2xrf]: setup finished\n");
 }
 
-/* TODO: Move to gnrc_ieee802.15.4 as soon as ready */
-int _assemble_tx_buf(kw2xrf_t *dev, gnrc_pktsnip_t *pkt)
+int kw2xrf_init(kw2xrf_t *dev, gpio_cb_t cb)
 {
-    gnrc_netif_hdr_t *hdr;
-    int index = 4;
-
     if (dev == NULL) {
-        return 0;
-    }
-
-    /* get netif header check address length */
-    hdr = (gnrc_netif_hdr_t *)pkt->data;
-
-    /* we are building a data frame here */
-    dev->buf[1] = IEEE802154_FCF_TYPE_DATA;
-    dev->buf[2] = IEEE802154_FCF_VERS_V0;
-
-    /* if AUTOACK is enabled, then we also expect ACKs for this packet */
-    if (!(hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) &&
-        !(hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST) &&
-        (dev->option & KW2XRF_OPT_AUTOACK)) {
-        dev->buf[1] |= IEEE802154_FCF_ACK_REQ;
-    }
-
-    /* set destination pan_id */
-    dev->buf[index++] = (uint8_t)((dev->radio_pan) & 0xff);
-    dev->buf[index++] = (uint8_t)((dev->radio_pan) >> 8);
-
-    /* fill in destination address */
-    if (hdr->flags &
-        (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
-        dev->buf[2] |= IEEE802154_FCF_DST_ADDR_SHORT;
-        dev->buf[index++] = 0xff;
-        dev->buf[index++] = 0xff;
-    }
-    else if (hdr->dst_l2addr_len == IEEE802154_SHORT_ADDRESS_LEN) {
-        /* set to short addressing mode */
-        dev->buf[2] |= IEEE802154_FCF_DST_ADDR_SHORT;
-        /* set destination address, byte order is inverted */
-        uint8_t *dst_addr = gnrc_netif_hdr_get_dst_addr(hdr);
-        dev->buf[index++] = dst_addr[1];
-        dev->buf[index++] = dst_addr[0];
-    }
-    else if (hdr->dst_l2addr_len == IEEE802154_LONG_ADDRESS_LEN) {
-        /* default to use long address mode for src and dst */
-        dev->buf[2] |= IEEE802154_FCF_DST_ADDR_LONG;
-        /* set destination address located directly after gnrc_ifhrd_t in memory */
-        uint8_t *dst_addr = gnrc_netif_hdr_get_dst_addr(hdr);
-        for (int i = IEEE802154_LONG_ADDRESS_LEN - 1;  i >= 0; i--) {
-            dev->buf[index++] = dst_addr[i];
-        }
-    }
-    else {
-        return 0;
+        return -ENODEV;
     }
 
-    /* fill in source PAN ID (if applicable */
-    if (dev->option & KW2XRF_OPT_USE_SRC_PAN) {
-        dev->buf[index++] = (uint8_t)((dev->radio_pan) & 0xff);
-        dev->buf[index++] = (uint8_t)((dev->radio_pan) >> 8);
-    }
-    else {
-        dev->buf[1] |= IEEE802154_FCF_PAN_COMP;
-    }
+    kw2xrf_set_out_clk(dev);
+    kw2xrf_disable_interrupts(dev);
+    /* set up GPIO-pin used for IRQ */
+    gpio_init_int(dev->params.int_pin, GPIO_IN, GPIO_FALLING, cb, dev);
 
-    /* insert source address according to length */
-    if (hdr->src_l2addr_len == IEEE802154_SHORT_ADDRESS_LEN) {
-        dev->buf[2] |= IEEE802154_FCF_SRC_ADDR_SHORT;
-        dev->buf[index++] = (uint8_t)(dev->addr_short[0]);
-        dev->buf[index++] = (uint8_t)(dev->addr_short[1]);
-    }
-    else {
-        dev->buf[2] |= IEEE802154_FCF_SRC_ADDR_LONG;
-        memcpy(&(dev->buf[index]), dev->addr_long, IEEE802154_LONG_ADDRESS_LEN);
-        index += IEEE802154_LONG_ADDRESS_LEN;
-    }
-    /* set sequence number */
-    dev->buf[3] = dev->seq_nr++;
+    kw2xrf_abort_sequence(dev);
+    kw2xrf_update_overwrites(dev);
+    kw2xrf_timer_init(dev, KW2XRF_TIMEBASE_62500HZ);
+    DEBUG("[kw2xrf]: init finished\n");
 
-    /* return header size */
-    return index;
+    return 0;
 }
 
-int kw2xrf_send(gnrc_netdev_t *netdev, gnrc_pktsnip_t *pkt)
+void kw2xrf_reset_phy(kw2xrf_t *dev)
 {
-    int index = 0;
-    kw2xrf_t *dev = (kw2xrf_t *) netdev;
-
-    if ((dev->option & KW2XRF_OPT_PRELOADING) == NETOPT_DISABLE) {
-        kw2xrf_set_sequence(dev, XCVSEQ_TRANSMIT);
-    }
-
-    if (pkt == NULL) {
-        return -ENOMSG;
-    }
-
-    gnrc_pktsnip_t *payload = pkt->next;
+    /* reset options and sequence number */
+    dev->netdev.seq = 0;
+    dev->netdev.flags = 0;
 
-    if (netdev == NULL) {
-        gnrc_pktbuf_release(pkt);
-        return -ENODEV;
-    }
-
-    if (pkt->type == GNRC_NETTYPE_NETIF) {
-        /* Build header and fills this already into the tx-buf */
-        index = _assemble_tx_buf(dev, pkt);
-        if (index == 0) {
-            DEBUG("Unable to create 802.15.4 header\n");
-            gnrc_pktbuf_release(pkt);
-            return -ENOMSG;
-        }
-        DEBUG("Assembled header for GNRC_NETTYPE_UNDEF to tx-buf, index: %i\n", index);
-    }
-    else if (pkt->type == GNRC_NETTYPE_UNDEF) {
-        /* IEEE packet is already included in the header,
-         * no need to build the header manually */
-        DEBUG("Incoming packet of type GNRC_NETTYPE_802154: %i\n", index);
-        DEBUG("size of pktsnip: %i\n", pkt->size);
+    /* set default protocol */
+#ifdef MODULE_GNRC_SIXLOWPAN
+    dev->netdev.proto = GNRC_NETTYPE_SIXLOWPAN;
+#elif MODULE_GNRC
+    dev->netdev.proto = GNRC_NETTYPE_UNDEF;
+#endif
 
-        for (int i = 0; i < pkt->size; i++) {
-            uint8_t *tmp = pkt->data;
-            dev->buf[index + i + 1] = tmp[i];
-        }
+    dev->tx_power = KW2XRF_DEFAULT_TX_POWER;
+    kw2xrf_set_tx_power(dev, dev->tx_power);
 
-        /* count bytes */
-        index += pkt->size;
-    }
-    else {
-        DEBUG("Driver does not support this type of packet\n");
-        return -ENOTSUP;
-    }
+    kw2xrf_set_channel(dev, KW2XRF_DEFAULT_CHANNEL);
 
-    while (payload) {
-        /* check we don't exceed FIFO size */
-        if (index + 2 + payload->size > KW2XRF_MAX_PKT_LENGTH) {
-            gnrc_pktbuf_release(pkt);
-            DEBUG("Packet exceeded FIFO size.\n");
-            return -ENOBUFS;
-        }
+    kw2xrf_set_pan(dev, KW2XRF_DEFAULT_PANID);
+    kw2xrf_set_address(dev);
 
-        for (int i = 0; i < payload->size; i++) {
-            uint8_t *tmp = payload->data;
-            dev->buf[index + i] = tmp[i];
-        }
+    kw2xrf_set_cca_mode(dev, 1);
 
-        /* count bytes */
-        index += payload->size;
+    kw2xrf_set_rx_watermark(dev, 1);
 
-        /* next snip */
-        payload = payload->next;
-    }
+    kw2xrf_set_option(dev, KW2XRF_OPT_AUTOACK, true);
+    kw2xrf_set_option(dev, KW2XRF_OPT_ACK_REQ, true);
+    kw2xrf_set_option(dev, KW2XRF_OPT_AUTOCCA, true);
 
-    dev->buf[0] = index + 1; /* set packet size */
+    kw2xrf_set_power_mode(dev, KW2XRF_AUTODOZE);
+    kw2xrf_set_sequence(dev, dev->idle_state);
 
-    gnrc_pktbuf_release(pkt);
-    DEBUG("kw2xrf: packet with size %i loaded to tx_buf\n", dev->buf[0]);
-    kw2xrf_write_fifo(dev->buf, dev->buf[0]);
+    kw2xrf_set_option(dev, KW2XRF_OPT_TELL_RX_START, true);
+    kw2xrf_set_option(dev, KW2XRF_OPT_TELL_RX_END, true);
+    kw2xrf_set_option(dev, KW2XRF_OPT_TELL_TX_END, true);
+    kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL2, MKW2XDM_PHY_CTRL2_SEQMSK);
 
-    if ((dev->option & KW2XRF_OPT_PRELOADING) == NETOPT_DISABLE) {
-        DEBUG("kw2xrf: Sending now.\n");
-        kw2xrf_set_sequence(dev, XCVSEQ_TRANSMIT);
-    }
+    kw2xrf_enable_irq_b(dev);
 
-    return index;
+    DEBUG("[kw2xrf]: Initialized and set to channel %d and pan %d.\n",
+          KW2XRF_DEFAULT_CHANNEL, KW2XRF_DEFAULT_PANID);
 }
-
-/* implementation of the netdev interface */
-const gnrc_netdev_driver_t kw2xrf_driver = {
-    .send_data = kw2xrf_send,
-    .add_event_callback = kw2xrf_add_cb,
-    .rem_event_callback = kw2xrf_rem_cb,
-    .get = kw2xrf_get,
-    .set = kw2xrf_set,
-    .isr_event = kw2xrf_isr_event,
-};
diff --git a/drivers/kw2xrf/kw2xrf_getset.c b/drivers/kw2xrf/kw2xrf_getset.c
new file mode 100644
index 0000000000..5f64b80eb8
--- /dev/null
+++ b/drivers/kw2xrf/kw2xrf_getset.c
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2016 PHYTEC Messtechnik GmbH
+ *
+ * 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     drivers_kw2xrf
+ * @{
+ * @file
+ * @brief       get/set functionality of kw2xrf driver
+ *
+ * @author      Johann Fischer <j.fischer@phytec.de>
+ * @author      Jonas Remmert <j.remmert@phytec.de>
+ * @author      Oliver Hahm <oliver.hahm@inria.fr>
+ * @}
+ */
+
+#include "kw2xrf.h"
+#include "kw2xrf_spi.h"
+#include "kw2xrf_reg.h"
+#include "kw2xrf_getset.h"
+#include "kw2xrf_intern.h"
+
+#define ENABLE_DEBUG    (0)
+#include "debug.h"
+
+#define KW2XRF_LQI_HW_MAX           230      /**< LQI Saturation Level */
+
+/* Modem_PA_PWR Register (PA Power Control) has a valid range from 3-31 */
+#define MKW2XDRF_PA_RANGE_MAX      31       /**< Maximum value of PA Power Control Register */
+#define MKW2XDRF_PA_RANGE_MIN      3        /**< Minimum value of PA Power Control Register */
+
+/* PLL integer and fractional lookup tables
+ *
+ * Fc = 2405 + 5(k - 11) , k = 11,12,...,26
+ *
+ * Equation for PLL frequency, MKW2xD Reference Manual, p.255 :
+ * F = ((PLL_INT0 + 64) + (PLL_FRAC0/65536))32MHz
+ *
+ */
+static const uint8_t pll_int_lt[16] = {
+    11, 11, 11, 11,
+    11, 11, 12, 12,
+    12, 12, 12, 12,
+    13, 13, 13, 13
+};
+
+static const uint16_t pll_frac_lt[16] = {
+    10240, 20480, 30720, 40960,
+    51200, 61440, 6144, 16384,
+    26624, 36864, 47104, 57344,
+    2048, 12288, 22528, 32768
+};
+
+static const uint8_t pow_lt[44] = {
+    3, 4, 4, 5,
+    6, 6, 7, 7,
+    8, 9, 9, 10,
+    11, 11, 12, 13,
+    13, 14, 14, 15,
+    16, 16, 17, 18,
+    18, 19, 20, 20,
+    21, 21, 22, 23,
+    23, 24, 25, 25,
+    26, 27, 27, 28,
+    28, 29, 30, 31
+};
+
+void kw2xrf_set_tx_power(kw2xrf_t *dev, int16_t txpower)
+{
+    if (txpower > MKW2XDRF_OUTPUT_POWER_MAX) {
+        txpower = MKW2XDRF_OUTPUT_POWER_MAX;
+    }
+
+    if (txpower < MKW2XDRF_OUTPUT_POWER_MIN) {
+        txpower = MKW2XDRF_OUTPUT_POWER_MIN;
+    }
+
+    uint8_t level = pow_lt[txpower - MKW2XDRF_OUTPUT_POWER_MIN];
+    kw2xrf_write_dreg(dev, MKW2XDM_PA_PWR, MKW2XDM_PA_PWR(level));
+    dev->tx_power = txpower;
+}
+
+uint16_t kw2xrf_get_txpower(kw2xrf_t *dev)
+{
+    return dev->tx_power;
+}
+
+uint8_t kw2xrf_get_channel(kw2xrf_t *dev)
+{
+    uint8_t pll_int = kw2xrf_read_dreg(dev, MKW2XDM_PLL_INT0);
+    uint16_t pll_frac = kw2xrf_read_dreg(dev, MKW2XDM_PLL_FRAC0_LSB);
+    pll_frac |= ((uint16_t)kw2xrf_read_dreg(dev, MKW2XDM_PLL_FRAC0_MSB) << 8);
+
+    for (int i = 0; i < 16; i++) {
+        if ((pll_frac_lt[i] == pll_frac) && (pll_int_lt[i] == pll_int)) {
+            return i + 11;
+        }
+    }
+    return 0;
+}
+
+static int kw2xrf_get_sequence(kw2xrf_t *dev)
+{
+    int reg = 0;
+    reg = kw2xrf_read_dreg(dev, MKW2XDM_PHY_CTRL1);
+    reg &= MKW2XDM_PHY_CTRL1_XCVSEQ_MASK;
+    return reg;
+}
+
+int kw2xrf_set_channel(kw2xrf_t *dev, uint8_t channel)
+{
+    /* Save old sequence to restore this state later */
+    uint8_t old_seq = kw2xrf_get_sequence(dev);
+
+    if (channel < KW2XRF_MIN_CHANNEL || channel > KW2XRF_MAX_CHANNEL) {
+        DEBUG("[kw2xrf]: Invalid channel %i set\n", channel);
+        return -1;
+    }
+
+    if (old_seq) {
+        kw2xrf_abort_sequence(dev);
+    }
+
+    uint8_t tmp = channel - 11;
+    kw2xrf_write_dreg(dev, MKW2XDM_PLL_INT0, MKW2XDM_PLL_INT0_VAL(pll_int_lt[tmp]));
+    kw2xrf_write_dreg(dev, MKW2XDM_PLL_FRAC0_LSB, (uint8_t)pll_frac_lt[tmp]);
+    kw2xrf_write_dreg(dev, MKW2XDM_PLL_FRAC0_MSB, (uint8_t)(pll_frac_lt[tmp] >> 8));
+
+    dev->netdev.chan = channel;
+
+    if (old_seq) {
+        kw2xrf_set_sequence(dev, old_seq);
+    }
+
+    DEBUG("[kw2xrf]: set channel to %u\n", channel);
+    return 0;
+}
+
+void kw2xrf_abort_sequence(kw2xrf_t *dev)
+{
+    uint8_t regs[MKW2XDM_PHY_CTRL4 + 1];
+
+    kw2xrf_mask_irq_b(dev);
+    kw2xrf_read_dregs(dev, MKW2XDM_IRQSTS1, regs, (MKW2XDM_PHY_CTRL4 + 1));
+
+    if ((regs[MKW2XDM_PHY_CTRL1] & MKW2XDM_PHY_CTRL1_XCVSEQ_MASK) != XCVSEQ_IDLE) {
+        /* abort any ongoing sequence */
+        regs[MKW2XDM_PHY_CTRL1] &= ~(MKW2XDM_PHY_CTRL1_XCVSEQ_MASK);
+        kw2xrf_write_dreg(dev, MKW2XDM_PHY_CTRL1, regs[MKW2XDM_PHY_CTRL1]);
+    }
+
+    uint8_t state;
+    do {
+        state = kw2xrf_read_dreg(dev, MKW2XDM_SEQ_STATE);
+        DEBUG("[kw2xrf]: abort SEQ_STATE: %x\n", state);
+    } while ((state & 0x1F) != 0);
+
+    /* clear all IRQ bits */
+    regs[MKW2XDM_IRQSTS1] = 0x7f;
+    regs[MKW2XDM_IRQSTS2] = 0x03;
+    regs[MKW2XDM_IRQSTS3] |= 0x0f;
+    kw2xrf_write_dregs(dev, MKW2XDM_IRQSTS1, regs, 3);
+
+    kw2xrf_enable_irq_b(dev);
+}
+
+/*
+ * Simplified version for irq handling where the state of
+ * the sequenz manager is known.
+ */
+void kw2xrf_set_idle_sequence(kw2xrf_t *dev)
+{
+    kw2xrf_mask_irq_b(dev);
+    uint8_t reg = kw2xrf_read_dreg(dev, MKW2XDM_PHY_CTRL1);
+
+    /* reset sequenz manager */
+    reg &= ~(MKW2XDM_PHY_CTRL1_XCVSEQ_MASK);
+    kw2xrf_write_dreg(dev, MKW2XDM_PHY_CTRL1, reg);
+
+    if (dev->pending_tx) {
+        DEBUG("[kw2xrf]: pending tx, cannot set idle sequenz\n");
+        return;
+    }
+
+    /* start new sequenz */
+    reg |= MKW2XDM_PHY_CTRL1_XCVSEQ(dev->idle_state);
+    kw2xrf_write_dreg(dev, MKW2XDM_PHY_CTRL1, reg);
+
+    switch (dev->idle_state) {
+        case XCVSEQ_IDLE:
+        /* for inexplicable reasons, the receive mode is also idle mode */
+        case XCVSEQ_RECEIVE:
+            dev->state = NETOPT_STATE_IDLE;
+            break;
+
+        case XCVSEQ_CONTINUOUS_CCA:
+        case XCVSEQ_CCA:
+            dev->state = NETOPT_STATE_RX;
+            break;
+
+        case XCVSEQ_TRANSMIT:
+        case XCVSEQ_TX_RX:
+            dev->state = NETOPT_STATE_TX;
+            break;
+
+        default:
+            dev->state = NETOPT_STATE_IDLE;
+    }
+
+    kw2xrf_enable_irq_b(dev);
+}
+
+void kw2xrf_set_sequence(kw2xrf_t *dev, kw2xrf_physeq_t seq)
+{
+    uint8_t reg = 0;
+
+    kw2xrf_abort_sequence(dev);
+
+    switch (seq) {
+        case XCVSEQ_IDLE:
+        /* for inexplicable reasons, the receive mode is also idle mode */
+        case XCVSEQ_RECEIVE:
+            dev->state = NETOPT_STATE_IDLE;
+            break;
+
+        case XCVSEQ_CONTINUOUS_CCA:
+        case XCVSEQ_CCA:
+            dev->state = NETOPT_STATE_RX;
+            break;
+
+        case XCVSEQ_TRANSMIT:
+        case XCVSEQ_TX_RX:
+            dev->state = NETOPT_STATE_TX;
+            break;
+
+        default:
+            DEBUG("[kw2xrf]: undefined state assigned to phy\n");
+            dev->state = NETOPT_STATE_IDLE;
+    }
+
+    DEBUG("[kw2xrf]: set sequence to %i\n", seq);
+    reg = kw2xrf_read_dreg(dev, MKW2XDM_PHY_CTRL1);
+    reg &= ~(MKW2XDM_PHY_CTRL1_XCVSEQ_MASK);
+    reg |= MKW2XDM_PHY_CTRL1_XCVSEQ(seq);
+    kw2xrf_write_dreg(dev, MKW2XDM_PHY_CTRL1, reg);
+}
+
+void kw2xrf_set_pan(kw2xrf_t *dev, uint16_t pan)
+{
+    dev->netdev.pan = pan;
+
+    uint8_t val_ar[2];
+    val_ar[1] = (pan >> 8);
+    val_ar[0] = (uint8_t)pan;
+    kw2xrf_write_iregs(dev, MKW2XDMI_MACPANID0_LSB, val_ar, 2);
+    dev->netdev.pan = pan;
+}
+
+void kw2xrf_set_addr_short(kw2xrf_t *dev, uint16_t addr)
+{
+    uint8_t val_ar[2];
+    val_ar[0] = (addr >> 8);
+    val_ar[1] = (uint8_t)addr;
+    dev->netdev.short_addr[0] = val_ar[1];
+    dev->netdev.short_addr[1] = val_ar[0];
+#ifdef MODULE_SIXLOWPAN
+    /* https://tools.ietf.org/html/rfc4944#section-12 requires the first bit to
+     * 0 for unicast addresses */
+    dev->netdev.short_addr[1] &= 0x7F;
+#endif
+    kw2xrf_write_iregs(dev, MKW2XDMI_MACSHORTADDRS0_LSB, val_ar,
+                       IEEE802154_SHORT_ADDRESS_LEN);
+}
+
+void kw2xrf_set_addr_long(kw2xrf_t *dev, uint64_t addr)
+{
+    uint64_t tmp;
+    uint8_t *ap = (uint8_t *)(&tmp);
+
+    for (int i = 0; i < IEEE802154_LONG_ADDRESS_LEN; i++) {
+        dev->netdev.long_addr[i] = (uint8_t)(addr >> (i * 8));
+        ap[i] = (addr >> ((IEEE802154_LONG_ADDRESS_LEN - 1 - i) * 8));
+    }
+
+    kw2xrf_write_iregs(dev, MKW2XDMI_MACLONGADDRS0_0, ap,
+                       IEEE802154_LONG_ADDRESS_LEN);
+}
+
+uint16_t kw2xrf_get_addr_short(kw2xrf_t *dev)
+{
+    return (dev->netdev.short_addr[0] << 8) | dev->netdev.short_addr[1];
+}
+
+uint64_t kw2xrf_get_addr_long(kw2xrf_t *dev)
+{
+    uint64_t addr;
+    uint8_t *ap = (uint8_t *)(&addr);
+
+    kw2xrf_read_iregs(dev, MKW2XDMI_MACLONGADDRS0_0, ap,
+                      IEEE802154_LONG_ADDRESS_LEN);
+
+    return addr;
+}
+
+int8_t kw2xrf_get_cca_threshold(kw2xrf_t *dev)
+{
+    uint8_t tmp;
+    kw2xrf_read_iregs(dev, MKW2XDMI_CCA1_THRESH, &tmp, 1);
+    /* KW2x register value represents absolute value in dBm
+     * default value: -75 dBm
+     */
+    return (-tmp);
+}
+
+void kw2xrf_set_cca_threshold(kw2xrf_t *dev, int8_t value)
+{
+    /* normalize to absolute value */
+    if (value < 0) {
+        value = -value;
+    }
+    kw2xrf_write_iregs(dev, MKW2XDMI_CCA1_THRESH, (uint8_t*)&value, 1);
+}
+
+void kw2xrf_set_cca_mode(kw2xrf_t *dev, uint8_t mode)
+{
+    uint8_t tmp;
+    tmp = kw2xrf_read_dreg(dev, MKW2XDM_PHY_CTRL4);
+    tmp &= ~MKW2XDM_PHY_CTRL4_CCATYPE_MASK;
+    tmp |= MKW2XDM_PHY_CTRL4_CCATYPE(mode);
+    kw2xrf_write_dreg(dev, MKW2XDM_PHY_CTRL4, tmp);
+}
+
+uint8_t kw2xrf_get_cca_mode(kw2xrf_t *dev)
+{
+    uint8_t tmp;
+    tmp = kw2xrf_read_dreg(dev, MKW2XDM_PHY_CTRL4);
+    return (tmp & MKW2XDM_PHY_CTRL4_CCATYPE_MASK) >> MKW2XDM_PHY_CTRL4_CCATYPE_SHIFT;
+}
+
+uint32_t kw2xrf_get_rssi(uint32_t value)
+{
+    /* Get rssi (Received Signal Strength Indicator, unit is dBm)
+     * from lqi (Link Quality Indicator) value.
+     * There are two different equations for RSSI:
+     * RF = (LQI – 286.6) / 2.69333 (MKW2xD Reference Manual)
+     * RF = (LQI – 295.4) / 2.84 (MCR20A Reference Manual)
+     * The last appears more to match the graphic (Figure 3-10).
+     * Since RSSI value is always positive and we want to
+     * avoid the floating point computation:
+     * -RF * 65536 = (LQI / 2.84 - 295.4 / 2.84) * 65536
+     * RF * 65536 = (295.4 * 65536 / 2.84) - (LQI * 65536 / 2.84)
+     */
+    uint32_t a = (uint32_t)(295.4 * 65536 / 2.84);
+    uint32_t b = (uint32_t)(65536 / 2.84);
+    return (a - (b * value)) >> 16;
+}
+
+void kw2xrf_set_option(kw2xrf_t *dev, uint16_t option, bool state)
+{
+    DEBUG("[kw2xrf]: set option %i to %i\n", option, state);
+
+    /* set option field */
+    if (state) {
+        dev->netdev.flags |= option;
+
+        /* trigger option specific actions */
+        switch (option) {
+            case KW2XRF_OPT_AUTOCCA:
+                DEBUG("[kw2xrf] opt: enabling CCA before TX mode\n");
+                kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL1,
+                    MKW2XDM_PHY_CTRL1_CCABFRTX);
+                break;
+
+            case KW2XRF_OPT_PROMISCUOUS:
+                DEBUG("[kw2xrf] opt: enabling PROMISCUOUS mode\n");
+                /* disable auto ACKs in promiscuous mode */
+                kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL1,
+                    MKW2XDM_PHY_CTRL1_AUTOACK | MKW2XDM_PHY_CTRL1_RXACKRQD);
+                /* enable promiscuous mode */
+                kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL4,
+                    MKW2XDM_PHY_CTRL4_PROMISCUOUS);
+                break;
+
+            case KW2XRF_OPT_AUTOACK:
+                kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL1,
+                    MKW2XDM_PHY_CTRL1_AUTOACK);
+                break;
+
+            case KW2XRF_OPT_ACK_REQ:
+                kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL1,
+                    MKW2XDM_PHY_CTRL1_RXACKRQD);
+                break;
+
+            case KW2XRF_OPT_TELL_RX_START:
+                kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL2,
+                    MKW2XDM_PHY_CTRL2_RX_WMRK_MSK);
+                break;
+
+            case KW2XRF_OPT_TELL_RX_END:
+                kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL2,
+                    MKW2XDM_PHY_CTRL2_RXMSK);
+                break;
+
+            case KW2XRF_OPT_TELL_TX_END:
+                kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL2,
+                    MKW2XDM_PHY_CTRL2_TXMSK);
+                break;
+
+            case KW2XRF_OPT_TELL_TX_START:
+            default:
+                /* do nothing */
+                break;
+        }
+    }
+    else {
+        dev->netdev.flags &= ~(option);
+        /* trigger option specific actions */
+        switch (option) {
+            case KW2XRF_OPT_AUTOCCA:
+                kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL1,
+                    MKW2XDM_PHY_CTRL1_CCABFRTX);
+                break;
+
+            case KW2XRF_OPT_PROMISCUOUS:
+                /* disable promiscuous mode */
+                kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL4,
+                    MKW2XDM_PHY_CTRL4_PROMISCUOUS);
+                /* re-enable AUTOACK only if the option is set */
+                if (dev->netdev.flags & KW2XRF_OPT_AUTOACK) {
+                    kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL1,
+                        MKW2XDM_PHY_CTRL1_AUTOACK);
+                }
+                if (dev->netdev.flags & KW2XRF_OPT_ACK_REQ) {
+                    kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL1,
+                        MKW2XDM_PHY_CTRL1_RXACKRQD);
+                }
+                break;
+
+            case KW2XRF_OPT_AUTOACK:
+                kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL1,
+                    MKW2XDM_PHY_CTRL1_AUTOACK);
+                break;
+
+            case KW2XRF_OPT_ACK_REQ:
+                kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL1,
+                    MKW2XDM_PHY_CTRL1_RXACKRQD);
+                break;
+
+            case KW2XRF_OPT_TELL_RX_START:
+                kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL2,
+                    MKW2XDM_PHY_CTRL2_RX_WMRK_MSK);
+                break;
+
+            case KW2XRF_OPT_TELL_RX_END:
+                kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL2,
+                    MKW2XDM_PHY_CTRL2_RXMSK);
+                break;
+
+            case KW2XRF_OPT_TELL_TX_END:
+                kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL2,
+                    MKW2XDM_PHY_CTRL2_TXMSK);
+                break;
+
+
+            case KW2XRF_OPT_TELL_TX_START:
+            default:
+                /* do nothing */
+                break;
+        }
+    }
+}
+
+netopt_state_t kw2xrf_get_status(kw2xrf_t *dev)
+{
+    uint8_t reg = kw2xrf_read_dreg(dev, MKW2XDM_PHY_CTRL1);
+
+    switch (reg & MKW2XDM_PHY_CTRL1_XCVSEQ_MASK) {
+        case XCVSEQ_RECEIVE:
+            return NETOPT_STATE_RX;
+
+        case XCVSEQ_TRANSMIT:
+            return NETOPT_STATE_TX;
+
+        case XCVSEQ_CCA:
+            return NETOPT_STATE_RX;
+
+        case XCVSEQ_TX_RX:
+            return NETOPT_STATE_TX;
+
+        case XCVSEQ_CONTINUOUS_CCA:
+            return NETOPT_STATE_RX;
+
+        case XCVSEQ_IDLE:
+            return NETOPT_STATE_IDLE;
+        default:
+            break;
+    }
+    return NETOPT_STATE_IDLE;
+}
+
+int kw2xrf_cca(kw2xrf_t *dev)
+{
+    /* TODO: add Standalone CCA here */
+    kw2xrf_seq_timeout_on(dev, 0x3ffff);
+    kw2xrf_set_sequence(dev, XCVSEQ_CONTINUOUS_CCA);
+    return 0;
+}
+
+void kw2xrf_set_rx_watermark(kw2xrf_t *dev, uint8_t value)
+{
+    kw2xrf_write_iregs(dev, MKW2XDMI_RX_WTR_MARK, &value, 1);
+}
diff --git a/drivers/kw2xrf/kw2xrf_intern.c b/drivers/kw2xrf/kw2xrf_intern.c
new file mode 100644
index 0000000000..5ef49177d3
--- /dev/null
+++ b/drivers/kw2xrf/kw2xrf_intern.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2016 PHYTEC Messtechnik GmbH
+ *
+ * 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     drivers_kw2xrf
+ * @{
+ * @file
+ * @brief       Internal function of kw2xrf driver
+ *
+ * @author      Johann Fischer <j.fischer@phytec.de>
+ * @}
+ */
+
+#include "panic.h"
+#include "kw2xrf.h"
+#include "kw2xrf_spi.h"
+#include "kw2xrf_reg.h"
+#include "kw2xrf_getset.h"
+#include "kw2xrf_intern.h"
+#include "overwrites.h"
+
+#define ENABLE_DEBUG    (0)
+#include "debug.h"
+
+void kw2xrf_disable_interrupts(kw2xrf_t *dev)
+{
+    /* Clear and disable all interrupts */
+    kw2xrf_write_dreg(dev, MKW2XDM_PHY_CTRL2, 0xff);
+    int reg = kw2xrf_read_dreg(dev, MKW2XDM_PHY_CTRL3);
+    reg |= MKW2XDM_PHY_CTRL3_WAKE_MSK | MKW2XDM_PHY_CTRL3_PB_ERR_MSK;
+    kw2xrf_write_dreg(dev, MKW2XDM_PHY_CTRL3, reg);
+
+    kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS1, 0x7f);
+    kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS2, 0x03);
+    kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS3, 0xff);
+}
+
+/* update overwrites register */
+void kw2xrf_update_overwrites(kw2xrf_t *dev)
+{
+    kw2xrf_write_dreg(dev, MKW2XDM_OVERWRITE_VER, overwrites_direct[0].data);
+    for (uint8_t i = 0; i < sizeof(overwrites_indirect)/sizeof(overwrites_t); i++) {
+        kw2xrf_write_iregs(dev, overwrites_indirect[i].address,
+                           (uint8_t *)&(overwrites_indirect[i].data), 1);
+    }
+}
+
+void kw2xrf_set_out_clk(kw2xrf_t *dev)
+{
+    /* TODO: add clock select */
+    /* check modem's crystal oscillator, CLK_OUT shall be 4MHz */
+    uint8_t tmp = kw2xrf_read_dreg(dev, MKW2XDM_CLK_OUT_CTRL);
+    if (tmp != 0x8Bu) {
+        core_panic(PANIC_GENERAL_ERROR, "Could not start MKW2XD radio transceiver");
+    }
+}
+
+void kw2xrf_set_power_mode(kw2xrf_t *dev, kw2xrf_powermode_t pm)
+{
+    uint8_t reg = 0;
+    switch (pm) {
+        case KW2XRF_HIBERNATE:
+            /* VREG off, XTAL off, Timer off, Current cons. < 1uA */
+            reg = 0;
+            dev->state = NETOPT_STATE_SLEEP;
+            break;
+
+        case KW2XRF_DOZE:
+            /* VREG off, XTAL on, Timer on/off, Current cons. 600uA */
+            reg = MKW2XDM_PWR_MODES_XTALEN;
+            dev->state = NETOPT_STATE_SLEEP;
+            break;
+
+        case KW2XRF_IDLE:
+            /* VREG on, XTAL on, Timer on, Current cons. 700uA */
+            reg = MKW2XDM_PWR_MODES_XTALEN | MKW2XDM_PWR_MODES_PMC_MODE;
+            dev->state = NETOPT_STATE_IDLE;
+            break;
+
+        case KW2XRF_AUTODOZE:
+            reg = MKW2XDM_PWR_MODES_XTALEN | MKW2XDM_PWR_MODES_AUTODOZE;
+            dev->state = NETOPT_STATE_IDLE;
+            break;
+    }
+
+    kw2xrf_write_dreg(dev, MKW2XDM_PWR_MODES, reg);
+}
+
+int kw2xrf_can_switch_to_idle(kw2xrf_t *dev)
+{
+    uint8_t state = kw2xrf_read_dreg(dev, MKW2XDM_SEQ_STATE);
+    uint8_t seq = kw2xrf_read_dreg(dev, MKW2XDM_PHY_CTRL1) & MKW2XDM_PHY_CTRL1_XCVSEQ_MASK;
+    DEBUG("[kw2xrf]: state 0x%0x, seq 0x%0x\n", state, seq);
+
+    if ((seq != XCVSEQ_TRANSMIT) && (seq != XCVSEQ_TX_RX)) {
+        return 1;
+    }
+
+    if (state != 0) {
+        return 0;
+    }
+
+    return 0;
+}
+
+/** Load the timer value (Setting Current Time) */
+static void kw2xrf_timer_load(kw2xrf_t *dev, uint32_t value)
+{
+    kw2xrf_write_dregs(dev, MKW2XDM_T1CMP_LSB, (uint8_t *)&value, sizeof(value));
+    kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL4, MKW2XDM_PHY_CTRL4_TMRLOAD);
+}
+
+static uint32_t kw2xrf_timer_get(kw2xrf_t *dev)
+{
+    uint32_t tmp;
+    kw2xrf_read_dregs(dev, MKW2XDM_EVENT_TIMER_LSB, (uint8_t*)&tmp, sizeof(tmp));
+    return tmp;
+}
+
+/** Set an absolute timeout value for the given compare register of the Event Timer */
+static void kw2xrf_timer_set_absolute(kw2xrf_t *dev, uint8_t cmp_reg, uint32_t value)
+{
+    kw2xrf_write_dregs(dev, cmp_reg, (uint8_t *)&value, 3);
+}
+
+/** Set an timeout value for the given compare register of the Event Timer */
+static void kw2xrf_timer_set(kw2xrf_t *dev, uint8_t cmp_reg, uint32_t timeout)
+{
+    uint32_t now = kw2xrf_timer_get(dev);
+
+    DEBUG("[kw2xrf] timer now: %" PRIx32 ", set %" PRIx32 "\n", now, now + timeout);
+    kw2xrf_timer_set_absolute(dev, cmp_reg, now + timeout);
+}
+
+void kw2xrf_timer_init(kw2xrf_t *dev, kw2xrf_timer_timebase_t tb)
+{
+    uint8_t tmp = MKW2XDMI_TMR_PRESCALE_SET(tb);
+
+    kw2xrf_write_iregs(dev, MKW2XDMI_TMR_PRESCALE, &tmp, 1);
+    kw2xrf_timer_load(dev, 0);
+}
+
+void kw2xrf_timer2_seq_start_on(kw2xrf_t *dev)
+{
+    kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL1, MKW2XDM_PHY_CTRL1_TMRTRIGEN);
+}
+
+void kw2xrf_timer2_seq_start_off(kw2xrf_t *dev)
+{
+    kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL1, MKW2XDM_PHY_CTRL1_TMRTRIGEN);
+}
+
+void kw2xrf_timer3_seq_abort_on(kw2xrf_t *dev)
+{
+    kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL4, MKW2XDM_PHY_CTRL4_TC3TMOUT);
+}
+
+void kw2xrf_timer3_seq_abort_off(kw2xrf_t *dev)
+{
+    kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL4, MKW2XDM_PHY_CTRL4_TC3TMOUT);
+}
+
+void kw2xrf_trigger_tx_ops_enable(kw2xrf_t *dev, uint32_t timeout)
+{
+    kw2xrf_timer_set(dev, MKW2XDM_T2CMP_LSB, timeout);
+    kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL3, MKW2XDM_PHY_CTRL3_TMR2CMP_EN);
+}
+
+void kw2xrf_trigger_tx_ops_disable(kw2xrf_t *dev)
+{
+    kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL3, MKW2XDM_PHY_CTRL3_TMR2CMP_EN);
+    kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS3, MKW2XDM_IRQSTS3_TMR2IRQ);
+    if (ENABLE_DEBUG) {
+        uint32_t now = kw2xrf_timer_get(dev);
+        printf("[kw2xrf] now: %" PRIx32 "\n", now);
+    }
+}
+
+void kw2xrf_abort_rx_ops_enable(kw2xrf_t *dev, uint32_t timeout)
+{
+    kw2xrf_timer_set(dev, MKW2XDM_T3CMP_LSB, timeout);
+    kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL3, MKW2XDM_PHY_CTRL3_TMR3CMP_EN);
+}
+
+void kw2xrf_abort_rx_ops_disable(kw2xrf_t *dev)
+{
+    kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL3, MKW2XDM_PHY_CTRL3_TMR3CMP_EN);
+    kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS3, MKW2XDM_IRQSTS3_TMR3IRQ);
+    if (ENABLE_DEBUG) {
+        uint32_t now = kw2xrf_timer_get(dev);
+        printf("[kw2xrf] now: %" PRIx32 "\n", now);
+    }
+}
+
+void kw2xrf_seq_timeout_on(kw2xrf_t *dev, uint32_t timeout)
+{
+    kw2xrf_mask_irq_b(dev);
+    kw2xrf_timer_set(dev, MKW2XDM_T4CMP_LSB, timeout);
+
+    /* enable and clear irq for timer 3 */
+    uint8_t irqsts3 = kw2xrf_read_dreg(dev, MKW2XDM_IRQSTS3) & 0xf0;
+    irqsts3 &= ~MKW2XDM_IRQSTS3_TMR4MSK;
+    irqsts3 |= MKW2XDM_IRQSTS3_TMR4IRQ;
+    kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS3, irqsts3);
+
+    kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL3, MKW2XDM_PHY_CTRL3_TMR4CMP_EN);
+    kw2xrf_enable_irq_b(dev);
+}
+
+void kw2xrf_seq_timeout_off(kw2xrf_t *dev)
+{
+    kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL3, MKW2XDM_PHY_CTRL3_TMR4CMP_EN);
+    kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS3, MKW2XDM_IRQSTS3_TMR4IRQ);
+    if (ENABLE_DEBUG) {
+        uint32_t now = kw2xrf_timer_get(dev);
+        printf("[kw2xrf] now: %" PRIx32 "\n", now);
+    }
+}
+
+uint32_t kw2xrf_get_timestamp(kw2xrf_t *dev)
+{
+    uint32_t tmp;
+    kw2xrf_read_dregs(dev, MKW2XDM_TIMESTAMP_LSB, (uint8_t*)&tmp, sizeof(tmp));
+    return tmp;
+}
diff --git a/drivers/kw2xrf/kw2xrf_netdev.c b/drivers/kw2xrf/kw2xrf_netdev.c
new file mode 100644
index 0000000000..ccdd2c7ba7
--- /dev/null
+++ b/drivers/kw2xrf/kw2xrf_netdev.c
@@ -0,0 +1,765 @@
+/*
+ * Copyright (C) 2016 Phytec Messtechnik GmbH
+ *
+ * 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     drivers_kw2xrf
+ * @{
+ *
+ * @file
+ * @brief       Netdev interface for kw2xrf drivers
+ *
+ * @author      Johann Fischer <j.fischer@phytec.de>
+ */
+
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "net/eui64.h"
+#include "net/ieee802154.h"
+#include "net/netdev2.h"
+#include "net/netdev2/ieee802154.h"
+
+#include "kw2xrf.h"
+#include "kw2xrf_spi.h"
+#include "kw2xrf_reg.h"
+#include "kw2xrf_netdev.h"
+#include "kw2xrf_getset.h"
+#include "kw2xrf_tm.h"
+#include "kw2xrf_intern.h"
+
+#define ENABLE_DEBUG    (0)
+#include "debug.h"
+
+#define _MAX_MHR_OVERHEAD           (25)
+
+#define _MACACKWAITDURATION         (864 / 16) /* 864us * 62500Hz */
+
+static uint8_t _send_last_fcf;
+
+static void _irq_handler(void *arg)
+{
+    netdev2_t *dev = (netdev2_t *) arg;
+
+    if (dev->event_callback) {
+        dev->event_callback(dev, NETDEV2_EVENT_ISR);
+    }
+}
+
+static int _init(netdev2_t *netdev)
+{
+    kw2xrf_t *dev = (kw2xrf_t *)netdev;
+
+    /* initialise SPI and GPIOs */
+    if (kw2xrf_init(dev, &_irq_handler)) {
+        DEBUG("[kw2xrf]: error: unable to initialize device\n");
+        return -1;
+    }
+
+#ifdef MODULE_NETSTATS_L2
+    memset(&netdev->stats, 0, sizeof(netstats_t));
+#endif
+
+    /* reset device to default values and put it into RX state */
+    kw2xrf_reset_phy(dev);
+
+    return 0;
+}
+
+static size_t kw2xrf_tx_load(uint8_t *pkt_buf, uint8_t *buf, size_t len, size_t offset)
+{
+    for (int i = 0; i < len; i++) {
+        pkt_buf[i + offset] = buf[i];
+    }
+    return offset + len;
+}
+
+static void kw2xrf_tx_exec(kw2xrf_t *dev)
+{
+    if ((dev->netdev.flags & KW2XRF_OPT_AUTOACK) &&
+        (_send_last_fcf & IEEE802154_FCF_ACK_REQ)) {
+        kw2xrf_set_sequence(dev, XCVSEQ_TX_RX);
+    }
+    else {
+        kw2xrf_set_sequence(dev, XCVSEQ_TRANSMIT);
+    }
+}
+
+static int _send(netdev2_t *netdev, const struct iovec *vector, unsigned count)
+{
+    kw2xrf_t *dev = (kw2xrf_t *)netdev;
+    const struct iovec *ptr = vector;
+    uint8_t *pkt_buf = &(dev->buf[1]);
+    size_t len = 0;
+
+    /* load packet data into buffer */
+    for (unsigned i = 0; i < count; i++, ptr++) {
+        /* current packet data + FCS too long */
+        if ((len + ptr->iov_len + IEEE802154_FCS_LEN) > KW2XRF_MAX_PKT_LENGTH) {
+            DEBUG("[kw2xrf]: error: packet too large (%u byte) to be send\n",
+                  (unsigned)len + IEEE802154_FCS_LEN);
+            return -EOVERFLOW;
+        }
+        len = kw2xrf_tx_load(pkt_buf, ptr->iov_base, ptr->iov_len, len);
+    }
+
+    /* make sure ongoing t or tr sequenz are finished */
+    if (kw2xrf_can_switch_to_idle(dev)) {
+        kw2xrf_set_sequence(dev, XCVSEQ_IDLE);
+        dev->pending_tx++;
+    }
+    else {
+        /* do not wait, this can lead to a dead lock */
+        return 0;
+    }
+
+    /*
+     * Nbytes = FRAME_LEN - 2 -> FRAME_LEN = Nbytes + 2
+     * MKW2xD Reference Manual, P.192
+     */
+    dev->buf[0] = len + IEEE802154_FCS_LEN;
+
+    /* Help for decision to use T or TR sequenz */
+    _send_last_fcf = dev->buf[1];
+
+    kw2xrf_write_fifo(dev, dev->buf, dev->buf[0]);
+#ifdef MODULE_NETSTATS_L2
+    netdev->stats.tx_bytes += len;
+#endif
+
+    /* send data out directly if pre-loading id disabled */
+    if (!(dev->netdev.flags & KW2XRF_OPT_PRELOADING)) {
+        kw2xrf_tx_exec(dev);
+    }
+
+    return (int)len;
+}
+
+static int _recv(netdev2_t *netdev, void *buf, size_t len, void *info)
+{
+    kw2xrf_t *dev = (kw2xrf_t *)netdev;
+    size_t pkt_len = 0;
+
+    /* get size of the received packet */
+    pkt_len = kw2xrf_read_dreg(dev, MKW2XDM_RX_FRM_LEN);
+
+    /* just return length when buf == NULL */
+    if (buf == NULL) {
+        return pkt_len + 1;
+    }
+
+#ifdef MODULE_NETSTATS_L2
+    netdev->stats.rx_count++;
+    netdev->stats.rx_bytes += pkt_len;
+#endif
+
+    if (pkt_len > len) {
+        /* not enough space in buf */
+        return -ENOBUFS;
+    }
+
+    kw2xrf_read_fifo(dev, (uint8_t *)buf, pkt_len + 1);
+
+    if (info != NULL) {
+        netdev2_ieee802154_rx_info_t *radio_info = info;
+        radio_info->lqi = ((uint8_t*)buf)[pkt_len];
+        radio_info->rssi = (uint8_t)kw2xrf_get_rssi(radio_info->lqi);
+    }
+
+    /* skip FCS and LQI */
+    return pkt_len - 2;
+}
+
+static int _set_state(kw2xrf_t *dev, netopt_state_t state)
+{
+    switch (state) {
+        case NETOPT_STATE_SLEEP:
+            kw2xrf_set_power_mode(dev, KW2XRF_DOZE);
+            break;
+        case NETOPT_STATE_IDLE:
+            kw2xrf_set_power_mode(dev, KW2XRF_AUTODOZE);
+            kw2xrf_set_sequence(dev, dev->idle_state);
+            break;
+        case NETOPT_STATE_TX:
+            if (dev->netdev.flags & KW2XRF_OPT_PRELOADING) {
+                kw2xrf_tx_exec(dev);
+            }
+            break;
+        case NETOPT_STATE_RESET:
+            kw2xrf_reset_phy(dev);
+            break;
+        case NETOPT_STATE_OFF:
+            /* TODO: Replace with powerdown (set reset input low) */
+            kw2xrf_set_power_mode(dev, KW2XRF_HIBERNATE);
+        default:
+            return -ENOTSUP;
+    }
+    return sizeof(netopt_state_t);
+}
+
+static netopt_state_t _get_state(kw2xrf_t *dev)
+{
+    return dev->state;
+}
+
+int _get(netdev2_t *netdev, netopt_t opt, void *value, size_t len)
+{
+    kw2xrf_t *dev = (kw2xrf_t *)netdev;
+
+    if (dev == NULL) {
+        return -ENODEV;
+    }
+
+    switch (opt) {
+        case NETOPT_MAX_PACKET_SIZE:
+            if (len < sizeof(int16_t)) {
+                return -EOVERFLOW;
+            }
+
+            *((uint16_t *)value) = KW2XRF_MAX_PKT_LENGTH - _MAX_MHR_OVERHEAD;
+            return sizeof(uint16_t);
+
+        case NETOPT_STATE:
+            if (len < sizeof(netopt_state_t)) {
+                return -EOVERFLOW;
+            }
+            *((netopt_state_t *)value) = _get_state(dev);
+            return sizeof(netopt_state_t);
+
+        case NETOPT_PRELOADING:
+            if (dev->netdev.flags & KW2XRF_OPT_PRELOADING) {
+                *((netopt_enable_t *)value) = NETOPT_ENABLE;
+            }
+            else {
+                *((netopt_enable_t *)value) = NETOPT_DISABLE;
+            }
+            return sizeof(netopt_enable_t);
+
+        case NETOPT_PROMISCUOUSMODE:
+            if (dev->netdev.flags & KW2XRF_OPT_PROMISCUOUS) {
+                *((netopt_enable_t *)value) = NETOPT_ENABLE;
+            }
+            else {
+                *((netopt_enable_t *)value) = NETOPT_DISABLE;
+            }
+            return sizeof(netopt_enable_t);
+
+        case NETOPT_RX_START_IRQ:
+            *((netopt_enable_t *)value) =
+                !!(dev->netdev.flags & KW2XRF_OPT_TELL_RX_START);
+            return sizeof(netopt_enable_t);
+
+        case NETOPT_RX_END_IRQ:
+            *((netopt_enable_t *)value) =
+                !!(dev->netdev.flags & KW2XRF_OPT_TELL_RX_END);
+            return sizeof(netopt_enable_t);
+
+        case NETOPT_TX_START_IRQ:
+            *((netopt_enable_t *)value) =
+                !!(dev->netdev.flags & KW2XRF_OPT_TELL_TX_START);
+            return sizeof(netopt_enable_t);
+
+        case NETOPT_TX_END_IRQ:
+            *((netopt_enable_t *)value) =
+                !!(dev->netdev.flags & KW2XRF_OPT_TELL_TX_END);
+            return sizeof(netopt_enable_t);
+
+        case NETOPT_AUTOCCA:
+            *((netopt_enable_t *)value) =
+                !!(dev->netdev.flags & KW2XRF_OPT_AUTOCCA);
+            return sizeof(netopt_enable_t);
+
+        case NETOPT_TX_POWER:
+            if (len < sizeof(int16_t)) {
+                return -EOVERFLOW;
+            }
+            *((uint16_t *)value) = kw2xrf_get_txpower(dev);
+            return sizeof(uint16_t);
+
+        case NETOPT_IS_CHANNEL_CLR:
+            if (kw2xrf_cca(dev)) {
+                *((netopt_enable_t *)value) = NETOPT_ENABLE;
+            }
+            else {
+                *((netopt_enable_t *)value) = NETOPT_DISABLE;
+            }
+            return sizeof(netopt_enable_t);
+
+        case NETOPT_CCA_THRESHOLD:
+            if (len < sizeof(uint8_t)) {
+                return -EOVERFLOW;
+            }
+            else {
+                *(int8_t *)value = kw2xrf_get_cca_threshold(dev);
+            }
+            return sizeof(int8_t);
+
+        case NETOPT_CCA_MODE:
+            if (len < sizeof(uint8_t)) {
+                return -EOVERFLOW;
+            }
+            else {
+                *(uint8_t *)value = kw2xrf_get_cca_mode(dev);
+                switch (*((int8_t *)value)) {
+                    case NETDEV2_IEEE802154_CCA_MODE_1:
+                    case NETDEV2_IEEE802154_CCA_MODE_2:
+                    case NETDEV2_IEEE802154_CCA_MODE_3:
+                        return sizeof(uint8_t);
+                    default:
+                        break;
+                }
+                return -EOVERFLOW;
+            }
+            break;
+
+        case NETOPT_CHANNEL_PAGE:
+        default:
+            break;
+    }
+
+    return netdev2_ieee802154_get((netdev2_ieee802154_t *)netdev, opt, value, len);
+}
+
+static int _set(netdev2_t *netdev, netopt_t opt, void *value, size_t len)
+{
+    kw2xrf_t *dev = (kw2xrf_t *)netdev;
+    int res = -ENOTSUP;
+
+    if (dev == NULL) {
+        return -ENODEV;
+    }
+
+    switch (opt) {
+        case NETOPT_ADDRESS:
+            if (len > sizeof(uint16_t)) {
+                res = -EOVERFLOW;
+            }
+            else {
+                kw2xrf_set_addr_short(dev, *((uint16_t *)value));
+                /* don't set res to set netdev2_ieee802154_t::short_addr */
+            }
+            break;
+
+        case NETOPT_ADDRESS_LONG:
+            if (len > sizeof(uint64_t)) {
+                return -EOVERFLOW;
+            }
+            else {
+                kw2xrf_set_addr_long(dev, *((uint64_t *)value));
+                /* don't set res to set netdev2_ieee802154_t::short_addr */
+            }
+            break;
+
+        case NETOPT_NID:
+            if (len > sizeof(uint16_t)) {
+                return -EOVERFLOW;
+            }
+
+            else {
+                kw2xrf_set_pan(dev, *((uint16_t *)value));
+                /* don't set res to set netdev2_ieee802154_t::pan */
+            }
+            break;
+
+        case NETOPT_CHANNEL:
+            if (len != sizeof(uint16_t)) {
+                res = -EINVAL;
+            }
+            else {
+                uint8_t chan = ((uint8_t *)value)[0];
+                if (kw2xrf_set_channel(dev, chan)) {
+                    res = -EINVAL;
+                    break;
+                }
+                dev->netdev.chan = chan;
+                /* don't set res to set netdev2_ieee802154_t::chan */
+            }
+            break;
+
+        case NETOPT_CHANNEL_PAGE:
+            res = -EINVAL;
+            break;
+
+        case NETOPT_TX_POWER:
+            if (len < sizeof(uint16_t)) {
+                res = -EOVERFLOW;
+            }
+            else {
+                kw2xrf_set_tx_power(dev, *(int16_t *)value);
+                res = sizeof(uint16_t);
+            }
+            break;
+
+        case NETOPT_STATE:
+            if (len > sizeof(netopt_state_t)) {
+                res = -EOVERFLOW;
+            }
+            else {
+                res = _set_state(dev, *((netopt_state_t *)value));
+            }
+            break;
+
+        case NETOPT_AUTOACK:
+            /* Set up HW generated automatic ACK after Receive */
+            kw2xrf_set_option(dev, KW2XRF_OPT_AUTOACK,
+                              ((bool *)value)[0]);
+            break;
+
+        case NETOPT_ACK_REQ:
+            kw2xrf_set_option(dev, KW2XRF_OPT_ACK_REQ,
+                              ((bool *)value)[0]);
+            break;
+
+        case NETOPT_PRELOADING:
+            kw2xrf_set_option(dev, KW2XRF_OPT_PRELOADING,
+                              ((bool *)value)[0]);
+            res = sizeof(netopt_enable_t);
+            break;
+
+        case NETOPT_PROMISCUOUSMODE:
+            kw2xrf_set_option(dev, KW2XRF_OPT_PROMISCUOUS,
+                              ((bool *)value)[0]);
+            res = sizeof(netopt_enable_t);
+            break;
+
+        case NETOPT_RX_START_IRQ:
+            kw2xrf_set_option(dev, KW2XRF_OPT_TELL_RX_START,
+                                 ((bool *)value)[0]);
+            res = sizeof(netopt_enable_t);
+            break;
+
+        case NETOPT_RX_END_IRQ:
+            kw2xrf_set_option(dev, KW2XRF_OPT_TELL_RX_END,
+                                 ((bool *)value)[0]);
+            res = sizeof(netopt_enable_t);
+            break;
+
+        case NETOPT_TX_START_IRQ:
+            kw2xrf_set_option(dev, KW2XRF_OPT_TELL_TX_START,
+                                 ((bool *)value)[0]);
+            res = sizeof(netopt_enable_t);
+            break;
+
+        case NETOPT_TX_END_IRQ:
+            kw2xrf_set_option(dev, KW2XRF_OPT_TELL_TX_END,
+                                 ((bool *)value)[0]);
+            res = sizeof(netopt_enable_t);
+            break;
+
+        case NETOPT_AUTOCCA:
+            kw2xrf_set_option(dev, KW2XRF_OPT_AUTOCCA,
+                                 ((bool *)value)[0]);
+            res = sizeof(netopt_enable_t);
+            break;
+
+        case NETOPT_CCA_THRESHOLD:
+            if (len < sizeof(uint8_t)) {
+                res = -EOVERFLOW;
+            }
+            else {
+                kw2xrf_set_cca_threshold(dev, *((int8_t*)value));
+                res = sizeof(uint8_t);
+            }
+            break;
+
+        case NETOPT_CCA_MODE:
+            if (len < sizeof(uint8_t)) {
+                res = -EOVERFLOW;
+            }
+            else {
+                switch (*((int8_t*)value)) {
+                    case NETDEV2_IEEE802154_CCA_MODE_1:
+                    case NETDEV2_IEEE802154_CCA_MODE_2:
+                    case NETDEV2_IEEE802154_CCA_MODE_3:
+                        kw2xrf_set_cca_mode(dev, *((int8_t*)value));
+                        res = sizeof(uint8_t);
+                        break;
+                    case NETDEV2_IEEE802154_CCA_MODE_4:
+                    case NETDEV2_IEEE802154_CCA_MODE_5:
+                    case NETDEV2_IEEE802154_CCA_MODE_6:
+                    default:
+                        break;
+                }
+            }
+            break;
+
+        case NETOPT_RF_TESTMODE:
+#ifdef KW2XRF_TESTMODE
+            if (len < sizeof(uint8_t)) {
+                res = -EOVERFLOW;
+            }
+            else {
+                kw2xrf_set_test_mode(dev, *((uint8_t *)value));
+                res = sizeof(uint8_t);
+            }
+#endif
+            break;
+
+        default:
+            break;
+    }
+
+    if (res == -ENOTSUP) {
+        res = netdev2_ieee802154_set((netdev2_ieee802154_t *)netdev, opt,
+                                     value, len);
+    }
+
+    return res;
+}
+
+static void _isr_event_seq_r(netdev2_t *netdev, uint8_t *dregs)
+{
+    kw2xrf_t *dev = (kw2xrf_t *)netdev;
+    uint8_t irqsts1 = 0;
+
+    if (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_RXWTRMRKIRQ) {
+        DEBUG("[kw2xrf]: got RXWTRMRKIRQ\n");
+        irqsts1 |= MKW2XDM_IRQSTS1_RXWTRMRKIRQ;
+        netdev->event_callback(netdev, NETDEV2_EVENT_RX_STARTED);
+    }
+
+    if (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_RXIRQ) {
+        DEBUG("[kw2xrf]: finished RXSEQ\n");
+        dev->state = NETOPT_STATE_RX;
+        irqsts1 |= MKW2XDM_IRQSTS1_RXIRQ;
+        netdev->event_callback(netdev, NETDEV2_EVENT_RX_COMPLETE);
+        if (dregs[MKW2XDM_PHY_CTRL1] & MKW2XDM_PHY_CTRL1_AUTOACK) {
+            DEBUG("[kw2xrf]: perform TX ACK\n");
+        }
+    }
+
+    if (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_TXIRQ) {
+        DEBUG("[kw2xrf]: finished (ACK) TXSEQ\n");
+        irqsts1 |= MKW2XDM_IRQSTS1_TXIRQ;
+    }
+
+    if (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_SEQIRQ) {
+        DEBUG("[kw2xrf]: SEQIRQ\n");
+        irqsts1 |= MKW2XDM_IRQSTS1_SEQIRQ;
+        kw2xrf_set_idle_sequence(dev);
+    }
+
+    kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS1, irqsts1);
+    dregs[MKW2XDM_IRQSTS1] &= ~irqsts1;
+}
+
+static void _isr_event_seq_t(netdev2_t *netdev, uint8_t *dregs)
+{
+    kw2xrf_t *dev = (kw2xrf_t *)netdev;
+    uint8_t irqsts1 = 0;
+
+    if (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_TXIRQ) {
+        DEBUG("[kw2xrf]: finished TXSEQ\n");
+        irqsts1 |= MKW2XDM_IRQSTS1_TXIRQ;
+    }
+
+    if (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_SEQIRQ) {
+        DEBUG("[kw2xrf]: SEQIRQ\n");
+        irqsts1 |= MKW2XDM_IRQSTS1_SEQIRQ;
+
+        if (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_CCAIRQ) {
+            irqsts1 |= MKW2XDM_IRQSTS1_CCAIRQ;
+            if (dregs[MKW2XDM_IRQSTS2] & MKW2XDM_IRQSTS2_CCA) {
+                DEBUG("[kw2xrf]: CCA CH busy\n");
+                netdev->event_callback(netdev, NETDEV2_EVENT_TX_MEDIUM_BUSY);
+            }
+            else {
+                netdev->event_callback(netdev, NETDEV2_EVENT_TX_COMPLETE);
+            }
+        }
+
+        assert(dev->pending_tx != 0);
+        dev->pending_tx--;
+        kw2xrf_set_idle_sequence(dev);
+    }
+
+    kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS1, irqsts1);
+    dregs[MKW2XDM_IRQSTS1] &= ~irqsts1;
+}
+
+/* Standalone CCA */
+static void _isr_event_seq_cca(netdev2_t *netdev, uint8_t *dregs)
+{
+    kw2xrf_t *dev = (kw2xrf_t *)netdev;
+    uint8_t irqsts1 = 0;
+
+    if ((dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_CCAIRQ) &&
+        (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_SEQIRQ)) {
+        irqsts1 |= MKW2XDM_IRQSTS1_CCAIRQ | MKW2XDM_IRQSTS1_SEQIRQ;
+        if (dregs[MKW2XDM_IRQSTS2] & MKW2XDM_IRQSTS2_CCA) {
+            DEBUG("[kw2xrf]: SEQIRQ, CCA CH busy\n");
+        }
+        else {
+            DEBUG("[kw2xrf]: SEQIRQ, CCA CH idle\n");
+        }
+        kw2xrf_set_idle_sequence(dev);
+    }
+    kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS1, irqsts1);
+    dregs[MKW2XDM_IRQSTS1] &= ~irqsts1;
+}
+
+static void _isr_event_seq_tr(netdev2_t *netdev, uint8_t *dregs)
+{
+    kw2xrf_t *dev = (kw2xrf_t *)netdev;
+    uint8_t irqsts1 = 0;
+
+    if (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_TXIRQ) {
+        DEBUG("[kw2xrf]: finished TXSEQ\n");
+        irqsts1 |= MKW2XDM_IRQSTS1_TXIRQ;
+        if (dregs[MKW2XDM_PHY_CTRL1] & MKW2XDM_PHY_CTRL1_RXACKRQD) {
+            DEBUG("[kw2xrf]: wait for RX ACK\n");
+            kw2xrf_seq_timeout_on(dev, _MACACKWAITDURATION);
+        }
+    }
+
+    if (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_RXWTRMRKIRQ) {
+        DEBUG("[kw2xrf]: got RXWTRMRKIRQ\n");
+        irqsts1 |= MKW2XDM_IRQSTS1_RXWTRMRKIRQ;
+    }
+
+    if (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_FILTERFAIL_IRQ) {
+        DEBUG("[kw2xrf]: got FILTERFAILIRQ\n");
+        irqsts1 |= MKW2XDM_IRQSTS1_FILTERFAIL_IRQ;
+    }
+
+    if (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_RXIRQ) {
+        DEBUG("[kw2xrf]: got RX ACK\n");
+        irqsts1 |= MKW2XDM_IRQSTS1_RXIRQ;
+    }
+
+    if (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_SEQIRQ) {
+        if (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_CCAIRQ) {
+            irqsts1 |= MKW2XDM_IRQSTS1_CCAIRQ;
+            if (dregs[MKW2XDM_IRQSTS2] & MKW2XDM_IRQSTS2_CCA) {
+                DEBUG("[kw2xrf]: CCA CH busy\n");
+                netdev->event_callback(netdev, NETDEV2_EVENT_TX_MEDIUM_BUSY);
+            }
+        }
+
+        DEBUG("[kw2xrf]: SEQIRQ\n");
+        irqsts1 |= MKW2XDM_IRQSTS1_SEQIRQ;
+        assert(dev->pending_tx != 0);
+        dev->pending_tx--;
+        netdev->event_callback(netdev, NETDEV2_EVENT_TX_COMPLETE);
+        kw2xrf_seq_timeout_off(dev);
+        kw2xrf_set_idle_sequence(dev);
+    }
+    else if (dregs[MKW2XDM_IRQSTS3] & MKW2XDM_IRQSTS3_TMR4IRQ) {
+        DEBUG("[kw2xrf]: TC4TMOUT, no SEQIRQ, TX failed\n");
+        assert(dev->pending_tx != 0);
+        dev->pending_tx--;
+        netdev->event_callback(netdev, NETDEV2_EVENT_TX_NOACK);
+        kw2xrf_seq_timeout_off(dev);
+        kw2xrf_set_sequence(dev, dev->idle_state);
+    }
+
+    kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS1, irqsts1);
+    dregs[MKW2XDM_IRQSTS1] &= ~irqsts1;
+}
+
+static void _isr_event_seq_ccca(netdev2_t *netdev, uint8_t *dregs)
+{
+    kw2xrf_t *dev = (kw2xrf_t *)netdev;
+    uint8_t irqsts1 = 0;
+
+    if ((dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_CCAIRQ) &&
+        (dregs[MKW2XDM_IRQSTS1] & MKW2XDM_IRQSTS1_SEQIRQ)) {
+        irqsts1 |= MKW2XDM_IRQSTS1_CCAIRQ | MKW2XDM_IRQSTS1_SEQIRQ;
+        DEBUG("[kw2xrf]: CCCA CH idle\n");
+        kw2xrf_seq_timeout_off(dev);
+        kw2xrf_set_sequence(dev, dev->idle_state);
+    }
+    else if (dregs[MKW2XDM_IRQSTS3] & MKW2XDM_IRQSTS3_TMR4IRQ) {
+        irqsts1 |= MKW2XDM_IRQSTS1_CCAIRQ | MKW2XDM_IRQSTS1_SEQIRQ;
+        DEBUG("[kw2xrf]: CCCA timeout\n");
+        kw2xrf_seq_timeout_off(dev);
+        kw2xrf_set_sequence(dev, dev->idle_state);
+    }
+    kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS1, irqsts1);
+    dregs[MKW2XDM_IRQSTS1] &= ~irqsts1;
+}
+
+static void _isr(netdev2_t *netdev)
+{
+    uint8_t dregs[MKW2XDM_PHY_CTRL4 + 1];
+    kw2xrf_t *dev = (kw2xrf_t *)netdev;
+
+    kw2xrf_read_dregs(dev, MKW2XDM_IRQSTS1, dregs, MKW2XDM_PHY_CTRL4 + 1);
+    kw2xrf_mask_irq_b(dev);
+
+    DEBUG("[kw2xrf]: CTRL1 %0x, IRQSTS1 %0x, IRQSTS2 %0x\n",
+          dregs[MKW2XDM_PHY_CTRL1], dregs[MKW2XDM_IRQSTS1], dregs[MKW2XDM_IRQSTS2]);
+
+    switch (dregs[MKW2XDM_PHY_CTRL1] & MKW2XDM_PHY_CTRL1_XCVSEQ_MASK) {
+        case XCVSEQ_RECEIVE:
+            _isr_event_seq_r(netdev, dregs);
+            break;
+
+        case XCVSEQ_TRANSMIT:
+            _isr_event_seq_t(netdev, dregs);
+            break;
+
+        case XCVSEQ_CCA:
+            _isr_event_seq_cca(netdev, dregs);
+            break;
+
+        case XCVSEQ_TX_RX:
+            _isr_event_seq_tr(netdev, dregs);
+            break;
+
+        case XCVSEQ_CONTINUOUS_CCA:
+            _isr_event_seq_ccca(netdev, dregs);
+            break;
+
+        case XCVSEQ_IDLE:
+        default:
+            DEBUG("[kw2xrf]: undefined seq state in isr\n");
+            break;
+    }
+
+    uint8_t irqsts2 = 0;
+    if (dregs[MKW2XDM_IRQSTS2] & MKW2XDM_IRQSTS2_PB_ERR_IRQ) {
+        DEBUG("[kw2xrf]: untreated PB_ERR_IRQ\n");
+        irqsts2 |= MKW2XDM_IRQSTS2_PB_ERR_IRQ;
+    }
+    if (dregs[MKW2XDM_IRQSTS2] & MKW2XDM_IRQSTS2_WAKE_IRQ) {
+        DEBUG("[kw2xrf]: untreated WAKE_IRQ\n");
+        irqsts2 |= MKW2XDM_IRQSTS2_WAKE_IRQ;
+    }
+    kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS2, irqsts2);
+
+    if (ENABLE_DEBUG) {
+        /* for debugging only */
+        kw2xrf_read_dregs(dev, MKW2XDM_IRQSTS1, dregs, MKW2XDM_IRQSTS1 + 3);
+        if (dregs[MKW2XDM_IRQSTS1] & 0x7f) {
+            DEBUG("[kw2xrf]: IRQSTS1 contains untreated IRQs: 0x%02x\n",
+                dregs[MKW2XDM_IRQSTS1]);
+        }
+        if (dregs[MKW2XDM_IRQSTS2] & 0x02) {
+            DEBUG("[kw2xrf]: IRQSTS2 contains untreated IRQs: 0x%02x\n",
+                dregs[MKW2XDM_IRQSTS2]);
+        }
+        if (dregs[MKW2XDM_IRQSTS3] & 0x0f) {
+            DEBUG("[kw2xrf]: IRQSTS3 contains untreated IRQs: 0x%02x\n",
+                dregs[MKW2XDM_IRQSTS3]);
+        }
+    }
+
+    kw2xrf_enable_irq_b(dev);
+}
+
+const netdev2_driver_t kw2xrf_driver = {
+    .init = _init,
+    .send = _send,
+    .recv = _recv,
+    .get = _get,
+    .set = _set,
+    .isr = _isr,
+};
+
+/** @} */
diff --git a/drivers/kw2xrf/kw2xrf_spi.c b/drivers/kw2xrf/kw2xrf_spi.c
index f129925dcc..ba59ca5139 100644
--- a/drivers/kw2xrf/kw2xrf_spi.c
+++ b/drivers/kw2xrf/kw2xrf_spi.c
@@ -32,31 +32,39 @@
 
 static uint8_t ibuf[KW2XRF_IBUF_LENGTH];
 
-/** Set up in kw2xrf_spi_init during initialization */
-static spi_t kw2xrf_spi;
-static spi_clk_t kw2xrf_clk;
-static spi_cs_t kw2xrf_cs_pin;
-
-static inline void kw2xrf_spi_transfer_head(void)
+void kw2xrf_spi_transfer_head(kw2xrf_t *dev)
 {
-    spi_acquire(kw2xrf_spi, kw2xrf_cs_pin, SPI_MODE, kw2xrf_clk);
+#if KW2XRF_SHARED_SPI
+    spi_acquire(dev->params.spi);
+    gpio_clear(dev->params.cs_pin);
+#endif
 }
 
-static inline void kw2xrf_spi_transfer_tail(void)
+void kw2xrf_spi_transfer_tail(kw2xrf_t *dev)
 {
-    spi_release(kw2xrf_spi);
+#if KW2XRF_SHARED_SPI
+    gpio_set(dev->params.cs_pin);
+    spi_release(dev->params.spi);
+#endif
 }
 
-int kw2xrf_spi_init(spi_t spi, spi_clk_t spi_clk, spi_cs_t cs_pin)
+int kw2xrf_spi_init(kw2xrf_t *dev)
 {
     int res;
-    kw2xrf_spi = spi;
-    kw2xrf_clk = spi_clk;
-    kw2xrf_cs_pin = cs_pin;     /**< for later reference */
 
-    res = spi_init_cs(kw2xrf_spi, kw2xrf_cs_pin);
-    if (res != SPI_OK) {
-        DEBUG("kw2xrf_spi_init: error initializing SPI_DEV(%i) (code %i)\n",
+#if KW2XRF_SHARED_SPI
+    spi_acquire(dev->params.spi);
+#endif
+    res = spi_init_master(dev->params.spi, SPI_CONF_FIRST_RISING, dev->params.spi_speed);
+#if KW2XRF_SHARED_SPI
+    spi_release(dev->params.spi);
+
+    gpio_init(dev->params.cs_pin, GPIO_OUT);
+    gpio_set(dev->params.cs_pin);
+#endif
+
+    if (res < 0) {
+        DEBUG("[kw2xrf]: error initializing SPI_%i device (code %i)\n",
               kw2xrf_spi, res);
         return -1;
     }
@@ -64,25 +72,43 @@ int kw2xrf_spi_init(spi_t spi, spi_clk_t spi_clk, spi_cs_t cs_pin)
     return 0;
 }
 
-void kw2xrf_write_dreg(uint8_t addr, uint8_t value)
+void kw2xrf_write_dreg(kw2xrf_t *dev, uint8_t addr, uint8_t value)
 {
-    kw2xrf_spi_transfer_head();
-    spi_transfer_reg(kw2xrf_spi, kw2xrf_cs_pin, addr, value);
-    kw2xrf_spi_transfer_tail();
+    kw2xrf_spi_transfer_head(dev);
+    spi_transfer_reg(dev->params.spi, dev->params.cs_pin, addr, value);
+    kw2xrf_spi_transfer_tail(dev);
     return;
 }
 
-uint8_t kw2xrf_read_dreg(uint8_t addr)
+uint8_t kw2xrf_read_dreg(kw2xrf_t *dev, uint8_t addr)
 {
     uint8_t value;
-    kw2xrf_spi_transfer_head();
-    value = spi_transfer_reg(kw2xrf_spi, kw2xrf_cs_pin,
+    kw2xrf_spi_transfer_head(dev);
+    value = spi_transfer_reg(dev->params.spi, dev->params.cs_pin,
                              (addr | MKW2XDRF_REG_READ), 0x0);
-    kw2xrf_spi_transfer_tail();
+    kw2xrf_spi_transfer_tail(dev);
     return value;
 }
 
-void kw2xrf_write_iregs(uint8_t addr, uint8_t *buf, uint8_t length)
+size_t kw2xrf_write_dregs(kw2xrf_t *dev, uint8_t addr, uint8_t *buf, uint8_t length)
+{
+    kw2xrf_spi_transfer_head(dev);
+    size_t i = spi_transfer_regs(dev->params.spi, addr, (char *)buf, NULL, length);
+    kw2xrf_spi_transfer_tail(dev);
+    return i;
+}
+
+size_t kw2xrf_read_dregs(kw2xrf_t *dev, uint8_t addr, uint8_t *buf, uint8_t length)
+{
+    kw2xrf_spi_transfer_head(dev);
+    size_t i = spi_transfer_regs(dev->params.spi, (addr | MKW2XDRF_REG_READ),
+                                 NULL, (char *)buf, length);
+    kw2xrf_spi_transfer_tail(dev);
+    return i;
+}
+
+
+void kw2xrf_write_iregs(kw2xrf_t *dev, uint8_t addr, uint8_t *buf, uint8_t length)
 {
     if (length > (KW2XRF_IBUF_LENGTH - 1)) {
         length = KW2XRF_IBUF_LENGTH - 1;
@@ -94,15 +120,15 @@ void kw2xrf_write_iregs(uint8_t addr, uint8_t *buf, uint8_t length)
         ibuf[i + 1] = buf[i];
     }
 
-    kw2xrf_spi_transfer_head();
-    spi_transfer_regs(kw2xrf_spi, kw2xrf_cs_pin, MKW2XDM_IAR_INDEX,
+    kw2xrf_spi_transfer_head(dev);
+    spi_transfer_regs(dev->params.spi, dev->params.cs_pin, MKW2XDM_IAR_INDEX,
                       ibuf, NULL, length + 1);
-    kw2xrf_spi_transfer_tail();
+    kw2xrf_spi_transfer_tail(dev);
 
     return;
 }
 
-void kw2xrf_read_iregs(uint8_t addr, uint8_t *buf, uint8_t length)
+void kw2xrf_read_iregs(kw2xrf_t *dev, uint8_t addr, uint8_t *buf, uint8_t length)
 {
     if (length > (KW2XRF_IBUF_LENGTH - 1)) {
         length = KW2XRF_IBUF_LENGTH - 1;
@@ -110,11 +136,11 @@ void kw2xrf_read_iregs(uint8_t addr, uint8_t *buf, uint8_t length)
 
     ibuf[0] = addr;
 
-    kw2xrf_spi_transfer_head();
-    spi_transfer_regs(kw2xrf_spi, kw2xrf_cs_pin,
-                      MKW2XDM_IAR_INDEX | MKW2XDRF_REG_READ,
+    kw2xrf_spi_transfer_head(dev);
+    spi_transfer_regs(dev->params.spi, dev->params.cs_pin,
+                      (MKW2XDM_IAR_INDEX | MKW2XDRF_REG_READ),
                       ibuf, ibuf, length + 1);
-    kw2xrf_spi_transfer_tail();
+    kw2xrf_spi_transfer_tail(dev);
 
     for (uint8_t i = 0; i < length; i++) {
         buf[i] = ibuf[i + 1];
@@ -123,18 +149,18 @@ void kw2xrf_read_iregs(uint8_t addr, uint8_t *buf, uint8_t length)
     return;
 }
 
-void kw2xrf_write_fifo(uint8_t *data, uint8_t length)
+void kw2xrf_write_fifo(kw2xrf_t *dev, uint8_t *data, uint8_t length)
 {
-    kw2xrf_spi_transfer_head();
-    spi_transfer_regs(kw2xrf_spi, kw2xrf_cs_pin, MKW2XDRF_BUF_WRITE,
-                      data, NULL, length);
-    kw2xrf_spi_transfer_tail();
+    kw2xrf_spi_transfer_head(dev);
+    spi_transfer_regs(dev->params.spi, dev->params.cs_pin,
+                      MKW2XDRF_BUF_WRITE, data, NULL, length);
+    kw2xrf_spi_transfer_tail(dev);
 }
 
-void kw2xrf_read_fifo(uint8_t *data, uint8_t length)
+void kw2xrf_read_fifo(kw2xrf_t *dev, uint8_t *data, uint8_t length)
 {
-    kw2xrf_spi_transfer_head();
-    spi_transfer_regs(kw2xrf_spi, kw2xrf_cs_pin, MKW2XDRF_BUF_READ,
-                      NULL, data, length);
-    kw2xrf_spi_transfer_tail();
+    kw2xrf_spi_transfer_head(dev);
+    spi_transfer_regs(dev->params.spi, dev->params.cs_pin,
+                      MKW2XDRF_BUF_READ, NULL, data, length);
+    kw2xrf_spi_transfer_tail(dev);
 }
diff --git a/drivers/kw2xrf/kw2xrf_tm.c b/drivers/kw2xrf/kw2xrf_tm.c
new file mode 100644
index 0000000000..576459597d
--- /dev/null
+++ b/drivers/kw2xrf/kw2xrf_tm.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2016 Phytec Messtechnik GmbH
+ *
+ * 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     drivers_kw2xrf
+ * @{
+ *
+ * @file
+ * @brief       Testing function of kw2xrf driver
+ *
+ * @author      Johann Fischer <j.fischer@phytec.de>
+ */
+
+#include "kw2xrf.h"
+#include "kw2xrf_spi.h"
+#include "kw2xrf_reg.h"
+#include "kw2xrf_tm.h"
+
+#ifdef KW2XRF_TESTMODE
+
+inline static void enable_xcvr_test_mode(kw2xrf_t *dev)
+{
+    uint8_t reg;
+
+    kw2xrf_read_iregs(dev, MKW2XDMI_DTM_CTRL1, &reg, 1);
+    reg |= MKW2XDMI_DTM_CTRL1_DTM_EN;
+    kw2xrf_write_iregs(dev, MKW2XDMI_DTM_CTRL1, &reg, 1);
+
+    kw2xrf_read_iregs(dev, MKW2XDMI_TESTMODE_CTRL, &reg, 1);
+    reg |= MKW2XDMI_TESTMODE_CTRL_CONTINUOUS_EN | MKW2XDMI_TESTMODE_CTRL_IDEAL_PFC_EN;
+    kw2xrf_write_iregs(dev, MKW2XDMI_TESTMODE_CTRL, &reg, 1);
+}
+
+inline static void disable_xcvr_test_mode(kw2xrf_t *dev)
+{
+    uint8_t reg;
+
+    kw2xrf_read_iregs(dev, MKW2XDMI_DTM_CTRL1, &reg, 1);
+    reg &= MKW2XDMI_DTM_CTRL1_DTM_EN;
+    kw2xrf_write_iregs(dev, MKW2XDMI_DTM_CTRL1, &reg, 1);
+
+    kw2xrf_read_iregs(dev, MKW2XDMI_TESTMODE_CTRL, &reg, 1);
+    reg &= ~(MKW2XDMI_TESTMODE_CTRL_CONTINUOUS_EN | MKW2XDMI_TESTMODE_CTRL_IDEAL_PFC_EN);
+    kw2xrf_write_iregs(dev, MKW2XDMI_TESTMODE_CTRL, &reg, 1);
+}
+
+int kw2xrf_set_test_mode(kw2xrf_t *dev, uint8_t mode)
+{
+    uint8_t reg = 0;
+    uint8_t buf[2];
+
+    kw2xrf_abort_sequence(dev);
+    disable_xcvr_test_mode(dev);
+    kw2xrf_set_channel(dev, dev->netdev.chan);
+
+    switch(mode) {
+        case NETOPT_RF_TESTMODE_IDLE:
+            reg = 0;
+            kw2xrf_write_iregs(dev, MKW2XDMI_TX_MODE_CTRL, &reg, 1);
+
+            kw2xrf_set_sequence(dev, XCVSEQ_IDLE);
+            break;
+
+        case NETOPT_RF_TESTMODE_CRX:
+            /* set continuous RX mode */
+            reg = 0;
+            kw2xrf_write_iregs(dev, MKW2XDMI_TX_MODE_CTRL, &reg, 1);
+            enable_xcvr_test_mode(dev);
+
+            /* set data length */
+            reg = 127;
+            kw2xrf_write_iregs(dev, MKW2XDMI_DUAL_PAN_DWELL, &reg, 1);
+
+            kw2xrf_set_sequence(dev, XCVSEQ_RECEIVE);
+            break;
+
+        case KW2XRF_TM_CTX_PREAMBLE:
+            /* set continuous TX mode, transmit 10101010 pattern */
+            reg = 0;
+            kw2xrf_write_iregs(dev, MKW2XDMI_TX_MODE_CTRL, &reg, 1);
+            enable_xcvr_test_mode(dev);
+
+            buf[0] = 1;
+            buf[1] = 0xaa;
+            kw2xrf_write_fifo(dev, buf, buf[0] + 1);
+
+            kw2xrf_set_sequence(dev, XCVSEQ_TRANSMIT);
+            break;
+
+        case NETOPT_RF_TESTMODE_CTX_CW:
+            /* set continuous TX mode, transmit unmodulated carrier */
+            reg = MKW2XDMI_TX_MODE_CTRL_DTS0;
+            kw2xrf_write_iregs(dev, MKW2XDMI_TX_MODE_CTRL, &reg, 1);
+            enable_xcvr_test_mode(dev);
+
+            /* fix pll frequency for cw mode */
+            uint16_t pll_frac = kw2xrf_read_dreg(dev, MKW2XDM_PLL_FRAC0_LSB);
+            pll_frac |= ((uint16_t)kw2xrf_read_dreg(dev, MKW2XDM_PLL_FRAC0_MSB) << 8);
+            pll_frac -= 0x400;
+
+            kw2xrf_write_dreg(dev, MKW2XDM_PLL_FRAC0_LSB, (uint8_t)pll_frac);
+            kw2xrf_write_dreg(dev, MKW2XDM_PLL_FRAC0_MSB, (uint8_t)(pll_frac >> 8));
+
+            kw2xrf_set_sequence(dev, XCVSEQ_TRANSMIT);
+            break;
+
+        case KW2XRF_TM_CTX_NM1:
+            /* set continuous TX mode */
+            reg = MKW2XDMI_TX_MODE_CTRL_DTS0;
+            kw2xrf_write_iregs(dev, MKW2XDMI_TX_MODE_CTRL, &reg, 1);
+            enable_xcvr_test_mode(dev);
+
+            kw2xrf_set_sequence(dev, XCVSEQ_TRANSMIT);
+            break;
+
+        case KW2XRF_TM_CTX_NM0:
+            /* set continuous TX mode */
+            reg = MKW2XDMI_TX_MODE_CTRL_DTS1;
+            kw2xrf_write_iregs(dev, MKW2XDMI_TX_MODE_CTRL, &reg, 1);
+            enable_xcvr_test_mode(dev);
+
+            kw2xrf_set_sequence(dev, XCVSEQ_TRANSMIT);
+            break;
+
+        case KW2XRF_TM_CTX_2MHZ:
+            /* set continuous TX mode */
+            reg = MKW2XDMI_TX_MODE_CTRL_DTS1 | MKW2XDMI_TX_MODE_CTRL_DTS0;
+            kw2xrf_write_iregs(dev, MKW2XDMI_TX_MODE_CTRL, &reg, 1);
+            enable_xcvr_test_mode(dev);
+
+            kw2xrf_set_sequence(dev, XCVSEQ_TRANSMIT);
+            break;
+
+        case KW2XRF_TM_CTX_200KHZ:
+            /* set continuous TX mode */
+            reg = MKW2XDMI_TX_MODE_CTRL_DTS2;
+            kw2xrf_write_iregs(dev, MKW2XDMI_TX_MODE_CTRL, &reg, 1);
+            enable_xcvr_test_mode(dev);
+
+            kw2xrf_set_sequence(dev, XCVSEQ_TRANSMIT);
+            break;
+
+        case KW2XRF_TM_CTX_1MBPS_PRBS9:
+            /* set continuous TX mode, transmit PRBS9 pattern */
+            reg = MKW2XDMI_TX_MODE_CTRL_DTS2 | MKW2XDMI_TX_MODE_CTRL_DTS0;
+            kw2xrf_write_iregs(dev, MKW2XDMI_TX_MODE_CTRL, &reg, 1);
+            enable_xcvr_test_mode(dev);
+
+            kw2xrf_set_sequence(dev, XCVSEQ_TRANSMIT);
+            break;
+
+        case KW2XRF_TM_CTX_EXT:
+            /* set continuous TX mode */
+            reg = MKW2XDMI_TX_MODE_CTRL_DTS2 | MKW2XDMI_TX_MODE_CTRL_DTS1;
+            kw2xrf_write_iregs(dev, MKW2XDMI_TX_MODE_CTRL, &reg, 1);
+            enable_xcvr_test_mode(dev);
+
+            kw2xrf_set_sequence(dev, XCVSEQ_TRANSMIT);
+            break;
+
+        case NETOPT_RF_TESTMODE_CTX_PRBS9:
+            /* set continuous TX mode, transmit PRBS9 pattern */
+            reg = MKW2XDMI_TX_MODE_CTRL_DTS2 | MKW2XDMI_TX_MODE_CTRL_DTS1
+                | MKW2XDMI_TX_MODE_CTRL_DTS0;
+            kw2xrf_write_iregs(dev, MKW2XDMI_TX_MODE_CTRL, &reg, 1);
+            enable_xcvr_test_mode(dev);
+
+            kw2xrf_set_sequence(dev, XCVSEQ_TRANSMIT);
+            break;
+
+    }
+    return 1;
+}
+
+#endif
+/** @} */
diff --git a/sys/auto_init/netif/auto_init_kw2xrf.c b/sys/auto_init/netif/auto_init_kw2xrf.c
index 25410443f1..2ac62261be 100644
--- a/sys/auto_init/netif/auto_init_kw2xrf.c
+++ b/sys/auto_init/netif/auto_init_kw2xrf.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
- * Copyright (C) 2015 PHYTEC Messtechnik GmbH
+ * Copyright (C) 2016 PHYTEC Messtechnik GmbH
  *
  * 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
@@ -24,7 +24,7 @@
 #include "log.h"
 #include "board.h"
 #include "net/gnrc/netdev2.h"
-#include "net/gnrc/nomac.h"
+#include "net/gnrc/netdev2/ieee802154.h"
 #include "net/gnrc.h"
 
 #include "kw2xrf.h"
@@ -42,7 +42,8 @@
 #define KW2XRF_NUM (sizeof(kw2xrf_params)/sizeof(kw2xrf_params[0]))
 
 static kw2xrf_t kw2xrf_devs[KW2XRF_NUM];
-static char _nomac_stacks[KW2XRF_NUM][KW2XRF_MAC_STACKSIZE];
+static gnrc_netdev2_t gnrc_adpt[KW2XRF_NUM];
+static char _nomac_stacks[KW2XRF_MAC_STACKSIZE][KW2XRF_NUM];
 
 void auto_init_kw2xrf(void)
 {
@@ -51,19 +52,18 @@ void auto_init_kw2xrf(void)
 
         LOG_DEBUG("[auto_init_netif] initializing kw2xrf #%u\n", i);
 
-        int res = kw2xrf_init(&kw2xrf_devs[i],
-                p->spi,
-                p->spi_speed,
-                p->cs_pin,
-                p->int_pin);
-
+        kw2xrf_setup(&kw2xrf_devs[i], (kw2xrf_params_t*) p);
+        int res = gnrc_netdev2_ieee802154_init(&gnrc_adpt[i],
+                                               (netdev2_ieee802154_t *)&kw2xrf_devs[i]);
         if (res < 0) {
             LOG_ERROR("[auto_init_netif] initializing kw2xrf #%u\n", i);
         }
         else {
-            gnrc_nomac_init(_nomac_stacks[i],
-                            KW2XRF_MAC_STACKSIZE, KW2XRF_MAC_PRIO,
-                            "kw2xrf", (gnrc_netdev_t *)&kw2xrf_devs[i]);
+            gnrc_netdev2_init(_nomac_stacks[i],
+                              KW2XRF_MAC_STACKSIZE,
+                              KW2XRF_MAC_PRIO,
+                              "kw2xrf",
+                              &gnrc_adpt[i]);
         }
     }
 }
-- 
GitLab