diff --git a/Makefile.dep b/Makefile.dep
index 0bdcebd297a46febab9808796896e7177aba9371..8545ac3e3c197d9dfb5aec7a447324b1b9441275 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -36,6 +36,10 @@ ifneq (,$(filter at86rf2%,$(USEMODULE)))
   USEMODULE += netif
 endif
 
+ifneq (,$(filter cc110x,$(USEMODULE)))
+  USEMODULE += ieee802154
+endif
+
 ifneq (,$(filter kw2xrf,$(USEMODULE)))
   USEMODULE += ieee802154
   USEMODULE += netif
diff --git a/drivers/cc110x/Makefile b/drivers/cc110x/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..a6588efa9cd44d0b40348aded59e2425c90d04e1
--- /dev/null
+++ b/drivers/cc110x/Makefile
@@ -0,0 +1,3 @@
+DIRS += gnrc_cc110x
+
+include $(RIOTBASE)/Makefile.base
diff --git a/drivers/cc110x/cc110x-defaultsettings.c b/drivers/cc110x/cc110x-defaultsettings.c
new file mode 100644
index 0000000000000000000000000000000000000000..aded9ece1f52845d4380cb4bc45e1288dcf1e69f
--- /dev/null
+++ b/drivers/cc110x/cc110x-defaultsettings.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 INRIA
+ *               2015 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * 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_cc110x
+ * @{
+ *
+ * @file
+ * @brief   TI Chipcon CC110x default settings
+ *
+ * @author    Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
+ * @author    Heiko Will <hwill@inf.fu-berlin.de>
+ * @author    Oliver Hahm <oliver.hahm@inria.fr>
+ * @author    Kaspar Schleiser <kaspar@schleiser.de>
+ * @}
+ */
+
+#include "board.h"
+#include "cc110x.h"
+
+/**
+ * @brief   PATABLE with available output powers
+ * @note    If changed in size, adjust MAX_OUTPUT_POWER definition
+ *          in CC110x interface
+*/
+const char cc110x_default_pa_table[8] = {
+    0x00,   /*< -52 dBm */
+    0x0D,   /*< -20 dBm */
+    0x34,   /*< -10 dBm */
+    0x57,   /*< - 5 dBm */
+    0x8E,   /*<   0 dBm */
+    0x85,   /*< + 5 dBm */
+    0xCC,   /*< + 7 dBm */
+    0xC3    /*< +10 dBm */
+};
+
+const char cc110x_default_base_freq[3] = { 0x21, 0x71, 0x7F };
+
+/**
+ * @brief cc110x default settings
+ */
+const char cc110x_default_conf[] = {
+    0x06, /* IOCFG2 */
+    0x2E, /* IOCFG1 */
+    /* some boards use cc110x' GDO0 as clock source, so for those, we allow
+     * overriding of the corresponding setting, e.g., in board.h */
+#ifdef CC110X_IOCONF0_VAL
+    CC110X_IOCONF0_VAL,
+#else
+    0x0E, /* IOCFG0 */
+#endif
+    0x07, /* FIFOTHR */
+    0x9B, /* SYNC1 */
+    0xAD, /* SYNC0 */
+    0xFF, /* PKTLEN */
+    0x06, /* PKTCTRL1 */
+    0x45, /* PKTCTRL0 (variable packet length) */
+    0xFF, /* ADDR */
+    0x00, /* CHANNR */
+    0x0F, /* FSCTRL1 */
+    0x00, /* FSCTRL0 */
+    0x21, /* FREQ2 */
+    0x71, /* FREQ1 */
+    0x7A, /* FREQ0 */
+    0x7C, /* MDMCFG4 */
+    0x7A, /* MDMCFG3 */
+    0x06, /* MDMCFG2 */
+    0xC0, /* MDMCFG1 */
+    0xF8, /* MDMCFG0 */
+    0x44, /* DEVIATN */
+    0x07, /* MCSM2 */
+    0x03, /* MCSM1 */
+    0x18, /* MCSM0 */
+    0x16, /* FOCCFG */
+    0x6C, /* BSCFG */
+    0x45, /* AGCCTRL2 */
+    0x40, /* AGCCTRL1 */
+    0x91, /* AGCCTRL0 */
+    0x87, /* WOREVT1 */
+    0x6B, /* WOREVT0 */
+    0xF8, /* WORCTRL */
+    0x56, /* FREND1 */
+    0x17, /* FREND0 */
+    0xEA, /* FSCAL3 */
+    0x2A, /* FSCAL2 */
+    0x00, /* FSCAL1 */
+    0x1F, /* FSCAL0 */
+    0x00  /* padding to 4 bytes */
+};
+
+/**
+ * @brief The size of the configuration array for CC110X in bytes
+ * */
+const uint8_t cc110x_default_conf_size = sizeof(cc110x_default_conf);
diff --git a/drivers/cc110x/cc110x-netdev2.c b/drivers/cc110x/cc110x-netdev2.c
new file mode 100644
index 0000000000000000000000000000000000000000..96da07dc82c1aa599110434f82bc5d9804a9cf4e
--- /dev/null
+++ b/drivers/cc110x/cc110x-netdev2.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2014 Freie Universität Berlin
+ *               2015 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * 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_cc110x
+ * @{
+ * @file
+ * @brief       Implementation of netdev2 interface for cc110x
+ *
+ * @author      Fabian Nack <nack@inf.fu-berlin.de>
+ * @author      Kaspar Schleiser <kaspar@schleiser.de>
+ * @}
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "cc110x.h"
+#include "cc110x/cc110x-netdev2.h"
+#include "cc110x/cc110x-internal.h"
+#include "cc110x/cc110x-interface.h"
+#include "net/eui64.h"
+
+#include "periph/cpuid.h"
+#include "periph/gpio.h"
+#include "net/netdev2.h"
+#include "net/gnrc/nettype.h"
+
+#define ENABLE_DEBUG    (0)
+#include "debug.h"
+
+static int _send(netdev2_t *dev, const struct iovec *vector, int count)
+{
+    DEBUG("%s:%u\n", __func__, __LINE__);
+
+    netdev2_cc110x_t *netdev2_cc110x = (netdev2_cc110x_t*) dev;
+    cc110x_pkt_t *cc110x_pkt = vector[0].iov_base;
+
+    return cc110x_send(&netdev2_cc110x->cc110x, cc110x_pkt);
+}
+
+static int _recv(netdev2_t *dev, char* buf, int len)
+{
+    DEBUG("%s:%u\n", __func__, __LINE__);
+
+    cc110x_t *cc110x = &((netdev2_cc110x_t*) dev)->cc110x;
+
+    cc110x_pkt_t *cc110x_pkt = &cc110x->pkt_buf.packet;
+    if (cc110x_pkt->length > len) {
+        return -ENOSPC;
+    }
+
+    memcpy(buf, (void*)cc110x_pkt, cc110x_pkt->length);
+    return cc110x_pkt->length;
+}
+
+static inline int _get_iid(netdev2_t *netdev, eui64_t *value, size_t max_len)
+{
+    if (max_len < sizeof(eui64_t)) {
+        return -EOVERFLOW;
+    }
+
+    uint8_t *eui64 = (uint8_t*) value;
+#ifdef CPUID_ID_LEN
+    int n = (CPUID_ID_LEN < sizeof(eui64_t))
+        ? CPUID_ID_LEN
+        : sizeof(eui64_t);
+
+    char cpuid[CPUID_ID_LEN];
+    cpuid_get(cpuid);
+
+    memcpy(eui64 + 8 - n, cpuid, n);
+
+#else
+    for (int i = 0; i < 8; i++) {
+        eui64[i] = i;
+    }
+#endif
+
+    /* make sure we mark the address as non-multicast and not globally unique */
+    eui64[0] &= ~(0x01);
+    eui64[0] |= 0x02;
+
+    return sizeof(eui64_t);
+}
+
+static int _get(netdev2_t *dev, netopt_t opt, void *value, size_t value_len)
+{
+    cc110x_t *cc110x = &((netdev2_cc110x_t*) dev)->cc110x;
+
+    switch (opt) {
+        case NETOPT_DEVICE_TYPE:
+            assert(value_len == 2);
+            *((uint16_t *) value) = NETDEV2_TYPE_CC110X;
+            return 2;
+        case NETOPT_PROTO:
+            assert(value_len == sizeof(gnrc_nettype_t));
+#ifdef MODULE_GNRC_SIXLOWPAN
+            *((gnrc_nettype_t*)value) = GNRC_NETTYPE_SIXLOWPAN;
+#else
+            *((gnrc_nettype_t*)value) = GNRC_NETTYPE_UNDEF;
+#endif
+            return sizeof(gnrc_nettype_t);
+        case NETOPT_CHANNEL:
+            assert(value_len > 1);
+            *((uint16_t *)value) = (uint16_t)cc110x->radio_channel;
+            return 2;
+        case NETOPT_ADDRESS:
+            assert(value_len > 0);
+            *((uint8_t *)value) = cc110x->radio_address;
+            return 1;
+        case NETOPT_MAX_PACKET_SIZE:
+            assert(value_len > 0);
+            *((uint8_t *)value) = CC110X_PACKET_LENGTH;
+            return 1;
+        case NETOPT_IPV6_IID:
+            return _get_iid(dev, value, value_len);
+        default:
+            break;
+    }
+
+    return -ENOTSUP;
+}
+
+static int _set(netdev2_t *dev, netopt_t opt, void *value, size_t value_len)
+{
+    cc110x_t *cc110x = &((netdev2_cc110x_t*) dev)->cc110x;
+
+    switch (opt) {
+        case NETOPT_CHANNEL:
+            {
+                uint8_t *arg = (uint8_t*)value;
+                uint8_t channel = arg[value_len-1];
+                if ((channel < CC110X_MIN_CHANNR) || (channel > CC110X_MAX_CHANNR)) {
+                    return -EINVAL;
+                }
+                if (cc110x_set_channel(cc110x, channel) == -1) {
+                    return -EINVAL;
+                }
+                return 1;
+            }
+        case NETOPT_ADDRESS:
+            if (value_len < 1) {
+                return -EINVAL;
+            }
+            if (!cc110x_set_address(cc110x, *(uint8_t*)value)) {
+                return -EINVAL;
+            }
+            return 1;
+        default:
+            return -ENOTSUP;
+    }
+
+    return 0;
+}
+
+static void _netdev2_cc110x_isr(void *arg)
+{
+    netdev2_t *netdev2 = (netdev2_t*) arg;
+    netdev2->event_callback(netdev2, NETDEV2_EVENT_ISR, netdev2->isr_arg);
+}
+
+static void _netdev2_cc110x_rx_callback(void *arg)
+{
+    netdev2_t *netdev2 = (netdev2_t*) arg;
+    cc110x_t *cc110x = &((netdev2_cc110x_t*) arg)->cc110x;
+    gpio_irq_disable(cc110x->params.gdo2);
+    netdev2->event_callback(netdev2, NETDEV2_EVENT_RX_COMPLETE, netdev2->isr_arg);
+}
+
+static void _isr(netdev2_t *dev)
+{
+    cc110x_t *cc110x = &((netdev2_cc110x_t*) dev)->cc110x;
+    cc110x_isr_handler(cc110x, _netdev2_cc110x_rx_callback, (void*)dev);
+}
+
+static int _init(netdev2_t *dev)
+{
+    DEBUG("%s:%u\n", __func__, __LINE__);
+
+    cc110x_t *cc110x = &((netdev2_cc110x_t*) dev)->cc110x;
+
+    gpio_init_int(cc110x->params.gdo2, GPIO_NOPULL, GPIO_BOTH,
+            &_netdev2_cc110x_isr, (void*)dev);
+
+    gpio_set(cc110x->params.gdo2);
+    gpio_irq_disable(cc110x->params.gdo2);
+
+    /* Switch to RX mode */
+    cc110x_rd_set_mode(cc110x, RADIO_MODE_ON);
+
+    return 0;
+}
+
+const netdev2_driver_t netdev2_cc110x_driver = {
+    .send=_send,
+    .recv=_recv,
+    .init=_init,
+    .get=_get,
+    .set=_set,
+    .isr=_isr
+};
+
+int netdev2_cc110x_setup(netdev2_cc110x_t *netdev2_cc110x, const cc110x_params_t *params)
+{
+    DEBUG("netdev2_cc110x_setup()\n");
+    netdev2_cc110x->netdev.driver = &netdev2_cc110x_driver;
+
+    return cc110x_setup(&netdev2_cc110x->cc110x, params);
+}
diff --git a/drivers/cc110x/cc110x-rxtx.c b/drivers/cc110x/cc110x-rxtx.c
new file mode 100644
index 0000000000000000000000000000000000000000..f2936db5f1645f1a786671ccc00c9937f044c011
--- /dev/null
+++ b/drivers/cc110x/cc110x-rxtx.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2014 Freie Universität Berlin
+ * Copyright (C) 2013 INRIA
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     drivers_cc110x
+ * @{
+ * @file
+ * @brief       Functions for packet reception and transmission on cc110x devices
+ *
+ * @author      Oliver Hahm <oliver.hahm@inria.fr>
+ * @author      Fabian Nack <nack@inf.fu-berlin.de>
+ * @author      Kaspar Schleiser <kaspar@schleiser.de>
+ * @}
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "cc110x.h"
+#include "cc110x/cc110x-spi.h"
+#include "cc110x/cc110x-internal.h"
+#include "cc110x/cc110x-interface.h"
+#include "cc110x/cc110x-defines.h"
+
+#include "periph/gpio.h"
+#include "irq.h"
+
+#include "kernel_types.h"
+#include "msg.h"
+
+#include "cpu_conf.h"
+#include "cpu.h"
+
+#include "log.h"
+
+#define ENABLE_DEBUG (0)
+#include "debug.h"
+
+static void _rx_abort(cc110x_t *dev)
+{
+    gpio_irq_disable(dev->params.gdo2);
+
+    cc110x_strobe(dev, CC110X_SIDLE);    /* Switch to IDLE (should already be)... */
+    cc110x_strobe(dev, CC110X_SFRX);     /* ...for flushing the RX FIFO */
+
+    cc110x_switch_to_rx(dev);
+}
+
+static void _rx_start(cc110x_t *dev)
+{
+    dev->radio_state = RADIO_RX_BUSY;
+
+    cc110x_pkt_buf_t *pkt_buf = &dev->pkt_buf;
+    pkt_buf->pos = 0;
+
+    gpio_irq_disable(dev->params.gdo2);
+    cc110x_write_reg(dev, CC110X_IOCFG2, 0x01);
+    gpio_irq_enable(dev->params.gdo2);
+}
+
+static void _rx_read_data(cc110x_t *dev, void(*callback)(void*), void*arg)
+{
+    int fifo = cc110x_get_reg_robust(dev, 0xfb);
+
+    if (fifo & 0x80) {
+        DEBUG("%s:%s:%u rx overflow\n", RIOT_FILE_RELATIVE, __func__, __LINE__);
+        _rx_abort(dev);
+        return;
+    }
+
+    if (!fifo) {
+        gpio_irq_enable(dev->params.gdo2);
+        return;
+    }
+
+    cc110x_pkt_buf_t *pkt_buf = &dev->pkt_buf;
+    if (!pkt_buf->pos) {
+        pkt_buf->pos = 1;
+        pkt_buf->packet.length = cc110x_read_reg(dev, CC110X_RXFIFO);
+
+        /* Possible packet received, RX -> IDLE (0.1 us) */
+        dev->cc110x_statistic.packets_in++;
+    }
+
+    int left = pkt_buf->packet.length+1 - pkt_buf->pos;
+
+    /* if the fifo doesn't contain the rest of the packet,
+     * leav at least one byte as per spec sheet. */
+    int to_read = (fifo < left) ? (fifo-1) : fifo;
+    if (to_read > left) {
+        to_read = left;
+    }
+
+    if (to_read) {
+        cc110x_readburst_reg(dev, CC110X_RXFIFO,
+                ((char *)&pkt_buf->packet)+pkt_buf->pos, to_read);
+        pkt_buf->pos += to_read;
+    }
+
+    if (to_read == left) {
+        uint8_t status[2];
+        /* full packet received. */
+        /* Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI) */
+        cc110x_readburst_reg(dev, CC110X_RXFIFO, (char *)status, 2);
+
+        /* Store RSSI value of packet */
+        pkt_buf->rssi = status[I_RSSI];
+
+        /* Bit 0-6 of LQI indicates the link quality (LQI) */
+        pkt_buf->lqi = status[I_LQI] & LQI_EST;
+
+        /* MSB of LQI is the CRC_OK bit */
+        int crc_ok = (status[I_LQI] & CRC_OK) >> 7;
+
+        if (crc_ok) {
+                    LOG_DEBUG("cc110x: received packet from=%u to=%u payload "
+                            "len=%u\n",
+                    (unsigned)pkt_buf->packet.phy_src,
+                    (unsigned)pkt_buf->packet.address,
+                    pkt_buf->packet.length-3);
+            /* let someone know that we've got a packet */
+            callback(arg);
+
+            cc110x_switch_to_rx(dev);
+        }
+        else {
+            DEBUG("%s:%s:%u crc-error\n", RIOT_FILE_RELATIVE, __func__, __LINE__);
+            dev->cc110x_statistic.packets_in_crc_fail++;
+            _rx_abort(dev);
+        }
+    }
+}
+
+static void _rx_continue(cc110x_t *dev, void(*callback)(void*), void*arg)
+{
+
+    if (dev->radio_state != RADIO_RX_BUSY) {
+        DEBUG("%s:%s:%u _rx_continue in invalid state\n", RIOT_FILE_RELATIVE,
+                __func__, __LINE__);
+        _rx_abort(dev);
+        return;
+    }
+
+    gpio_irq_disable(dev->params.gdo2);
+
+    do {
+        _rx_read_data(dev, callback, arg);
+    }
+    while (gpio_read(dev->params.gdo2));
+}
+
+static void _tx_abort(cc110x_t *dev)
+{
+    cc110x_switch_to_rx(dev);
+}
+
+static void _tx_continue(cc110x_t *dev)
+{
+    gpio_irq_disable(dev->params.gdo2);
+
+    cc110x_pkt_t *pkt = &dev->pkt_buf.packet;
+    int size = pkt->length + 1;
+    int left = size - dev->pkt_buf.pos;
+
+    if (!left) {
+        dev->cc110x_statistic.raw_packets_out++;
+
+        LOG_DEBUG("cc110x: packet successfully sent.\n");
+
+        cc110x_switch_to_rx(dev);
+        return;
+    }
+
+    int fifo = 64 - cc110x_get_reg_robust(dev, 0xfa);
+
+    if (fifo & 0x80) {
+        DEBUG("%s:%s:%u tx underflow!\n", RIOT_FILE_RELATIVE, __func__, __LINE__);
+        _tx_abort(dev);
+        return;
+    }
+
+    if (!fifo) {
+        DEBUG("%s:%s:%u fifo full!?\n", RIOT_FILE_RELATIVE, __func__, __LINE__);
+        _tx_abort(dev);
+        return;
+    }
+
+    int to_send = left > fifo ? fifo : left;
+
+    /* Write packet into TX FIFO */
+    cc110x_writeburst_reg(dev, CC110X_TXFIFO, ((char *)pkt)+dev->pkt_buf.pos, to_send);
+    dev->pkt_buf.pos += to_send;
+
+    if (left == size) {
+        /* Switch to TX mode */
+        cc110x_strobe(dev, CC110X_STX);
+    }
+
+    if (to_send < left) {
+        /* set GDO2 to 0x2 -> will deassert at TX FIFO below threshold */
+        gpio_irq_enable(dev->params.gdo2);
+        cc110x_write_reg(dev, CC110X_IOCFG2, 0x02);
+    }
+    else {
+        /* set GDO2 to 0x6 -> will deassert at packet end */
+        cc110x_write_reg(dev, CC110X_IOCFG2, 0x06);
+        gpio_irq_enable(dev->params.gdo2);
+    }
+}
+
+void cc110x_isr_handler(cc110x_t *dev, void(*callback)(void*), void*arg)
+{
+    switch (dev->radio_state) {
+        case RADIO_RX:
+            if (gpio_read(dev->params.gdo2)) {
+                _rx_start(dev);
+            }
+            else {
+                DEBUG("cc110x_isr_handler((): isr handled too slow?\n");
+                _rx_abort(dev);
+            }
+            break;
+        case RADIO_RX_BUSY:
+            _rx_continue(dev, callback, arg);
+            break;
+        case RADIO_TX_BUSY:
+            if (!gpio_read(dev->params.gdo2)) {
+                _tx_continue(dev);
+            }
+            else {
+                DEBUG("cc110x_isr_handler() RADIO_TX_BUSY + GDO2\n");
+            }
+            break;
+        default:
+            DEBUG("%s:%s:%u: unhandled mode\n", RIOT_FILE_RELATIVE,
+                    __func__, __LINE__);
+    }
+}
+
+int cc110x_send(cc110x_t *dev, cc110x_pkt_t *packet)
+{
+    DEBUG("cc110x: snd pkt to %u payload_length=%u\n",
+            (unsigned)packet->address, (unsigned)packet->length-3);
+    uint8_t size;
+
+    switch (dev->radio_state) {
+        case RADIO_RX_BUSY:
+        case RADIO_TX_BUSY:
+            DEBUG("cc110x: invalid state for sending: %s\n",
+                    cc110x_state_to_text(dev->radio_state));
+            return -EAGAIN;
+    }
+
+    /*
+     * Number of bytes to send is:
+     * length of phy payload (packet->length)
+     * + size of length field (1 byte)
+     */
+    size = packet->length + 1;
+
+    if (size > CC110X_PACKET_LENGTH) {
+        DEBUG("%s:%s:%u trying to send oversized packet\n",
+                RIOT_FILE_RELATIVE, __func__, __LINE__);
+        return -ENOSPC;
+    }
+
+    /* set source address */
+    packet->phy_src = dev->radio_address;
+
+    /* Disable RX interrupt */
+    gpio_irq_disable(dev->params.gdo2);
+    dev->radio_state = RADIO_TX_BUSY;
+
+#ifdef MODULE_CC110X_HOOKS
+    cc110x_hook_tx();
+#endif
+
+    cc110x_write_reg(dev, CC110X_IOCFG2, 0x02);
+
+    /* Put CC110x in IDLE mode to flush the FIFO */
+    cc110x_strobe(dev, CC110X_SIDLE);
+    /* Flush TX FIFO to be sure it is empty */
+    cc110x_strobe(dev, CC110X_SFTX);
+
+    memcpy((char*)&dev->pkt_buf.packet, packet, size);
+    dev->pkt_buf.pos = 0;
+
+    _tx_continue(dev);
+
+    return size;
+}
diff --git a/drivers/cc110x/cc110x-spi.c b/drivers/cc110x/cc110x-spi.c
new file mode 100644
index 0000000000000000000000000000000000000000..9c8f0dbc7a554f07cca83c8e42fbdbb21fb11525
--- /dev/null
+++ b/drivers/cc110x/cc110x-spi.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2014 Freie Universität Berlin
+ * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * 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_cc110x
+ * @{
+ *
+ * @file
+ * @brief       TI Chipcon CC110x spi driver
+ *
+ * @author      Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
+ * @author      Heiko Will <hwill@inf.fu-berlin.de>
+ * @author      Fabian Nack <nack@inf.fu-berlin.de>
+ * @author      Joakim Gebart <joakim.gebart@eistec.se>
+ * @author      Kaspar Schleiser <kaspar@schleiser.de>
+ * @}
+ */
+
+#include <stdio.h>
+
+#include "cc110x.h"
+#include "cc110x/cc110x-spi.h"
+#include "cc110x/cc110x-internal.h"
+#include "cc110x/cc110x-defines.h"
+
+#include "periph/gpio.h"
+#include "periph/spi.h"
+
+#include "xtimer.h"
+#include "irq.h"
+
+/**********************************************************************
+ *                      CC110x spi access
+ **********************************************************************/
+
+void cc110x_cs(cc110x_t *dev)
+{
+    volatile int retry_count = 0;
+    /* Switch MISO/GDO1 to GPIO input mode */
+#ifndef GPIO_READS_SPI_PINS
+    gpio_init(dev->params.gdo1, GPIO_DIR_IN, GPIO_NOPULL);
+#endif
+    /* CS to low */
+    gpio_clear(dev->params.cs);
+    /* Wait for SO to go low (voltage regulator
+     * has stabilized and the crystal is running) */
+    while (gpio_read(dev->params.gdo1)) {
+        /* Wait ~500us and try again */
+        xtimer_usleep(CS_SO_WAIT_TIME);
+
+        if (gpio_read(dev->params.gdo1)) {
+            retry_count++;
+
+            if (retry_count > CC110X_GDO1_LOW_RETRY) {
+                puts("[CC110X spi] fatal error\n");
+                break;
+            }
+
+            gpio_set(dev->params.cs);
+            gpio_clear(dev->params.cs);
+        }
+    }
+    /* Switch MISO/GDO1 to spi mode */
+#ifndef GPIO_READS_SPI_PINS
+    spi_conf_pins(dev->params.spi);
+#endif
+}
+
+void cc110x_writeburst_reg(cc110x_t *dev, uint8_t addr, const char *src, uint8_t count)
+{
+    unsigned int cpsr;
+    spi_acquire(dev->params.spi);
+    cpsr = disableIRQ();
+    cc110x_cs(dev);
+    spi_transfer_regs(dev->params.spi, addr | CC110X_WRITE_BURST, (char *)src, 0, count);
+    gpio_set(dev->params.cs);
+    restoreIRQ(cpsr);
+    spi_release(dev->params.spi);
+}
+
+void cc110x_readburst_reg(cc110x_t *dev, uint8_t addr, char *buffer, uint8_t count)
+{
+    int i = 0;
+    unsigned int cpsr;
+    spi_acquire(dev->params.spi);
+    cpsr = disableIRQ();
+    cc110x_cs(dev);
+    spi_transfer_byte(dev->params.spi, addr | CC110X_READ_BURST, 0);
+    while (i < count) {
+        spi_transfer_byte(dev->params.spi, CC110X_NOBYTE, &buffer[i]);
+        i++;
+    }
+    gpio_set(dev->params.cs);
+    restoreIRQ(cpsr);
+    spi_release(dev->params.spi);
+}
+
+void cc110x_write_reg(cc110x_t *dev, uint8_t addr, uint8_t value)
+{
+    unsigned int cpsr;
+    spi_acquire(dev->params.spi);
+    cpsr = disableIRQ();
+    cc110x_cs(dev);
+    spi_transfer_reg(dev->params.spi, addr, value, 0);
+    gpio_set(dev->params.cs);
+    restoreIRQ(cpsr);
+    spi_release(dev->params.spi);
+}
+
+uint8_t cc110x_read_reg(cc110x_t *dev, uint8_t addr)
+{
+    char result;
+    unsigned int cpsr;
+    spi_acquire(dev->params.spi);
+    cpsr = disableIRQ();
+    cc110x_cs(dev);
+    spi_transfer_reg(dev->params.spi, addr | CC110X_READ_SINGLE, CC110X_NOBYTE, &result);
+    gpio_set(dev->params.cs);
+    restoreIRQ(cpsr);
+    spi_release(dev->params.spi);
+    return (uint8_t) result;
+}
+
+uint8_t cc110x_read_status(cc110x_t *dev, uint8_t addr)
+{
+    char result;
+    unsigned int cpsr;
+    spi_acquire(dev->params.spi);
+    cpsr = disableIRQ();
+    cc110x_cs(dev);
+    spi_transfer_reg(dev->params.spi, addr | CC110X_READ_BURST, CC110X_NOBYTE, &result);
+    gpio_set(dev->params.cs);
+    restoreIRQ(cpsr);
+    spi_release(dev->params.spi);
+    return (uint8_t) result;
+}
+
+uint8_t cc110x_get_reg_robust(cc110x_t *dev, uint8_t addr)
+{
+    char result, result2;
+    unsigned int cpsr;
+    spi_acquire(dev->params.spi);
+    cpsr = disableIRQ();
+    cc110x_cs(dev);
+    do {
+        spi_transfer_reg(dev->params.spi, addr | CC110X_READ_BURST, CC110X_NOBYTE, &result);
+        spi_transfer_reg(dev->params.spi, addr | CC110X_READ_BURST, CC110X_NOBYTE, &result2);
+    } while (result != result2);
+    gpio_set(dev->params.cs);
+    restoreIRQ(cpsr);
+    spi_release(dev->params.spi);
+    return (uint8_t) result;
+}
+
+uint8_t cc110x_strobe(cc110x_t *dev, uint8_t c)
+{
+#ifdef CC110X_DONT_RESET
+    if (c == CC110X_SRES) {
+        return 0;
+    }
+#endif
+
+    char result;
+    unsigned int cpsr;
+    spi_acquire(dev->params.spi);
+    cpsr = disableIRQ();
+    cc110x_cs(dev);
+    spi_transfer_byte(dev->params.spi, c, &result);
+    gpio_set(dev->params.cs);
+    restoreIRQ(cpsr);
+    spi_release(dev->params.spi);
+    return (uint8_t) result;
+}
diff --git a/drivers/cc110x/cc110x.c b/drivers/cc110x/cc110x.c
new file mode 100644
index 0000000000000000000000000000000000000000..bb965d4f32211e23c8f26094281f673e0825bdbd
--- /dev/null
+++ b/drivers/cc110x/cc110x.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2014 Freie Universität Berlin
+ * Copyright (C) 2013 INRIA
+ * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * 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_cc110x
+ * @{
+ * @file
+ * @brief       Basic functionality of cc110x driver
+ *
+ * @author      Oliver Hahm <oliver.hahm@inria.fr>
+ * @author      Fabian Nack <nack@inf.fu-berlin.de>
+ * @author      Kaspar Schleiser <kaspar@schleiser.de>
+ * @}
+ */
+
+#include "board.h"
+#include "periph/cpuid.h"
+#include "periph/gpio.h"
+#include "periph/spi.h"
+#include "xtimer.h"
+#include "cpu.h"
+#include "log.h"
+
+#include "cc110x.h"
+#include "cc110x/cc110x-defaultsettings.h"
+#include "cc110x/cc110x-defines.h"
+#include "cc110x/cc110x-interface.h"
+#include "cc110x/cc110x-internal.h"
+#include "cc110x/cc110x-spi.h"
+
+#define ENABLE_DEBUG    (0)
+#include "debug.h"
+
+/* Internal function prototypes */
+#ifndef CC110X_DONT_RESET
+static void _reset(cc110x_t *dev);
+static void _power_up_reset(cc110x_t *dev);
+#endif
+
+int cc110x_setup(cc110x_t *dev, const cc110x_params_t *params)
+{
+    DEBUG("%s:%s:%u\n", RIOT_FILE_RELATIVE, __func__, __LINE__);
+
+#ifdef MODULE_CC110X_HOOKS
+    cc110x_hooks_init();
+#endif
+
+    dev->params = *params;
+
+    /* Configure chip-select */
+    gpio_init(dev->params.cs, GPIO_DIR_OUT, GPIO_NOPULL);
+    gpio_set(dev->params.cs);
+
+    /* Configure GDO1 */
+    gpio_init(dev->params.gdo1, GPIO_DIR_IN, GPIO_NOPULL);
+
+    /* Configure SPI */
+    spi_acquire(dev->params.spi);
+    spi_init_master(dev->params.spi, SPI_CONF_FIRST_RISING, SPI_SPEED_5MHZ);
+    spi_release(dev->params.spi);
+
+#ifndef CC110X_DONT_RESET
+    /* reset device*/
+    _power_up_reset(dev);
+#endif
+
+    /* set default state */
+    dev->radio_state = RADIO_IDLE;
+
+    /* Write configuration to configuration registers */
+    cc110x_writeburst_reg(dev, 0x00, cc110x_default_conf, cc110x_default_conf_size);
+
+    /* Write PATABLE (power settings) */
+    cc110x_writeburst_reg(dev, CC110X_PATABLE, CC110X_DEFAULT_PATABLE, 8);
+
+    /* set base frequency */
+    cc110x_set_base_freq_raw(dev, CC110X_DEFAULT_FREQ);
+
+    /* Set default channel number */
+    cc110x_set_channel(dev, CC110X_DEFAULT_CHANNEL);
+
+    /* set default node id */
+#ifdef CPUID_ID_LEN
+    if (CPUID_ID_LEN>0) {
+        char cpuid[CPUID_ID_LEN];
+        cpuid_get(cpuid);
+        cc110x_set_address(dev, (uint8_t) cpuid[CPUID_ID_LEN-1]);
+    }
+#endif
+
+    LOG_INFO("cc110x: initialized with address=%u and channel=%i\n",
+            (unsigned)dev->radio_address,
+            dev->radio_channel);
+
+    return 0;
+}
+
+uint8_t cc110x_set_address(cc110x_t *dev, uint8_t address)
+{
+    DEBUG("%s:%s:%u setting address %u\n", RIOT_FILE_RELATIVE, __func__,
+            __LINE__, (unsigned)address);
+    if (!(address < MIN_UID) || (address > MAX_UID)) {
+        if (dev->radio_state != RADIO_UNKNOWN) {
+            cc110x_write_register(dev, CC110X_ADDR, address);
+            dev->radio_address = address;
+            return address;
+        }
+    }
+
+    return 0;
+}
+
+void cc110x_set_base_freq_raw(cc110x_t *dev, const char* freq_array)
+{
+#if ENABLE_DEBUG == 1
+    uint8_t _tmp[] = { freq_array[2], freq_array[1], freq_array[0], 0x00};
+    uint32_t *FREQ = (uint32_t*) _tmp;
+
+    DEBUG("cc110x_set_base_freq_raw(): setting base frequency to %uHz\n",
+            (26000000>>16) * (unsigned)(*FREQ));
+#endif
+    cc110x_writeburst_reg(dev, CC110X_FREQ2, freq_array, 3);
+}
+
+void cc110x_set_monitor(cc110x_t *dev, uint8_t mode)
+{
+    DEBUG("%s:%s:%u\n", RIOT_FILE_RELATIVE, __func__, __LINE__);
+
+    cc110x_write_register(dev, CC110X_PKTCTRL1, mode ? 0x04 : 0x06);
+}
+
+void cc110x_setup_rx_mode(cc110x_t *dev)
+{
+    DEBUG("%s:%s:%u\n", RIOT_FILE_RELATIVE, __func__, __LINE__);
+
+    /* Stay in RX mode until end of packet */
+    cc110x_write_reg(dev, CC110X_MCSM2, 0x07);
+    cc110x_switch_to_rx(dev);
+}
+
+void cc110x_switch_to_rx(cc110x_t *dev)
+{
+    DEBUG("%s:%s:%u\n", RIOT_FILE_RELATIVE, __func__, __LINE__);
+
+#ifdef MODULE_CC110X_HOOKS
+    cc110x_hook_rx();
+#endif
+
+    gpio_irq_disable(dev->params.gdo2);
+
+    /* flush RX fifo */
+    cc110x_strobe(dev, CC110X_SIDLE);
+    cc110x_strobe(dev, CC110X_SFRX);
+
+    dev->radio_state = RADIO_RX;
+
+    cc110x_write_reg(dev, CC110X_IOCFG2, 0x6);
+    cc110x_strobe(dev, CC110X_SRX);
+
+    gpio_irq_enable(dev->params.gdo2);
+}
+
+void cc110x_wakeup_from_rx(cc110x_t *dev)
+{
+    if (dev->radio_state != RADIO_RX) {
+        return;
+    }
+
+    LOG_DEBUG("cc110x: switching to idle mode\n");
+
+    cc110x_strobe(dev, CC110X_SIDLE);
+    dev->radio_state = RADIO_IDLE;
+}
+
+void cc110x_switch_to_pwd(cc110x_t *dev)
+{
+    LOG_DEBUG("cc110x: switching to powerdown mode\n");
+    cc110x_wakeup_from_rx(dev);
+    cc110x_strobe(dev, CC110X_SPWD);
+    dev->radio_state = RADIO_PWD;
+
+#ifdef MODULE_CC110X_HOOKS
+     cc110x_hook_off();
+#endif
+}
+
+#ifndef MODULE_CC110X_HOOKS
+int16_t cc110x_set_channel(cc110x_t *dev, uint8_t channr)
+{
+    DEBUG("%s:%s:%u\n", RIOT_FILE_RELATIVE, __func__, __LINE__);
+
+    if (channr > MAX_CHANNR) {
+        return -1;
+    }
+
+    cc110x_write_register(dev, CC110X_CHANNR, channr * 10);
+    dev->radio_channel = channr;
+
+    return channr;
+}
+#endif
+
+#ifndef CC110X_DONT_RESET
+static void _reset(cc110x_t *dev)
+{
+    DEBUG("%s:%s:%u\n", RIOT_FILE_RELATIVE, __func__, __LINE__);
+    cc110x_wakeup_from_rx(dev);
+    cc110x_cs(dev);
+    cc110x_strobe(dev, CC110X_SRES);
+    xtimer_usleep(100);
+}
+
+static void _power_up_reset(cc110x_t *dev)
+{
+    DEBUG("%s:%s:%u\n", RIOT_FILE_RELATIVE, __func__, __LINE__);
+    gpio_set(dev->params.cs);
+    gpio_clear(dev->params.cs);
+    gpio_set(dev->params.cs);
+    xtimer_usleep(RESET_WAIT_TIME);
+    _reset(dev);
+}
+#endif
+
+void cc110x_write_register(cc110x_t *dev, uint8_t r, uint8_t value)
+{
+    /* Save old radio state */
+    uint8_t old_state = dev->radio_state;
+
+    /* Wake up from RX (no effect if in other mode) */
+    cc110x_wakeup_from_rx(dev);
+    cc110x_write_reg(dev, r, value);
+
+    /* Have to put radio back to RX if old radio state
+     * was RX, otherwise no action is necessary */
+    if (old_state == RADIO_RX) {
+        cc110x_switch_to_rx(dev);
+    }
+}
+
+int cc110x_rd_set_mode(cc110x_t *dev, int mode)
+{
+    DEBUG("%s:%s:%u\n", RIOT_FILE_RELATIVE, __func__, __LINE__);
+
+    int result;
+
+    /* Get current radio mode */
+    if ((dev->radio_state == RADIO_UNKNOWN) || (dev->radio_state == RADIO_PWD)) {
+        result = RADIO_MODE_OFF;
+    }
+    else {
+        result = RADIO_MODE_ON;
+    }
+
+    switch(mode) {
+        case RADIO_MODE_ON:
+            LOG_DEBUG("cc110x: switching to RX mode\n");
+            cc110x_setup_rx_mode(dev);          /* Set chip to desired mode */
+            break;
+
+        case RADIO_MODE_OFF:
+            gpio_irq_disable(dev->params.gdo2); /* Disable interrupts */
+            cc110x_switch_to_pwd(dev);          /* Set chip to power down mode */
+            break;
+
+        case RADIO_MODE_GET:
+            /* do nothing, just return current mode */
+        default:
+            /* do nothing */
+            break;
+    }
+
+    /* Return previous mode */
+    return result;
+}
diff --git a/drivers/cc110x/gnrc_cc110x/Makefile b/drivers/cc110x/gnrc_cc110x/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..48422e909a47d7cd428d10fa73825060ccc8d8c2
--- /dev/null
+++ b/drivers/cc110x/gnrc_cc110x/Makefile
@@ -0,0 +1 @@
+include $(RIOTBASE)/Makefile.base
diff --git a/drivers/cc110x/gnrc_cc110x/gnrc_netdev2_cc110x.c b/drivers/cc110x/gnrc_cc110x/gnrc_netdev2_cc110x.c
new file mode 100644
index 0000000000000000000000000000000000000000..d8de98c55ca41639326f8602c0409662a54c20d2
--- /dev/null
+++ b/drivers/cc110x/gnrc_cc110x/gnrc_netdev2_cc110x.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * 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.
+ */
+
+#include <assert.h>
+
+#include <sys/uio.h>
+
+#include "net/netdev2.h"
+#include "net/gnrc.h"
+#include "cc110x.h"
+#include "cc110x/cc110x-netdev2.h"
+#include "net/gnrc/gnrc_netdev2.h"
+#include "od.h"
+
+#define ENABLE_DEBUG    (0)
+#include "debug.h"
+
+static int _send(gnrc_netdev2_t *gnrc_netdev2, gnrc_pktsnip_t *pkt)
+{
+    cc110x_pkt_t cc110x_pkt;
+    netdev2_t *dev = gnrc_netdev2->dev;
+    netdev2_cc110x_t *netdev_cc110x = (netdev2_cc110x_t *) dev;
+    cc110x_t *cc110x = &netdev_cc110x->cc110x;
+
+    assert(pkt != NULL);
+    assert(dev->driver == &netdev2_cc110x_driver);
+
+    gnrc_netif_hdr_t *netif_hdr;
+    gnrc_pktsnip_t *payload;
+
+    payload = pkt->next;
+
+    if (pkt->type != GNRC_NETTYPE_NETIF) {
+        DEBUG("gnrc_netdev2_cc110x: First header was not generic netif header\n");
+        gnrc_pktbuf_release(pkt);
+        return -EBADMSG;
+    }
+
+    netif_hdr = (gnrc_netif_hdr_t *) pkt->data;
+
+    /* set up header */
+    if (netif_hdr->src_l2addr_len == 1) {
+        uint8_t *_src_addr = gnrc_netif_hdr_get_src_addr(netif_hdr);
+        cc110x_pkt.phy_src = *_src_addr;
+    }
+    else {
+        cc110x_pkt.phy_src = cc110x->radio_address;
+    }
+
+    if (netif_hdr->flags & (GNRC_NETIF_HDR_FLAGS_BROADCAST |
+                GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
+        cc110x_pkt.address = 0;
+    }
+    else {
+        uint8_t *_dst_addr = gnrc_netif_hdr_get_dst_addr(netif_hdr);
+        cc110x_pkt.address = _dst_addr[netif_hdr->dst_l2addr_len-1];
+    }
+
+    switch (payload->type) {
+#ifdef MODULE_GNRC_SIXLOWPAN
+        case GNRC_NETTYPE_SIXLOWPAN:
+            cc110x_pkt.flags = 1;
+            break;
+#endif
+        default:
+            cc110x_pkt.flags = 0;
+    }
+
+    struct iovec vector;
+    vector.iov_base = (char*)&cc110x_pkt;
+    vector.iov_len = sizeof(cc110x_pkt_t);
+
+    unsigned payload_len = 0;
+    uint8_t *pos = cc110x_pkt.data;
+
+    while (payload) {
+        payload_len += payload->size;
+
+        if (payload_len > CC110X_MAX_DATA_LENGTH) {
+            DEBUG("gnrc_netdev2_cc110x: payload length exceeds maximum"
+                    "(%u>%u)\n", payload_len, CC110X_MAX_DATA_LENGTH);
+            gnrc_pktbuf_release(pkt);
+            return -EBADMSG;
+        }
+
+        memcpy(pos, payload->data, payload->size);
+        pos += payload->size;
+        payload = payload->next;
+    }
+
+    /* pkt has been copied into iovec, we're done with it. */
+    gnrc_pktbuf_release(pkt);
+
+    cc110x_pkt.length = (uint8_t) payload_len + CC110X_HEADER_LENGTH;
+
+    DEBUG("gnrc_netdev2_cc110x: sending packet from %u to %u with payload "
+            "length %u\n",
+            (unsigned)cc110x_pkt.phy_src,
+            (unsigned)cc110x_pkt.address,
+            (unsigned)cc110x_pkt.length);
+
+    return dev->driver->send(dev, &vector, 1);
+}
+
+static gnrc_pktsnip_t *_recv(gnrc_netdev2_t *gnrc_netdev2)
+{
+    netdev2_t *dev = gnrc_netdev2->dev;
+    cc110x_t *cc110x = &((netdev2_cc110x_t*) dev)->cc110x;
+
+    cc110x_pkt_t *cc110x_pkt = &cc110x->pkt_buf.packet;
+
+    int payload_length = cc110x_pkt->length - CC110X_HEADER_LENGTH;
+
+    int nettype;
+
+    int addr_len;
+    switch (cc110x_pkt->flags) {
+#ifdef MODULE_GNRC_SIXLOWPAN
+        case 1:
+            addr_len = 8;
+            nettype = GNRC_NETTYPE_SIXLOWPAN;
+            break;
+#endif
+        default:
+            addr_len = 1;
+            nettype = GNRC_NETTYPE_UNDEF;
+    }
+
+    /* copy packet payload into pktbuf */
+    gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, cc110x_pkt->data,
+            payload_length, nettype);
+
+    if(!pkt) {
+        DEBUG("cc110x: _recv: cannot allocate pktsnip.\n");
+        return NULL;
+    }
+
+
+    gnrc_pktsnip_t *netif_hdr;
+    netif_hdr = gnrc_pktbuf_add(NULL, NULL,
+            sizeof(gnrc_netif_hdr_t) + 2*addr_len,
+            GNRC_NETTYPE_NETIF);
+
+    if (netif_hdr == NULL) {
+        DEBUG("gnrc_netdev2_cc110x: no space left in packet buffer\n");
+        gnrc_pktbuf_release(pkt);
+        return NULL;
+    }
+
+    gnrc_netif_hdr_init(netif_hdr->data, addr_len, addr_len);
+    if (addr_len == 8) {
+        uint64_t src_addr = cc110x_pkt->phy_src;
+        uint64_t dst_addr = cc110x_pkt->address;
+        gnrc_netif_hdr_set_src_addr(netif_hdr->data, (uint8_t*)&src_addr, addr_len);
+        gnrc_netif_hdr_set_dst_addr(netif_hdr->data, (uint8_t*)&dst_addr, addr_len);
+    }
+    else {
+        gnrc_netif_hdr_set_src_addr(netif_hdr->data, (uint8_t*)&cc110x_pkt->phy_src, addr_len);
+        gnrc_netif_hdr_set_dst_addr(netif_hdr->data, (uint8_t*)&cc110x_pkt->address, addr_len);
+    }
+
+    ((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = thread_getpid();
+    ((gnrc_netif_hdr_t *)netif_hdr->data)->lqi = cc110x->pkt_buf.lqi;
+    ((gnrc_netif_hdr_t *)netif_hdr->data)->rssi = cc110x->pkt_buf.rssi;
+
+    DEBUG("gnrc_netdev2_cc110x: received packet from %02x"
+            " of length %u\n",
+            (unsigned)cc110x_pkt->phy_src,
+            (unsigned)cc110x_pkt->length-CC110X_HEADER_LENGTH);
+#if defined(MODULE_OD) && ENABLE_DEBUG
+    od_hex_dump(cc110x_pkt->data, payload_length, OD_WIDTH_DEFAULT);
+#endif
+
+
+    pkt->next = netif_hdr;
+
+    return pkt;
+}
+
+int gnrc_netdev2_cc110x_init(gnrc_netdev2_t *gnrc_netdev2, netdev2_t *dev)
+{
+    gnrc_netdev2->send = _send;
+    gnrc_netdev2->recv = _recv;
+    gnrc_netdev2->dev = dev;
+
+    return 0;
+}
diff --git a/drivers/include/cc110x.h b/drivers/include/cc110x.h
new file mode 100644
index 0000000000000000000000000000000000000000..a5df225ed26e204c19f6978e7bd2a68f7ab580dc
--- /dev/null
+++ b/drivers/include/cc110x.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2014 Freie Universität Berlin
+ *               2015 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup    drivers_cc110x CC110x
+ * @ingroup     drivers
+ * @brief       TI CC110x
+ * @{
+ * @file
+ * @brief       Public interface for cc110x driver
+ * @author      Kaspar Schleiser <kaspar@schleiser.de>
+ */
+
+#ifndef CC110X_H
+#define CC110X_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "periph/spi.h"
+#include "periph/gpio.h"
+#include "cc110x/cc110x-internal.h"
+
+/**
+ * @brief Struct for holding cc110x IO parameters
+ */
+typedef struct cc110x_params {
+    spi_t spi;          /**< what */
+    gpio_t cs;          /**< does */
+    gpio_t gdo0;        /**< this */
+    gpio_t gdo1;        /**< look */
+    gpio_t gdo2;        /**< like */
+} cc110x_params_t;
+
+/**
+ * @brief forward declaration
+ */
+typedef struct cc110x cc110x_t;
+
+/**
+ * @brief Struct for holding cc110x device state
+ */
+struct cc110x {
+    cc110x_params_t params;                     /**< cc110x IO configuration */
+
+    cc110x_statistic_t cc110x_statistic;        /**< Statistic values for
+                                                     debugging */
+
+    uint8_t radio_state;                        /**< Radio state */
+    uint8_t radio_channel;                      /**< current Radio channel */
+    uint8_t radio_address;                      /**< current Radio address */
+
+    cc110x_pkt_buf_t pkt_buf;                   /**< RX/TX buffer */
+    void (*isr_cb)(cc110x_t *dev, void* arg);   /**< isr callback */
+    void *isr_cb_arg;                           /**< isr callback argument */
+};
+
+/**
+ * @brief Setup cc110x device parameters
+ *
+ * @param[in] dev       device struct to set up
+ * @param[in] params    struct holding parameters
+ *
+ * @return always succeeds
+ */
+int cc110x_setup(cc110x_t *dev, const cc110x_params_t *params);
+
+/**
+ * @brief Set cc110x channel number
+ *
+ * @param[in] dev       device to work on
+ * @param[in] channr    guess what
+ *
+ * @return nr of set channel on success
+ * @return -1 on error
+ */
+int16_t cc110x_set_channel(cc110x_t *dev, uint8_t channr);
+
+
+/**
+ * @brief Send raw cc110x packet
+ *
+ * @param[in] dev       Device to send on
+ * @param[in] packet    ptr to packet to be sent
+ *
+ * @return size of packet on success
+ * @return <0 on error
+ */
+int cc110x_send(cc110x_t *dev, cc110x_pkt_t *packet);
+
+/**
+ * @brief Set cc110x radio address
+ *
+ * @param[in] dev   device to query
+ *
+ * @return nr of currently set address
+ */
+uint8_t cc110x_get_address(cc110x_t *dev);
+
+/**
+ * @brief Set cc110x radio address
+ *
+ * @param[in] dev       device to work on
+ * @param[in] address   new address
+ *
+ * @return address set on success
+ * @return 0 on error
+ */
+uint8_t cc110x_set_address(cc110x_t *dev, uint8_t address);
+
+
+/**
+ * @brief Set cc110x monitor mode setting
+ *
+ * @param[in] dev   device to work on
+ * @param[in] mode  mode to set (0 or 1)
+ */
+void cc110x_set_monitor(cc110x_t *dev, uint8_t mode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CC110X_H */
+/** @} */
diff --git a/drivers/include/cc110x/cc110x-defaultsettings.h b/drivers/include/cc110x/cc110x-defaultsettings.h
new file mode 100644
index 0000000000000000000000000000000000000000..7161c33e4b872b0f34f01fdec1f7acf6caee6c78
--- /dev/null
+++ b/drivers/include/cc110x/cc110x-defaultsettings.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * 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   driver_cc110x
+ * @{
+ *
+ * @file
+ * @brief     cc110x default settings override
+ *
+ * By setting either CC110X_DEFAULT_PATABLE or CC110X_DEFAULT_FREQ in board.h,
+ * it is possible to override the default pa table or base frequency registers
+ * on a per-device basis.
+ *
+ * @author    Kaspar Schleiser <kaspar@schleiser.de>
+ */
+#ifndef CC110X_DEFAULTSETTINGS_H
+#define CC110X_DEFAULTSETTINGS_H
+
+#include "board.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef CC110X_DEFAULT_PATABLE
+#define CC110X_DEFAULT_PATABLE cc110x_default_pa_table
+extern const char cc110x_default_pa_table[8];
+#endif
+
+#ifndef CC110X_DEFAULT_FREQ
+#define CC110X_DEFAULT_FREQ cc110x_default_base_freq
+extern const char cc110x_default_base_freq[3];
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CC110X_DEFAULTSETTINGS_H */
+/** @} */
diff --git a/drivers/include/cc110x/cc110x-defines.h b/drivers/include/cc110x/cc110x-defines.h
new file mode 100644
index 0000000000000000000000000000000000000000..1c1966ef832296595c524d771730ecec8599f836
--- /dev/null
+++ b/drivers/include/cc110x/cc110x-defines.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2008 Freie Universität Berlin
+ * Copyright (C) 2013 INRIA
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     drivers_cc110x
+ * @{
+ *
+ * @file
+ * @brief       Driver internal constants for CC110x chip configuration
+ *
+ * @author      Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
+ * @author      Heiko Will <hwill@inf.fu-berlin.de>
+ * @author      Oliver Hahm <oliver.hahm@inria.fr>
+ */
+
+#ifndef CC110X_DEFINES_H
+#define CC110X_DEFINES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief   Variable packet length PKTCTRL0 bit configuration
+ *
+ * If variable packet length is configured in PKTCTRL0 the
+ * first byte after the synch word determines the packet length.
+ */
+#define VARIABLE_PKTLEN     (0x01)
+
+/**
+ * @name    Bitmasks for reading out status register values
+ * @{
+ */
+
+/**
+ * @brief   Bitmask (=10000000) for reading CRC_OK.
+ *
+ * If CRC_OK == 1: CRC for received data OK (or CRC disabled).
+ * If CRC_OK == 0: CRC error in received data.
+ */
+#define CRC_OK              (0x80)
+/**
+ * @brief  Bitmask (=01111111) for reading LQI_EST.
+ *
+ * The Link Quality Indicator estimates how easily a received signal can be demodulated.
+ */
+#define LQI_EST                 (0x7F)
+#define I_RSSI                  (0x00)  /**< Index 0 contains RSSI information (from optionally appended packet status bytes). */
+#define I_LQI                   (0x01)  /**< Index 1 contains LQI & CRC_OK information (from optionally appended packet status bytes). */
+#define MARC_STATE              (0x1F)  /**< Bitmask (=00011111) for reading MARC_STATE in MARCSTATE status register. */
+#define PKTSTATUS_CS            (0x40)  /**< Bitmask (=01000000) for reading CS (Carrier Sense) in PKTSTATUS status register. */
+#define PKTSTATUS_PQT_REACHED   (0x20)  /**< Bitmask (=00100000) for reading PQT_REACHED (Preamble Quality reached) in PKTSTATUS status register. */
+#define PKTSTATUS_CCA           (0x10)  /**< Bitmask (=00010000) for reading CCA (clear channel assessment) in PKTSTATUS status register. */
+#define PKTSTATUS_SFD           (0x08)  /**< Bitmask (=00001000) for reading SFD (Sync word found) in PKTSTATUS status register. */
+#define PKTSTATUS_GDO2          (0x04)  /**< Bitmask (=00000100) for reading GDO2 (current value on GDO2 pin) in PKTSTATUS status register. */
+#define PKTSTATUS_GDO1          (0x02)  /**< Bitmask (=00000010) for reading GDO1 (current value on GDO1 pin) in PKTSTATUS status register. */
+#define PKTSTATUS_GDO0          (0x01)  /**< Bitmask (=00000001) for reading GDO0 (current value on GDO0 pin) in PKTSTATUS status register. */
+#define TXFIFO_UNDERFLOW        (0x80)  /**< Bitmask (=10000000) for reading TXFIFO_UNDERFLOW in TXBYTES status register. */
+#define BYTES_IN_TXFIFO         (0x7F)  /**< Bitmask (=01111111) for reading NUM_TXBYTES in TXBYTES status register. */
+#define RXFIFO_OVERFLOW         (0x80)  /**< Bitmask (=10000000) for reading RXFIFO_OVERFLOW in RXBYTES status register. */
+#define BYTES_IN_RXFIFO         (0x7F)  /**< Bitmask (=01111111) for reading NUM_RXBYTES in RXBYTES status register. */
+/** @} */
+
+/**
+ * @name    Bitmasks for reading out configuration register values
+ * @{
+ */
+#define PKT_LENGTH_CONFIG   (0x03)      /**< Bitmask (=00000011) for reading LENGTH_CONFIG in PKTCTRL0 configuration register. */
+/** @} */
+
+/**
+ * @name    Definitions to support burst/single access
+ * @{
+ */
+#define CC110X_WRITE_BURST  (0x40) /**< Offset for burst write. */
+#define CC110X_READ_SINGLE  (0x80) /**< Offset for read single byte. */
+#define CC110X_READ_BURST   (0xC0) /**< Offset for read burst. */
+#define CC110X_NOBYTE       (0xFF) /**< No command (for reading). */
+/** @} */
+
+/**
+ * @name    Configuration Registers (47x)
+ * @{
+ */
+#define CC110X_IOCFG2       (0x00)      /**< GDO2 output pin configuration */
+#define CC110X_IOCFG1       (0x01)      /**< GDO1 output pin configuration */
+#define CC110X_IOCFG0       (0x02)      /**< GDO0 output pin configuration */
+#define CC110X_FIFOTHR      (0x03)      /**< RX FIFO and TX FIFO thresholds */
+#define CC110X_SYNC1        (0x04)      /**< Sync word, high byte */
+#define CC110X_SYNC0        (0x05)      /**< Sync word, low byte */
+#define CC110X_PKTLEN       (0x06)      /**< Packet length */
+#define CC110X_PKTCTRL1     (0x07)      /**< Packet automation control */
+#define CC110X_PKTCTRL0     (0x08)      /**< Packet automation control */
+#define CC110X_ADDR         (0x09)      /**< Device address */
+#define CC110X_CHANNR       (0x0A)      /**< Channel number */
+#define CC110X_FSCTRL1      (0x0B)      /**< Frequency synthesizer control */
+#define CC110X_FSCTRL0      (0x0C)      /**< Frequency synthesizer control */
+#define CC110X_FREQ2        (0x0D)      /**< Frequency control word, high byte */
+#define CC110X_FREQ1        (0x0E)      /**< Frequency control word, middle byte */
+#define CC110X_FREQ0        (0x0F)      /**< Frequency control word, low byte */
+#define CC110X_MDMCFG4      (0x10)      /**< Modem configuration */
+#define CC110X_MDMCFG3      (0x11)      /**< Modem configuration */
+#define CC110X_MDMCFG2      (0x12)      /**< Modem configuration */
+#define CC110X_MDMCFG1      (0x13)      /**< Modem configuration */
+#define CC110X_MDMCFG0      (0x14)      /**< Modem configuration */
+#define CC110X_DEVIATN      (0x15)      /**< Modem deviation setting */
+#define CC110X_MCSM2        (0x16)      /**< Main Radio Control State Machine configuration */
+#define CC110X_MCSM1        (0x17)      /**< Main Radio Control State Machine configuration */
+#define CC110X_MCSM0        (0x18)      /**< Main Radio Control State Machine configuration */
+#define CC110X_FOCCFG       (0x19)      /**< Frequency Offset Compensation configuration */
+#define CC110X_BSCFG        (0x1A)      /**< Bit Synchronization configuration */
+#define CC110X_AGCCTRL2     (0x1B)      /**< AGC control */
+#define CC110X_AGCCTRL1     (0x1C)      /**< AGC control */
+#define CC110X_AGCCTRL0     (0x1D)      /**< AGC control */
+#define CC110X_WOREVT1      (0x1E)      /**< High byte Event 0 timeout */
+#define CC110X_WOREVT0      (0x1F)      /**< Low byte Event 0 timeout */
+#define CC110X_WORCTRL      (0x20)      /**< Wake On Radio control */
+#define CC110X_FREND1       (0x21)      /**< Front end RX configuration */
+#define CC110X_FREND0       (0x22)      /**< Front end TX configuration */
+#define CC110X_FSCAL3       (0x23)      /**< Frequency synthesizer calibration */
+#define CC110X_FSCAL2       (0x24)      /**< Frequency synthesizer calibration */
+#define CC110X_FSCAL1       (0x25)      /**< Frequency synthesizer calibration */
+#define CC110X_FSCAL0       (0x26)      /**< Frequency synthesizer calibration */
+#define CC110X_RCCTRL1      (0x27)      /**< RC oscillator configuration */
+#define CC110X_RCCTRL0      (0x28)      /**< RC oscillator configuration */
+#define CC110X_FSTEST       (0x29)      /**< Frequency synthesizer calibration control */
+#define CC110X_PTEST        (0x2A)      /**< Production test */
+#define CC110X_AGCTEST      (0x2B)      /**< AGC test */
+#define CC110X_TEST2        (0x2C)      /**< Various test settings */
+#define CC110X_TEST1        (0x2D)      /**< Various test settings */
+#define CC110X_TEST0        (0x2E)      /**< Various test settings */
+/** @} */
+
+/**
+ * @name    Strobe commands (14x)
+ * @{
+ */
+#define CC110X_SRES         (0x30)      /**< Reset chip. */
+/**
+ * @brief   Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1).
+ *
+ * If in RX/TX: Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround).
+ */
+#define CC110X_SFSTXON      (0x31)
+#define CC110X_SXOFF        (0x32)      /**< Turn off crystal oscillator. */
+#define CC110X_SCAL         (0x33)      /**< Calibrate frequency synthesizer and turn it off (enables quick start). */
+#define CC110X_SRX          (0x34)      /**< Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1. */
+/**
+ * In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1.
+ * If in RX state and CCA is enabled: Only go to TX if channel is clear.
+ */
+#define CC110X_STX          (0x35)
+#define CC110X_SIDLE        (0x36)      /**< Exit RX / TX, turn off frequency synthesizer and exit WOR mode if applicable. */
+#define CC110X_SAFC         (0x37)      /**< Perform AFC adjustment of the frequency synthesizer */
+#define CC110X_SWOR         (0x38)      /**< Start automatic RX polling sequence (Wake-on-Radio) */
+#define CC110X_SPWD         (0x39)      /**< Enter power down mode when CSn goes high. */
+#define CC110X_SFRX         (0x3A)      /**< Flush the RX FIFO buffer (CC110X should be in IDLE state). */
+#define CC110X_SFTX         (0x3B)      /**< Flush the TX FIFO buffer (CC110X should be in IDLE state). */
+#define CC110X_SWORRST      (0x3C)      /**< Reset real time clock. */
+#define CC110X_SNOP         (0x3D)      /**< No operation. May be used to pad strobe commands to two bytes for simpler software. */
+/** @} */
+
+/**
+ * @name    Status registers (12x)
+ * @{
+ */
+#define CC110X_PARTNUM      (0x30)      /**< Part number of CC110X. */
+#define CC110X_VERSION      (0x31)      /**< Current version number. */
+#define CC110X_FREQEST      (0x32)      /**< Frequency Offset Estimate. */
+#define CC110X_LQI          (0x33)      /**< Demodulator estimate for Link Quality. */
+#define CC110X_RSSI         (0x34)      /**< Received signal strength indication. */
+#define CC110X_MARCSTATE    (0x35)      /**< Control state machine state. */
+#define CC110X_WORTIME1     (0x36)      /**< High byte of WOR timer. */
+#define CC110X_WORTIME0     (0x37)      /**< Low byte of WOR timer. */
+#define CC110X_PKTSTATUS    (0x38)      /**< Current GDOx status and packet status. */
+#define CC110X_VCO_VC_DAC   (0x39)      /**< Current setting from PLL calibration module. */
+#define CC110X_TXBYTES      (0x3A)      /**< Underflow and number of bytes in the TX FIFO. */
+#define CC110X_RXBYTES      (0x3B)      /**< Overflow and number of bytes in the RX FIFO. */
+/** @} */
+
+/**
+ * @name    Multi byte registers
+ * @{
+ */
+/**
+ * @brief   Register for eight user selected output power settings.
+ *
+ * 3-bit FREND0.PA_POWER value selects the PATABLE entry to use.
+ */
+#define CC110X_PATABLE      (0x3E)
+#define CC110X_TXFIFO       (0x3F)      /**< TX FIFO: Write operations write to the TX FIFO (SB: +0x00; BURST: +0x40) */
+#define CC110X_RXFIFO       (0x3F)      /**< RX FIFO: Read operations read from the RX FIFO (SB: +0x80; BURST: +0xC0) */
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+#endif
diff --git a/drivers/include/cc110x/cc110x-interface.h b/drivers/include/cc110x/cc110x-interface.h
new file mode 100644
index 0000000000000000000000000000000000000000..624696609970e6c26e14a073b908c2da962b5d8a
--- /dev/null
+++ b/drivers/include/cc110x/cc110x-interface.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
+ * Copyright (C) 2014 Freie Universität Berlin
+ * Copyright (C) 2013 INRIA
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     drivers_cc110x
+ * @{
+ *
+ * @file
+ * @brief       internal declarations for cc110x driver
+ *
+ * @author      Oliver Hahm <oliver.hahm@inria.fr>
+ * @author      Kaspar Schleiser <kaspar@schleiser.de>
+ */
+
+#ifndef CC110X_INTERFACE_H
+#define CC110X_INTERFACE_H
+
+#include <stdint.h>
+#include "cc110x.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @name cc110x raw low-level interface
+ * @internal
+ * @{
+ */
+char *cc110x_get_marc_state(cc110x_t *dev);
+char *cc110x_state_to_text(uint8_t state);
+int cc110x_rd_set_mode(cc110x_t *dev, int mode);
+uint8_t cc110x_get_buffer_pos(cc110x_t *dev);
+void cc110x_isr_handler(cc110x_t *dev, void(*callback)(void*), void*arg);
+void cc110x_set_base_freq_raw(cc110x_t *dev, const char* freq_array);
+void cc110x_setup_rx_mode(cc110x_t *dev);
+void cc110x_switch_to_pwd(cc110x_t *dev);
+void cc110x_switch_to_rx(cc110x_t *dev);
+void cc110x_wakeup_from_rx(cc110x_t *dev);
+void cc110x_write_register(cc110x_t *dev, uint8_t r, uint8_t value);
+
+extern const char cc110x_default_conf[];
+extern const uint8_t cc110x_default_conf_size;
+extern const uint8_t cc110x_pa_table[];
+
+#ifdef MODULE_CC110X_HOOKS
+void cc110x_hooks_init(void);
+void cc110x_hook_rx(void);
+void cc110x_hook_tx(void);
+void cc110x_hook_off(void);
+#endif
+/* @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+#endif /* CC110X_INTERFACE_H */
diff --git a/drivers/include/cc110x/cc110x-internal.h b/drivers/include/cc110x/cc110x-internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..5d51697dffc718967abc07e87edbd9fb850d7b8e
--- /dev/null
+++ b/drivers/include/cc110x/cc110x-internal.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
+ * Copyright (C) 2014 Freie Universität Berlin
+ * Copyright (C) 2013 INRIA
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     drivers_cc110x
+ * @{
+ *
+ * @file
+ * @brief       Data structures and variables for the cc110x driver interface
+ *
+ * @author      Oliver Hahm <oliver.hahm@inria.fr>
+ * @author      Kaspar Schleiser <kaspar@schleiser.de>
+ */
+
+#ifndef CC110X_INTERNAL_H
+#define CC110X_INTERNAL_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CC110X_RXBUF_SIZE           (2)
+#define CC110X_MAX_DATA_LENGTH      (58+64)
+
+#define CC110X_HEADER_LENGTH        (3)     /**< Header covers SRC, DST and
+                                                 FLAGS */
+#define CC110X_BROADCAST_ADDRESS    (0x00)  /**< CC110X broadcast address */
+
+#define MIN_UID                     (0x01)  /**< Minimum UID of a node is
+                                                 1 */
+#define MAX_UID                     (0xFF)  /**< Maximum UID of a node is
+                                                 255 */
+
+#define MIN_CHANNR                  (0)     /**< Minimum channel number */
+#define MAX_CHANNR                  (24)    /**< Maximum channel number */
+
+#define CC110X_PACKET_LENGTH        (0xFF)  /**< max packet length = 255b */
+#define CC110X_SYNC_WORD_TX_TIME    (90000) /**< loop count (max. timeout ~15ms)
+                                                 to wait for sync word to be
+                                                 transmitted (GDO2 from low to
+                                                 high) */
+
+#define RESET_WAIT_TIME             (610)   /**< Reset wait time (in reset
+                                                 procedure) */
+#define IDLE_TO_RX_TIME             (122)   /**< Time chip needs to go to RX */
+#define CS_SO_WAIT_TIME             (488)   /**< Time to wait for SO to go low
+                                                 after CS */
+#define CC110X_GDO1_LOW_RETRY       (100)   /**< Max. retries for SO to go low
+                                                 after CS */
+#define CC110X_DEFAULT_CHANNEL      (0)     /**< The default channel number */
+#define CC110X_MIN_CHANNR           (0)     /**< lowest possible channel number */
+#define CC110X_MAX_CHANNR           (0)     /**< highest possible channel number */
+
+/**
+ * @name    State values for state machine
+ * @{
+ */
+enum {
+    RADIO_UNKNOWN,
+    RADIO_IDLE,
+    RADIO_TX_BUSY,
+    RADIO_RX,
+    RADIO_RX_BUSY,
+    RADIO_PWD,
+};
+/** @} */
+
+/**
+ * @brief array holding cc110x register values
+ */
+extern char cc110x_conf[];
+
+/**
+ * @brief   CC110X layer 0 protocol
+ *
+ * <pre>
+---------------------------------------------------
+|        |         |         |       |            |
+| Length | Address | PhySrc  | Flags |    Data    |
+|        |         |         |       |            |
+---------------------------------------------------
+  1 byte   1 byte    1 byte   1 byte   <= 251 bytes
+
+Flags:
+        Bit | Meaning
+        --------------------
+        7:4 | -
+        3:1 | Protocol
+          0 | Identification
+</pre>
+Notes:
+\li length & address are given by CC110X
+\li Identification is increased is used to scan duplicates. It must be increased
+    for each new packet and kept for packet retransmissions.
+ */
+typedef struct __attribute__((packed))
+{
+    uint8_t length;                         /**< Length of the packet (without length byte) */
+    uint8_t address;                        /**< Destination address */
+    uint8_t phy_src;                        /**< Source address (physical source) */
+    uint8_t flags;                          /**< Flags */
+    uint8_t data[CC110X_MAX_DATA_LENGTH];   /**< Data (high layer protocol) */
+} cc110x_pkt_t;
+
+/**
+ * @brief struct holding cc110x packet + metadata
+ */
+typedef struct {
+    uint8_t rssi;                           /**< RSSI value */
+    uint8_t lqi;                            /**< link quality indicator */
+    uint8_t pos;                            /**< I have no clue. */
+    cc110x_pkt_t packet;                    /**< whole packet */
+} cc110x_pkt_buf_t;
+
+/**
+ * @brief enum for holding cc110x radio on/off state */
+enum cc110x_radio_mode {
+    RADIO_MODE_GET  = -1,                   /**< leave mode unchanged */
+    RADIO_MODE_OFF  = 0,                    /**< turn radio off */
+    RADIO_MODE_ON   = 1                     /**< turn radio on */
+};
+
+/**
+ * @brief   CC110x register configuration
+ */
+typedef struct {
+    uint8_t _IOCFG2;      /**< GDO2 output pin configuration */
+    uint8_t _IOCFG1;      /**< GDO1 output pin configuration */
+    uint8_t _IOCFG0;      /**< GDO0 output pin configuration */
+    uint8_t _FIFOTHR;     /**< RX FIFO and TX FIFO thresholds */
+    uint8_t _SYNC1;       /**< Sync word, high byte */
+    uint8_t _SYNC0;       /**< Sync word, low byte */
+    uint8_t _PKTLEN;      /**< Packet length */
+    uint8_t _PKTCTRL1;    /**< Packet automation control */
+    uint8_t _PKTCTRL0;    /**< Packet automation control */
+    uint8_t _ADDR;        /**< Device address */
+    uint8_t _CHANNR;      /**< Channel number */
+    uint8_t _FSCTRL1;     /**< Frequency synthesizer control */
+    uint8_t _FSCTRL0;     /**< Frequency synthesizer control */
+    uint8_t _FREQ2;       /**< Frequency control word, high byte */
+    uint8_t _FREQ1;       /**< Frequency control word, middle byte */
+    uint8_t _FREQ0;       /**< Frequency control word, low byte */
+    uint8_t _MDMCFG4;     /**< Modem configuration */
+    uint8_t _MDMCFG3;     /**< Modem configuration */
+    uint8_t _MDMCFG2;     /**< Modem configuration */
+    uint8_t _MDMCFG1;     /**< Modem configuration */
+    uint8_t _MDMCFG0;     /**< Modem configuration */
+    uint8_t _DEVIATN;     /**< Modem deviation setting */
+    uint8_t _MCSM2;       /**< Main Radio Control State Machine configuration */
+    uint8_t _MCSM1;       /**< Main Radio Control State Machine configuration */
+    uint8_t _MCSM0;       /**< Main Radio Control State Machine configuration */
+    uint8_t _FOCCFG;      /**< Frequency Offset Compensation configuration */
+    uint8_t _BSCFG;       /**< Bit Synchronization configuration */
+    uint8_t _AGCCTRL2;    /**< AGC control */
+    uint8_t _AGCCTRL1;    /**< AGC control */
+    uint8_t _AGCCTRL0;    /**< AGC control */
+    uint8_t _WOREVT1;     /**< High byte Event 0 timeout */
+    uint8_t _WOREVT0;     /**< Low byte Event 0 timeout */
+    uint8_t _WORCTRL;     /**< Wake On Radio control */
+    uint8_t _FREND1;      /**< Front end RX configuration */
+    uint8_t _FREND0;      /**< Front end TX configuration */
+    uint8_t _FSCAL3;      /**< Frequency synthesizer calibration */
+    uint8_t _FSCAL2;      /**< Frequency synthesizer calibration */
+    uint8_t _FSCAL1;      /**< Frequency synthesizer calibration */
+    uint8_t _FSCAL0;      /**< Frequency synthesizer calibration */
+} cc110x_reg_t;
+
+/**
+ * @brief   CC110x radio configuration
+ */
+typedef struct {
+    cc110x_reg_t reg_cfg;       /**< CC110X register configuration */
+    uint8_t pa_power;           /**< Output power setting */
+} cc110x_cfg_t;
+
+/**
+ * @brief   Radio Control Flags
+ */
+typedef struct {
+    uint8_t  _RSSI;             /**< The RSSI value of last received packet */
+    uint8_t  _LQI;              /**< The LQI value of the last received packet */
+} cc110x_flags_t;
+
+/**
+ * @brief   Statistic interface for debugging
+ */
+typedef struct cc110x_statistic {
+    uint32_t    packets_in;             /**< total nr of packets received */
+    uint32_t    packets_in_crc_fail;    /**< dropped because of invalid crc */
+    uint32_t    packets_in_while_tx;    /**< receive while tx */
+    uint32_t    raw_packets_out;        /**< packets sent */
+} cc110x_statistic_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+#endif /* CC110X_INTERNAL_H */
diff --git a/drivers/include/cc110x/cc110x-netdev2.h b/drivers/include/cc110x/cc110x-netdev2.h
new file mode 100644
index 0000000000000000000000000000000000000000..742e3ef9a429b23a59bf017696b828608d62a783
--- /dev/null
+++ b/drivers/include/cc110x/cc110x-netdev2.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 Freie Universität Berlin
+ *               2015 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * 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_cc110x
+ * @{
+ *
+ * @file
+ * @brief       Variables for the cc110x ng_netdev base interface
+ *
+ * @author      Fabian Nack <nack@inf.fu-berlin.de>
+ * @author      Kaspar Schleiser <kaspar@schleiser.de>
+ */
+
+#ifndef CC110X_NETDEV_H
+#define CC110X_NETDEV_H
+
+#include "periph/gpio.h"
+#include "periph/spi.h"
+#include "net/netdev2.h"
+#include "cc110x.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief   Implementation of netdev2_driver_t for CC110X device
+ */
+extern const netdev2_driver_t netdev2_cc110x_driver;
+
+/**
+ * @brief cc110x netdev2 struct
+ */
+typedef struct netdev2_cc110x {
+    netdev2_t netdev;       /**< writing obious */
+    cc110x_t cc110x;        /**< documentation here */
+} netdev2_cc110x_t;
+
+
+/**
+ * @brief netdev2 <-> cc110x glue code initialization function
+ *
+ * @param[out]      netdev2_cc110x  ptr to netdev2_cc110x struct ti initialize
+ * @param[in]       params          cc110x IO parameter struct to use
+ *
+ * @return          0               on success
+ * @return          -1              on error
+ */
+int netdev2_cc110x_setup(netdev2_cc110x_t *netdev2_cc110x, const cc110x_params_t *params);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CC110X_NETDEV_H */
diff --git a/drivers/include/cc110x/cc110x-spi.h b/drivers/include/cc110x/cc110x-spi.h
new file mode 100644
index 0000000000000000000000000000000000000000..e5422873b249e5095c6d2485abf8deb117666bd2
--- /dev/null
+++ b/drivers/include/cc110x/cc110x-spi.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2014 Freie Universität Berlin
+ * Copyright (C) 2013 INRIA
+ * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * 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_cc110x
+ * @{
+ *
+ * @file
+ * @brief       CC110X SPI functions
+ *
+ * @author      Oliver Hahm <oliver.hahm@inria.fr>
+ * @author      Fabian Nack <nack@inf.fu-berlin.de>
+ * @author      Kaspar Schleiser <kaspar@schleiser.de>
+ */
+
+#ifndef CC110X_SPI_H
+#define CC110X_SPI_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Write a set of bytes using burst mode (if available)
+ *
+ * @param dev       Device to work on
+ * @param addr      Destination register
+ * @param buffer    Data to be written
+ * @param count     Size of data
+ */
+void cc110x_writeburst_reg(cc110x_t *dev, uint8_t addr, const char *buffer, uint8_t count);
+
+/**
+ * @brief Read a set of bytes using burst mode (if available)
+ *
+ * @param dev       Device to work on
+ * @param addr      Source register
+ * @param buffer    Buffer to store read data
+ * @param count     Size of data to be read
+ */
+void cc110x_readburst_reg(cc110x_t *dev, uint8_t addr, char *buffer, uint8_t count);
+
+/**
+ * @brief Write one byte to a register
+ *
+ * @param dev       Device to work on
+ * @param addr      Destinatoin register
+ * @param value     New value
+ */
+void cc110x_write_reg(cc110x_t *dev, uint8_t addr, uint8_t value);
+
+/**
+ * @brief Read a byte from register
+ *
+ * @param dev       Device to work on
+ * @param addr  Source register
+ *
+ * @return Read state and value of register
+ */
+uint8_t cc110x_read_reg(cc110x_t *dev, uint8_t addr);
+
+/**
+ * @brief Read a byte from register, robust version
+ *
+ * Datasheet states some registered should be read twice until
+ * it returns the same value.
+ *
+ * @param dev       Device to work on
+ * @param addr      Source register
+ *
+ * @return Read state and value of register
+ */
+uint8_t cc110x_get_reg_robust(cc110x_t *dev, uint8_t addr);
+
+/**
+ * @brief Read state of a register
+ *
+ * @param dev       Device to work on
+ * @param addr      Source register
+ *
+ * @return State of register
+ */
+uint8_t cc110x_read_status(cc110x_t *dev, uint8_t addr);
+
+/**
+ * @brief Sends a command strobe
+ *
+ * @param dev       Device to work on
+ * @param c         Command code
+ *
+ * @return Command response
+ */
+uint8_t cc110x_strobe(cc110x_t *dev, uint8_t c);
+
+/**
+ * @brief Pull CS to low and wait for CC110x stabilization
+ *
+ * @param dev       Device to work on
+ */
+void cc110x_cs(cc110x_t *dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+#endif /* CC110X_SPI_H */
diff --git a/drivers/include/cc110x/gnrc_netdev2_cc110x.h b/drivers/include/cc110x/gnrc_netdev2_cc110x.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a6ccfafb610070cea070329c4aa86ac2ba49f8c
--- /dev/null
+++ b/drivers/include/cc110x/gnrc_netdev2_cc110x.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * 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   driver_cc110x
+ * @{
+ *
+ * @file
+ * @brief     cc110x gnrc glue code interface
+ *
+ * @author    Kaspar Schleiser <kaspar@schleiser.de>
+ */
+
+#include "net/gnrc/gnrc_netdev2.h"
+#include "cc110x/cc110x-netdev2.h"
+
+#ifndef GNRC_CC110X_H
+#define GNRC_CC110X_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief initialize cc110x gnrc glue code
+ *
+ * @param[in] gnrc_netdev2  gnrc_netdev2 state structure to initialize
+ * @param[in] dev           cc110x device structure to setup
+ *
+ * @return 1    on sucess
+ * @return <=0  on error
+ */
+int gnrc_netdev2_cc110x_init(gnrc_netdev2_t *gnrc_netdev2, netdev2_cc110x_t *dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GNRC_CC110X_H */
+/** @} */
diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c
index faaf8cde6c91b038f1a1a6e85d796d791bdea9fc..b7fe1305ba595c4b8b13f3e81c7e709d502a70a0 100644
--- a/sys/auto_init/auto_init.c
+++ b/sys/auto_init/auto_init.c
@@ -158,6 +158,11 @@ void auto_init(void)
     auto_init_slip();
 #endif
 
+#ifdef MODULE_CC110X
+    extern void auto_init_cc110x(void);
+    auto_init_cc110x();
+#endif
+
 #ifdef MODULE_XBEE
     extern void auto_init_xbee(void);
     auto_init_xbee();
diff --git a/sys/auto_init/netif/auto_init_cc110x.c b/sys/auto_init/netif/auto_init_cc110x.c
new file mode 100644
index 0000000000000000000000000000000000000000..291922f7030704e884fb1e5b9a5e29245e068b5a
--- /dev/null
+++ b/sys/auto_init/netif/auto_init_cc110x.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * 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 auto_init_ng_netif
+ * @{
+ *
+ * @file
+ * @brief   Auto initialization for cc110x network interfaces
+ *
+ * @author  Kaspar Schleiser <kaspar@schleiser.de>
+ */
+
+#ifdef MODULE_CC110X
+
+#include "board.h"
+#include "net/gnrc/gnrc_netdev2.h"
+#include "cc110x/gnrc_netdev2_cc110x.h"
+#include "net/gnrc.h"
+
+#include "cc110x.h"
+#include "cc110x_params.h"
+
+#define ENABLE_DEBUG (0)
+#include "debug.h"
+
+/**
+ * @brief   Define stack parameters for the MAC layer thread
+ * @{
+ */
+#define CC110X_MAC_STACKSIZE     (THREAD_STACKSIZE_DEFAULT + DEBUG_EXTRA_STACKSIZE)
+#define CC110X_MAC_PRIO          (THREAD_PRIORITY_MAIN - 3)
+
+#define CC110X_NUM (sizeof(cc110x_params)/sizeof(cc110x_params[0]))
+
+static netdev2_cc110x_t cc110x_devs[CC110X_NUM];
+static char _stacks[CC110X_MAC_STACKSIZE][CC110X_NUM];
+
+static gnrc_netdev2_t _gnrc_netdev2_devs[CC110X_NUM];
+
+void auto_init_cc110x(void)
+{
+    for (int i = 0; i < CC110X_NUM; i++) {
+        const cc110x_params_t *p = &cc110x_params[i];
+        DEBUG("Initializing CC110X radio at SPI_%i\n", p->spi);
+        int res = netdev2_cc110x_setup(&cc110x_devs[i], p);
+        if (res < 0) {
+            DEBUG("Error initializing CC110X radio device!");
+        }
+        else {
+            gnrc_netdev2_cc110x_init(&_gnrc_netdev2_devs[i], &cc110x_devs[i]);
+            res = gnrc_netdev2_init(_stacks[i], CC110X_MAC_STACKSIZE,
+                    CC110X_MAC_PRIO, "cc110x", &_gnrc_netdev2_devs[i]);
+            if (res < 0) {
+                DEBUG("Error starting gnrc_cc110x thread for CC110X!");
+            }
+        }
+    }
+}
+#else
+typedef int dont_be_pedantic;
+#endif /* MODULE_CC110X */
+
+/** @} */