You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/01/08 15:02:16 UTC

[incubator-nuttx] branch pr56 updated: nrf52: add support for SPI

This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch pr56
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/pr56 by this push:
     new 6c711f0  nrf52: add support for SPI
     new 6313226  Merge pull request #56 from raiden00pl/nrf52
6c711f0 is described below

commit 6c711f0c52ce3a53f58eb9361a8acefd38214294
Author: raiden00pl <ra...@gmail.com>
AuthorDate: Wed Jan 8 15:48:20 2020 +0100

    nrf52: add support for SPI
    
    nrf52: add support for GPIO interrupts
    
    nrf52: add macros to decode GPIO PIN and GPIO PORT
    
    nrf52: various cosmetic changes
    
    nrf52: fix GPIO P1 memory address
    
    boards/nrf52840-dk: add support for SPI
    
    boards/nrf52840-dk: add support for LSM6DSL sensor
    
    boards/nrf52840-dk: add support for SX127X radio
---
 arch/arm/src/nrf52/Kconfig                         |   16 +-
 arch/arm/src/nrf52/Make.defs                       |   12 +
 arch/arm/src/nrf52/hardware/nrf52_gpio.h           |   10 +-
 arch/arm/src/nrf52/hardware/nrf52_gpiote.h         |    8 +-
 arch/arm/src/nrf52/hardware/nrf52_memorymap.h      |    2 +-
 arch/arm/src/nrf52/hardware/nrf52_spi.h            |   10 +-
 arch/arm/src/nrf52/hardware/nrf52_twi.h            |    4 +-
 arch/arm/src/nrf52/hardware/nrf52_uarte.h          |    8 +-
 arch/arm/src/nrf52/nrf52_gpio.c                    |   24 +-
 arch/arm/src/nrf52/nrf52_gpio.h                    |   61 +-
 arch/arm/src/nrf52/nrf52_gpiote.c                  |  287 ++++++
 .../arm/src/nrf52/nrf52_gpiote.h                   |   67 +-
 arch/arm/src/nrf52/nrf52_i2c.c                     |   16 +-
 arch/arm/src/nrf52/nrf52_irq.c                     |   23 +-
 arch/arm/src/nrf52/nrf52_lowputc.c                 |   17 +-
 arch/arm/src/nrf52/nrf52_lowputc.h                 |   42 +-
 arch/arm/src/nrf52/nrf52_spi.c                     | 1017 ++++++++++++++++++++
 arch/arm/src/nrf52/nrf52_spi.h                     |  130 +++
 boards/arm/nrf52/nrf52-feather/include/board.h     |    2 +-
 boards/arm/nrf52/nrf52832-dk/include/board.h       |    2 +-
 boards/arm/nrf52/nrf52840-dk/include/board.h       |   24 +-
 boards/arm/nrf52/nrf52840-dk/src/Makefile          |   12 +
 boards/arm/nrf52/nrf52840-dk/src/nrf52840-dk.h     |   46 +
 boards/arm/nrf52/nrf52840-dk/src/nrf52_boot.c      |    6 +
 boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c   |   78 +-
 .../src/{nrf52_boot.c => nrf52_lsm6dsl.c}          |   85 +-
 boards/arm/nrf52/nrf52840-dk/src/nrf52_spi.c       |  206 ++++
 boards/arm/nrf52/nrf52840-dk/src/nrf52_sx127x.c    |  225 +++++
 boards/arm/nrf52/nrf52840-dongle/include/board.h   |    2 +-
 29 files changed, 2222 insertions(+), 220 deletions(-)

diff --git a/arch/arm/src/nrf52/Kconfig b/arch/arm/src/nrf52/Kconfig
index b7024cd..2c92c39 100644
--- a/arch/arm/src/nrf52/Kconfig
+++ b/arch/arm/src/nrf52/Kconfig
@@ -118,6 +118,18 @@ config NRF52_SPI3_MASTER
 	select NRF52_SPI_MASTER
 	depends on NRF52_HAVE_SPI3_MASTER
 
+if NRF52_SPI_MASTER
+
+config NRF52_SPI_MASTER_INTERRUPTS
+	bool "SPI Master interrupts support"
+	default n
+
+endif
+
+config NRF52_GPIOTE
+	bool "GPIOTE (GPIO interrupts)"
+	default n
+
 config NRF52_UART0
 	bool "UART0"
 	default n
@@ -220,8 +232,4 @@ config NRF52_PROGMEM
 
 menu "GPIO Interrupt Configuration"
 
-config NRF52_GPIOIRQ
-	bool "Support GPIO Interrupts"
-	default n
-
 endmenu # GPIO Interrupt Configuration
diff --git a/arch/arm/src/nrf52/Make.defs b/arch/arm/src/nrf52/Make.defs
index 58ff7d6..e33aeed 100644
--- a/arch/arm/src/nrf52/Make.defs
+++ b/arch/arm/src/nrf52/Make.defs
@@ -101,6 +101,10 @@ ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y)
 CHIP_CSRCS += nrf52_idle.c
 endif
 
+ifeq ($(CONFIG_NRF52_GPIOTE),y)
+CHIP_CSRCS += nrf52_gpiote.c
+endif
+
 ifeq ($(CONFIG_NRF52_UART),y)
 CHIP_CSRCS += nrf52_serial.c
 endif
@@ -117,3 +121,11 @@ ifeq ($(CONFIG_NRF52_RNG),y)
 CHIP_CSRCS += nrf52_rng.c
 endif
 
+ifeq ($(CONFIG_NRF52_SPI_MASTER),y)
+CHIP_CSRCS += nrf52_spi.c
+endif
+
+ifeq ($(CONFIG_NRF52_I2C_MASTER),y)
+CHIP_CSRCS += nrf52_i2c.c
+endif
+
diff --git a/arch/arm/src/nrf52/hardware/nrf52_gpio.h b/arch/arm/src/nrf52/hardware/nrf52_gpio.h
index 118e2f9..47a7751 100644
--- a/arch/arm/src/nrf52/hardware/nrf52_gpio.h
+++ b/arch/arm/src/nrf52/hardware/nrf52_gpio.h
@@ -48,8 +48,14 @@
  * Pre-processor Definitions
  ************************************************************************************/
 
-#define NRF52_GPIO_PORT0            0
-#define NRF52_GPIO_NPORTS           1
+#ifdef CONFIG_ARCH_CHIP_NRF52840
+#  define NRF52_GPIO_NPORTS         2
+#  define NRF52_GPIO_PORT0          0
+#  define NRF52_GPIO_PORT1          1
+#else
+#  define NRF52_GPIO_PORT0          0
+#  define NRF52_GPIO_NPORTS         1
+#endif
 
 /* Register offsets *****************************************************************/
 
diff --git a/arch/arm/src/nrf52/hardware/nrf52_gpiote.h b/arch/arm/src/nrf52/hardware/nrf52_gpiote.h
index fe7528d..b313d5d 100644
--- a/arch/arm/src/nrf52/hardware/nrf52_gpiote.h
+++ b/arch/arm/src/nrf52/hardware/nrf52_gpiote.h
@@ -71,6 +71,10 @@
 
 /* Register offsets for GPIOTE *********************************************/
 
+/* EVENT_IN Register */
+
+#define GPIOTE_EVENT_IN_EVENT   (1 << 0) /* Bit 0: Event generated from pin */
+
 /* INTENSET/INTENCLR Register */
 
 #define GPIOTE_INT_IN_SHIFT      0    /* Bits 0-7: Enable interrupt for event IN[i] */
@@ -83,8 +87,8 @@
 #define GPIOTE_CONFIG_MODE_SHIFT 0    /* Bits 0-1: Mode */
 #define GPIOTE_CONFIG_MODE_MASK  (0x3 << GPIOTE_CONFIG_MODE_SHIFT)
 #  define GPIOTE_CONFIG_MODE_DIS (0x0 << GPIOTE_CONFIG_MODE_SHIFT) /* 0: Disabled */
-#  define GPIOTE_CONFIG_MODE_EV  (0x0 << GPIOTE_CONFIG_MODE_SHIFT) /* 1: Event */
-#  define GPIOTE_CONFIG_MODE_TS  (0x0 << GPIOTE_CONFIG_MODE_SHIFT) /* 2: Task */
+#  define GPIOTE_CONFIG_MODE_EV  (0x1 << GPIOTE_CONFIG_MODE_SHIFT) /* 1: Event */
+#  define GPIOTE_CONFIG_MODE_TS  (0x3 << GPIOTE_CONFIG_MODE_SHIFT) /* 2: Task */
 #define GPIOTE_CONFIG_PSEL_SHIFT (8)  /* Bits 8-12: GPIO number */
 #define GPIOTE_CONFIG_PSEL_MASK  (0x1f << GPIOTE_CONFIG_PSEL_SHIFT)
 #define GPIOTE_CONFIG_PORT_SHIFT (13) /* Bit 13: GPIO port */
diff --git a/arch/arm/src/nrf52/hardware/nrf52_memorymap.h b/arch/arm/src/nrf52/hardware/nrf52_memorymap.h
index 3673c16..a741943 100644
--- a/arch/arm/src/nrf52/hardware/nrf52_memorymap.h
+++ b/arch/arm/src/nrf52/hardware/nrf52_memorymap.h
@@ -139,7 +139,7 @@
 
 #define NRF52_GPIO_P0_BASE        0x50000000
 #ifdef CONFIG_ARCH_CHIP_NRF52840
-#  define NRF52_GPIO_P1_BASE      0x50003000
+#  define NRF52_GPIO_P1_BASE      0x50000300
 #endif
 
 #ifdef CONFIG_ARCH_CHIP_NRF52840
diff --git a/arch/arm/src/nrf52/hardware/nrf52_spi.h b/arch/arm/src/nrf52/hardware/nrf52_spi.h
index 8b554ab..1972d00 100644
--- a/arch/arm/src/nrf52/hardware/nrf52_spi.h
+++ b/arch/arm/src/nrf52/hardware/nrf52_spi.h
@@ -171,7 +171,7 @@
 /* PSELSCK Register */
 
 #define SPIM_PSELSCK_PIN_SHIFT      (0)       /* Bits 0-4: SCK pin number */
-#define SPIM_PSELSCK_PIN_MASK       (0xf << SPIM_PSELSCK_PIN_SHIFT)
+#define SPIM_PSELSCK_PIN_MASK       (0x1f << SPIM_PSELSCK_PIN_SHIFT)
 #define SPIM_PSELSCK_PORT_SHIFT     (5)       /* Bit 5: SCK port number */
 #define SPIM_PSELSCK_PORT_MASK      (0x1 << SPIM_PSELSCK_PORT_SHIFT)
 #define SPIM_PSELSCK_CONNECTED      (1 << 31) /* Bit 31: Connection */
@@ -180,7 +180,7 @@
 /* PSELMOSI Register */
 
 #define SPIM_PSELMOSI_PIN_SHIFT     (0)       /* Bits 0-4: MOSI pin number */
-#define SPIM_PSELMOSI_PIN_MASK      (0xf << SPIM_PSELMOSI_PIN_SHIFT)
+#define SPIM_PSELMOSI_PIN_MASK      (0x1f << SPIM_PSELMOSI_PIN_SHIFT)
 #define SPIM_PSELMOSI_PORT_SHIFT    (5)       /* Bit 5: MOSI port number */
 #define SPIM_PSELMOSI_PORT_MASK     (0x1 << SPIM_PSELMOSI_PORT_SHIFT)
 #define SPIM_PSELMOSI_CONNECTED     (1 << 31) /* Bit 31: Connection */
@@ -189,7 +189,7 @@
 /* PSELMISO Register */
 
 #define SPIM_PSELMISO_PIN_SHIFT     (0)       /* Bits 0-4: MISO pin number */
-#define SPIM_PSELMISO_PIN_MASK      (0xf << SPIM_PSELMISO_PIN_SHIFT)
+#define SPIM_PSELMISO_PIN_MASK      (0x1f << SPIM_PSELMISO_PIN_SHIFT)
 #define SPIM_PSELMISO_PORT_SHIFT    (5)       /* Bit 5: MISO port number */
 #define SPIM_PSELMISO_PORT_MASK     (0x1 << SPIM_PSELMISO_PORT_SHIFT)
 #define SPIM_PSELMISO_CONNECTED     (1 << 31) /* Bit 31: Connection */
@@ -198,7 +198,7 @@
 /* PSELCSN Register */
 
 #define SPIM_PSELCSN_PIN_SHIFT      (0)       /* Bits 0-4: CSN pin number */
-#define SPIM_PSELCSN_PIN_MASK       (0xf << SPIM_PSELCSN_PIN_SHIFT)
+#define SPIM_PSELCSN_PIN_MASK       (0x1f << SPIM_PSELCSN_PIN_SHIFT)
 #define SPIM_PSELCSN_PORT_SHIFT     (5)       /* Bit 5: CSN port number */
 #define SPIM_PSELCSN_PORT_MASK      (0x1 << SPIM_PSELCSN_PORT_SHIFT)
 #define SPIM_PSELCSN_CONNECTED      (1 << 31) /* Bit 31: Connection */
@@ -245,7 +245,7 @@
 /* PSELDCX Register */
 
 #define SPIM_PSELDCX_PIN_SHIFT      (0)       /* Bits 0-4: DCX pin number */
-#define SPIM_PSELDCX_PIN_MASK       (0xf << SPIM_PSELDCX_PIN_SHIFT)
+#define SPIM_PSELDCX_PIN_MASK       (0x1f << SPIM_PSELDCX_PIN_SHIFT)
 #define SPIM_PSELDCX_PORT_SHIFT     (5)       /* Bit 5: SCK port number */
 #define SPIM_PSELDCX_PORT_MASK      (0x1 << SPIM_PSELDCX_PORT_SHIFT)
 #define SPIM_PSELDCX_CONNECTED      (1 << 31) /* Bit 31: Connection */
diff --git a/arch/arm/src/nrf52/hardware/nrf52_twi.h b/arch/arm/src/nrf52/hardware/nrf52_twi.h
index e17d706..219ed20 100644
--- a/arch/arm/src/nrf52/hardware/nrf52_twi.h
+++ b/arch/arm/src/nrf52/hardware/nrf52_twi.h
@@ -150,7 +150,7 @@
 /* PSELSCL Register */
 
 #define TWIM_PSELSCL_PIN_SHIFT              (0)        /* Bits 0-4: SCL pin number */
-#define TWIM_PSELSCL_PIN_MASK               (0xf << TWIM_PSELSCL_PIN_SHIFT)
+#define TWIM_PSELSCL_PIN_MASK               (0x1f << TWIM_PSELSCL_PIN_SHIFT)
 #define TWIM_PSELSCL_PORT_SHIFT             (5)        /* Bit 5: SCL port number */
 #define TWIM_PSELSCL_PORT_MASK              (0x1 << TWIM_PSELSCL_PORT_SHIFT)
 #define TWIM_PSELSCL_CONNECTED              (1 << 31)  /* Bit 31: Connection */
@@ -159,7 +159,7 @@
 /* PSELSDA Register */
 
 #define TWIM_PSELSDA_PIN_SHIFT              (0)        /* Bits 0-4: SDA pin number */
-#define TWIM_PSELSDA_PIN_MASK               (0xf << TWIM_PSELSDA_PIN_SHIFT)
+#define TWIM_PSELSDA_PIN_MASK               (0x1f << TWIM_PSELSDA_PIN_SHIFT)
 #define TWIM_PSELSDA_PORT_SHIFT             (5)        /* Bit 5: SDA port number */
 #define TWIM_PSELSDA_PORT_MASK              (0x1 << TWIM_PSELSDA_PORT_SHIFT)
 #define TWIM_PSELSDA_CONNECTED              (1 << 31)  /* Bit 31: Connection */
diff --git a/arch/arm/src/nrf52/hardware/nrf52_uarte.h b/arch/arm/src/nrf52/hardware/nrf52_uarte.h
index 3a0e05c..3d5a6e9 100644
--- a/arch/arm/src/nrf52/hardware/nrf52_uarte.h
+++ b/arch/arm/src/nrf52/hardware/nrf52_uarte.h
@@ -238,7 +238,7 @@
 /* PSELRTS Register */
 
 #define UART_PSELRTS_PIN_SHIFT              (0)       /* Bits 0-4: Pin number*/
-#define UART_PSELRTS_PIN_MASK               (0xf << UART_PSELRTS_PIN_SHIFT)
+#define UART_PSELRTS_PIN_MASK               (0x1f << UART_PSELRTS_PIN_SHIFT)
 #define UART_PSELRTS_PORT_SHIFT             (5)       /* Bit 5: Port number */
 #define UART_PSELRTS_PORT_MASK              (0x1 << UART_PSELRTS_PORT_SHIFT)
 #define UART_PSELRTS_CONNECT                (1 << 31) /* Bit 31: Connection */
@@ -247,7 +247,7 @@
 /* PSELTXD Register */
 
 #define UART_PSELTXD_PIN_SHIFT              (0)       /* Bits 0-4: Pin number*/
-#define UART_PSELTXD_PIN_MASK               (0xf << UART_PSELTXD_PIN_SHIFT)
+#define UART_PSELTXD_PIN_MASK               (0x1f << UART_PSELTXD_PIN_SHIFT)
 #define UART_PSELTXD_PORT_SHIFT             (5)       /* Bit 5: Port number */
 #define UART_PSELTXD_PORT_MASK              (0x1 << UART_PSELTXD_PORT_SHIFT)
 #define UART_PSELTXD_CONNECT                (1 << 31) /* Bit 31: Connection */
@@ -256,7 +256,7 @@
 /* PSELCTS Register */
 
 #define UART_PSELCTS_PIN_SHIFT              (0)       /* Bits 0-4: Pin number*/
-#define UART_PSELCTS_PIN_MASK               (0xf << UART_PSELCTS_PIN_SHIFT)
+#define UART_PSELCTS_PIN_MASK               (0x1f << UART_PSELCTS_PIN_SHIFT)
 #define UART_PSELCTS_PORT_SHIFT             (5)       /* Bit 5: Port number */
 #define UART_PSELCTS_PORT_MASK              (0x1 << UART_PSELCTS_PORT_SHIFT)
 #define UART_PSELCTS_CONNECT                (1 << 31) /* Bit 31: Connection */
@@ -265,7 +265,7 @@
 /* PSELRXD Register */
 
 #define UART_PSELRXD_PIN_SHIFT              (0)       /* Bits 0-4: Pin number*/
-#define UART_PSELRXD_PIN_MASK               (0xf << UART_PSELRXD_PIN_SHIFT)
+#define UART_PSELRXD_PIN_MASK               (0x1f << UART_PSELRXD_PIN_SHIFT)
 #define UART_PSELRXD_PORT_SHIFT             (5)       /* Bit 5: Port number */
 #define UART_PSELRXD_PORT_MASK              (0x1 << UART_PSELRXD_PORT_SHIFT)
 #define UART_PSELRXD_CONNECT                (1 << 31) /* Bit 31: Connection */
diff --git a/arch/arm/src/nrf52/nrf52_gpio.c b/arch/arm/src/nrf52/nrf52_gpio.c
index c5f29d0..2ccc1ef 100644
--- a/arch/arm/src/nrf52/nrf52_gpio.c
+++ b/arch/arm/src/nrf52/nrf52_gpio.c
@@ -186,7 +186,7 @@ int nrf52_gpio_config(nrf52_pinset_t cfgset)
        * that pin.
        */
 
-      pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
+      pin = GPIO_PIN_DECODE(cfgset);
 
       /* First, configure the port as a generic input so that we have a
        * known starting point and consistent behavior during the re-
@@ -206,16 +206,6 @@ int nrf52_gpio_config(nrf52_pinset_t cfgset)
         case GPIO_INPUT:   /* GPIO input pin */
           break;           /* Already configured */
 
-#ifdef CONFIG_NRF52_GPIOIRQ
-        case GPIO_INTFE:   /* GPIO interrupt falling edge */
-        case GPIO_INTRE:   /* GPIO interrupt rising edge */
-        case GPIO_INTBOTH: /* GPIO interrupt both edges */
-        case GPIO_INTLOW:  /* GPIO interrupt low level */
-        case GPIO_INTHIGH: /* GPIO interrupt high level */
-          nrf52_gpio_interrupt(cfgset);
-          break;
-#endif
-
         case GPIO_OUTPUT:  /* GPIO outpout pin */
           nrf52_gpio_output(cfgset, port, pin);
           break;
@@ -244,8 +234,8 @@ int nrf52_gpio_unconfig(nrf52_pinset_t cfgset)
 
   /* Get port and pin number */
 
-  port = (cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
-  pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
+  pin  = GPIO_PIN_DECODE(cfgset);
+  port = GPIO_PORT_DECODE(cfgset);
 
   /* Get address offset */
 
@@ -274,8 +264,8 @@ void nrf52_gpio_write(nrf52_pinset_t pinset, bool value)
 
   /* Get port and pin number */
 
-  pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
-  port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+  pin  = GPIO_PIN_DECODE(pinset);
+  port = GPIO_PORT_DECODE(pinset);
 
   /* Get register address */
 
@@ -310,8 +300,8 @@ bool nrf52_gpio_read(nrf52_pinset_t pinset)
 
   /* Get port and pin number */
 
-  port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
-  pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
+  pin  = GPIO_PIN_DECODE(pinset);
+  port = GPIO_PORT_DECODE(pinset);
 
   /* Get register address */
 
diff --git a/arch/arm/src/nrf52/nrf52_gpio.h b/arch/arm/src/nrf52/nrf52_gpio.h
index 612d0af..e03810d 100644
--- a/arch/arm/src/nrf52/nrf52_gpio.h
+++ b/arch/arm/src/nrf52/nrf52_gpio.h
@@ -176,6 +176,11 @@
 #  define GPIO_PIN31            (31 << GPIO_PIN_SHIFT)
 #  define GPIO_PIN(n)           ((n) << GPIO_PIN_SHIFT)
 
+/* Helper macros */
+
+#define GPIO_PIN_DECODE(p)  (((p) & GPIO_PIN_MASK)  >> GPIO_PIN_SHIFT)
+#define GPIO_PORT_DECODE(p) (((p) & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT)
+
 /************************************************************************************
  * Public Types
  ************************************************************************************/
@@ -201,21 +206,6 @@ extern "C"
  ************************************************************************************/
 
 /************************************************************************************
- * Name: nrf52_gpio_irqinitialize
- *
- * Description:
- *   Initialize logic to support interrupting GPIO pins.  This function is called by
- *   the OS inialization logic and is not a user interface.
- *
- ************************************************************************************/
-
-#ifdef CONFIG_NRF52_GPIOIRQ
-void nrf52_gpio_irqinitialize(void);
-#else
-#  define nrf52_gpio_irqinitialize()
-#endif
-
-/************************************************************************************
  * Name: nrf52_gpio_config
  *
  * Description:
@@ -236,47 +226,6 @@ int nrf52_gpio_config(nrf52_pinset_t cfgset);
 int nrf52_gpio_unconfig(nrf52_pinset_t cfgset);
 
 /************************************************************************************
- * Name: nrf52_gpio_interrupt
- *
- * Description:
- *   Configure a GPIO interrupt pin based on bit-encoded description of the pin.
- *   This function is called by nrf52_gpio_config to setup interrupting pins.  It is
- *   not a user interface.
- *
- ************************************************************************************/
-
-#ifdef CONFIG_NRF52_GPIOIRQ
-int nrf52_gpio_interrupt(nrf52_pinset_t pinset);
-#endif
-
-/************************************************************************************
- * Name: nrf52_gpio_irqno
- *
- * Description:
- *   Returns the IRQ number that was associated with an interrupt pin after it was
- *   configured.
- *
- ************************************************************************************/
-
-#ifdef CONFIG_NRF52_GPIOIRQ
-int nrf52_gpio_irqno(nrf52_pinset_t pinset);
-#endif
-
-/************************************************************************************
- * Name: nrf52_gpio_ackedge
- *
- * Description:
- *   Acknowledge edge interrupts by clearing the associated bits in the rising and
- *   falling registers.  This acknowledgemment is, of course, not needed for level
- *   interupts.
- *
- ************************************************************************************/
-
-#ifdef CONFIG_NRF52_GPIOIRQ
-int nrf52_gpio_ackedge(int irq);
-#endif
-
-/************************************************************************************
  * Name: rnf52_gpio_write
  *
  * Description:
diff --git a/arch/arm/src/nrf52/nrf52_gpiote.c b/arch/arm/src/nrf52/nrf52_gpiote.c
new file mode 100644
index 0000000..3481711
--- /dev/null
+++ b/arch/arm/src/nrf52/nrf52_gpiote.c
@@ -0,0 +1,287 @@
+/****************************************************************************
+ * arch/arm/src/nrf52/nrf52_gpiote.c
+ *
+ *   Copyright (C) 2019 Gregory Nutt. All rights reserved.
+ *   Author: Mateusz Szafoni <ra...@railab.me>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name NuttX 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 OWNER 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <debug.h>
+#include <string.h>
+
+#include <arch/irq.h>
+#include <nuttx/arch.h>
+
+#include "up_arch.h"
+
+#include "nrf52_gpio.h"
+#include "nrf52_gpiote.h"
+
+#include "hardware/nrf52_gpiote.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define GPIOTE_CHANNELS 8
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct nrf52_gpiote_callback_s
+{
+  xcpt_t     callback;
+  FAR void  *arg;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Interrupt handlers attached to each GPIOTE */
+
+static struct nrf52_gpiote_callback_s g_gpiote_callbacks[GPIOTE_CHANNELS];
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_gpiote_putreg
+ *
+ * Description:
+ *   Put a 32-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline void nrf52_gpiote_putreg(uint32_t offset, uint32_t value)
+{
+  putreg32(value, NRF52_GPIOTE_BASE + offset);
+}
+
+/****************************************************************************
+ * Name: nrf52_gpiote_getreg
+ *
+ * Description:
+ *   Get a 32-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline uint32_t nrf52_gpiote_getreg(uint32_t offset)
+{
+  return getreg32(NRF52_GPIOTE_BASE + offset);
+}
+
+/****************************************************************************
+ * Name: nrf52_gpiote_isr
+ *
+ * Description:
+ *   Common GPIOTE interrupt handler
+ *
+ ****************************************************************************/
+
+static int nrf52_gpiote_isr(int irq, FAR void *context, FAR void *arg)
+{
+  uint32_t regval = 0;
+  int      ret    = OK;
+  int      i      = 0;
+
+  /* Scan all GPIOTE channels */
+
+  for (i = 0; i < GPIOTE_CHANNELS; i += 1)
+    {
+      /* Only if callback is registered */
+
+      if (g_gpiote_callbacks[i].callback != NULL)
+        {
+          /* Get input event register */
+
+          regval = nrf52_gpiote_getreg(NRF52_GPIOTE_EVENTS_IN_OFFSET(i));
+          if (regval == GPIOTE_EVENT_IN_EVENT)
+            {
+              /* Execute callback */
+
+              xcpt_t callback = g_gpiote_callbacks[i].callback;
+              FAR void *cbarg = g_gpiote_callbacks[i].arg;
+              ret = callback(irq, context, cbarg);
+
+              /* Clear event */
+
+              nrf52_gpiote_putreg(NRF52_GPIOTE_EVENTS_IN_OFFSET(i), 0);
+            }
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_gpiosetevent
+ *
+ * Description:
+ *   Sets/clears GPIO based event and interrupt triggers.
+ *
+ * Input Parameters:
+ *  - pinset:      GPIO pin configuration
+ *  - risingedge:  Enables interrupt on rising edges
+ *  - fallingedge: Enables interrupt on falling edges
+ *  - event:       Generate event when set
+ *  - func:        When non-NULL, generate interrupt
+ *  - arg:         Argument passed to the interrupt callback
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value on failure indicating the
+ *   nature of the failure.
+ *
+ ****************************************************************************/
+
+int nrf52_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge,
+                       bool event, xcpt_t func, FAR void *arg)
+{
+  int        ret    = OK;
+  int        i      = 0;
+  int        pin    = 0;
+  int        port   = 0;
+  uint32_t   regval = 0;
+  bool       found  = false;
+  irqstate_t flags;
+
+  /* Find available GPIOTE channel */
+
+  flags = enter_critical_section();
+
+  for (i = 0; i < GPIOTE_CHANNELS; i += 1)
+    {
+      if (g_gpiote_callbacks[i].callback == NULL)
+        {
+          found = true;
+          break;
+        }
+    }
+
+  leave_critical_section(flags);
+
+  /* Return error if there is no free channel */
+
+  if (found == false)
+    {
+      ret = -ENODEV;
+      goto errout;
+    }
+
+  /* NOTE: GPIOTE module has priority over GPIO module
+   *       so GPIO configuration will be ignored
+   */
+
+  /* Select GPIOTE pin */
+
+  pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
+  port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+
+  regval = (pin << GPIOTE_CONFIG_PSEL_SHIFT);
+  regval |= (port << GPIOTE_CONFIG_PORT_SHIFT);
+
+  /* Select EVENT mode */
+
+  if (event || func)
+    {
+      regval |= GPIOTE_CONFIG_MODE_EV;
+    }
+
+  /* Select polarity */
+
+  if (risingedge == true && fallingedge == true)
+    {
+      regval |= GPIOTE_CONFIG_POL_TG;
+    }
+  else if (risingedge == true)
+    {
+      regval |= GPIOTE_CONFIG_POL_LTH;
+    }
+  else if (fallingedge == true)
+    {
+      regval |= GPIOTE_CONFIG_POL_HTL;
+    }
+
+  /* Write CONFIG register */
+
+  nrf52_gpiote_putreg(NRF52_GPIOTE_CONFIG_OFFSET(i), regval);
+
+  /* Enable interrupt for given event */
+
+  nrf52_gpiote_putreg(NRF52_GPIOTE_INTENSET_OFFSET, GPIOTE_INT_IN(i));
+
+  /* Connect callback */
+
+  g_gpiote_callbacks[i].callback = func;
+  g_gpiote_callbacks[i].arg      = arg;
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_gpiote_init
+ *
+ * Description:
+ *   Initialize GPIOTE
+ *
+ ****************************************************************************/
+
+int nrf52_gpiote_init(void)
+{
+  /* Reset GPIOTE data */
+
+  memset(&g_gpiote_callbacks,
+         0,
+         sizeof(struct nrf52_gpiote_callback_s)*GPIOTE_CHANNELS);
+
+  /* Attach GPIOTE interrupt handler */
+
+  irq_attach(NRF52_IRQ_GPIOTE, nrf52_gpiote_isr, NULL);
+  up_enable_irq(NRF52_IRQ_GPIOTE);
+
+  return OK;
+}
diff --git a/boards/arm/nrf52/nrf52840-dk/src/nrf52_boot.c b/arch/arm/src/nrf52/nrf52_gpiote.h
similarity index 64%
copy from boards/arm/nrf52/nrf52840-dk/src/nrf52_boot.c
copy to arch/arm/src/nrf52/nrf52_gpiote.h
index af1dca2..3b1e162 100644
--- a/boards/arm/nrf52/nrf52840-dk/src/nrf52_boot.c
+++ b/arch/arm/src/nrf52/nrf52_gpiote.h
@@ -1,8 +1,8 @@
 /****************************************************************************
- * boards/arm/nrf52/nrf52840-dk/src/nrf52_boot.c
+ * arch/arm/src/nrf52/nrf52_gpiote.h
  *
  *   Copyright (C) 2019 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <gn...@nuttx.org>
+ *   Author: Mateusz Szafoni <ra...@railab.me>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,64 +33,57 @@
  *
  ****************************************************************************/
 
+#ifndef __ARCH_ARM_SRC_NRF52_NRF52_GPIOTE_H
+#define __ARCH_ARM_SRC_NRF52_NRF52_GPIOTE_H
+
 /****************************************************************************
  * Included Files
  ****************************************************************************/
 
 #include <nuttx/config.h>
 
-#include <debug.h>
-
-#include <nuttx/board.h>
-#include <arch/board/board.h>
+#include <nuttx/irq.h>
 
-#include "up_arch.h"
-#include "up_internal.h"
+#include "chip.h"
 
-#include "nrf52840-dk.h"
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
 
 /****************************************************************************
- * Public Functions
+ * Public Function Prototypes
  ****************************************************************************/
 
 /****************************************************************************
- * Name: nrf52_board_initialize
+ * Name: nrf52_gpiosetevent
  *
  * Description:
- *   All NRF52xxx architectures must provide the following entry point.
- *   This entry point is called early in the initialization -- after all
- *   memory has been configured and mapped but before any devices have been
- *   initialized.
+ *   Sets/clears GPIO based event and interrupt triggers.
+ *
+ * Input Parameters:
+ *  - pinset: gpio pin configuration
+ *  - rising/falling edge: enables
+ *  - event:  generate event when set
+ *  - func:   when non-NULL, generate interrupt
+ *  - arg:    Argument passed to the interrupt callback
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value on failure indicating the
+ *   nature of the failure.
  *
  ****************************************************************************/
 
-void nrf52_board_initialize(void)
-{
-  /* Configure on-board LEDs if LED support has been selected. */
-
-#ifdef CONFIG_ARCH_LEDS
-  board_autoled_initialize();
-#endif
-}
+int nrf52_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge,
+                       bool event, xcpt_t func, FAR void *arg);
 
 /****************************************************************************
- * Name: board_late_initialize
+ * Name: nrf52_gpiote_init
  *
  * Description:
- *   If CONFIG_BOARD_LATE_INITIALIZE is selected, then an additional
- *   initialization call will be performed in the boot-up sequence to a
- *   function called board_late_initialize().  board_late_initialize() will be
- *   called immediately after up_initialize() is called and just before the
- *   initial application is started.  This additional initialization phase
- *   may be used, for example, to initialize board-specific device drivers.
+ *   Initialize GPIOTE
  *
  ****************************************************************************/
 
-#ifdef CONFIG_BOARD_LATE_INITIALIZE
-void board_late_initialize(void)
-{
-  /* Perform board-specific initialization */
+int nrf52_gpiote_init(void);
 
-  (void)nrf52_bringup();
-}
-#endif
+#endif /* __ARCH_ARM_SRC_NRF52_NRF52_GPIOTE_H */
diff --git a/arch/arm/src/nrf52/nrf52_i2c.c b/arch/arm/src/nrf52/nrf52_i2c.c
index 258917a..dd64971 100644
--- a/arch/arm/src/nrf52/nrf52_i2c.c
+++ b/arch/arm/src/nrf52/nrf52_i2c.c
@@ -310,6 +310,10 @@ static int nrf52_i2c_transfer(FAR struct i2c_master_s *dev,
 #ifdef CONFIG_I2C_POLLED
           while (nrf52_i2c_getreg(priv,
                                   NRF52_TWIM_EVENTS_LASTTX_OFFSET) != 1);
+
+          /* Clear event */
+
+          nrf52_i2c_putreg(priv, NRF52_TWIM_EVENTS_LASTTX_OFFSET, 0);
 #endif
 
           /* TWIM stop */
@@ -321,6 +325,10 @@ static int nrf52_i2c_transfer(FAR struct i2c_master_s *dev,
 #ifdef CONFIG_I2C_POLLED
           while (nrf52_i2c_getreg(priv,
                                   NRF52_TWIM_EVENTS_STOPPED_OFFSET) != 1);
+
+          /* Clear event */
+
+          nrf52_i2c_putreg(priv, NRF52_TWIM_EVENTS_STOPPED_OFFSET, 0);
 #endif
         }
       else
@@ -425,8 +433,8 @@ static int nrf52_i2c_init(FAR struct nrf52_i2c_priv_s *priv)
 
   /* Select SCL pin */
 
-  pin = (priv->scl_pin & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
-  port = (priv->scl_pin & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+  pin  = GPIO_PIN_DECODE(priv->scl_pin);
+  port = GPIO_PORT_DECODE(priv->scl_pin);
 
   regval = (pin << TWIM_PSELSCL_PIN_SHIFT);
   regval |= (port << TWIM_PSELSCL_PORT_SHIFT);
@@ -434,8 +442,8 @@ static int nrf52_i2c_init(FAR struct nrf52_i2c_priv_s *priv)
 
   /* Select SDA pin */
 
-  pin = (priv->sda_pin & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
-  port = (priv->sda_pin & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+  pin  = GPIO_PIN_DECODE(priv->sda_pin);
+  port = GPIO_PORT_DECODE(priv->sda_pin);
 
   regval = (pin << TWIM_PSELSDA_PIN_SHIFT);
   regval |= (port << TWIM_PSELSDA_PORT_SHIFT);
diff --git a/arch/arm/src/nrf52/nrf52_irq.c b/arch/arm/src/nrf52/nrf52_irq.c
index 384e7c5..f80cd9d 100644
--- a/arch/arm/src/nrf52/nrf52_irq.c
+++ b/arch/arm/src/nrf52/nrf52_irq.c
@@ -53,8 +53,10 @@
 #include "up_arch.h"
 #include "up_internal.h"
 
-#include "nrf52_gpio.h"
 #include "nrf52_irq.h"
+#ifdef CONFIG_NRF52_GPIOTE
+#  include "nrf52_gpiote.h"
+#endif
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -114,9 +116,12 @@ static void nrf52_dumpnvic(const char *msg, int irq)
   irqinfo("  INTCTRL:    %08x VECTAB: %08x\n",
           getreg32(NVIC_INTCTRL), getreg32(NVIC_VECTAB));
 #if 0
-  irqinfo("  SYSH ENABLE MEMFAULT: %08x BUSFAULT: %08x USGFAULT: %08x SYSTICK: %08x\n",
-          getreg32(NVIC_SYSHCON_MEMFAULTENA), getreg32(NVIC_SYSHCON_BUSFAULTENA),
-          getreg32(NVIC_SYSHCON_USGFAULTENA), getreg32(NVIC_SYSTICK_CTRL_ENABLE));
+  irqinfo("  SYSH ENABLE MEMFAULT: %08x BUSFAULT: %08x \n",
+          getreg32(NVIC_SYSHCON_MEMFAULTENA),
+          getreg32(NVIC_SYSHCON_BUSFAULTENA));
+  irqinfo("  USGFAULT: %08x SYSTICK: %08x\n",
+          getreg32(NVIC_SYSHCON_USGFAULTENA),
+          getreg32(NVIC_SYSTICK_CTRL_ENABLE));
 #endif
   irqinfo("  IRQ ENABLE: %08x %08x\n",
           getreg32(NVIC_IRQ0_31_ENABLE), getreg32(NVIC_IRQ32_63_ENABLE));
@@ -370,7 +375,9 @@ void up_irqinitialize(void)
   /* Set the priority of the SVCall interrupt */
 
 #ifdef CONFIG_ARCH_IRQPRIO
-  /* up_prioritize_irq(NRF52_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); */
+#  if 0
+  up_prioritize_irq(NRF52_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN);
+#  endif
 #endif
 
 #ifdef CONFIG_ARMV7M_USEBASEPRI
@@ -413,10 +420,10 @@ void up_irqinitialize(void)
   putreg32(regval, NVIC_DEMCR);
 #endif
 
-#ifdef CONFIG_NRF52_GPIOIRQ
-  /* Initialize GPIO interrupts */
+#ifdef CONFIG_NRF52_GPIOTE
+  /* Initialize GPIOTE */
 
-  nrf52_gpio_irqinitialize();
+  nrf52_gpiote_init();
 #endif
 
 #ifndef CONFIG_SUPPRESS_INTERRUPTS
diff --git a/arch/arm/src/nrf52/nrf52_lowputc.c b/arch/arm/src/nrf52/nrf52_lowputc.c
index 68f7600..212d1ab 100644
--- a/arch/arm/src/nrf52/nrf52_lowputc.c
+++ b/arch/arm/src/nrf52/nrf52_lowputc.c
@@ -114,8 +114,7 @@ static const struct uart_config_s g_console_config =
  ****************************************************************************/
 
 #ifdef HAVE_UART_DEVICE
-static void nrf52_setbaud(uintptr_t base,
-                          FAR const struct uart_config_s *config)
+static void nrf52_setbaud(uintptr_t base, const struct uart_config_s *config)
 {
   uint32_t br = 0;
 
@@ -164,8 +163,7 @@ void nrf52_lowsetup(void)
  ****************************************************************************/
 
 #ifdef HAVE_UART_DEVICE
-void nrf52_usart_configure(uintptr_t base,
-                           FAR const struct uart_config_s *config)
+void nrf52_usart_configure(uintptr_t base, const struct uart_config_s *config)
 {
   uint32_t pin    = 0;
   uint32_t port   = 0;
@@ -186,8 +184,8 @@ void nrf52_usart_configure(uintptr_t base,
 
   /* Setect TX pins for UART */
 
-  pin = (config->txpin & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
-  port = (config->txpin & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+  pin  = GPIO_PIN_DECODE(config->txpin);
+  port = GPIO_PORT_DECODE(config->txpin);
 
   regval = (pin << UART_PSELTXD_PIN_SHIFT);
   regval |= (port << UART_PSELTXD_PORT_SHIFT);
@@ -195,8 +193,8 @@ void nrf52_usart_configure(uintptr_t base,
 
   /* Setect RX pins for UART */
 
-  pin = (config->rxpin & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
-  port = (config->rxpin & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+  pin  = GPIO_PIN_DECODE(config->rxpin);
+  port = GPIO_PORT_DECODE(config->rxpin);
 
   regval = (pin << UART_PSELRXD_PIN_SHIFT);
   regval |= (port << UART_PSELRXD_PORT_SHIFT);
@@ -218,8 +216,7 @@ void nrf52_usart_configure(uintptr_t base,
  ****************************************************************************/
 
 #ifdef HAVE_UART_DEVICE
-void nrf52_usart_disable(uintptr_t base,
-                         FAR const struct uart_config_s *config)
+void nrf52_usart_disable(uintptr_t base, const struct uart_config_s *config)
 {
   /* Disable interrupts */
 
diff --git a/arch/arm/src/nrf52/nrf52_lowputc.h b/arch/arm/src/nrf52/nrf52_lowputc.h
index aac31d9..d587c3d 100644
--- a/arch/arm/src/nrf52/nrf52_lowputc.h
+++ b/arch/arm/src/nrf52/nrf52_lowputc.h
@@ -1,4 +1,4 @@
-/************************************************************************************
+/****************************************************************************
  * arch/arm/src/nrf52/nrf52_lowputc.h
  *
  *   Copyright (C) 2018 Gregory Nutt. All rights reserved.
@@ -31,14 +31,14 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 #ifndef __ARCH_ARM_SRC_NRF52_NRF52_LOWPUTC_H
 #define __ARCH_ARM_SRC_NRF52_NRF52_LOWPUTC_H
 
-/************************************************************************************
+/****************************************************************************
  * Included Files
- ************************************************************************************/
+ ****************************************************************************/
 
 #include <nuttx/config.h>
 
@@ -46,9 +46,9 @@
 #include <stdbool.h>
 #include <nrf52_gpio.h>
 
-/************************************************************************************
+/****************************************************************************
  * Public Types
- ************************************************************************************/
+ ****************************************************************************/
 
 #ifdef HAVE_UART_DEVICE
 /* This structure describes the configuration of an UART */
@@ -58,56 +58,56 @@ struct uart_config_s
   uint32_t baud;          /* Configured baud */
   uint8_t  parity;        /* 0=none, 1=odd, 2=even */
   uint8_t  bits;          /* Number of bits (5-9) */
-  bool     stopbits2;     /* true: Configure with 2 stop bits instead of 1 */
+  bool     stopbits2;     /* Configure with 2 stop bits instead of 1 */
 #ifdef CONFIG_SERIAL_IFLOWCONTROL
-  bool     iflow;         /* true: Input flow control supported */
+  bool     iflow;         /* Input flow control supported */
 #endif
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
-  bool     oflow;         /* true: Output flow control supported. */
+  bool     oflow;         /* Output flow control supported. */
 #endif
   nrf52_pinset_t txpin;   /* TX pin */
   nrf52_pinset_t rxpin;   /* RX pin */
 };
 #endif
 
-/************************************************************************************
+/****************************************************************************
  * Public Functions
- ************************************************************************************/
+ ****************************************************************************/
 
-/************************************************************************************
+/****************************************************************************
  * Name: nrf52_lowsetup
  *
  * Description:
- *   Called at the very beginning of _start.  Performs low level initialization
- *   including setup of the console UART.  This UART initialization is done
- *   early so that the serial console is available for debugging very early in
- *   the boot sequence.
+ *   Called at the very beginning of _start. Performs low level
+ *   initialization including setup of the console UART. This UART
+ *   initialization is done early so that the serial console is available
+ *   for debugging very early in the boot sequence.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 void nrf52_lowsetup(void);
 
-/************************************************************************************
+/****************************************************************************
  * Name: nrf52_usart_configure
  *
  * Description:
  *   Configure a UART for non-interrupt driven operation
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 #ifdef HAVE_UART_DEVICE
 void nrf52_usart_configure(uintptr_t base,
                            FAR const struct uart_config_s *config);
 #endif
 
-/************************************************************************************
+/****************************************************************************
  * Name: nrf52_usart_disable
  *
  * Description:
  *   Disable a UART.  it will be necessary to again call
  *   nrf52_usart_configure() in order to use this UART channel again.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 #ifdef HAVE_UART_DEVICE
 void nrf52_usart_disable(uintptr_t base,
diff --git a/arch/arm/src/nrf52/nrf52_spi.c b/arch/arm/src/nrf52/nrf52_spi.c
new file mode 100644
index 0000000..9b67e84
--- /dev/null
+++ b/arch/arm/src/nrf52/nrf52_spi.c
@@ -0,0 +1,1017 @@
+/****************************************************************************
+ * arch/arm/src/nrf52/nrf52_spi.c
+ *
+ *   Copyright (C) 2019 Gregory Nutt. All rights reserved.
+ *   Author: Mateusz Szafoni <ra...@railab.me>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name NuttX 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 OWNER 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/semaphore.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+
+#include "nrf52_gpio.h"
+#include "nrf52_spi.h"
+
+#include "hardware/nrf52_spi.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* I2C0/SPI0 and I2C1/SPI1 share the same peripherals */
+
+#if defined(CONFIG_NRF52_I2C0_MASTER) && defined(CONFIG_NRF52_SPI0_MASTER)
+#  error Unsupported configuration I2C0 + SPI0
+#endif
+#if defined(CONFIG_NRF52_I2C1_MASTER) && defined(CONFIG_NRF52_SPI1_MASTER)
+#  error Unsupported configuration I2C1 + SPI1
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct nrf52_spidev_s
+{
+  struct spi_dev_s spidev;     /* Externally visible part of the SPI interface */
+  uint32_t         base;       /* Base address of SPI register */
+#ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS
+  uint32_t         irq;        /* SPI IRQ number */
+#endif
+  uint32_t         sck_pin;    /* SCK pin configuration */
+  uint32_t         mosi_pin;   /* MOSI pin configuration */
+  uint32_t         miso_pin;   /* MISO pin configuration */
+  uint32_t         frequency;  /* Requested clock frequency */
+  uint8_t          mode;       /* Mode 0,1,2,3 */
+
+  sem_t            exclsem;    /* Held while chip is selected for mutual exclusion */
+#ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS
+  sem_t            sem_isr;    /* Interrupt wait semaphore */
+#endif
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static inline void nrf52_spi_putreg(FAR struct nrf52_spidev_s *priv,
+                                    uint32_t offset,
+                                    uint32_t value);
+static inline uint32_t nrf52_spi_getreg(FAR struct nrf52_spidev_s *priv,
+                                        uint32_t offset);
+
+/* SPI methods */
+
+static int nrf52_spi_lock(FAR struct spi_dev_s *dev, bool lock);
+static uint32_t nrf52_spi_setfrequency(FAR struct spi_dev_s *dev,
+                                       uint32_t frequency);
+static void nrf52_spi_setmode(FAR struct spi_dev_s *priv,
+                              enum spi_mode_e mode);
+static void nrf52_spi_setbits(FAR struct spi_dev_s *priv, int nbits);
+#ifdef CONFIG_SPI_HWFEATURES
+static int nrf52_spi_hwfeatures(FAR struct spi_dev_s *dev,
+                                spi_hwfeatures_t features);
+#endif
+static uint16_t nrf52_spi_send(FAR struct spi_dev_s *dev, uint16_t wd);
+static void nrf52_spi_exchange(FAR struct spi_dev_s *dev,
+                               FAR const void *txbuffer,
+                               FAR void *rxbuffer, size_t nwords);
+#ifndef CONFIG_SPI_EXCHANGE
+static void nrf52_spi_sndblock(FAR struct spi_dev_s *dev,
+                               FAR const void *txbuffer,
+                               size_t nwords);
+static void nrf52_spi_recvblock(FAR struct spi_dev_s *dev,
+                                FAR void *rxbuffer,
+                                size_t nwords);
+#endif
+
+#ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS
+static int nrf52_spi_isr(int irq, FAR void *context, FAR void *arg);
+#endif
+
+/* Initialization */
+
+static int nrf52_spi_init(FAR struct nrf52_spidev_s *priv);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* SPI0 */
+
+#ifdef CONFIG_NRF52_SPI0_MASTER
+static const struct spi_ops_s g_spi0ops =
+{
+  .lock              = nrf52_spi_lock,
+  .select            = nrf52_spi0select,
+  .setfrequency      = nrf52_spi_setfrequency,
+  .setmode           = nrf52_spi_setmode,
+  .setbits           = nrf52_spi_setbits,
+#  ifdef CONFIG_SPI_HWFEATURES
+  .hwfeatures        = nrf52_spi_hwfeatures,
+#  endif
+  .status            = nrf52_spi0status,
+#  ifdef CONFIG_SPI_CMDDATA
+  .cmddata           = nrf52_spi1cmddata,
+#  endif
+  .send              = nrf52_spi_send,
+#  ifdef CONFIG_SPI_EXCHANGE
+  .exchange          = nrf52_spi_exchange,
+#  else
+  .sendlock          = nrf52_spi_sendblock,
+  .recvblock         = nrf52_spi_recvblock
+#  endif
+};
+
+static struct nrf52_spidev_s g_spi0dev =
+{
+  .spidev    =
+  {
+    &g_spi0ops
+  },
+
+  .base      = NRF52_SPIM0_BASE,
+#ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS
+  .irq       = NRF52_IRQ_SPI_TWI_0,
+#endif
+  .sck_pin   = BOARD_SPI0_SCK_PIN,
+  .mosi_pin  = BOARD_SPI0_MOSI_PIN,
+  .miso_pin  = BOARD_SPI0_MISO_PIN,
+  .frequency = 0,
+  .mode      = 0
+};
+#endif
+
+/* SPI1 */
+
+#ifdef CONFIG_NRF52_SPI1_MASTER
+static const struct spi_ops_s g_spi1ops =
+{
+  .lock              = nrf52_spi_lock,
+  .select            = nrf52_spi1select,
+  .setfrequency      = nrf52_spi_setfrequency,
+  .setmode           = nrf52_spi_setmode,
+  .setbits           = nrf52_spi_setbits,
+#  ifdef CONFIG_SPI_HWFEATURES
+  .hwfeatures        = nrf52_spi_hwfeatures,
+#  endif
+  .status            = nrf52_spi1status,
+#  ifdef CONFIG_SPI_CMDDATA
+  .cmddata           = nrf52_spi1cmddata,
+#  endif
+  .send              = nrf52_spi_send,
+#  ifdef CONFIG_SPI_EXCHANGE
+  .exchange          = nrf52_spi_exchange,
+#  else
+  .sendlock          = nrf52_spi_sendblock,
+  .recvblock         = nrf52_spi_recvblock
+#  endif
+};
+
+static struct nrf52_spidev_s g_spi1dev =
+{
+  .spidev    =
+  {
+    &g_spi1ops
+  },
+
+  .base      = NRF52_SPIM0_BASE,
+#ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS
+  .irq       = NRF52_IRQ_SPI_TWI_1,
+#endif
+  .sck_pin   = BOARD_SPI1_SCK_PIN,
+  .mosi_pin  = BOARD_SPI1_MOSI_PIN,
+  .miso_pin  = BOARD_SPI1_MISO_PIN,
+  .frequency = 0,
+  .mode      = 0
+};
+#endif
+
+/* SPI2 */
+
+#ifdef CONFIG_NRF52_SPI2_MASTER
+static const struct spi_ops_s g_spi2ops =
+{
+  .lock              = nrf52_spi_lock,
+  .select            = nrf52_spi2select,
+  .setfrequency      = nrf52_spi_setfrequency,
+  .setmode           = nrf52_spi_setmode,
+  .setbits           = nrf52_spi_setbits,
+#  ifdef CONFIG_SPI_HWFEATURES
+  .hwfeatures        = nrf52_spi_hwfeatures,
+#  endif
+  .status            = nrf52_spi2status,
+#  ifdef CONFIG_SPI_CMDDATA
+  .cmddata           = nrf52_spi1cmddata,
+#  endif
+  .send              = nrf52_spi_send,
+#  ifdef CONFIG_SPI_EXCHANGE
+  .exchange          = nrf52_spi_exchange,
+#  else
+  .sendlock          = nrf52_spi_sendblock,
+  .recvblock         = nrf52_spi_recvblock
+#  endif
+};
+
+static struct nrf52_spidev_s g_spi2dev =
+{
+  .spidev    =
+  {
+    &g_spi2ops
+  },
+
+  .base      = NRF52_SPIM0_BASE,
+#ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS
+  .irq       = NRF52_IRQ_SPI2,
+#endif
+  .sck_pin   = BOARD_SPI2_SCK_PIN,
+  .mosi_pin  = BOARD_SPI2_MOSI_PIN,
+  .miso_pin  = BOARD_SPI2_MISO_PIN,
+  .frequency = 0,
+  .mode      = 0
+};
+#endif
+
+/* SPI3 */
+
+#ifdef CONFIG_NRF52_SPI3_MASTER
+static const struct spi_ops_s g_spi3ops =
+{
+  .lock              = nrf52_spi_lock,
+  .select            = nrf52_spi3select,
+  .setfrequency      = nrf52_spi_setfrequency,
+  .setmode           = nrf52_spi_setmode,
+  .setbits           = nrf52_spi_setbits,
+#  ifdef CONFIG_SPI_HWFEATURES
+  .hwfeatures        = nrf52_spi_hwfeatures,
+#  endif
+  .status            = nrf52_spi3status,
+#  ifdef CONFIG_SPI_CMDDATA
+  .cmddata           = nrf52_spi1cmddata,
+#  endif
+  .send              = nrf52_spi_send,
+#  ifdef CONFIG_SPI_EXCHANGE
+  .exchange          = nrf52_spi_exchange,
+#  else
+  .sendlock          = nrf52_spi_sendblock,
+  .recvblock         = nrf52_spi_recvblock
+#  endif
+};
+
+static struct nrf52_spidev_s g_spi3dev =
+{
+  .spidev    =
+  {
+    &g_spi3ops
+  },
+
+  .base      = NRF52_SPIM0_BASE,
+#ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS
+  .irq       = NRF52_IRQ_SPI3,
+#endif
+  .sck_pin   = BOARD_SPI3_SCK_PIN,
+  .mosi_pin  = BOARD_SPI3_MOSI_PIN,
+  .miso_pin  = BOARD_SPI3_MISO_PIN,
+  .frequency = 0,
+  .mode      = 0
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_spi_putreg
+ *
+ * Description:
+ *   Put a 32-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline void nrf52_spi_putreg(FAR struct nrf52_spidev_s *priv,
+                                    uint32_t offset,
+                                    uint32_t value)
+{
+  putreg32(value, priv->base + offset);
+}
+
+/****************************************************************************
+ * Name: nrf52_spi_getreg
+ *
+ * Description:
+ *   Get a 32-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline uint32_t nrf52_spi_getreg(FAR struct nrf52_spidev_s *priv,
+                                        uint32_t offset)
+{
+  return getreg32(priv->base + offset);
+}
+
+/****************************************************************************
+ * Name: nrf52_spi_isr
+ *
+ * Description:
+ *   Common SPI interrupt service routine
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS
+static int nrf52_spi_isr(int irq, FAR void *context, FAR void *arg)
+{
+  FAR struct nrf52_spidev_s *priv = (FAR struct nrf52_spidev_s *)arg;
+  uint32_t regval = 0;
+
+  /* Get interrupt event */
+
+  if (nrf52_spi_getreg(priv, NRF52_SPIM_EVENTS_END_OFFSET) == 1)
+    {
+      /* Transfer is complete */
+
+      nxsem_post(&priv->sem_isr);
+
+      /* Clear event */
+
+      nrf52_spi_putreg(priv, NRF52_SPIM_EVENTS_END_OFFSET, 0);
+    }
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: nrf52_spi_init
+ *
+ * Description:
+ *   Configure SPI
+ *
+ ****************************************************************************/
+
+static int nrf52_spi_init(FAR struct nrf52_spidev_s *priv)
+{
+  uint32_t regval = 0;
+  int      pin    = 0;
+  int      port   = 0;
+
+  /* Disable SPI */
+
+  nrf52_spi_putreg(priv, NRF52_SPIM_ENABLE_OFFSET, SPIM_ENABLE_DIS);
+
+  /* Configure SPI pins */
+
+  nrf52_gpio_config(priv->sck_pin);
+  nrf52_gpio_config(priv->mosi_pin);
+  nrf52_gpio_config(priv->miso_pin);
+
+  /* Select SCK pins */
+
+  pin  = GPIO_PIN_DECODE(priv->sck_pin);
+  port = GPIO_PORT_DECODE(priv->sck_pin);
+
+  regval = (pin << SPIM_PSELSCK_PIN_SHIFT);
+  regval |= (port << SPIM_PSELSCK_PORT_SHIFT);
+  nrf52_spi_putreg(priv, NRF52_SPIM_PSELSCK_OFFSET, regval);
+
+  /* Select MOSI pins */
+
+  pin  = GPIO_PIN_DECODE(priv->mosi_pin);
+  port = GPIO_PORT_DECODE(priv->mosi_pin);
+
+  regval = (pin << SPIM_PSELMOSI_PIN_SHIFT);
+  regval |= (port << SPIM_PSELMOSI_PORT_SHIFT);
+  nrf52_spi_putreg(priv, NRF52_SPIM_PSELMOSI_OFFSET, regval);
+
+  /* According to manual we have to write 0 to MOSI pin */
+
+  nrf52_gpio_write(priv->mosi_pin, false);
+
+  /* Select MISO pins */
+
+  pin   = GPIO_PIN_DECODE(priv->miso_pin);
+  port  = GPIO_PORT_DECODE(priv->miso_pin);
+
+  regval = (pin << SPIM_PSELMISO_PIN_SHIFT);
+  regval |= (port << SPIM_PSELMISO_PORT_SHIFT);
+  nrf52_spi_putreg(priv, NRF52_SPIM_PSELMISO_OFFSET, regval);
+
+  /* NOTE: Chip select pin must be configured by board-specific logic */
+
+#ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS
+  /* Enable interrupts for RX and TX done */
+
+  regval = SPIM_INT_END;
+  nrf52_spi_putreg(priv, NRF52_SPIM_INTENSET_OFFSET, regval);
+#endif
+
+  /* Enable SPI */
+
+  nrf52_spi_putreg(priv, NRF52_SPIM_ENABLE_OFFSET, SPIM_ENABLE_EN);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_spi_lock
+ *
+ * Description:
+ *   On SPI busses where there are multiple devices, it will be necessary to
+ *   lock SPI to have exclusive access to the busses for a sequence of
+ *   transfers.  The bus should be locked before the chip is selected. After
+ *   locking the SPI bus, the caller should then also call the setfrequency,
+ *   setbits, and setmode methods to make sure that the SPI is properly
+ *   configured for the device.  If the SPI buss is being shared, then it
+ *   may have been left in an incompatible state.
+ *
+ * Input Parameters:
+ *   dev  - Device-specific state data
+ *   lock - true: Lock spi bus, false: unlock SPI bus
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static int nrf52_spi_lock(FAR struct spi_dev_s *dev, bool lock)
+{
+  FAR struct nrf52_spidev_s *priv = (FAR struct nrf52_spidev_s *)dev;
+  int ret = OK;
+
+  if (lock)
+    {
+      /* Take the semaphore (perhaps waiting) */
+
+      do
+        {
+          ret = nxsem_wait(&priv->exclsem);
+
+          /* The only case that an error should occur here is if the wait
+           * was awakened by a signal.
+           */
+
+          DEBUGASSERT(ret == OK || ret == -EINTR);
+        }
+      while (ret == -EINTR);
+    }
+  else
+    {
+      (void)nxsem_post(&priv->exclsem);
+      ret = OK;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_spi_setfrequency
+ *
+ * Description:
+ *   Set the SPI frequency.
+ *
+ * Input Parameters:
+ *   dev -       Device-specific state data
+ *   frequency - The SPI frequency requested
+ *
+ * Returned Value:
+ *   Returns the actual frequency selected
+ *
+ ****************************************************************************/
+
+static uint32_t nrf52_spi_setfrequency(FAR struct spi_dev_s *dev,
+                                       uint32_t frequency)
+{
+  FAR struct nrf52_spidev_s *priv = (FAR struct nrf52_spidev_s *)dev;
+  uint32_t regval = 0;
+
+  if (priv->frequency == frequency)
+    {
+      /* We are already at this frequency */
+
+      return priv->frequency;
+    }
+
+  /* Frequencies are hardcoded */
+
+  switch (frequency)
+    {
+      case 125000:
+      {
+        regval = SPIM_FREQUENCY_125KBPS;
+        break;
+      }
+
+      case 250000:
+        {
+          regval = SPIM_FREQUENCY_250KBPS;
+          break;
+        }
+
+      case 500000:
+        {
+          regval = SPIM_FREQUENCY_500KBPS;
+          break;
+        }
+
+      case 1000000:
+        {
+          regval = SPIM_FREQUENCY_1MBPS;
+          break;
+        }
+
+      case 2000000:
+      {
+        regval = SPIM_FREQUENCY_2MBPS;
+        break;
+      }
+
+      case 4000000:
+        {
+          regval = SPIM_FREQUENCY_4MBPS;
+          break;
+        }
+
+      case 8000000:
+        {
+          regval = SPIM_FREQUENCY_8MBPS;
+          break;
+        }
+
+      default:
+        {
+          spierr("Frequency unsupported %d\n", frequency);
+          goto errout;
+        }
+    }
+
+  /* Write register */
+
+  nrf52_spi_putreg(priv, NRF52_SPIM_FREQUENCY_OFFSET, regval);
+
+  /* Save the frequency setting */
+
+  priv->frequency = frequency;
+
+  spiinfo("Frequency %d\n", frequency);
+
+errout:
+  return priv->frequency;
+}
+
+/****************************************************************************
+ * Name: nrf52_spi_setmode
+ *
+ * Description:
+ *   Set the SPI mode.  see enum spi_mode_e for mode definitions
+ *
+ * Input Parameters:
+ *   dev  - Device-specific state data
+ *   mode - The SPI mode requested
+ *
+ * Returned Value:
+ *   Returns the actual frequency selected
+ *
+ ****************************************************************************/
+
+static void nrf52_spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
+{
+  FAR struct nrf52_spidev_s *priv = (FAR struct nrf52_spidev_s *)dev;
+  uint32_t regval = 0;
+
+  spiinfo("mode=%d\n", mode);
+
+  /* Has the mode changed? */
+
+  if (mode != priv->mode)
+    {
+      regval = nrf52_spi_getreg(priv, NRF52_SPIM_CONFIG_OFFSET);
+      regval &= ~(SPIM_CONFIG_CPHA | SPIM_CONFIG_CPOL);
+
+      switch (mode)
+        {
+          case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */
+            {
+              break;
+            }
+
+          case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */
+            {
+              regval |= SPIM_CONFIG_CPHA;
+              break;
+            }
+
+          case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */
+            {
+              regval |= SPIM_CONFIG_CPOL;
+              break;
+            }
+
+          case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */
+            {
+              regval |= SPIM_CONFIG_CPHA;
+              regval |= SPIM_CONFIG_CPOL;
+              break;
+            }
+
+          default:
+            {
+              DEBUGASSERT(0);
+              return;
+            }
+        }
+
+      /* According to manual we have to set SCK pin output
+       * value the same as CPOL value
+       */
+
+      if (mode == SPIDEV_MODE2 || mode == SPIDEV_MODE3)
+        {
+          nrf52_gpio_write(priv->sck_pin, true);
+        }
+      else
+        {
+          nrf52_gpio_write(priv->sck_pin, false);
+        }
+
+      priv->mode = mode;
+    }
+}
+
+/****************************************************************************
+ * Name: nrf52_spi_setbits
+ *
+ * Description:
+ *   Set the number of bits per word.
+ *
+ * Input Parameters:
+ *   dev   - Device-specific state data
+ *   nbits - The number of bits requested
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void nrf52_spi_setbits(FAR struct spi_dev_s *dev, int nbits)
+{
+  if (nbits != 8)
+    {
+      spierr("ERROR: nbits not supported: %d\n", nbits);
+    }
+
+  return;
+}
+
+/****************************************************************************
+ * Name: nrf52_spi_hwfeatures
+ *
+ * Description:
+ *   Set hardware-specific feature flags.
+ *
+ * Input Parameters:
+ *   dev      - Device-specific state data
+ *   features - H/W feature flags
+ *
+ * Returned Value:
+ *   Zero (OK) if the selected H/W features are enabled; A negated errno
+ *   value if any H/W feature is not supportable.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SPI_HWFEATURES
+static int nrf52_spi_hwfeatures(FAR struct spi_dev_s *dev,
+                                spi_hwfeatures_t features)
+{
+#ifdef CONFIG_SPI_BITORDER
+  FAR struct nrf52_spidev_s *priv = (FAR struct nrf52_spidev_s *)dev;
+  uint32_t setbits = 0;
+  uint32_t clrbits = 0;
+
+  spiinfo("features=%08x\n", features);
+
+  /* Transfer data LSB first? */
+
+  if ((features & HWFEAT_LSBFIRST) != 0)
+    {
+      setbits = SPIM_CONFIG_ORDER;
+      clrbits = 0;
+    }
+  else
+    {
+      setbits = 0;
+      clrbits = SPIM_CONFIG_ORDER;
+    }
+
+  regval = nrf52_spi_getreg(priv, NRF52_SPIM_CONFIG_OFFSET);
+  regval &= ~clrbits;
+  regval |= setbits;
+  nrf52_spi_putreg(priv, NRF52_SPIM_CONFIG_OFFSET, regval);
+
+#endif
+  /* Other H/W features are not supported */
+
+  return ((features & ~HWFEAT_LSBFIRST) == 0) ? OK : -ENOSYS;
+}
+#endif
+
+/****************************************************************************
+ * Name: n4f52_spi_send
+ *
+ * Description:
+ *   Exchange one word on SPI
+ *
+ * Input Parameters:
+ *   dev - Device-specific state data
+ *   wd  - The word to send.  the size of the data is determined by the
+ *         number of bits selected for the SPI interface.
+ *
+ * Returned Value:
+ *   response
+ *
+ ****************************************************************************/
+
+static uint16_t nrf52_spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
+{
+  uint16_t ret = 0;
+
+  /* Exchange one word on SPI */
+
+  nrf52_spi_exchange(dev, &wd, &ret, 1);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_spi_exchange
+ *
+ * Description:
+ *   Exchange a block of data on SPI without using DMA
+ *
+ * Input Parameters:
+ *   dev      - Device-specific state data
+ *   txbuffer - A pointer to the buffer of data to be sent
+ *   rxbuffer - A pointer to a buffer in which to receive data
+ *   nwords   - the length of data to be exchaned in units of words.
+ *              The wordsize is determined by the number of bits-per-word
+ *              selected for the SPI interface.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void nrf52_spi_exchange(FAR struct spi_dev_s *dev,
+                               FAR const void *txbuffer,
+                               FAR void *rxbuffer, size_t nwords)
+{
+  FAR struct nrf52_spidev_s *priv = (FAR struct nrf52_spidev_s *)dev;
+  uint32_t regval = 0;
+
+  if (rxbuffer != NULL)
+    {
+      /* Write RXD data pointer */
+
+      regval = (uint32_t)rxbuffer;
+      nrf52_spi_putreg(priv, NRF52_SPIM_RXDPTR_OFFSET, regval);
+
+      /* Write number of bytes in RXD buffer */
+
+      regval = nwords;
+      nrf52_spi_putreg(priv, NRF52_SPIM_RXDMAXCNT_OFFSET, regval);
+    }
+
+  if (txbuffer != NULL)
+    {
+      /* Write TXD data pointer */
+
+      regval = (uint32_t)txbuffer;
+      nrf52_spi_putreg(priv, NRF52_SPIM_TXDPTR_OFFSET, regval);
+
+      /* Write number of bytes in TXD buffer */
+
+      regval = nwords;
+      nrf52_spi_putreg(priv, NRF52_SPIM_TXDMAXCNT_OFFSET, regval);
+    }
+
+  /* SPI start */
+
+  nrf52_spi_putreg(priv, NRF52_SPIM_TASK_START_OFFSET, SPIM_TASKS_START);
+
+#ifndef CONFIG_NRF52_SPI_MASTER_INTERRUPTS
+  /* Wait for RX done and TX done */
+
+  while (nrf52_spi_getreg(priv, NRF52_SPIM_EVENTS_END_OFFSET) != 1);
+
+  /* Clear event */
+
+  nrf52_spi_putreg(priv, NRF52_SPIM_EVENTS_END_OFFSET, 0);
+#else
+  /* Wait for transfer complete */
+
+  nxsem_wait(&priv->sem_isr);
+#endif
+
+  /* SPI stop */
+
+  nrf52_spi_putreg(priv, NRF52_SPIM_TASK_STOP_OFFSET, SPIM_TASKS_STOP);
+
+  /* Wait for STOP event */
+
+  while (nrf52_spi_getreg(priv, NRF52_SPIM_EVENTS_STOPPED_OFFSET) != 1);
+
+  /* Clear event */
+
+  nrf52_spi_putreg(priv, NRF52_SPIM_EVENTS_STOPPED_OFFSET, 0);
+
+  /* Clear RX/TX DMA after tranfer */
+
+  nrf52_spi_putreg(priv, NRF52_SPIM_RXDPTR_OFFSET, 0);
+  nrf52_spi_putreg(priv, NRF52_SPIM_RXDMAXCNT_OFFSET, 0);
+  nrf52_spi_putreg(priv, NRF52_SPIM_TXDPTR_OFFSET, 0);
+  nrf52_spi_putreg(priv, NRF52_SPIM_TXDMAXCNT_OFFSET, 0);
+}
+
+#ifndef CONFIG_SPI_EXCHANGE
+
+/****************************************************************************
+ * Name: nrf52_spi_sndblock
+ *
+ * Description:
+ *   Send a block of data on SPI
+ *
+ * Input Parameters:
+ *   dev      - Device-specific state data
+ *   txbuffer - A pointer to the buffer of data to be sent
+ *   nwords   - the length of data to send from the buffer in number of words.
+ *              The wordsize is determined by the number of bits-per-word
+ *              selected for the SPI interface.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void nrf52_spi_sndblock(FAR struct spi_dev_s *dev,
+                               FAR const void *txbuffer,
+                               size_t nwords)
+{
+  spiinfo("txbuffer=%p nwords=%d\n", txbuffer, nwords);
+  return nrf52_spi_exchange(dev, txbuffer, NULL, nwords);
+}
+
+/****************************************************************************
+ * Name: nrf52_spi_recvblock
+ *
+ * Description:
+ *   Receive a block of data from SPI
+ *
+ * Input Parameters:
+ *   dev      - Device-specific state data
+ *   rxbuffer - A pointer to the buffer in which to receive data
+ *   nwords   - the length of data that can be received in the buffer in
+ *              number of words. The wordsize is determined by the number of
+ *              bits-per-word selected for the SPI interface.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void nrf52_spi_recvblock(FAR struct spi_dev_s *dev,
+                                FAR void *rxbuffer,
+                                size_t nwords)
+{
+  spiinfo("txbuffer=%p nwords=%d\n", txbuffer, nwords);
+  return nrf52_spi_exchange(dev, txbuffer, NULL, nwords);
+}
+#endif  /* CONFIG_SPI_EXCHANGE */
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_spibus_initialize
+ *
+ * Description:
+ *   Initialize the selected SPI port.
+ *
+ * Input Parameters:
+ *   Port number (for hardware that has multiple SPI interfaces)
+ *
+ * Returned Value:
+ *   Valid SPI device structure reference on success; a NULL on failure
+ *
+ ****************************************************************************/
+
+FAR struct spi_dev_s *nrf52_spibus_initialize(int port)
+{
+  FAR struct nrf52_spidev_s *priv = NULL;
+
+  /* Get SPI driver data */
+
+  switch (port)
+    {
+#ifdef CONFIG_NRF52_SPI0_MASTER
+      case 0:
+        {
+          priv = &g_spi0dev;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_NRF52_SPI1_MASTER
+      case 1:
+        {
+          priv = &g_spi1dev;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_NRF52_SPI2_MASTER
+      case 2:
+        {
+          priv = &g_spi2dev;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_NRF52_SPI3_MASTER
+      case 3:
+        {
+          priv = &g_spi3dev;
+          break;
+        }
+#endif
+
+      default:
+        {
+          goto errout;
+        }
+    }
+
+  /* Initialize the SPI */
+
+  nrf52_spi_init(priv);
+
+  /* Initialize the SPI semaphore */
+
+  nxsem_init(&priv->exclsem, 0, 1);
+
+#ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS
+  /* This semaphore is used for signaling and, hence, should not have
+   * priority inheritance enabled.
+   */
+
+  nxsem_init(&priv->sem_isr, 0, 0);
+  nxsem_setprotocol(&priv->sem_isr, SEM_PRIO_NONE);
+
+  /* Attach SPI interrupt */
+
+  irq_attach(priv->irq, nrf52_spi_isr, priv);
+  up_enable_irq(priv->irq);
+#endif
+
+errout:
+  return (FAR struct spi_dev_s *)priv;
+}
diff --git a/arch/arm/src/nrf52/nrf52_spi.h b/arch/arm/src/nrf52/nrf52_spi.h
new file mode 100644
index 0000000..c87e7db
--- /dev/null
+++ b/arch/arm/src/nrf52/nrf52_spi.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+ * arch/arm/src/nrf52/nrf52_spi.h
+ *
+ *   Copyright (C) 2019 Gregory Nutt. All rights reserved.
+ *   Author: Mateusz Szafoni <ra...@railab.me>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name NuttX 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 OWNER 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 __ARCH_ARM_SRC_NRF52_NRF52_SPI_H
+#define __ARCH_ARM_SRC_NRF52_NRF52_SPI_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/spi/spi.h>
+
+#include "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_spibus_initialize
+ *
+ * Description:
+ *   Initialize the selected SPI port.
+ *
+ * Input Parameters:
+ *   Port number (for hardware that has multiple SPI interfaces)
+ *
+ * Returned Value:
+ *   Valid SPI device structure reference on success; a NULL on failure
+ *
+ ****************************************************************************/
+
+FAR struct spi_dev_s *nrf52_spibus_initialize(int port);
+
+/****************************************************************************
+ * Name:  nrf52_spi0/1/...select and nrf52_spi0/1/...status
+ *
+ * Description:
+ *   The external functions, nrf52_spi0/1/...select, nrf52_spi0/1/...status,
+ *   and nrf52_spi0/1/...cmddata must be provided by board-specific logic.
+ *   These are implementations of the select, status, and cmddata methods of
+ *   the SPI interface defined by struct spi_ops_s (include/nuttx/spi/spi.h).
+ *   All other methods (including nrf52_spibus_initialize()) are provided by
+ *   common NRF52 logic. To use this common SPI logic on your board:
+ *
+ *   1. Provide logic in nrf52_boardinitialize() to configure SPI chip select
+ *      pins.
+ *   2. Provide nrf52_spi0/1/...select() and nrf52_spi0/1/...status()
+ *      functions in your board-specific logic. These functions will perform
+ *      chip selection and status operations using GPIOs in the way your board
+ *      is configured.
+ *   3. If CONFIG_SPI_CMDDATA is defined in your NuttX configuration file,
+ *      then provide nrf52_spi0/1/...cmddata() functions in your
+ *      board-specific logic. These functions will perform cmd/data selection
+ *      operations using GPIOs in the way your board is configured.
+ *   4. Add a calls to nrf52_spibus_initialize() in your low level application
+ *      initialization logic
+ *   5. The handle returned by nrf52_spibus_initialize() may then be used to
+ *      bind the SPI driver to higher level logic (e.g., calling
+ *      mmcsd_spislotinitialize(), for example, will bind the SPI driver to
+ *      the SPI MMC/SD driver).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NRF52_SPI0_MASTER
+void nrf52_spi0select(FAR struct spi_dev_s *dev, uint32_t devid,
+                      bool selected);
+uint8_t nrf52_spi0status(FAR struct spi_dev_s *dev, uint32_t devid);
+int nrf52_spi0cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
+#endif
+
+#ifdef CONFIG_NRF52_SPI1_MASTER
+void nrf52_spi1select(FAR struct spi_dev_s *dev, uint32_t devid,
+                      bool selected);
+uint8_t nrf52_spi1status(FAR struct spi_dev_s *dev, uint32_t devid);
+int nrf52_spi1cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
+#endif
+
+#ifdef CONFIG_NRF52_SPI2_MASTER
+void nrf52_spi2select(FAR struct spi_dev_s *dev, uint32_t devid,
+                      bool selected);
+uint8_t nrf52_spi2status(FAR struct spi_dev_s *dev, uint32_t devid);
+int nrf52_spi2cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
+#endif
+
+#ifdef CONFIG_NRF52_SPI3_MASTER
+void nrf52_spi3select(FAR struct spi_dev_s *dev, uint32_t devid,
+                      bool selected);
+uint8_t nrf52_spi3status(FAR struct spi_dev_s *dev, uint32_t devid);
+int nrf52_spi3cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
+#endif
+
+#endif /* __ARCH_ARM_SRC_NRF52_NRF52_SPI_H */
diff --git a/boards/arm/nrf52/nrf52-feather/include/board.h b/boards/arm/nrf52/nrf52-feather/include/board.h
index b50587b..6a69b9a 100644
--- a/boards/arm/nrf52/nrf52-feather/include/board.h
+++ b/boards/arm/nrf52/nrf52-feather/include/board.h
@@ -43,7 +43,7 @@
 #include <nuttx/config.h>
 #include <stdbool.h>
 
-#if defined(CONFIG_ARCH_IRQBUTTONS) && defined(CONFIG_NRF52_GPIO_IRQ)
+#if defined(CONFIG_ARCH_IRQBUTTONS) && defined(CONFIG_NRF52_GPIOTE)
 #  include <nuttx/irq.h>
 #endif
 
diff --git a/boards/arm/nrf52/nrf52832-dk/include/board.h b/boards/arm/nrf52/nrf52832-dk/include/board.h
index 6488aba..2031729 100644
--- a/boards/arm/nrf52/nrf52832-dk/include/board.h
+++ b/boards/arm/nrf52/nrf52832-dk/include/board.h
@@ -43,7 +43,7 @@
 #include <nuttx/config.h>
 #include <stdbool.h>
 
-#if defined(CONFIG_ARCH_IRQBUTTONS) && defined(CONFIG_NRF52_GPIO_IRQ)
+#if defined(CONFIG_ARCH_IRQBUTTONS) && defined(CONFIG_NRF52_GPIOTE)
 #  include <nuttx/irq.h>
 #endif
 
diff --git a/boards/arm/nrf52/nrf52840-dk/include/board.h b/boards/arm/nrf52/nrf52840-dk/include/board.h
index b207d04..6916d3b 100644
--- a/boards/arm/nrf52/nrf52840-dk/include/board.h
+++ b/boards/arm/nrf52/nrf52840-dk/include/board.h
@@ -43,7 +43,7 @@
 #include <nuttx/config.h>
 #include <stdbool.h>
 
-#if defined(CONFIG_ARCH_IRQBUTTONS) && defined(CONFIG_NRF52_GPIO_IRQ)
+#if defined(CONFIG_ARCH_IRQBUTTONS) && defined(CONFIG_NRF52_GPIOTE)
 #  include <nuttx/irq.h>
 #endif
 
@@ -130,4 +130,26 @@
 #define BOARD_UART1_RX_PIN  (GPIO_INPUT  | GPIO_PORT1 | GPIO_PIN(1))
 #define BOARD_UART1_TX_PIN  (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT1 | GPIO_PIN(2))
 
+/* SPI Pins *****************************************************************/
+
+/* SPI0 - Arduino PINs
+ *   SPI0_SCK  - P1.15 (P13)
+ *   SPI0_MOSI - P1.13 (D11)
+ *   SPI0_MISO - P1.14 (D12)
+ */
+
+#define BOARD_SPI0_SCK_PIN  (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT1 | GPIO_PIN(15))
+#define BOARD_SPI0_MOSI_PIN (GPIO_OUTPUT | GPIO_PORT1 | GPIO_PIN(13))
+#define BOARD_SPI0_MISO_PIN (GPIO_INPUT  | GPIO_PORT1 | GPIO_PIN(14))
+
+/* I2C Pins *****************************************************************/
+
+/* I2C0 (TWI0) - Arduino PINs
+ *    I2C0_SCL - P0.27
+ *    I2C0_SDA - P0.26
+ */
+
+#define BOARD_I2C0_SCL_PIN (GPIO_OUTPUT | GPIO_PORT0 | GPIO_PIN(27))
+#define BOARD_I2C0_SDA_PIN (GPIO_INPUT  | GPIO_PORT0 | GPIO_PIN(26))
+
 #endif  /* __BOARDS_ARM_NRF52_NRF52840_DK_INCLUDE_BOARD_H */
diff --git a/boards/arm/nrf52/nrf52840-dk/src/Makefile b/boards/arm/nrf52/nrf52840-dk/src/Makefile
index b99bdec..53dd1d7 100644
--- a/boards/arm/nrf52/nrf52840-dk/src/Makefile
+++ b/boards/arm/nrf52/nrf52840-dk/src/Makefile
@@ -52,4 +52,16 @@ ifeq ($(CONFIG_ARCH_BUTTONS),y)
 CSRCS += nrf52_buttons.c
 endif
 
+ifeq ($(CONFIG_NRF52_SPI_MASTER),y)
+CSRCS += nrf52_spi.c
+endif
+
+ifeq ($(CONFIG_SENSORS_LSM6DSL),y)
+CSRCS += nrf52_lsm6dsl.c
+endif
+
+ifeq ($(CONFIG_LPWAN_SX127X),y)
+CSRCS += nrf52_sx127x.c
+endif
+
 include $(TOPDIR)/boards/Board.mk
diff --git a/boards/arm/nrf52/nrf52840-dk/src/nrf52840-dk.h b/boards/arm/nrf52/nrf52840-dk/src/nrf52840-dk.h
index 9744b8c..c209e1b 100644
--- a/boards/arm/nrf52/nrf52840-dk/src/nrf52840-dk.h
+++ b/boards/arm/nrf52/nrf52840-dk/src/nrf52840-dk.h
@@ -67,6 +67,16 @@
 #define GPIO_BUTTON3 (GPIO_INPUT | GPIO_PULLUP | GPIO_PORT0 | GPIO_PIN(24))
 #define GPIO_BUTTON4 (GPIO_INPUT | GPIO_PULLUP | GPIO_PORT0 | GPIO_PIN(25))
 
+/* Dragino LORA shield (v1.4) - RF98 module (based on SX127X)
+ * RESET - P1.11 (D9)
+ * CS    - P1.12 (D10)
+ * DIO0  - P1.03 (D2)
+ */
+
+#define GPIO_SX127X_RESET (GPIO_PORT1 | GPIO_PIN(11))
+#define GPIO_SX127X_CS    (GPIO_OUTPUT | GPIO_PORT1 | GPIO_PIN(12))
+#define GPIO_SX127X_DIO0  (GPIO_INPUT  | GPIO_PORT1 | GPIO_PIN(3))
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
@@ -97,5 +107,41 @@
 
 int nrf52_bringup(void);
 
+/****************************************************************************
+ * Name: nrf52_spidev_initialize
+ *
+ * Description:
+ *   Called to configure SPI chip select GPIO pins for the
+ *   nrf52840-dk board.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NRF52_SPI_MASTER
+void nrf52_spidev_initialize(void);
+#endif
+
+/*****************************************************************************
+ * Name: nrf52_lsm6dsl_initialize
+ *
+ * Description:
+ *   Initialize I2C-based LSM6DSL.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SENSORS_LSM303AGR
+int nrf52_lsm6dsl_initialize(char *devpath);
+#endif
+
+/*****************************************************************************
+ * Name: nrf52_lpwaninitialize
+ *
+ * Description:
+ *   Initialize SX127X LPWAN interaface.
+ ****************************************************************************/
+
+#ifdef CONFIG_LPWAN_SX127X
+int nrf52_lpwaninitialize(void);
+#endif
+
 #endif /* __ASSEMBLY__ */
 #endif /* __BOARDS_ARM_NRF52_NRF52840_DK_SRC_NRF52840_DK_H */
diff --git a/boards/arm/nrf52/nrf52840-dk/src/nrf52_boot.c b/boards/arm/nrf52/nrf52840-dk/src/nrf52_boot.c
index af1dca2..1e8bad1 100644
--- a/boards/arm/nrf52/nrf52840-dk/src/nrf52_boot.c
+++ b/boards/arm/nrf52/nrf52840-dk/src/nrf52_boot.c
@@ -71,6 +71,12 @@ void nrf52_board_initialize(void)
 #ifdef CONFIG_ARCH_LEDS
   board_autoled_initialize();
 #endif
+
+#ifdef CONFIG_NRF52_SPI_MASTER
+  /* Configure SPI chip selects */
+
+  nrf52_spidev_initialize();
+#endif
 }
 
 /****************************************************************************
diff --git a/boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c b/boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c
index a5604a9..732efa2 100644
--- a/boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c
+++ b/boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c
@@ -46,11 +46,65 @@
 #  include <nuttx/leds/userled.h>
 #endif
 
+#include "nrf52840-dk.h"
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
+ * Name: nrf52_i2c_register
+ *
+ * Description:
+ *   Register one I2C drivers for the I2C tool.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SYSTEM_I2CTOOL)
+static void nrf52_i2c_register(int bus)
+{
+  struct i2c_master_s *i2c;
+  int ret;
+
+  i2c = nrf52_i2cbus_initialize(bus);
+  if (i2c == NULL)
+    {
+      syslog(LOG_ERR, "ERROR: Failed to get I2C%d interface\n", bus);
+    }
+  else
+    {
+      ret = i2c_register(i2c, bus);
+      if (ret < 0)
+        {
+          syslog(LOG_ERR, "ERROR: Failed to register I2C%d driver: %d\n",
+                 bus, ret);
+          nrf52_i2cbus_uninitialize(i2c);
+        }
+    }
+}
+#endif
+
+/****************************************************************************
+ * Name: nrf52_i2ctool
+ *
+ * Description:
+ *   Register I2C drivers for the I2C tool.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SYSTEM_I2CTOOL)
+static void nrf52_i2ctool(void)
+{
+#ifdef CONFIG_NRF52_I2C0
+  nrf52_i2c_register(0);
+#endif
+#ifdef CONFIG_NRF52_I2C1
+  nrf52_i2c_register(1);
+#endif
+}
+#endif
+
+/****************************************************************************
  * Name: nrf52_bringup
  *
  * Description:
@@ -74,10 +128,32 @@ int nrf52_bringup(void)
   ret = userled_lower_initialize(CONFIG_EXAMPLES_LEDS_DEVPATH);
   if (ret < 0)
     {
-      syslog(LOG_ERR, "ERROR: userled_lower_initialize() failed: %d\n", ret);
+      syslog(LOG_ERR,
+             "ERROR: userled_lower_initialize() failed: %d\n",
+             ret);
     }
 #endif
 
+#ifdef CONFIG_SENSORS_LSM6DSL
+  ret = nrf52_lsm6dsl_initialize("/dev/lsm6dsl0");
+  if (ret < 0)
+    {
+      syslog(LOG_ERR,
+             "ERROR: Failed to initialize LSM6DSL driver: %d\n",
+             ret);
+    }
+#endif  /* CONFIG_SENSORS_LSM6DSL */
+
+#ifdef CONFIG_LPWAN_SX127X
+  ret = nrf52_lpwaninitialize();
+  if (ret < 0)
+    {
+      syslog(LOG_ERR,
+             "ERROR: Failed to initialize wireless driver: %d\n",
+             ret);
+    }
+#endif  /* CONFIG_LPWAN_SX127X */
+
   UNUSED(ret);
   return OK;
 }
diff --git a/boards/arm/nrf52/nrf52840-dk/src/nrf52_boot.c b/boards/arm/nrf52/nrf52840-dk/src/nrf52_lsm6dsl.c
similarity index 63%
copy from boards/arm/nrf52/nrf52840-dk/src/nrf52_boot.c
copy to boards/arm/nrf52/nrf52840-dk/src/nrf52_lsm6dsl.c
index af1dca2..7185662 100644
--- a/boards/arm/nrf52/nrf52840-dk/src/nrf52_boot.c
+++ b/boards/arm/nrf52/nrf52840-dk/src/nrf52_lsm6dsl.c
@@ -1,8 +1,8 @@
-/****************************************************************************
- * boards/arm/nrf52/nrf52840-dk/src/nrf52_boot.c
+/*****************************************************************************
+ * boards/arm/nrf52/nrf52840-dk/src/nrf52_lsm6dsl.c
  *
- *   Copyright (C) 2019 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <gn...@nuttx.org>
+ *   Copyright (C) 2019 Greg Nutt. All rights reserved.
+ *   Author: Mateusz Szafoni <ra...@railab.me>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,67 +30,68 @@
  * 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.
- *
  ****************************************************************************/
 
-/****************************************************************************
+/*****************************************************************************
  * Included Files
  ****************************************************************************/
 
 #include <nuttx/config.h>
+#include <nuttx/arch.h>
 
+#include <errno.h>
 #include <debug.h>
 
 #include <nuttx/board.h>
-#include <arch/board/board.h>
+#include "nrf52_i2c.h"
+#include "nrf52840-dk.h"
+#include <nuttx/sensors/lsm6dsl.h>
 
-#include "up_arch.h"
-#include "up_internal.h"
+/*****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
 
-#include "nrf52840-dk.h"
+#ifndef CONFIG_NRF52_I2C0_MASTER
+#  error "LSM6DSL driver requires CONFIG_NRF52_I2C0_MASTER to be enabled"
+#endif
 
-/****************************************************************************
+/*****************************************************************************
  * Public Functions
  ****************************************************************************/
 
-/****************************************************************************
- * Name: nrf52_board_initialize
+/*****************************************************************************
+ * Name: nrf52_lsm6dsl_initialize
  *
  * Description:
- *   All NRF52xxx architectures must provide the following entry point.
- *   This entry point is called early in the initialization -- after all
- *   memory has been configured and mapped but before any devices have been
- *   initialized.
- *
+ *   Initialize I2C-based LSM6DSL.
  ****************************************************************************/
 
-void nrf52_board_initialize(void)
+int nrf52_lsm6dsl_initialize(char *devpath)
 {
-  /* Configure on-board LEDs if LED support has been selected. */
+  FAR struct i2c_master_s *i2c;
+  int ret = OK;
 
-#ifdef CONFIG_ARCH_LEDS
-  board_autoled_initialize();
-#endif
-}
+  sninfo("Initializing LMS6DSL!\n");
 
-/****************************************************************************
- * Name: board_late_initialize
- *
- * Description:
- *   If CONFIG_BOARD_LATE_INITIALIZE is selected, then an additional
- *   initialization call will be performed in the boot-up sequence to a
- *   function called board_late_initialize().  board_late_initialize() will be
- *   called immediately after up_initialize() is called and just before the
- *   initial application is started.  This additional initialization phase
- *   may be used, for example, to initialize board-specific device drivers.
- *
- ****************************************************************************/
+#ifdef CONFIG_NRF52_I2C0_MASTER
+  i2c = nrf52_i2cbus_initialize(0);
+  if (i2c == NULL)
+    {
+      return -ENODEV;
+    }
 
-#ifdef CONFIG_BOARD_LATE_INITIALIZE
-void board_late_initialize(void)
-{
-  /* Perform board-specific initialization */
+  sninfo("INFO: Initializing LMS6DSL accelero-gyro sensor over I2C%d\n", ret);
 
-  (void)nrf52_bringup();
-}
+  ret = lsm6dsl_sensor_register(devpath, i2c, LSM6DSLACCEL_ADDR1);
+  if (ret < 0)
+    {
+      snerr("ERROR: Failed to initialize LMS6DSL accelero-gyro driver %s\n",
+            devpath);
+      return -ENODEV;
+    }
+
+  sninfo("INFO: LMS6DSL sensor has been initialized successfully\n");
 #endif
+
+  return ret;
+}
diff --git a/boards/arm/nrf52/nrf52840-dk/src/nrf52_spi.c b/boards/arm/nrf52/nrf52840-dk/src/nrf52_spi.c
new file mode 100644
index 0000000..2f66c20
--- /dev/null
+++ b/boards/arm/nrf52/nrf52840-dk/src/nrf52_spi.c
@@ -0,0 +1,206 @@
+/****************************************************************************
+ * boards/arm/nrf52/nrf52840-dk/src/nrf52_spi.c
+ *
+ *   Copyright (C) 2019 Greg Nutt. All rights reserved.
+ *   Author: Mateusz Szafoni <ra...@railab.me>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name NuttX 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 OWNER 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/spi/spi.h>
+
+#include "up_arch.h"
+#include "chip.h"
+#include "nrf52_gpio.h"
+#include "nrf52_spi.h"
+
+#include "nrf52840-dk.h"
+#include <arch/board/board.h>
+
+#ifdef CONFIG_NRF52_SPI_MASTER
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_spidev_initialize
+ *
+ * Description:
+ *   Called to configure SPI chip select GPIO pins for the Nucleo-144 board.
+ *
+ ****************************************************************************/
+
+void nrf52_spidev_initialize(void)
+{
+#ifdef CONFIG_NRF52_SPI0_MASTER
+#  ifdef CONFIG_LPWAN_SX127X
+  /* Configure the SPI-based SX127X chip select GPIO */
+
+  spiinfo("Configure GPIO for SX127X SPI1/CS\n");
+
+  nrf52_gpio_config(GPIO_SX127X_CS);
+  nrf52_gpio_write(GPIO_SX127X_CS, true);
+#  endif
+#endif
+}
+
+/****************************************************************************
+ * Name:  nrf52_spi0/1/2/3/select and nrf52_spi0/1/2/3/status
+ *
+ * Description:
+ *   The external functions, nrf52_spi0/1/2/3select and
+ *   nrf52_spi0/1/2/3status must be provided by board-specific logic.
+ *   They are implementations of the select and status methods of the SPI
+ *   interface defined by struct spi_ops_s (see include/nuttx/spi/spi.h).
+ *   All other methods (including nrf52_spibus_initialize()) are provided
+ *   by common NRF52 logic.  To use this common SPI logic on your board:
+ *
+ *   1. Provide logic in nrf52_boardinitialize() to configure SPI chip select
+ *      pins.
+ *   2. Provide nrf52_spi0/1/2/3select() and nrf52_spi0/1/2/3status()
+ *      functions in your board-specific logic. These functions will perform
+ *      chip selection and status operations using GPIOs in the way your
+ *      board is configured.
+ *   3. Add a calls to nrf52_spibus_initialize() in your low level application
+ *      initialization logic
+ *   4. The handle returned by nrf52_spibus_initialize() may then be used to
+ *      bind the SPI driver to higher level logic (e.g., calling
+ *      mmcsd_spislotinitialize(), for example, will bind the SPI driver to
+ *      the SPI MMC/SD driver).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NRF52_SPI0_MASTER
+void nrf52_spi0select(FAR struct spi_dev_s *dev, uint32_t devid,
+                      bool selected)
+{
+  spiinfo("devid: %08lx CS: %s\n",
+          (unsigned long)devid, selected ? "assert" : "de-assert");
+
+  switch (devid)
+    {
+#ifdef CONFIG_LPWAN_SX127X
+      case SPIDEV_LPWAN(0):
+        {
+          spiinfo("SX127X device %s\n",
+                  selected ? "asserted" : "de-asserted");
+
+          /* Set the GPIO low to select and high to de-select */
+
+          nrf52_gpio_write(GPIO_SX127X_CS, !selected);
+          break;
+        }
+#endif
+
+      default:
+        {
+          break;
+        }
+    }
+}
+
+uint8_t nrf52_spi0status(FAR struct spi_dev_s *dev, uint32_t devid)
+{
+  uint8_t status = 0;
+
+  switch (devid)
+    {
+#ifdef CONFIG_LPWAN_SX127X
+      case SPIDEV_LPWAN(0):
+        {
+          status |= SPI_STATUS_PRESENT;
+          break;
+        }
+#endif
+
+      default:
+        {
+          break;
+        }
+    }
+
+  return status;
+}
+#endif
+
+#ifdef CONFIG_NRF52_SPI1_MASTER
+void nrf52_spi1select(FAR struct spi_dev_s *dev, uint32_t devid,
+                      bool selected)
+{
+  spiinfo("devid: %08lx CS: %s\n",
+          (unsigned long)devid, selected ? "assert" : "de-assert");
+}
+
+uint8_t nrf52_spi1status(FAR struct spi_dev_s *dev, uint32_t devid)
+{
+  return 0;
+}
+#endif
+
+#ifdef CONFIG_nrf52_SPI2_MASTER
+void nrf52_spi2select(FAR struct spi_dev_s *dev, uint32_t devid,
+                      bool selected)
+{
+  spiinfo("devid: %08lx CS: %s\n",
+          (unsigned long)devid, selected ? "assert" : "de-assert");
+}
+
+uint8_t nrf52_spi2status(FAR struct spi_dev_s *dev, uint32_t devid)
+{
+  return 0;
+}
+#endif
+
+#ifdef CONFIG_NRF52_SPI3_MASTER
+void nrf52_spi3select(FAR struct spi_dev_s *dev, uint32_t devid,
+                      bool selected)
+{
+  spiinfo("devid: %08lx CS: %s\n",
+          (unsigned long)devid, selected ? "assert" : "de-assert");
+}
+
+uint8_t nrf52_spi3status(FAR struct spi_dev_s *dev, uint32_t devid)
+{
+  return 0;
+}
+#endif
+
+#endif /* CONFIG_NRF52_SPI_MASTER */
diff --git a/boards/arm/nrf52/nrf52840-dk/src/nrf52_sx127x.c b/boards/arm/nrf52/nrf52840-dk/src/nrf52_sx127x.c
new file mode 100644
index 0000000..74e695f
--- /dev/null
+++ b/boards/arm/nrf52/nrf52840-dk/src/nrf52_sx127x.c
@@ -0,0 +1,225 @@
+/****************************************************************************
+ * boards/arm/nrf52/nrf52840-dk/src/nrf52_sx127x.c
+ * This logic is specific for the RFM98 modules (433MHz)
+ *
+ *   Copyright (C) 2019 Gregory Nutt. All rights reserved.
+ *   Author: Mateusz Szafoni <ra...@railab.me>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name NuttX 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 OWNER 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+#include <stdint.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/board.h>
+#include <nuttx/signal.h>
+#include <nuttx/wireless/lpwan/sx127x.h>
+#include <arch/board/board.h>
+
+#include "nrf52_gpio.h"
+#include "nrf52_gpiote.h"
+#include "nrf52_spi.h"
+
+#include "nrf52840-dk.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* SX127X on SPI0 bus */
+
+#define SX127X_SPI 0
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void sx127x_chip_reset(void);
+static int sx127x_opmode_change(int opmode);
+static int sx127x_freq_select(uint32_t freq);
+static int sx127x_pa_select(bool enable);
+static int sx127x_irq0_attach(xcpt_t isr, FAR void *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+struct sx127x_lower_s lower =
+{
+  .irq0attach    = sx127x_irq0_attach,
+  .reset         = sx127x_chip_reset,
+  .opmode_change = sx127x_opmode_change,
+  .freq_select   = sx127x_freq_select,
+  .pa_select     = sx127x_pa_select,
+  .pa_force      = true
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sx127x_irq0_attach
+ ****************************************************************************/
+
+static int sx127x_irq0_attach(xcpt_t isr, FAR void *arg)
+{
+  wlinfo("Attach DIO0 IRQ\n");
+
+  /* IRQ on rising edge */
+
+  nrf52_gpiosetevent(GPIO_SX127X_DIO0, true, false, false, isr, arg);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: sx127x_chip_reset
+ ****************************************************************************/
+
+static void sx127x_chip_reset(void)
+{
+  wlinfo("SX127X RESET\n");
+
+  /* Configure reset as output */
+
+  nrf52_gpio_config(GPIO_SX127X_RESET | GPIO_OUTPUT | GPIO_VALUE_ZERO);
+
+  /* Set pin to zero */
+
+  nrf52_gpio_write(GPIO_SX127X_RESET, false);
+
+  /* Wait 1 ms */
+
+  nxsig_usleep(1000);
+
+  /* Configure reset as input */
+
+  nrf52_gpio_config(GPIO_SX127X_RESET | GPIO_INPUT | GPIO_FLOAT);
+
+  /* Wait 10 ms */
+
+  nxsig_usleep(10000);
+}
+
+/****************************************************************************
+ * Name: sx127x_opmode_change
+ ****************************************************************************/
+
+static int sx127x_opmode_change(int opmode)
+{
+  /* Do nothing */
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: sx127x_freq_select
+ ****************************************************************************/
+
+static int sx127x_freq_select(uint32_t freq)
+{
+  int ret = OK;
+
+  /* NOTE: this depends on your module version */
+
+  if (freq > SX127X_HFBAND_THR)
+    {
+      ret = -EINVAL;
+      wlerr("HF band not supported\n");
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: sx127x_pa_select
+ ****************************************************************************/
+
+static int sx127x_pa_select(bool enable)
+{
+  int ret = OK;
+
+  /* Only PA_BOOST output connected to antenna */
+
+  if (enable == false)
+    {
+      ret = -EINVAL;
+      wlerr("Module supports only PA_BOOST pin,"
+            " so PA_SELECT must be enabled!\n");
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int nrf52_lpwaninitialize(void)
+{
+  FAR struct spi_dev_s *spidev;
+  int ret = OK;
+
+  wlinfo("Register the sx127x module\n");
+
+  /* Setup DIO0 */
+
+  nrf52_gpio_config(GPIO_SX127X_DIO0);
+
+  /* Init SPI bus */
+
+  spidev = nrf52_spibus_initialize(SX127X_SPI);
+  if (!spidev)
+    {
+      wlerr("ERROR: Failed to initialize SPI %d bus\n", SX127X_SPI);
+      ret = -ENODEV;
+      goto errout;
+    }
+
+  /* Initialize SX127X */
+
+  ret = sx127x_register(spidev, &lower);
+  if (ret < 0)
+    {
+      wlerr("ERROR: Failed to register sx127x\n");
+      goto errout;
+    }
+
+errout:
+  return ret;
+}
diff --git a/boards/arm/nrf52/nrf52840-dongle/include/board.h b/boards/arm/nrf52/nrf52840-dongle/include/board.h
index ebf2d34..105223f 100644
--- a/boards/arm/nrf52/nrf52840-dongle/include/board.h
+++ b/boards/arm/nrf52/nrf52840-dongle/include/board.h
@@ -43,7 +43,7 @@
 #include <nuttx/config.h>
 #include <stdbool.h>
 
-#if defined(CONFIG_ARCH_IRQBUTTONS) && defined(CONFIG_NRF52_GPIO_IRQ)
+#if defined(CONFIG_ARCH_IRQBUTTONS) && defined(CONFIG_NRF52_GPIOTE)
 #  include <nuttx/irq.h>
 #endif