This is an automated email from Gerrit.

"Tomáš Beneš <to...@dronetag.cz>" just uploaded a new patch set to Gerrit, 
which you can find at https://review.openocd.org/c/openocd/+/8062

-- gerrit

commit 6491bb86bd2a72a6745251b667b5a74c6df16e86
Author: Tomáš Beneš <to...@dronetag.cz>
Date:   Sun Dec 31 14:38:39 2023 +0100

    flash: nor: add support for Nordic nRF9160
    
    Original patch by Tobias Rohde <t...@lobaro.com>, Anton D. Kachalov 
<mo...@ya.ru>
    
    Change-Id: I3c2a0745e9d7abc51bbefb0ba0a73b6e5122e0bd
    Signed-off-by: Tomáš Beneš <to...@dronetag.cz>

diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h
index a63b72c8fa..e25b51ddda 100644
--- a/src/flash/nor/driver.h
+++ b/src/flash/nor/driver.h
@@ -275,6 +275,8 @@ extern const struct flash_driver msp432_flash;
 extern const struct flash_driver niietcm4_flash;
 extern const struct flash_driver npcx_flash;
 extern const struct flash_driver nrf51_flash;
+extern const struct flash_driver nrf52_flash;
+extern const struct flash_driver nrf91_flash;
 extern const struct flash_driver nrf5_flash;
 extern const struct flash_driver numicro_flash;
 extern const struct flash_driver ocl_flash;
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index 3157bd3292..bd935a70a6 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -53,6 +53,8 @@ static const struct flash_driver * const flash_drivers[] = {
        &npcx_flash,
        &nrf5_flash,
        &nrf51_flash,
+       &nrf52_flash,
+       &nrf91_flash,
        &numicro_flash,
        &ocl_flash,
        &pic32mx_flash,
diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c
index d5de4a4644..a17af371be 100644
--- a/src/flash/nor/nrf5.c
+++ b/src/flash/nor/nrf5.c
@@ -5,6 +5,8 @@
  *   Andrey Smirnov <andrew.smir...@gmail.com>                             *
  *   Angus Gratton <g...@projectgus.com>                                    *
  *   Erdem U. Altunyurt <spamjunkea...@gmail.com>                          *
+ *   Tobias Rohde <t...@lobaro.com>                                          *
+ *   Anton D. Kachalov <mo...@yandex.ru>                                   *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -12,7 +14,9 @@
 #endif
 
 #include "imp.h"
+#include <helper/align.h>
 #include <helper/binarybuffer.h>
+#include <helper/bits.h>
 #include <target/algorithm.h>
 #include <target/armv7m.h>
 #include <helper/types.h>
@@ -23,155 +27,481 @@
 #define WATCHDOG_REFRESH_VALUE          0x6e524635
 
 enum {
-       NRF5_FLASH_BASE = 0x00000000,
+       NRFX_FLASH_BASE = 0x00000000,
 };
 
-enum nrf5_ficr_registers {
-       NRF5_FICR_BASE = 0x10000000, /* Factory Information Configuration 
Registers */
-
-#define NRF5_FICR_REG(offset) (NRF5_FICR_BASE + offset)
-
-       NRF5_FICR_CODEPAGESIZE          = NRF5_FICR_REG(0x010),
-       NRF5_FICR_CODESIZE              = NRF5_FICR_REG(0x014),
-
-       NRF51_FICR_CLENR0               = NRF5_FICR_REG(0x028),
-       NRF51_FICR_PPFC                 = NRF5_FICR_REG(0x02C),
-       NRF51_FICR_NUMRAMBLOCK          = NRF5_FICR_REG(0x034),
-       NRF51_FICR_SIZERAMBLOCK0        = NRF5_FICR_REG(0x038),
-       NRF51_FICR_SIZERAMBLOCK1        = NRF5_FICR_REG(0x03C),
-       NRF51_FICR_SIZERAMBLOCK2        = NRF5_FICR_REG(0x040),
-       NRF51_FICR_SIZERAMBLOCK3        = NRF5_FICR_REG(0x044),
-
-       NRF5_FICR_CONFIGID              = NRF5_FICR_REG(0x05C),
-       NRF5_FICR_DEVICEID0             = NRF5_FICR_REG(0x060),
-       NRF5_FICR_DEVICEID1             = NRF5_FICR_REG(0x064),
-       NRF5_FICR_ER0                   = NRF5_FICR_REG(0x080),
-       NRF5_FICR_ER1                   = NRF5_FICR_REG(0x084),
-       NRF5_FICR_ER2                   = NRF5_FICR_REG(0x088),
-       NRF5_FICR_ER3                   = NRF5_FICR_REG(0x08C),
-       NRF5_FICR_IR0                   = NRF5_FICR_REG(0x090),
-       NRF5_FICR_IR1                   = NRF5_FICR_REG(0x094),
-       NRF5_FICR_IR2                   = NRF5_FICR_REG(0x098),
-       NRF5_FICR_IR3                   = NRF5_FICR_REG(0x09C),
-       NRF5_FICR_DEVICEADDRTYPE        = NRF5_FICR_REG(0x0A0),
-       NRF5_FICR_DEVICEADDR0           = NRF5_FICR_REG(0x0A4),
-       NRF5_FICR_DEVICEADDR1           = NRF5_FICR_REG(0x0A8),
-
-       NRF51_FICR_OVERRIDEN            = NRF5_FICR_REG(0x0AC),
-       NRF51_FICR_NRF_1MBIT0           = NRF5_FICR_REG(0x0B0),
-       NRF51_FICR_NRF_1MBIT1           = NRF5_FICR_REG(0x0B4),
-       NRF51_FICR_NRF_1MBIT2           = NRF5_FICR_REG(0x0B8),
-       NRF51_FICR_NRF_1MBIT3           = NRF5_FICR_REG(0x0BC),
-       NRF51_FICR_NRF_1MBIT4           = NRF5_FICR_REG(0x0C0),
-       NRF51_FICR_BLE_1MBIT0           = NRF5_FICR_REG(0x0EC),
-       NRF51_FICR_BLE_1MBIT1           = NRF5_FICR_REG(0x0F0),
-       NRF51_FICR_BLE_1MBIT2           = NRF5_FICR_REG(0x0F4),
-       NRF51_FICR_BLE_1MBIT3           = NRF5_FICR_REG(0x0F8),
-       NRF51_FICR_BLE_1MBIT4           = NRF5_FICR_REG(0x0FC),
+/* Factory Information Configuration Registers */
+#define NRF5_FICR_BASE 0x10000000
+#define NRF9_FICR_BASE 0x00ff0000
+
+#define NRF5_FICR_REG(offset) (NRF5_FICR_BASE + (offset))
+#define NRF9_FICR_REG(offset) (NRF9_FICR_BASE + (offset))
+
+#define NRFX_UNIMPLEMENTED 0xffffffff
+
+/*
+ * The following nrfx_<unit>_registers enums contain "virtual"
+ * registers definitions: they just link each register's name to an integer
+ * index. The index is made of a 12bits progressive number ored with
+ * another number which represents the hw unit the register itself belongs to.
+ */
+#define REG_INDEX_BITS 12
+
+#define REG_INDEX_MASK ((1 << REG_INDEX_BITS) - 1)
+
+#define FICR_ID (0 << REG_INDEX_BITS)
+#define UICR_ID BIT(REG_INDEX_BITS)
+#define NVMC_ID (2 << REG_INDEX_BITS)
+
+#define FICR_BASE FICR_ID
+#define UICR_BASE UICR_ID
+#define NVMC_BASE NVMC_ID
+
+#define reg_index(r) ((r) & REG_INDEX_MASK)
+
+enum nrfx_ficr_registers {
+       NRFX_FICR_CODEPAGESIZE = FICR_BASE,
+       NRFX_FICR_CODESIZE,
+       NRFX_FICR_CLENR0,
+       NRFX_FICR_PPFC,
+       NRFX_FICR_NUMRAMBLOCK,
+       NRFX_FICR_SIZERAMBLOCK0,
+       NRFX_FICR_SIZERAMBLOCK1,
+       NRFX_FICR_SIZERAMBLOCK2,
+       NRFX_FICR_SIZERAMBLOCK3,
+       NRFX_FICR_CONFIGID,
+       NRFX_FICR_DEVICEID0,
+       NRFX_FICR_DEVICEID1,
+       NRFX_FICR_ER0,
+       NRFX_FICR_ER1,
+       NRFX_FICR_ER2,
+       NRFX_FICR_ER3,
+       NRFX_FICR_IR0,
+       NRFX_FICR_IR1,
+       NRFX_FICR_IR2,
+       NRFX_FICR_IR3,
+       NRFX_FICR_DEVICEADDRTYPE,
+       NRFX_FICR_DEVICEADDR0,
+       NRFX_FICR_DEVICEADDR1,
+       NRFX_FICR_OVERRIDEN,
+       NRFX_FICR_NRF_1MBIT0,
+       NRFX_FICR_NRF_1MBIT1,
+       NRFX_FICR_NRF_1MBIT2,
+       NRFX_FICR_NRF_1MBIT3,
+       NRFX_FICR_NRF_1MBIT4,
+       NRFX_FICR_BLE_1MBIT0,
+       NRFX_FICR_BLE_1MBIT1,
+       NRFX_FICR_BLE_1MBIT2,
+       NRFX_FICR_BLE_1MBIT3,
+       NRFX_FICR_BLE_1MBIT4,
+       NRFX_FICR_INFO_PART,
+       NRFX_FICR_INFO_VARIANT,
+       NRFX_FICR_INFO_PACKAGE,
+       NRFX_FICR_INFO_RAM,
+       NRFX_FICR_INFO_FLASH,
+       NRFX_FICR_NREGS = ((NRFX_FICR_INFO_FLASH + 1) & REG_INDEX_MASK),
+};
+
+static const uint32_t nrf51_ficr_registers[] = {
+       [reg_index(NRFX_FICR_CODEPAGESIZE)]     = NRF5_FICR_REG(0x010),
+       [reg_index(NRFX_FICR_CODESIZE)]         = NRF5_FICR_REG(0x014),
+
+       [reg_index(NRFX_FICR_CLENR0)]           = NRF5_FICR_REG(0x028),
+       [reg_index(NRFX_FICR_PPFC)]                     = NRF5_FICR_REG(0x02C),
+       [reg_index(NRFX_FICR_NUMRAMBLOCK)]      = NRF5_FICR_REG(0x034),
+       [reg_index(NRFX_FICR_SIZERAMBLOCK0)]    = NRF5_FICR_REG(0x038),
+       [reg_index(NRFX_FICR_SIZERAMBLOCK1)]    = NRF5_FICR_REG(0x03C),
+       [reg_index(NRFX_FICR_SIZERAMBLOCK2)]    = NRF5_FICR_REG(0x040),
+       [reg_index(NRFX_FICR_SIZERAMBLOCK3)]    = NRF5_FICR_REG(0x044),
+
+       [reg_index(NRFX_FICR_CONFIGID)]         = NRF5_FICR_REG(0x05C),
+       [reg_index(NRFX_FICR_DEVICEID0)]        = NRF5_FICR_REG(0x060),
+       [reg_index(NRFX_FICR_DEVICEID1)]        = NRF5_FICR_REG(0x064),
+       [reg_index(NRFX_FICR_ER0)]              = NRF5_FICR_REG(0x080),
+       [reg_index(NRFX_FICR_ER1)]              = NRF5_FICR_REG(0x084),
+       [reg_index(NRFX_FICR_ER2)]              = NRF5_FICR_REG(0x088),
+       [reg_index(NRFX_FICR_ER3)]              = NRF5_FICR_REG(0x08C),
+       [reg_index(NRFX_FICR_IR0)]              = NRF5_FICR_REG(0x090),
+       [reg_index(NRFX_FICR_IR1)]              = NRF5_FICR_REG(0x094),
+       [reg_index(NRFX_FICR_IR2)]              = NRF5_FICR_REG(0x098),
+       [reg_index(NRFX_FICR_IR3)]              = NRF5_FICR_REG(0x09C),
+       [reg_index(NRFX_FICR_DEVICEADDRTYPE)]   = NRF5_FICR_REG(0x0A0),
+       [reg_index(NRFX_FICR_DEVICEADDR0)]      = NRF5_FICR_REG(0x0A4),
+       [reg_index(NRFX_FICR_DEVICEADDR1)]      = NRF5_FICR_REG(0x0A8),
+
+       [reg_index(NRFX_FICR_OVERRIDEN)]        = NRF5_FICR_REG(0x0AC),
+       [reg_index(NRFX_FICR_NRF_1MBIT0)]       = NRF5_FICR_REG(0x0B0),
+       [reg_index(NRFX_FICR_NRF_1MBIT1)]       = NRF5_FICR_REG(0x0B4),
+       [reg_index(NRFX_FICR_NRF_1MBIT2)]       = NRF5_FICR_REG(0x0B8),
+       [reg_index(NRFX_FICR_NRF_1MBIT3)]       = NRF5_FICR_REG(0x0BC),
+       [reg_index(NRFX_FICR_NRF_1MBIT4)]       = NRF5_FICR_REG(0x0C0),
+       [reg_index(NRFX_FICR_BLE_1MBIT0)]       = NRF5_FICR_REG(0x0EC),
+       [reg_index(NRFX_FICR_BLE_1MBIT1)]       = NRF5_FICR_REG(0x0F0),
+       [reg_index(NRFX_FICR_BLE_1MBIT2)]       = NRF5_FICR_REG(0x0F4),
+       [reg_index(NRFX_FICR_BLE_1MBIT3)]       = NRF5_FICR_REG(0x0F8),
+       [reg_index(NRFX_FICR_BLE_1MBIT4)]       = NRF5_FICR_REG(0x0FC),
 
        /* Following registers are available on nRF52 and on nRF51 since rev 3 
*/
-       NRF5_FICR_INFO_PART                     = NRF5_FICR_REG(0x100),
-       NRF5_FICR_INFO_VARIANT          = NRF5_FICR_REG(0x104),
-       NRF5_FICR_INFO_PACKAGE          = NRF5_FICR_REG(0x108),
-       NRF5_FICR_INFO_RAM                      = NRF5_FICR_REG(0x10C),
-       NRF5_FICR_INFO_FLASH            = NRF5_FICR_REG(0x110),
+       [reg_index(NRFX_FICR_INFO_PART)]        = NRF5_FICR_REG(0x100),
+       [reg_index(NRFX_FICR_INFO_VARIANT)] = NRF5_FICR_REG(0x104),
+       [reg_index(NRFX_FICR_INFO_PACKAGE)]     = NRF5_FICR_REG(0x108),
+       [reg_index(NRFX_FICR_INFO_RAM)]         = NRF5_FICR_REG(0x10C),
+       [reg_index(NRFX_FICR_INFO_FLASH)]       = NRF5_FICR_REG(0x110),
+};
+
+static const uint32_t nrf52_ficr_registers[] = {
+       [reg_index(NRFX_FICR_CODEPAGESIZE)]     = NRF5_FICR_REG(0x010),
+       [reg_index(NRFX_FICR_CODESIZE)]         = NRF5_FICR_REG(0x014),
+
+       [reg_index(NRFX_FICR_CLENR0)]           = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_PPFC)]                     = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_NUMRAMBLOCK)]      = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_SIZERAMBLOCK0)]    = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_SIZERAMBLOCK1)]    = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_SIZERAMBLOCK2)]    = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_SIZERAMBLOCK3)]    = NRFX_UNIMPLEMENTED,
+
+       [reg_index(NRFX_FICR_CONFIGID)]         = NRF5_FICR_REG(0x05C),
+       [reg_index(NRFX_FICR_DEVICEID0)]        = NRF5_FICR_REG(0x060),
+       [reg_index(NRFX_FICR_DEVICEID1)]        = NRF5_FICR_REG(0x064),
+       [reg_index(NRFX_FICR_ER0)]              = NRF5_FICR_REG(0x080),
+       [reg_index(NRFX_FICR_ER1)]              = NRF5_FICR_REG(0x084),
+       [reg_index(NRFX_FICR_ER2)]              = NRF5_FICR_REG(0x088),
+       [reg_index(NRFX_FICR_ER3)]              = NRF5_FICR_REG(0x08C),
+       [reg_index(NRFX_FICR_IR0)]              = NRF5_FICR_REG(0x090),
+       [reg_index(NRFX_FICR_IR1)]              = NRF5_FICR_REG(0x094),
+       [reg_index(NRFX_FICR_IR2)]              = NRF5_FICR_REG(0x098),
+       [reg_index(NRFX_FICR_IR3)]              = NRF5_FICR_REG(0x09C),
+       [reg_index(NRFX_FICR_DEVICEADDRTYPE)]   = NRF5_FICR_REG(0x0A0),
+       [reg_index(NRFX_FICR_DEVICEADDR0)]      = NRF5_FICR_REG(0x0A4),
+       [reg_index(NRFX_FICR_DEVICEADDR1)]      = NRF5_FICR_REG(0x0A8),
+
+       [reg_index(NRFX_FICR_OVERRIDEN)]        = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_NRF_1MBIT0)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_NRF_1MBIT1)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_NRF_1MBIT2)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_NRF_1MBIT3)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_NRF_1MBIT4)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_BLE_1MBIT0)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_BLE_1MBIT1)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_BLE_1MBIT2)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_BLE_1MBIT3)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_BLE_1MBIT4)]       = NRFX_UNIMPLEMENTED,
+
+       [reg_index(NRFX_FICR_INFO_PART)]        = NRF5_FICR_REG(0x100),
+       [reg_index(NRFX_FICR_INFO_VARIANT)]     = NRF5_FICR_REG(0x104),
+       [reg_index(NRFX_FICR_INFO_PACKAGE)]     = NRF5_FICR_REG(0x108),
+       [reg_index(NRFX_FICR_INFO_RAM)]         = NRF5_FICR_REG(0x10C),
+       [reg_index(NRFX_FICR_INFO_FLASH)]       = NRF5_FICR_REG(0x110),
+};
+
+static const uint32_t nrf91_ficr_registers[] = {
+       [reg_index(NRFX_FICR_CODEPAGESIZE)]     = NRF9_FICR_REG(0x220),
+       [reg_index(NRFX_FICR_CODESIZE)]         = NRF9_FICR_REG(0x224),
+
+       [reg_index(NRFX_FICR_CLENR0)]           = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_PPFC)]                     = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_NUMRAMBLOCK)]      = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_SIZERAMBLOCK0)]    = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_SIZERAMBLOCK1)]    = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_SIZERAMBLOCK2)]    = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_SIZERAMBLOCK3)]    = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_CONFIGID)]                 = NRFX_UNIMPLEMENTED,
+
+       [reg_index(NRFX_FICR_DEVICEID0)]        = NRF9_FICR_REG(0x204),
+       [reg_index(NRFX_FICR_DEVICEID1)]        = NRF9_FICR_REG(0x208),
+
+       [reg_index(NRFX_FICR_ER0)]              = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_ER1)]              = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_ER2)]              = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_ER3)]              = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_IR0)]              = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_IR1)]              = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_IR2)]              = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_IR3)]              = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_DEVICEADDRTYPE)]   = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_DEVICEADDR0)]      = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_DEVICEADDR1)]      = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_OVERRIDEN)]        = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_NRF_1MBIT0)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_NRF_1MBIT1)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_NRF_1MBIT2)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_NRF_1MBIT3)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_NRF_1MBIT4)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_BLE_1MBIT0)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_BLE_1MBIT1)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_BLE_1MBIT2)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_BLE_1MBIT3)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_FICR_BLE_1MBIT4)]       = NRFX_UNIMPLEMENTED,
+
+       [reg_index(NRFX_FICR_INFO_PART)]        = NRF9_FICR_REG(0x20c),
+       [reg_index(NRFX_FICR_INFO_VARIANT)]     = NRF9_FICR_REG(0x210),
+       [reg_index(NRFX_FICR_INFO_PACKAGE)]     = NRF9_FICR_REG(0x214),
+       [reg_index(NRFX_FICR_INFO_RAM)]         = NRF9_FICR_REG(0x218),
+       [reg_index(NRFX_FICR_INFO_FLASH)]       = NRF9_FICR_REG(0x21c),
+};
+
+/* User Information Configuration Registers */
+#define NRF5_UICR_BASE 0x10001000
+#define NRF9_UICR_BASE 0x00ff8000
+
+#define NRF5_UICR_REG(offset) (NRF5_UICR_BASE + (offset))
+#define NRF9_UICR_REG(offset) (NRF9_UICR_BASE + (offset))
+#define NRFX_UICR_SIZE 0x1000
+
+enum nrfx_family {
+       NRFX_FAMILY_UNK = 0,
+       NRFX_FAMILY_5X = 0xff,
+       NRFX_FAMILY_51 = 51,
+       NRFX_FAMILY_52 = 52,
+       NRFX_FAMILY_91 = 91,
 };
 
-enum nrf5_uicr_registers {
-       NRF5_UICR_BASE = 0x10001000, /* User Information
-                                      * Configuration Registers */
+static inline uint32_t nrfx_uicr_base(enum nrfx_family family)
+{
+       switch (family) {
+       case NRFX_FAMILY_51:
+       case NRFX_FAMILY_52:
+               return NRF5_UICR_BASE;
+       case NRFX_FAMILY_91:
+               return NRF9_UICR_BASE;
+       default:
+               return NRFX_UNIMPLEMENTED;
+       }
+       return NRFX_UNIMPLEMENTED;
+}
 
-#define NRF5_UICR_REG(offset) (NRF5_UICR_BASE + offset)
+enum nrfx_uicr_registers {
+       NRFX_UICR_CLENR0 = UICR_BASE,
+       NRFX_UICR_RBPCONF,
+       NRFX_UICR_XTALFREQ,
+       NRFX_UICR_FWID,
+       NRFX_UICR_PSELRESET0,
+       NRFX_UICR_PSELRESET1,
+       NRFX_UICR_APPROTECT,
+       NRFX_UICR_NFCPINS,
+       NRFX_UICR_SECUREAPPROTECT,
+       NRFX_UICR_ERASEPROTECT,
+       NRFX_UICR_NREGS = ((NRFX_UICR_ERASEPROTECT + 1) & REG_INDEX_MASK),
+};
 
-       NRF51_UICR_CLENR0       = NRF5_UICR_REG(0x000),
-       NRF51_UICR_RBPCONF      = NRF5_UICR_REG(0x004),
-       NRF51_UICR_XTALFREQ     = NRF5_UICR_REG(0x008),
-       NRF51_UICR_FWID         = NRF5_UICR_REG(0x010),
+static const uint32_t nrf51_uicr_registers[] = {
+       [reg_index(NRFX_UICR_CLENR0)]   = NRF5_UICR_REG(0x000),
+       [reg_index(NRFX_UICR_RBPCONF)]  = NRF5_UICR_REG(0x004),
+       [reg_index(NRFX_UICR_XTALFREQ)] = NRF5_UICR_REG(0x008),
+       [reg_index(NRFX_UICR_FWID)]             = NRF5_UICR_REG(0x010),
+       [reg_index(NRFX_UICR_PSELRESET0)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_PSELRESET1)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_APPROTECT)]        = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_NFCPINS)]          = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_SECUREAPPROTECT)] = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_ERASEPROTECT)] = NRFX_UNIMPLEMENTED,
 };
 
-enum nrf5_nvmc_registers {
-       NRF5_NVMC_BASE = 0x4001E000, /* Non-Volatile Memory
-                                      * Controller Registers */
+static const uint32_t nrf52_uicr_registers[] = {
+       [reg_index(NRFX_UICR_CLENR0)]           = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_RBPCONF)]          = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_XTALFREQ)]         = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_FWID)]                     = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_PSELRESET0)]       = NRF5_UICR_REG(0x200),
+       [reg_index(NRFX_UICR_PSELRESET1)]       = NRF5_UICR_REG(0x204),
+       [reg_index(NRFX_UICR_APPROTECT)]        = NRF5_UICR_REG(0x208),
+       [reg_index(NRFX_UICR_NFCPINS)]          = NRF5_UICR_REG(0x20C),
+       [reg_index(NRFX_UICR_SECUREAPPROTECT)]  = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_ERASEPROTECT)]     = NRFX_UNIMPLEMENTED,
+};
 
-#define NRF5_NVMC_REG(offset) (NRF5_NVMC_BASE + offset)
+static const uint32_t nrf91_uicr_registers[] = {
+       [reg_index(NRFX_UICR_CLENR0)]           = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_RBPCONF)]          = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_XTALFREQ)]         = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_FWID)]                     = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_PSELRESET0)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_PSELRESET1)]       = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_APPROTECT)]        = NRF9_UICR_REG(0x000),
+       [reg_index(NRFX_UICR_NFCPINS)]          = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_UICR_SECUREAPPROTECT)]  = NRF9_UICR_REG(0x02C),
+       [reg_index(NRFX_UICR_ERASEPROTECT)]     = NRF9_UICR_REG(0x030),
+};
+
+/* Non-Volatile Memory Controller Registers */
+#define NRF5_NVMC_BASE 0x4001E000
+#define NRF9_NVMC_BASE 0x50039000
+
+#define NRF5_NVMC_REG(offset) (NRF5_NVMC_BASE + (offset))
+#define NRF9_NVMC_REG(offset) (NRF9_NVMC_BASE + (offset))
 
-       NRF5_NVMC_READY = NRF5_NVMC_REG(0x400),
-       NRF5_NVMC_CONFIG        = NRF5_NVMC_REG(0x504),
-       NRF5_NVMC_ERASEPAGE     = NRF5_NVMC_REG(0x508),
-       NRF5_NVMC_ERASEALL      = NRF5_NVMC_REG(0x50C),
-       NRF5_NVMC_ERASEUICR     = NRF5_NVMC_REG(0x514),
+enum nrfx_nvmc_registers {
+       NRFX_NVMC_READY = NVMC_BASE,
+       NRFX_NVMC_CONFIG,
+       NRFX_NVMC_ERASEPAGE,
+       NRFX_NVMC_ERASEALL,
+       NRFX_NVMC_ERASEUICR,
+       NRFX_BPROT_BASE,
+};
 
-       NRF5_BPROT_BASE = 0x40000000,
+enum nrfx_nvmc_config_bits {
+       NRFX_NVMC_CONFIG_REN = 0x00,
+       NRFX_NVMC_CONFIG_WEN = 0x01,
+       NRFX_NVMC_CONFIG_EEN = 0x02,
 };
 
-enum nrf5_nvmc_config_bits {
-       NRF5_NVMC_CONFIG_REN = 0x00,
-       NRF5_NVMC_CONFIG_WEN = 0x01,
-       NRF5_NVMC_CONFIG_EEN = 0x02,
+static const uint32_t nrf5_nvmc_registers[] = {
+       [reg_index(NRFX_NVMC_READY)]            = NRF5_NVMC_REG(0x400),
+       [reg_index(NRFX_NVMC_CONFIG)]           = NRF5_NVMC_REG(0x504),
+       [reg_index(NRFX_NVMC_ERASEPAGE)]        = NRF5_NVMC_REG(0x508),
+       [reg_index(NRFX_NVMC_ERASEALL)]         = NRF5_NVMC_REG(0x50C),
+       [reg_index(NRFX_NVMC_ERASEUICR)]        = NRF5_NVMC_REG(0x514),
+       [reg_index(NRFX_BPROT_BASE)]            = 0x40000000,
+};
 
+static const uint32_t nrf91_nvmc_registers[] = {
+       [reg_index(NRFX_NVMC_READY)]            = NRF9_NVMC_REG(0x400),
+       [reg_index(NRFX_NVMC_CONFIG)]           = NRF9_NVMC_REG(0x504),
+       [reg_index(NRFX_NVMC_ERASEPAGE)]        = NRFX_UNIMPLEMENTED,
+       [reg_index(NRFX_NVMC_ERASEALL)]         = NRF9_NVMC_REG(0x50C),
+       [reg_index(NRFX_NVMC_ERASEUICR)]        = NRF9_NVMC_REG(0x514),
+       [reg_index(NRFX_BPROT_BASE)]            = NRFX_UNIMPLEMENTED,
 };
 
-struct nrf52_ficr_info {
+enum nrfx_features {
+       NRFX_FEATURE_SERIES_51  = 1 << 0,
+       NRFX_FEATURE_SERIES_52  = 1 << 1,
+       NRFX_FEATURE_SERIES_91  = 1 << 2,
+       NRFX_FEATURE_BPROT              = 1 << 3,
+       NRFX_FEATURE_ACL_PROT   = 1 << 4,
+};
+
+struct nrfx_device_id {
+       uint16_t hwid;
+       uint32_t part;
+};
+
+struct nrfx_ficr_info {
        uint32_t part;
        uint32_t variant;
        uint32_t package;
        uint32_t ram;
        uint32_t flash;
+       uint32_t flash_page_size;
+       uint32_t num_sectors;
 };
 
-enum nrf5_features {
-       NRF5_FEATURE_SERIES_51  = 1 << 0,
-       NRF5_FEATURE_SERIES_52  = 1 << 1,
-       NRF5_FEATURE_BPROT              = 1 << 2,
-       NRF5_FEATURE_ACL_PROT   = 1 << 3,
-};
-
-struct nrf5_device_spec {
-       uint16_t hwid;
+struct nrfx_device_spec {
+       struct nrfx_device_id id;
        const char *part;
        const char *variant;
        const char *build_code;
        unsigned int flash_size_kb;
-       enum nrf5_features features;
+       enum nrfx_features features;
 };
 
-struct nrf5_info {
+struct nrfx_info {
        unsigned int refcount;
 
-       struct nrf5_bank {
-               struct nrf5_info *chip;
-               bool probed;
+       struct nrfx_bank {
+               struct nrfx_info *chip;
+               int probed;
        } bank[2];
+       enum nrfx_family family;
+       const uint32_t *ficr_registers;
+       const uint32_t *uicr_registers;
+       const uint32_t *nvmc_registers;
        struct target *target;
-
-       /* chip identification stored in nrf5_probe() for use in nrf5_info() */
+       /* chip identification stored in nrfx_probe() for use in nrfx_info() */
        bool ficr_info_valid;
-       struct nrf52_ficr_info ficr_info;
-       const struct nrf5_device_spec *spec;
        uint16_t hwid;
-       enum nrf5_features features;
-       unsigned int flash_size_kb;
-       unsigned int ram_size_kb;
+       struct nrfx_ficr_info ficr_info;
+       const struct nrfx_device_spec *spec;
+       enum nrfx_features features;
+       uint32_t flash_size_kb;
+       uint32_t ram_size_kb;
 };
 
-#define NRF51_DEVICE_DEF(id, pt, var, bcode, fsize) \
-{                                                   \
-.hwid          = (id),                              \
-.part          = pt,                                \
-.variant       = var,                               \
-.build_code    = bcode,                             \
-.flash_size_kb = (fsize),                           \
-.features      = NRF5_FEATURE_SERIES_51,            \
+static inline int reg_read(struct nrfx_info *chip, uint32_t addr, uint32_t 
*out)
+{
+       if (addr == NRFX_UNIMPLEMENTED)
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       return target_read_u32(chip->target, addr, out);
+}
+
+static inline int reg_write(struct nrfx_info *chip, uint32_t addr, uint32_t in)
+{
+       if (addr == NRFX_UNIMPLEMENTED)
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       return target_write_u32(chip->target, addr, in);
+}
+
+static inline int ficr_read(struct nrfx_info *chip, enum nrfx_ficr_registers r,
+                               uint32_t *out)
+{
+       return reg_read(chip, chip->ficr_registers[r & REG_INDEX_MASK], out);
+}
+
+static inline int uicr_read(struct nrfx_info *chip, enum nrfx_uicr_registers r,
+                               uint32_t *out)
+{
+       return reg_read(chip, chip->uicr_registers[r & REG_INDEX_MASK], out);
+}
+
+static inline int uicr_write(struct nrfx_info *chip, enum nrfx_uicr_registers 
r,
+                                uint32_t in)
+{
+       return reg_write(chip, chip->uicr_registers[r & REG_INDEX_MASK], in);
+}
+
+static inline int nvmc_read(struct nrfx_info *chip, enum nrfx_nvmc_registers r,
+                               uint32_t *out)
+{
+       return reg_read(chip, chip->nvmc_registers[r & REG_INDEX_MASK], out);
+}
+
+static inline int nvmc_write(struct nrfx_info *chip, enum nrfx_nvmc_registers 
r,
+                                uint32_t in)
+{
+       return reg_write(chip, chip->nvmc_registers[r & REG_INDEX_MASK], in);
+}
+
+static inline int ficr_is_implemented(struct nrfx_info *chip,
+                                         enum nrfx_ficr_registers r)
+{
+       return chip->ficr_registers[r & REG_INDEX_MASK] != NRFX_UNIMPLEMENTED;
+}
+
+static inline int uicr_is_implemented(struct nrfx_info *chip,
+                                         enum nrfx_uicr_registers r)
+{
+       return chip->uicr_registers[r & REG_INDEX_MASK] != NRFX_UNIMPLEMENTED;
+}
+
+#define NRF51_DEVICE_DEF(_id, pt, var, bcode, fsize)  \
+{ \
+.id            = { .hwid = (_id), .part = 0x ## pt }, \
+.part          = # pt,                                \
+.variant       = var,                                 \
+.build_code    = bcode,                               \
+.flash_size_kb = (fsize),                             \
+.features      = NRFX_FEATURE_SERIES_51,              \
 }
 
-#define NRF5_DEVICE_DEF(id, pt, var, bcode, fsize, features) \
-{                                                   \
-.hwid          = (id),                              \
-.part          = pt,                                \
-.variant       = var,                               \
-.build_code    = bcode,                             \
-.flash_size_kb = (fsize),                           \
-.features      = features,                          \
+#define NRF52_DEVICE_DEF(_id, pt, var, bcode, fsize, _features) \
+{                                                      \
+.id            = { .hwid = (_id), .part = 0x ## pt },            \
+.part          = # pt,                                \
+.variant       = var,                                  \
+.build_code    = bcode,                                 \
+.flash_size_kb = (fsize),                              \
+.features      = NRFX_FEATURE_SERIES_52 | (_features),          \
+}
+
+#define NRF91_DEVICE_DEF(pt, var, bcode, fsize)       \
+{ \
+.id            = { .hwid = 0xFFFF, .part = 0x ## pt }, \
+.part          = # pt,                                \
+.variant       = var,                                 \
+.build_code    = bcode,                               \
+.flash_size_kb = (fsize),                             \
+.features      = NRFX_FEATURE_SERIES_91,              \
 }
 
 /* The known devices table below is derived from the "nRF5x series
@@ -191,121 +521,124 @@ struct nrf5_info {
  * shown as Gx0, Bx0, etc. In these cases the HWID in the matrix is
  * for x==0, x!=0 means different (unspecified) HWIDs.
  */
-static const struct nrf5_device_spec nrf5_known_devices_table[] = {
+static const struct nrfx_device_spec nrfx_known_devices_table[] = {
        /* nRF51822 Devices (IC rev 1). */
-       NRF51_DEVICE_DEF(0x001D, "51822", "QFAA", "CA/C0", 256),
-       NRF51_DEVICE_DEF(0x0026, "51822", "QFAB", "AA",    128),
-       NRF51_DEVICE_DEF(0x0027, "51822", "QFAB", "A0",    128),
-       NRF51_DEVICE_DEF(0x0020, "51822", "CEAA", "BA",    256),
-       NRF51_DEVICE_DEF(0x002F, "51822", "CEAA", "B0",    256),
+       NRF51_DEVICE_DEF(0x001D, 51822, "QFAA", "CA/C0", 256),
+       NRF51_DEVICE_DEF(0x0026, 51822, "QFAB", "AA",    128),
+       NRF51_DEVICE_DEF(0x0027, 51822, "QFAB", "A0",    128),
+       NRF51_DEVICE_DEF(0x0020, 51822, "CEAA", "BA",    256),
+       NRF51_DEVICE_DEF(0x002F, 51822, "CEAA", "B0",    256),
 
        /* Some early nRF51-DK (PCA10028) & nRF51-Dongle (PCA10031) boards
           with built-in jlink seem to use engineering samples not listed
           in the nRF51 Series Compatibility Matrix V1.0. */
-       NRF51_DEVICE_DEF(0x0071, "51822", "QFAC", "AB",    256),
+       NRF51_DEVICE_DEF(0x0071, 51822, "QFAC", "AB",    256),
 
        /* nRF51822 Devices (IC rev 2). */
-       NRF51_DEVICE_DEF(0x002A, "51822", "QFAA", "FA0",   256),
-       NRF51_DEVICE_DEF(0x0044, "51822", "QFAA", "GC0",   256),
-       NRF51_DEVICE_DEF(0x003C, "51822", "QFAA", "G0",    256),
-       NRF51_DEVICE_DEF(0x0057, "51822", "QFAA", "G2",    256),
-       NRF51_DEVICE_DEF(0x0058, "51822", "QFAA", "G3",    256),
-       NRF51_DEVICE_DEF(0x004C, "51822", "QFAB", "B0",    128),
-       NRF51_DEVICE_DEF(0x0040, "51822", "CEAA", "CA0",   256),
-       NRF51_DEVICE_DEF(0x0047, "51822", "CEAA", "DA0",   256),
-       NRF51_DEVICE_DEF(0x004D, "51822", "CEAA", "D00",   256),
+       NRF51_DEVICE_DEF(0x002A, 51822, "QFAA", "FA0",   256),
+       NRF51_DEVICE_DEF(0x0044, 51822, "QFAA", "GC0",   256),
+       NRF51_DEVICE_DEF(0x003C, 51822, "QFAA", "G0",    256),
+       NRF51_DEVICE_DEF(0x0057, 51822, "QFAA", "G2",    256),
+       NRF51_DEVICE_DEF(0x0058, 51822, "QFAA", "G3",    256),
+       NRF51_DEVICE_DEF(0x004C, 51822, "QFAB", "B0",    128),
+       NRF51_DEVICE_DEF(0x0040, 51822, "CEAA", "CA0",   256),
+       NRF51_DEVICE_DEF(0x0047, 51822, "CEAA", "DA0",   256),
+       NRF51_DEVICE_DEF(0x004D, 51822, "CEAA", "D00",   256),
 
        /* nRF51822 Devices (IC rev 3). */
-       NRF51_DEVICE_DEF(0x0072, "51822", "QFAA", "H0",    256),
-       NRF51_DEVICE_DEF(0x00D1, "51822", "QFAA", "H2",    256),
-       NRF51_DEVICE_DEF(0x007B, "51822", "QFAB", "C0",    128),
-       NRF51_DEVICE_DEF(0x0083, "51822", "QFAC", "A0",    256),
-       NRF51_DEVICE_DEF(0x0084, "51822", "QFAC", "A1",    256),
-       NRF51_DEVICE_DEF(0x007D, "51822", "CDAB", "A0",    128),
-       NRF51_DEVICE_DEF(0x0079, "51822", "CEAA", "E0",    256),
-       NRF51_DEVICE_DEF(0x0087, "51822", "CFAC", "A0",    256),
-       NRF51_DEVICE_DEF(0x008F, "51822", "QFAA", "H1",    256),
+       NRF51_DEVICE_DEF(0x0072, 51822, "QFAA", "H0",    256),
+       NRF51_DEVICE_DEF(0x00D1, 51822, "QFAA", "H2",    256),
+       NRF51_DEVICE_DEF(0x007B, 51822, "QFAB", "C0",    128),
+       NRF51_DEVICE_DEF(0x0083, 51822, "QFAC", "A0",    256),
+       NRF51_DEVICE_DEF(0x0084, 51822, "QFAC", "A1",    256),
+       NRF51_DEVICE_DEF(0x007D, 51822, "CDAB", "A0",    128),
+       NRF51_DEVICE_DEF(0x0079, 51822, "CEAA", "E0",    256),
+       NRF51_DEVICE_DEF(0x0087, 51822, "CFAC", "A0",    256),
+       NRF51_DEVICE_DEF(0x008F, 51822, "QFAA", "H1",    256),
 
        /* nRF51422 Devices (IC rev 1). */
-       NRF51_DEVICE_DEF(0x001E, "51422", "QFAA", "CA",    256),
-       NRF51_DEVICE_DEF(0x0024, "51422", "QFAA", "C0",    256),
-       NRF51_DEVICE_DEF(0x0031, "51422", "CEAA", "A0A",   256),
+       NRF51_DEVICE_DEF(0x001E, 51422, "QFAA", "CA",    256),
+       NRF51_DEVICE_DEF(0x0024, 51422, "QFAA", "C0",    256),
+       NRF51_DEVICE_DEF(0x0031, 51422, "CEAA", "A0A",   256),
 
        /* nRF51422 Devices (IC rev 2). */
-       NRF51_DEVICE_DEF(0x002D, "51422", "QFAA", "DAA",   256),
-       NRF51_DEVICE_DEF(0x002E, "51422", "QFAA", "E0",    256),
-       NRF51_DEVICE_DEF(0x0061, "51422", "QFAB", "A00",   128),
-       NRF51_DEVICE_DEF(0x0050, "51422", "CEAA", "B0",    256),
+       NRF51_DEVICE_DEF(0x002D, 51422, "QFAA", "DAA",   256),
+       NRF51_DEVICE_DEF(0x002E, 51422, "QFAA", "E0",    256),
+       NRF51_DEVICE_DEF(0x0061, 51422, "QFAB", "A00",   128),
+       NRF51_DEVICE_DEF(0x0050, 51422, "CEAA", "B0",    256),
 
        /* nRF51422 Devices (IC rev 3). */
-       NRF51_DEVICE_DEF(0x0073, "51422", "QFAA", "F0",    256),
-       NRF51_DEVICE_DEF(0x007C, "51422", "QFAB", "B0",    128),
-       NRF51_DEVICE_DEF(0x0085, "51422", "QFAC", "A0",    256),
-       NRF51_DEVICE_DEF(0x0086, "51422", "QFAC", "A1",    256),
-       NRF51_DEVICE_DEF(0x007E, "51422", "CDAB", "A0",    128),
-       NRF51_DEVICE_DEF(0x007A, "51422", "CEAA", "C0",    256),
-       NRF51_DEVICE_DEF(0x0088, "51422", "CFAC", "A0",    256),
+       NRF51_DEVICE_DEF(0x0073, 51422, "QFAA", "F0",    256),
+       NRF51_DEVICE_DEF(0x007C, 51422, "QFAB", "B0",    128),
+       NRF51_DEVICE_DEF(0x0085, 51422, "QFAC", "A0",    256),
+       NRF51_DEVICE_DEF(0x0086, 51422, "QFAC", "A1",    256),
+       NRF51_DEVICE_DEF(0x007E, 51422, "CDAB", "A0",    128),
+       NRF51_DEVICE_DEF(0x007A, 51422, "CEAA", "C0",    256),
+       NRF51_DEVICE_DEF(0x0088, 51422, "CFAC", "A0",    256),
 
        /* The driver fully autodetects nRF52 series devices by FICR INFO,
         * no need for nRF52xxx HWIDs in this table */
-#if 0
+
        /* nRF52810 Devices */
-       NRF5_DEVICE_DEF(0x0142, "52810", "QFAA", "B0",    192,  
NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT),
-       NRF5_DEVICE_DEF(0x0143, "52810", "QCAA", "C0",    192,  
NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT),
+       NRF52_DEVICE_DEF(0x0142, 52810, "QFAA", "B0",    192,   
NRFX_FEATURE_BPROT),
+       NRF52_DEVICE_DEF(0x0143, 52810, "QCAA", "C0",    192,   
NRFX_FEATURE_BPROT),
 
        /* nRF52832 Devices */
-       NRF5_DEVICE_DEF(0x00C7, "52832", "QFAA", "B0",    512,  
NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT),
-       NRF5_DEVICE_DEF(0x0139, "52832", "QFAA", "E0",    512,  
NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT),
-       NRF5_DEVICE_DEF(0x00E3, "52832", "CIAA", "B0",    512,  
NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT),
+       NRF52_DEVICE_DEF(0x00C7, 52832, "QFAA", "B0",    512,   
NRFX_FEATURE_BPROT),
+       NRF52_DEVICE_DEF(0x0139, 52832, "QFAA", "E0",    512,   
NRFX_FEATURE_BPROT),
+       NRF52_DEVICE_DEF(0x00E3, 52832, "CIAA", "B0",    512,   
NRFX_FEATURE_BPROT),
 
        /* nRF52840 Devices */
-       NRF5_DEVICE_DEF(0x0150, "52840", "QIAA", "C0",    1024, 
NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_ACL_PROT),
-#endif
+       NRF52_DEVICE_DEF(0x0150, 52840, "QIAA", "C0",    1024, 
NRFX_FEATURE_ACL_PROT),
+       NRF52_DEVICE_DEF(0x0164, 52840, "0DAA", "CK",    1024, 
NRFX_FEATURE_ACL_PROT),
+
+       /* nRF91xx Devices */
+       NRF91_DEVICE_DEF(9120, "0BAA", "QF", 1024),
 };
 
-struct nrf5_device_package {
+struct nrfx_device_package {
        uint32_t package;
        const char *code;
 };
 
 /* Newer devices have FICR INFO.PACKAGE.
  * This table converts its value to two character code */
-static const struct nrf5_device_package nrf5_packages_table[] = {
+static const struct nrfx_device_package nrfx_packages_table[] = {
        { 0x2000, "QF" },
        { 0x2001, "CH" },
        { 0x2002, "CI" },
        { 0x2005, "CK" },
 };
 
-const struct flash_driver nrf5_flash, nrf51_flash;
+const struct flash_driver nrf5_flash, nrf51_flash, nrf52_flash, nrf91_flash;
 
-static bool nrf5_bank_is_probed(const struct flash_bank *bank)
+static bool nrfx_bank_is_probed(const struct flash_bank *bank)
 {
-       struct nrf5_bank *nbank = bank->driver_priv;
+       struct nrfx_bank *nbank = bank->driver_priv;
 
        assert(nbank);
 
-       return nbank->probed;
+       struct nrfx_info *chip = nbank->chip;
+       assert(chip);
+
+       return chip->bank[bank->bank_number].probed;
 }
-static int nrf5_probe(struct flash_bank *bank);
+static int nrfx_auto_probe(struct flash_bank *bank);
 
-static int nrf5_get_probed_chip_if_halted(struct flash_bank *bank, struct 
nrf5_info **chip)
+static int nrfx_get_probed_chip_if_halted(struct flash_bank *bank, struct 
nrfx_info **chip)
 {
        if (bank->target->state != TARGET_HALTED) {
                LOG_ERROR("Target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       struct nrf5_bank *nbank = bank->driver_priv;
+       struct nrfx_bank *nbank = bank->driver_priv;
        *chip = nbank->chip;
 
-       if (nrf5_bank_is_probed(bank))
-               return ERROR_OK;
-
-       return nrf5_probe(bank);
+       return nrfx_auto_probe(bank);
 }
 
-static int nrf5_wait_for_nvmc(struct nrf5_info *chip)
+static int nrfx_wait_for_nvmc(struct nrfx_info *chip)
 {
        uint32_t ready;
        int res;
@@ -313,7 +646,7 @@ static int nrf5_wait_for_nvmc(struct nrf5_info *chip)
        int64_t ts_start = timeval_ms();
 
        do {
-               res = target_read_u32(chip->target, NRF5_NVMC_READY, &ready);
+               res = nvmc_read(chip, NRFX_NVMC_READY, &ready);
                if (res != ERROR_OK) {
                        LOG_ERROR("Error waiting NVMC_READY: generic flash 
write/erase error (check protection etc...)");
                        return res;
@@ -324,18 +657,15 @@ static int nrf5_wait_for_nvmc(struct nrf5_info *chip)
 
                keep_alive();
 
-       } while ((timeval_ms()-ts_start) < timeout_ms);
+       } while ((timeval_ms() - ts_start) < timeout_ms);
 
        LOG_DEBUG("Timed out waiting for NVMC_READY");
        return ERROR_FLASH_BUSY;
 }
 
-static int nrf5_nvmc_erase_enable(struct nrf5_info *chip)
+static int nrfx_nvmc_erase_enable(struct nrfx_info *chip)
 {
-       int res;
-       res = target_write_u32(chip->target,
-                              NRF5_NVMC_CONFIG,
-                              NRF5_NVMC_CONFIG_EEN);
+       int res = nvmc_write(chip, NRFX_NVMC_CONFIG, NRFX_NVMC_CONFIG_EEN);
 
        if (res != ERROR_OK) {
                LOG_ERROR("Failed to enable erase operation");
@@ -346,19 +676,16 @@ static int nrf5_nvmc_erase_enable(struct nrf5_info *chip)
          According to NVMC examples in Nordic SDK busy status must be
          checked after writing to NVMC_CONFIG
         */
-       res = nrf5_wait_for_nvmc(chip);
+       res = nrfx_wait_for_nvmc(chip);
        if (res != ERROR_OK)
                LOG_ERROR("Erase enable did not complete");
 
        return res;
 }
 
-static int nrf5_nvmc_write_enable(struct nrf5_info *chip)
+static int nrfx_nvmc_write_enable(struct nrfx_info *chip)
 {
-       int res;
-       res = target_write_u32(chip->target,
-                              NRF5_NVMC_CONFIG,
-                              NRF5_NVMC_CONFIG_WEN);
+       int res = nvmc_write(chip, NRFX_NVMC_CONFIG, NRFX_NVMC_CONFIG_WEN);
 
        if (res != ERROR_OK) {
                LOG_ERROR("Failed to enable write operation");
@@ -369,19 +696,16 @@ static int nrf5_nvmc_write_enable(struct nrf5_info *chip)
          According to NVMC examples in Nordic SDK busy status must be
          checked after writing to NVMC_CONFIG
         */
-       res = nrf5_wait_for_nvmc(chip);
+       res = nrfx_wait_for_nvmc(chip);
        if (res != ERROR_OK)
                LOG_ERROR("Write enable did not complete");
 
        return res;
 }
 
-static int nrf5_nvmc_read_only(struct nrf5_info *chip)
+static int nrfx_nvmc_read_only(struct nrfx_info *chip)
 {
-       int res;
-       res = target_write_u32(chip->target,
-                              NRF5_NVMC_CONFIG,
-                              NRF5_NVMC_CONFIG_REN);
+       int res = nvmc_write(chip, NRFX_NVMC_CONFIG, NRFX_NVMC_CONFIG_REN);
 
        if (res != ERROR_OK) {
                LOG_ERROR("Failed to enable read-only operation");
@@ -391,67 +715,79 @@ static int nrf5_nvmc_read_only(struct nrf5_info *chip)
          According to NVMC examples in Nordic SDK busy status must be
          checked after writing to NVMC_CONFIG
         */
-       res = nrf5_wait_for_nvmc(chip);
+       res = nrfx_wait_for_nvmc(chip);
        if (res != ERROR_OK)
                LOG_ERROR("Read only enable did not complete");
 
        return res;
 }
 
-static int nrf5_nvmc_generic_erase(struct nrf5_info *chip,
-                              uint32_t erase_register, uint32_t erase_value)
+static int nrfx_nvmc_generic_erase(struct nrfx_info *chip,
+                                  uint32_t erase_addr,
+                                  enum nrfx_nvmc_registers erase_register,
+                                  uint32_t erase_value)
 {
        int res;
 
-       res = nrf5_nvmc_erase_enable(chip);
+       res = nrfx_nvmc_erase_enable(chip);
        if (res != ERROR_OK)
                goto error;
 
-       res = target_write_u32(chip->target,
-                              erase_register,
-                              erase_value);
-       if (res != ERROR_OK)
-               goto set_read_only;
+       if (chip->family != NRFX_FAMILY_91) {
+               res = nvmc_write(chip, erase_register, erase_value);
+               if (res != ERROR_OK)
+                       goto set_read_only;
+       } else {
+               target_write_u32(chip->target, erase_addr, 0xffffffff);
+               usleep(100000);
+       }
 
-       res = nrf5_wait_for_nvmc(chip);
+       res = nrfx_wait_for_nvmc(chip);
        if (res != ERROR_OK)
                goto set_read_only;
 
-       return nrf5_nvmc_read_only(chip);
+       return nrfx_nvmc_read_only(chip);
 
 set_read_only:
-       nrf5_nvmc_read_only(chip);
+       nrfx_nvmc_read_only(chip);
 error:
-       LOG_ERROR("Failed to erase reg: 0x%08"PRIx32" val: 0x%08"PRIx32,
+       LOG_ERROR("Failed to erase reg: 0x%08" PRIx32 " val: 0x%08" PRIx32,
                  erase_register, erase_value);
        return ERROR_FAIL;
 }
 
-static int nrf5_protect_check_clenr0(struct flash_bank *bank)
+static int nrf51_protect_check_clenr0(struct flash_bank *bank)
 {
        int res;
        uint32_t clenr0;
-       struct nrf5_bank *nbank = bank->driver_priv;
-       struct nrf5_info *chip = nbank->chip;
+
+       struct nrfx_bank *nbank = bank->driver_priv;
+       struct nrfx_info *chip = nbank->chip;
 
        assert(chip);
 
-       res = target_read_u32(chip->target, NRF51_FICR_CLENR0,
-                             &clenr0);
+       res = ficr_read(chip, NRFX_FICR_CLENR0, &clenr0);
+
+       if (res == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
+               /* CLENR0 not implemented */
+               clenr0 = 0xFFFFFFFF;
+               goto no_clenr0;
+       }
+
        if (res != ERROR_OK) {
                LOG_ERROR("Couldn't read code region 0 size[FICR]");
                return res;
        }
 
        if (clenr0 == 0xFFFFFFFF) {
-               res = target_read_u32(chip->target, NRF51_UICR_CLENR0,
-                                     &clenr0);
+               res = uicr_read(chip, NRFX_UICR_CLENR0, &clenr0);
                if (res != ERROR_OK) {
                        LOG_ERROR("Couldn't read code region 0 size[UICR]");
                        return res;
                }
        }
 
+no_clenr0:
        for (unsigned int i = 0; i < bank->num_sectors; i++)
                bank->sectors[i].is_protected =
                        clenr0 != 0xFFFFFFFF && bank->sectors[i].offset < 
clenr0;
@@ -459,10 +795,10 @@ static int nrf5_protect_check_clenr0(struct flash_bank 
*bank)
        return ERROR_OK;
 }
 
-static int nrf5_protect_check_bprot(struct flash_bank *bank)
+static int nrfx_protect_check_bprot(struct flash_bank *bank)
 {
-       struct nrf5_bank *nbank = bank->driver_priv;
-       struct nrf5_info *chip = nbank->chip;
+       struct nrfx_bank *nbank = bank->driver_priv;
+       struct nrfx_info *chip = nbank->chip;
 
        assert(chip);
 
@@ -477,7 +813,9 @@ static int nrf5_protect_check_bprot(struct flash_bank *bank)
                        if (n_reg >= ARRAY_SIZE(nrf5_bprot_offsets))
                                break;
 
-                       res = target_read_u32(chip->target, NRF5_BPROT_BASE + 
nrf5_bprot_offsets[n_reg], &bprot_reg);
+                       res = reg_read(chip,
+                                       chip->nvmc_registers[NRFX_BPROT_BASE & 
REG_INDEX_MASK] +
+                                       nrf5_bprot_offsets[n_reg], &bprot_reg);
                        if (res != ERROR_OK)
                                return res;
                }
@@ -486,42 +824,42 @@ static int nrf5_protect_check_bprot(struct flash_bank 
*bank)
        return ERROR_OK;
 }
 
-static int nrf5_protect_check(struct flash_bank *bank)
+static int nrfx_protect_check(struct flash_bank *bank)
 {
        /* UICR cannot be write protected so just return early */
-       if (bank->base == NRF5_UICR_BASE)
+       if (bank->base == NRF5_UICR_BASE ||
+               bank->base == NRF9_UICR_BASE)
                return ERROR_OK;
 
-       struct nrf5_bank *nbank = bank->driver_priv;
-       struct nrf5_info *chip = nbank->chip;
+       struct nrfx_bank *nbank = bank->driver_priv;
+       struct nrfx_info *chip = nbank->chip;
 
        assert(chip);
 
-       if (chip->features & NRF5_FEATURE_BPROT)
-               return nrf5_protect_check_bprot(bank);
+       if (chip->features & NRFX_FEATURE_BPROT)
+               return nrfx_protect_check_bprot(bank);
 
-       if (chip->features & NRF5_FEATURE_SERIES_51)
-               return nrf5_protect_check_clenr0(bank);
+       if (chip->features & NRFX_FEATURE_SERIES_51)
+               return nrf51_protect_check_clenr0(bank);
 
        LOG_WARNING("Flash protection of this nRF device is not supported");
        return ERROR_FLASH_OPER_UNSUPPORTED;
 }
 
-static int nrf5_protect_clenr0(struct flash_bank *bank, int set, unsigned int 
first,
+static int nrfx_protect_clenr0(struct flash_bank *bank, int set, unsigned int 
first,
                unsigned int last)
 {
        int res;
        uint32_t clenr0, ppfc;
-       struct nrf5_bank *nbank = bank->driver_priv;
-       struct nrf5_info *chip = nbank->chip;
+       struct nrfx_bank *nbank = bank->driver_priv;
+       struct nrfx_info *chip = nbank->chip;
 
        if (first != 0) {
                LOG_ERROR("Code region 0 must start at the beginning of the 
bank");
                return ERROR_FAIL;
        }
 
-       res = target_read_u32(chip->target, NRF51_FICR_PPFC,
-                             &ppfc);
+       res = ficr_read(chip, NRFX_FICR_PPFC, &ppfc);
        if (res != ERROR_OK) {
                LOG_ERROR("Couldn't read PPFC register");
                return res;
@@ -532,8 +870,7 @@ static int nrf5_protect_clenr0(struct flash_bank *bank, int 
set, unsigned int fi
                return ERROR_FAIL;
        }
 
-       res = target_read_u32(chip->target, NRF51_UICR_CLENR0,
-                             &clenr0);
+       res = uicr_read(chip, NRFX_UICR_CLENR0, &clenr0);
        if (res != ERROR_OK) {
                LOG_ERROR("Couldn't read code region 0 size from UICR");
                return res;
@@ -544,14 +881,14 @@ static int nrf5_protect_clenr0(struct flash_bank *bank, 
int set, unsigned int fi
                return ERROR_FAIL;
        }
 
-       res = nrf5_nvmc_write_enable(chip);
+       res = nrfx_nvmc_write_enable(chip);
        if (res != ERROR_OK)
                goto error;
 
        clenr0 = bank->sectors[last].offset + bank->sectors[last].size;
-       res = target_write_u32(chip->target, NRF51_UICR_CLENR0, clenr0);
+       res = uicr_write(chip, NRFX_UICR_CLENR0, clenr0);
 
-       int res2 = nrf5_wait_for_nvmc(chip);
+       int res2 = nrfx_wait_for_nvmc(chip);
 
        if (res == ERROR_OK)
                res = res2;
@@ -562,16 +899,16 @@ static int nrf5_protect_clenr0(struct flash_bank *bank, 
int set, unsigned int fi
                LOG_ERROR("Couldn't write code region 0 size to UICR");
 
 error:
-       nrf5_nvmc_read_only(chip);
+       nrfx_nvmc_read_only(chip);
 
        return res;
 }
 
-static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first,
+static int nrfx_protect(struct flash_bank *bank, int set, unsigned int first,
                unsigned int last)
 {
        int res;
-       struct nrf5_info *chip;
+       struct nrfx_info *chip;
 
        /* UICR cannot be write protected so just bail out early */
        if (bank->base == NRF5_UICR_BASE) {
@@ -579,18 +916,18 @@ static int nrf5_protect(struct flash_bank *bank, int set, 
unsigned int first,
                return ERROR_FLASH_OPER_UNSUPPORTED;
        }
 
-       res = nrf5_get_probed_chip_if_halted(bank, &chip);
+       res = nrfx_get_probed_chip_if_halted(bank, &chip);
        if (res != ERROR_OK)
                return res;
 
-       if (chip->features & NRF5_FEATURE_SERIES_51)
-               return nrf5_protect_clenr0(bank, set, first, last);
+       if (chip->features & NRFX_FEATURE_SERIES_51)
+               return nrfx_protect_clenr0(bank, set, first, last);
 
        LOG_ERROR("Flash protection setting is not supported on this nRF5 
device");
        return ERROR_FLASH_OPER_UNSUPPORTED;
 }
 
-static bool nrf5_info_variant_to_str(uint32_t variant, char *bf)
+static bool nrfx_info_variant_to_str(uint32_t variant, char *bf)
 {
        uint8_t b[4];
 
@@ -605,16 +942,16 @@ static bool nrf5_info_variant_to_str(uint32_t variant, 
char *bf)
        return false;
 }
 
-static const char *nrf5_decode_info_package(uint32_t package)
+static const char *nrfx_decode_info_package(uint32_t package)
 {
-       for (size_t i = 0; i < ARRAY_SIZE(nrf5_packages_table); i++) {
-               if (nrf5_packages_table[i].package == package)
-                       return nrf5_packages_table[i].code;
+       for (size_t i = 0; i < ARRAY_SIZE(nrfx_packages_table); i++) {
+               if (nrfx_packages_table[i].package == package)
+                       return nrfx_packages_table[i].code;
        }
        return "xx";
 }
 
-static int get_nrf5_chip_type_str(const struct nrf5_info *chip, char *buf, 
unsigned int buf_size)
+static int get_nrfx_chip_type_str(const struct nrfx_info *chip, char *buf, 
unsigned int buf_size)
 {
        int res;
        if (chip->spec) {
@@ -622,10 +959,10 @@ static int get_nrf5_chip_type_str(const struct nrf5_info 
*chip, char *buf, unsig
                                chip->spec->part, chip->spec->variant, 
chip->spec->build_code);
        } else if (chip->ficr_info_valid) {
                char variant[5];
-               nrf5_info_variant_to_str(chip->ficr_info.variant, variant);
+               nrfx_info_variant_to_str(chip->ficr_info.variant, variant);
                res = snprintf(buf, buf_size, "nRF%" PRIx32 "-%s%.2s(build 
code: %s)",
                                chip->ficr_info.part,
-                               
nrf5_decode_info_package(chip->ficr_info.package),
+                               
nrfx_decode_info_package(chip->ficr_info.package),
                                variant, &variant[2]);
        } else {
                res = snprintf(buf, buf_size, "nRF51xxx (HWID 0x%04" PRIx16 
")", chip->hwid);
@@ -639,13 +976,13 @@ static int get_nrf5_chip_type_str(const struct nrf5_info 
*chip, char *buf, unsig
        return ERROR_OK;
 }
 
-static int nrf5_info(struct flash_bank *bank, struct command_invocation *cmd)
+static int nrfx_info(struct flash_bank *bank, struct command_invocation *cmd)
 {
-       struct nrf5_bank *nbank = bank->driver_priv;
-       struct nrf5_info *chip = nbank->chip;
+       struct nrfx_bank *nbank = bank->driver_priv;
+       struct nrfx_info *chip = nbank->chip;
 
        char chip_type_str[256];
-       if (get_nrf5_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) 
!= ERROR_OK)
+       if (get_nrfx_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) 
!= ERROR_OK)
                return ERROR_FAIL;
 
        command_print_sameline(cmd, "%s %ukB Flash, %ukB RAM",
@@ -653,43 +990,60 @@ static int nrf5_info(struct flash_bank *bank, struct 
command_invocation *cmd)
        return ERROR_OK;
 }
 
-static int nrf5_read_ficr_info(struct nrf5_info *chip)
+static int nrfx_read_ficr_info(struct nrfx_info *chip)
 {
        int res;
-       struct target *target = chip->target;
 
        chip->ficr_info_valid = false;
 
-       res = target_read_u32(target, NRF5_FICR_INFO_PART, 
&chip->ficr_info.part);
+       if (!ficr_is_implemented(chip, NRFX_FICR_INFO_PART)) {
+               LOG_INFO("FICR INFO.PART register not supported");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       res = ficr_read(chip, NRFX_FICR_INFO_PART, &chip->ficr_info.part);
        if (res != ERROR_OK) {
-               LOG_DEBUG("Couldn't read FICR INFO.PART register");
+               LOG_INFO("Couldn't read FICR INFO.PART register");
                return res;
        }
 
        uint32_t series = chip->ficr_info.part & 0xfffff000;
        switch (series) {
        case 0x51000:
-               chip->features = NRF5_FEATURE_SERIES_51;
+               chip->features = NRFX_FEATURE_SERIES_51;
                break;
 
        case 0x52000:
-               chip->features = NRF5_FEATURE_SERIES_52;
+               chip->features = NRFX_FEATURE_SERIES_52;
 
                switch (chip->ficr_info.part) {
                case 0x52810:
                case 0x52832:
-                       chip->features |= NRF5_FEATURE_BPROT;
+                       chip->features |= NRFX_FEATURE_BPROT;
                        break;
 
                case 0x52840:
-                       chip->features |= NRF5_FEATURE_ACL_PROT;
+                       chip->features |= NRFX_FEATURE_ACL_PROT;
                        break;
                }
                break;
 
+       case 0x9000:
+               res = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               switch (chip->ficr_info.part) {
+                       case 0x9120:
+                       case 0x9160:
+                               chip->features |= NRFX_FEATURE_SERIES_91;
+                               res = ERROR_OK;
+                               break;
+               }
+               if (res == ERROR_OK)
+                       break;
+               /* fallthrough */
+
        default:
-               LOG_DEBUG("FICR INFO likely not implemented. Invalid PART value 
0x%08"
-                               PRIx32, chip->ficr_info.part);
+               LOG_INFO("FICR INFO likely not implemented. Invalid PART value 
(%x) 0x%08"
+                               PRIx32, series, chip->ficr_info.part);
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
@@ -699,19 +1053,19 @@ static int nrf5_read_ficr_info(struct nrf5_info *chip)
         * VARIANT and PACKAGE coding is unknown for a nRF51 device.
         * nRF52 devices have FICR INFO documented and always filled. */
 
-       res = target_read_u32(target, NRF5_FICR_INFO_VARIANT, 
&chip->ficr_info.variant);
+       res = ficr_read(chip, NRFX_FICR_INFO_VARIANT, &chip->ficr_info.variant);
        if (res != ERROR_OK)
                return res;
 
-       res = target_read_u32(target, NRF5_FICR_INFO_PACKAGE, 
&chip->ficr_info.package);
+       res = ficr_read(chip, NRFX_FICR_INFO_PACKAGE, &chip->ficr_info.package);
        if (res != ERROR_OK)
                return res;
 
-       res = target_read_u32(target, NRF5_FICR_INFO_RAM, &chip->ficr_info.ram);
+       res = ficr_read(chip, NRFX_FICR_INFO_RAM, &chip->ficr_info.ram);
        if (res != ERROR_OK)
                return res;
 
-       res = target_read_u32(target, NRF5_FICR_INFO_FLASH, 
&chip->ficr_info.flash);
+       res = ficr_read(chip, NRFX_FICR_INFO_FLASH, &chip->ficr_info.flash);
        if (res != ERROR_OK)
                return res;
 
@@ -719,14 +1073,14 @@ static int nrf5_read_ficr_info(struct nrf5_info *chip)
        return ERROR_OK;
 }
 
-static int nrf5_get_ram_size(struct target *target, uint32_t *ram_size)
+static int nrfx_get_ram_size(struct nrfx_info *chip, uint32_t *ram_size)
 {
        int res;
 
        *ram_size = 0;
 
        uint32_t numramblock;
-       res = target_read_u32(target, NRF51_FICR_NUMRAMBLOCK, &numramblock);
+       res = ficr_read(chip, NRFX_FICR_NUMRAMBLOCK, &numramblock);
        if (res != ERROR_OK) {
                LOG_DEBUG("Couldn't read FICR NUMRAMBLOCK register");
                return res;
@@ -739,7 +1093,7 @@ static int nrf5_get_ram_size(struct target *target, 
uint32_t *ram_size)
 
        for (unsigned int i = 0; i < numramblock; i++) {
                uint32_t sizeramblock;
-               res = target_read_u32(target, NRF51_FICR_SIZERAMBLOCK0 + 
sizeof(uint32_t)*i, &sizeramblock);
+               res = ficr_read(chip, NRFX_FICR_SIZERAMBLOCK0 + 
sizeof(uint32_t) * i, &sizeramblock);
                if (res != ERROR_OK) {
                        LOG_DEBUG("Couldn't read FICR NUMRAMBLOCK register");
                        return res;
@@ -752,77 +1106,138 @@ static int nrf5_get_ram_size(struct target *target, 
uint32_t *ram_size)
        return res;
 }
 
-static int nrf5_probe(struct flash_bank *bank)
+static int nrfx_set_registers(struct nrfx_info *chip, enum nrfx_family family)
+{
+       chip->family = family;
+       switch (chip->family) {
+       case NRFX_FAMILY_51:
+               LOG_DEBUG("Select 51 family");
+               /* fallthrough */
+       case NRFX_FAMILY_5X:
+               chip->ficr_registers = nrf51_ficr_registers;
+               chip->uicr_registers = nrf51_uicr_registers;
+               chip->nvmc_registers = nrf5_nvmc_registers;
+               break;
+       case NRFX_FAMILY_52:
+               chip->ficr_registers = nrf52_ficr_registers;
+               chip->uicr_registers = nrf52_uicr_registers;
+               chip->nvmc_registers = nrf5_nvmc_registers;
+               LOG_DEBUG("Select 52 family");
+               break;
+       case NRFX_FAMILY_91:
+               chip->ficr_registers = nrf91_ficr_registers;
+               chip->uicr_registers = nrf91_uicr_registers;
+               chip->nvmc_registers = nrf91_nvmc_registers;
+               LOG_DEBUG("Select 91 family");
+               break;
+       default:
+               LOG_ERROR("Unsupported family %d\n", chip->family);
+               return ERROR_FAIL;
+       }
+       return ERROR_OK;
+}
+
+static int nrfx_probe(struct flash_bank *bank)
 {
        int res;
-       struct nrf5_bank *nbank = bank->driver_priv;
-       struct nrf5_info *chip = nbank->chip;
-       struct target *target = chip->target;
+       struct nrfx_bank *nbank = bank->driver_priv;
+       struct nrfx_info *chip = nbank->chip;
+       enum nrfx_family old_family = chip->family;
 
        uint32_t configid;
-       res = target_read_u32(target, NRF5_FICR_CONFIGID, &configid);
-       if (res != ERROR_OK) {
-               LOG_ERROR("Couldn't read CONFIGID register");
-               return res;
-       }
-
-       /* HWID is stored in the lower two bytes of the CONFIGID register */
-       chip->hwid = configid & 0xFFFF;
+       chip->features = 0;
+       if (ficr_is_implemented(chip, NRFX_FICR_CONFIGID)) {
+               res = ficr_read(chip, NRFX_FICR_CONFIGID, &configid);
+               if (res != ERROR_OK) {
+                       LOG_ERROR("Couldn't read CONFIGID register");
+                       return res;
+               }
 
-       /* guess a nRF51 series if the device has no FICR INFO and we don't 
know HWID */
-       chip->features = NRF5_FEATURE_SERIES_51;
+               /* HWID is stored in the lower two bytes of the CONFIGID 
register */
+               chip->hwid = configid & 0xFFFF;
+       }
 
        /* Don't bail out on error for the case that some old engineering
         * sample has FICR INFO registers unreadable. We can proceed anyway. */
-       (void)nrf5_read_ficr_info(chip);
+       (void)nrfx_read_ficr_info(chip);
 
        chip->spec = NULL;
-       for (size_t i = 0; i < ARRAY_SIZE(nrf5_known_devices_table); i++) {
-               if (chip->hwid == nrf5_known_devices_table[i].hwid) {
-                       chip->spec = &nrf5_known_devices_table[i];
+       for (size_t i = 0; i < ARRAY_SIZE(nrfx_known_devices_table); i++) {
+               if (chip->hwid == nrfx_known_devices_table[i].id.hwid) {
+                       chip->spec = &nrfx_known_devices_table[i];
                        chip->features = chip->spec->features;
                        break;
                }
        }
 
-       if (chip->spec && chip->ficr_info_valid) {
+       if (!chip->spec && chip->ficr_info_valid) {
+               /* In case if CONFIGID is not supported */
+               for (size_t i = 0; i < ARRAY_SIZE(nrfx_known_devices_table); 
i++) {
+                       if (chip->ficr_info.part == 
nrfx_known_devices_table[i].id.part &&
+                               nrfx_known_devices_table[i].id.hwid == 0xFFFF) {
+                               chip->spec = &nrfx_known_devices_table[i];
+                               chip->features = chip->spec->features;
+                               break;
+                       }
+               }
+       }
+       if (chip->features & NRFX_FEATURE_SERIES_51)
+               chip->family = NRFX_FAMILY_51;
+       else if (chip->features & NRFX_FEATURE_SERIES_52)
+               chip->family = NRFX_FAMILY_52;
+       else if (chip->features & NRFX_FEATURE_SERIES_91)
+               chip->family = NRFX_FAMILY_91;
+       else
+               chip->family = old_family;
+
+       /* Update registers definition based on family */
+       res = nrfx_set_registers(chip, chip->family);
+       if (res != ERROR_OK)
+               return res;
+
+       if (!chip->spec) {
+               LOG_ERROR("Probing failed: HWID 0x%04" PRIx32 " FICR INFO.PART 
%" PRIx32, chip->hwid, chip->ficr_info.part);
+               return ERROR_FAIL;
+       }
+
+       if (chip->ficr_info_valid) {
                /* check if HWID table gives the same part as FICR INFO */
                if (chip->ficr_info.part != strtoul(chip->spec->part, NULL, 16))
                        LOG_WARNING("HWID 0x%04" PRIx32 " mismatch: FICR 
INFO.PART %"
                                                PRIx32, chip->hwid, 
chip->ficr_info.part);
        }
 
+       LOG_DEBUG("Probed: 0x%06x 0x%06x", chip->spec->id.hwid, 
chip->spec->id.part);
+
        if (chip->ficr_info_valid) {
                chip->ram_size_kb = chip->ficr_info.ram;
        } else {
                uint32_t ram_size;
-               nrf5_get_ram_size(target, &ram_size);
+               nrfx_get_ram_size(chip, &ram_size);
                chip->ram_size_kb = ram_size / 1024;
        }
 
-       /* The value stored in NRF5_FICR_CODEPAGESIZE is the number of bytes in 
one page of FLASH. */
-       uint32_t flash_page_size;
-       res = target_read_u32(chip->target, NRF5_FICR_CODEPAGESIZE,
-                               &flash_page_size);
-       if (res != ERROR_OK) {
-               LOG_ERROR("Couldn't read code page size");
-               return res;
-       }
+       if (bank->base == NRFX_FLASH_BASE) {
+               /* The value stored in NRFX_FICR_CODEPAGESIZE is the number of 
bytes in one page of FLASH. */
+               res = ficr_read(chip, NRFX_FICR_CODEPAGESIZE, 
&chip->ficr_info.flash_page_size);
+               if (res != ERROR_OK) {
+                       LOG_ERROR("Couldn't read code page size");
+                       return res;
+               }
 
-       /* Note the register name is misleading,
-        * NRF5_FICR_CODESIZE is the number of pages in flash memory, not the 
number of bytes! */
-       uint32_t num_sectors;
-       res = target_read_u32(chip->target, NRF5_FICR_CODESIZE, &num_sectors);
-       if (res != ERROR_OK) {
-               LOG_ERROR("Couldn't read code memory size");
-               return res;
+               /* Note the register name is misleading,
+               * NRF5_FICR_CODESIZE is the number of pages in flash memory, 
not the number of bytes! */
+               res = ficr_read(chip, NRFX_FICR_CODESIZE, 
&chip->ficr_info.num_sectors);
+               if (res != ERROR_OK) {
+                       LOG_ERROR("Couldn't read code memory size");
+                       return res;
+               }
+               chip->flash_size_kb = chip->ficr_info.num_sectors * 
chip->ficr_info.flash_page_size / 1024;
        }
 
-       chip->flash_size_kb = num_sectors * flash_page_size / 1024;
-
        if (!chip->bank[0].probed && !chip->bank[1].probed) {
                char chip_type_str[256];
-               if (get_nrf5_chip_type_str(chip, chip_type_str, 
sizeof(chip_type_str)) != ERROR_OK)
+               if (get_nrfx_chip_type_str(chip, chip_type_str, 
sizeof(chip_type_str)) != ERROR_OK)
                        return ERROR_FAIL;
                const bool device_is_unknown = (!chip->spec && 
!chip->ficr_info_valid);
                LOG_INFO("%s%s %ukB Flash, %ukB RAM",
@@ -834,27 +1249,40 @@ static int nrf5_probe(struct flash_bank *bank)
 
        free(bank->sectors);
 
-       if (bank->base == NRF5_FLASH_BASE) {
+       if (bank->base == NRFX_FLASH_BASE) {
                /* Sanity check */
                if (chip->spec && chip->flash_size_kb != 
chip->spec->flash_size_kb)
                        LOG_WARNING("Chip's reported Flash capacity does not 
match expected one");
                if (chip->ficr_info_valid && chip->flash_size_kb != 
chip->ficr_info.flash)
                        LOG_WARNING("Chip's reported Flash capacity does not 
match FICR INFO.FLASH");
 
-               bank->num_sectors = num_sectors;
-               bank->size = num_sectors * flash_page_size;
+               bank->num_sectors = chip->ficr_info.num_sectors;
+               bank->size = bank->num_sectors * 
chip->ficr_info.flash_page_size;
 
-               bank->sectors = alloc_block_array(0, flash_page_size, 
num_sectors);
+               bank->sectors = alloc_block_array(0, 
chip->ficr_info.flash_page_size, chip->ficr_info.num_sectors);
                if (!bank->sectors)
                        return ERROR_FAIL;
 
+               /* Fill out the sector information: all NRFX sectors are the 
same size and
+                * there is always a fixed number of them. */
+               for (unsigned int i = 0; i < bank->num_sectors; i++) {
+                       bank->sectors[i].size = chip->ficr_info.flash_page_size;
+                       bank->sectors[i].offset = i * 
chip->ficr_info.flash_page_size;
+
+                       /* mark as unknown */
+                       bank->sectors[i].is_erased = -1;
+                       bank->sectors[i].is_protected = -1;
+               }
+
+               nrfx_protect_check(bank);
+
                chip->bank[0].probed = true;
 
        } else {
                bank->num_sectors = 1;
-               bank->size = flash_page_size;
+               bank->size = NRFX_UICR_SIZE;
 
-               bank->sectors = alloc_block_array(0, flash_page_size, 
num_sectors);
+               bank->sectors = alloc_block_array(0, bank->size, 1);
                if (!bank->sectors)
                        return ERROR_FAIL;
 
@@ -866,35 +1294,39 @@ static int nrf5_probe(struct flash_bank *bank)
        return ERROR_OK;
 }
 
-static int nrf5_auto_probe(struct flash_bank *bank)
+static int nrfx_auto_probe(struct flash_bank *bank)
 {
-       if (nrf5_bank_is_probed(bank))
+       if(nrfx_bank_is_probed(bank))
                return ERROR_OK;
-
-       return nrf5_probe(bank);
+       return nrfx_probe(bank);
 }
 
-static int nrf5_erase_all(struct nrf5_info *chip)
+static int nrfx_erase_all(struct nrfx_info *chip)
 {
        LOG_DEBUG("Erasing all non-volatile memory");
-       return nrf5_nvmc_generic_erase(chip,
-                                       NRF5_NVMC_ERASEALL,
+       return nrfx_nvmc_generic_erase(chip,
+                                       0,
+                                       NRFX_NVMC_ERASEALL,
                                        0x00000001);
 }
 
-static int nrf5_erase_page(struct flash_bank *bank,
-                                                       struct nrf5_info *chip,
-                                                       struct flash_sector 
*sector)
+static int nrfx_erase_page(struct flash_bank *bank,
+                          struct nrfx_info *chip,
+                          struct flash_sector *sector)
 {
        int res;
+       LOG_DEBUG("Erasing page at 0x%" PRIx32, sector->offset);
 
-       LOG_DEBUG("Erasing page at 0x%"PRIx32, sector->offset);
+       /* TODO: Inspect #5348 further whether the removal is still valid*/
+       if (sector->is_protected) {
+               LOG_ERROR("Cannot erase protected sector at 0x%" PRIx32, 
sector->offset);
+               return ERROR_FAIL;
+       }
 
        if (bank->base == NRF5_UICR_BASE) {
-               if (chip->features & NRF5_FEATURE_SERIES_51) {
+               if (chip->features & NRFX_FEATURE_SERIES_51) {
                        uint32_t ppfc;
-                       res = target_read_u32(chip->target, NRF51_FICR_PPFC,
-                                     &ppfc);
+                       res = ficr_read(chip, NRFX_FICR_PPFC, &ppfc);
                        if (res != ERROR_OK) {
                                LOG_ERROR("Couldn't read PPFC register");
                                return res;
@@ -912,22 +1344,24 @@ static int nrf5_erase_page(struct flash_bank *bank,
                        }
                }
 
-               res = nrf5_nvmc_generic_erase(chip,
-                                              NRF5_NVMC_ERASEUICR,
-                                              0x00000001);
+               res = nrfx_nvmc_generic_erase(chip,
+                                                  0,
+                                                  NRFX_NVMC_ERASEUICR,
+                                                  0x00000001);
 
 
        } else {
-               res = nrf5_nvmc_generic_erase(chip,
-                                              NRF5_NVMC_ERASEPAGE,
-                                              sector->offset);
+               res = nrfx_nvmc_generic_erase(chip,
+                                                  sector->offset,
+                                                  NRFX_NVMC_ERASEPAGE,
+                                                  sector->offset);
        }
 
        return res;
 }
 
 /* Start a low level flash write for the specified region */
-static int nrf5_ll_flash_write(struct nrf5_info *chip, uint32_t address, const 
uint8_t *buffer, uint32_t bytes)
+static int nrf5_ll_flash_write(struct nrfx_info *chip, uint32_t address, const 
uint8_t *buffer, uint32_t bytes)
 {
        struct target *target = chip->target;
        uint32_t buffer_size = 8192;
@@ -937,15 +1371,15 @@ static int nrf5_ll_flash_write(struct nrf5_info *chip, 
uint32_t address, const u
        struct armv7m_algorithm armv7m_info;
        int retval = ERROR_OK;
 
-       static const uint8_t nrf5_flash_write_code[] = {
+       static const uint8_t nrfx_flash_write_code[] = {
 #include "../../../contrib/loaders/flash/nrf5/nrf5.inc"
        };
 
-       LOG_DEBUG("Writing buffer to flash address=0x%"PRIx32" 
bytes=0x%"PRIx32, address, bytes);
-       assert(bytes % 4 == 0);
+       LOG_DEBUG("Writing buffer to flash address=0x%" PRIx32 " bytes=0x%" 
PRIx32, address, bytes);
+       assert(IS_ALIGNED(bytes, 4));
 
        /* allocate working area with flash programming code */
-       if (target_alloc_working_area(target, sizeof(nrf5_flash_write_code),
+       if (target_alloc_working_area(target, sizeof(nrfx_flash_write_code),
                        &write_algorithm) != ERROR_OK) {
                LOG_WARNING("no working area available, falling back to slow 
memory writes");
 
@@ -954,7 +1388,7 @@ static int nrf5_ll_flash_write(struct nrf5_info *chip, 
uint32_t address, const u
                        if (retval != ERROR_OK)
                                return retval;
 
-                       retval = nrf5_wait_for_nvmc(chip);
+                       retval = nrfx_wait_for_nvmc(chip);
                        if (retval != ERROR_OK)
                                return retval;
 
@@ -966,8 +1400,8 @@ static int nrf5_ll_flash_write(struct nrf5_info *chip, 
uint32_t address, const u
        }
 
        retval = target_write_buffer(target, write_algorithm->address,
-                               sizeof(nrf5_flash_write_code),
-                               nrf5_flash_write_code);
+                               sizeof(nrfx_flash_write_code),
+                               nrfx_flash_write_code);
        if (retval != ERROR_OK)
                return retval;
 
@@ -1001,11 +1435,11 @@ static int nrf5_ll_flash_write(struct nrf5_info *chip, 
uint32_t address, const u
        buf_set_u32(reg_params[4].value, 0, 32, WATCHDOG_REFRESH_VALUE);
        buf_set_u32(reg_params[5].value, 0, 32, WATCHDOG_REFRESH_REGISTER);
 
-       retval = target_run_flash_async_algorithm(target, buffer, bytes/4, 4,
+       retval = target_run_flash_async_algorithm(target, buffer, bytes / 4, 4,
                        0, NULL,
                        ARRAY_SIZE(reg_params), reg_params,
                        source->address, source->size,
-                       write_algorithm->address, write_algorithm->address + 
sizeof(nrf5_flash_write_code) - 2,
+                       write_algorithm->address, write_algorithm->address + 
sizeof(nrfx_flash_write_code) - 2,
                        &armv7m_info);
 
        target_free_working_area(target, source);
@@ -1021,15 +1455,17 @@ static int nrf5_ll_flash_write(struct nrf5_info *chip, 
uint32_t address, const u
        return retval;
 }
 
-static int nrf5_write(struct flash_bank *bank, const uint8_t *buffer,
-                                       uint32_t offset, uint32_t count)
+static int nrfx_write(struct flash_bank *bank, const uint8_t *buffer,
+                          uint32_t offset, uint32_t count)
 {
-       struct nrf5_info *chip;
-
-       int res = nrf5_get_probed_chip_if_halted(bank, &chip);
+       struct nrfx_info *chip;
+       int res = nrfx_get_probed_chip_if_halted(bank, &chip);
        if (res != ERROR_OK)
                return res;
 
+       if (!chip)
+               return ERROR_FAIL;
+
        assert(offset % 4 == 0);
        assert(count % 4 == 0);
 
@@ -1041,9 +1477,9 @@ static int nrf5_write(struct flash_bank *bank, const 
uint8_t *buffer,
         *
         * Update protection state and check if any flash sector to be written
         * is protected. */
-       if (chip->features & NRF5_FEATURE_SERIES_51) {
+       if (chip->features & NRFX_FEATURE_SERIES_51) {
 
-               res = nrf5_protect_check_clenr0(bank);
+               res = nrf51_protect_check_clenr0(bank);
                if (res != ERROR_OK)
                        return res;
 
@@ -1061,29 +1497,31 @@ static int nrf5_write(struct flash_bank *bank, const 
uint8_t *buffer,
                }
        }
 
-       res = nrf5_nvmc_write_enable(chip);
+       res = nrfx_nvmc_write_enable(chip);
        if (res != ERROR_OK)
                goto error;
 
-       res = nrf5_ll_flash_write(chip, bank->base + offset, buffer, count);
+       if (chip->family != NRFX_FAMILY_91)
+               res = nrf5_ll_flash_write(chip, bank->base + offset, buffer, 
count);
+       else
+               res = target_write_buffer(chip->target, bank->base + offset, 
count, buffer);
        if (res != ERROR_OK)
                goto error;
-
-       return nrf5_nvmc_read_only(chip);
+       return nrfx_nvmc_read_only(chip);
 
 error:
-       nrf5_nvmc_read_only(chip);
-       LOG_ERROR("Failed to write to nrf5 flash");
+       nrfx_nvmc_read_only(chip);
+       LOG_ERROR("Failed to write to flash");
        return res;
 }
 
-static int nrf5_erase(struct flash_bank *bank, unsigned int first,
+static int nrfx_erase(struct flash_bank *bank, unsigned int first,
                unsigned int last)
 {
        int res;
-       struct nrf5_info *chip;
+       struct nrfx_info *chip;
 
-       res = nrf5_get_probed_chip_if_halted(bank, &chip);
+       res = nrfx_get_probed_chip_if_halted(bank, &chip);
        if (res != ERROR_OK)
                return res;
 
@@ -1093,23 +1531,21 @@ static int nrf5_erase(struct flash_bank *bank, unsigned 
int first,
         *
         * Update protection state and check if any flash sector to be erased
         * is protected. */
-       if (chip->features & NRF5_FEATURE_SERIES_51) {
-
-               res = nrf5_protect_check_clenr0(bank);
+       if (chip->features & NRFX_FEATURE_SERIES_51) {
+               res = nrf51_protect_check_clenr0(bank);
                if (res != ERROR_OK)
                        return res;
        }
 
        /* For each sector to be erased */
        for (unsigned int s = first; s <= last && res == ERROR_OK; s++) {
-
-               if (chip->features & NRF5_FEATURE_SERIES_51
+               if (chip->features & NRFX_FEATURE_SERIES_51
                                && bank->sectors[s].is_protected == 1) {
                        LOG_ERROR("Flash sector %d is protected", s);
                        return ERROR_FLASH_PROTECTED;
                }
 
-               res = nrf5_erase_page(bank, chip, &bank->sectors[s]);
+               res = nrfx_erase_page(bank, chip, &bank->sectors[s]);
                if (res != ERROR_OK) {
                        LOG_ERROR("Error erasing sector %d", s);
                        return res;
@@ -1119,10 +1555,10 @@ static int nrf5_erase(struct flash_bank *bank, unsigned 
int first,
        return ERROR_OK;
 }
 
-static void nrf5_free_driver_priv(struct flash_bank *bank)
+static void nrfx_free_driver_priv(struct flash_bank *bank)
 {
-       struct nrf5_bank *nbank = bank->driver_priv;
-       struct nrf5_info *chip = nbank->chip;
+       struct nrfx_bank *nbank = bank->driver_priv;
+       struct nrfx_info *chip = nbank->chip;
        if (!chip)
                return;
 
@@ -1133,19 +1569,21 @@ static void nrf5_free_driver_priv(struct flash_bank 
*bank)
        }
 }
 
-static struct nrf5_info *nrf5_get_chip(struct target *target)
+static struct nrfx_info *nrfx_get_chip(struct target *target)
 {
        struct flash_bank *bank_iter;
 
-       /* iterate over nrf5 banks of same target */
+       /* iterate over nrf banks of same target */
        for (bank_iter = flash_bank_list(); bank_iter; bank_iter = 
bank_iter->next) {
-               if (bank_iter->driver != &nrf5_flash && bank_iter->driver != 
&nrf51_flash)
+               if (bank_iter->driver != &nrf5_flash &&
+                       bank_iter->driver != &nrf51_flash &&
+                       bank_iter->driver != &nrf91_flash)
                        continue;
 
                if (bank_iter->target != target)
                        continue;
 
-               struct nrf5_bank *nbank = bank_iter->driver_priv;
+               struct nrfx_bank *nbank = bank_iter->driver_priv;
                if (!nbank)
                        continue;
 
@@ -1155,21 +1593,23 @@ static struct nrf5_info *nrf5_get_chip(struct target 
*target)
        return NULL;
 }
 
-FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command)
+static int nrfx_flash_bank_command(struct flash_bank *bank, enum nrfx_family 
family)
 {
-       struct nrf5_info *chip;
-       struct nrf5_bank *nbank = NULL;
+       int res;
+       struct nrfx_info *chip;
+       struct nrfx_bank *nbank = NULL;
 
        switch (bank->base) {
-       case NRF5_FLASH_BASE:
+       case NRFX_FLASH_BASE:
        case NRF5_UICR_BASE:
+       case NRF9_UICR_BASE:
                break;
        default:
                LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, bank->base);
                return ERROR_FAIL;
        }
 
-       chip = nrf5_get_chip(bank->target);
+       chip = nrfx_get_chip(bank->target);
        if (!chip) {
                /* Create a new chip */
                chip = calloc(1, sizeof(*chip));
@@ -1177,16 +1617,23 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command)
                        return ERROR_FAIL;
 
                chip->target = bank->target;
+               res = nrfx_set_registers(chip, family);
+               if (res != ERROR_OK) {
+                       free(chip);
+                       return res;
+               }
        }
 
        switch (bank->base) {
-       case NRF5_FLASH_BASE:
+       case NRFX_FLASH_BASE:
                nbank = &chip->bank[0];
                break;
        case NRF5_UICR_BASE:
+       case NRF9_UICR_BASE:
                nbank = &chip->bank[1];
                break;
        }
+
        assert(nbank);
 
        chip->refcount++;
@@ -1194,32 +1641,50 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command)
        nbank->probed = false;
        bank->driver_priv = nbank;
        bank->write_start_alignment = bank->write_end_alignment = 4;
-
        return ERROR_OK;
 }
 
-COMMAND_HANDLER(nrf5_handle_mass_erase_command)
+FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command)
+{
+       return nrfx_flash_bank_command(bank, NRFX_FAMILY_5X);
+}
+
+FLASH_BANK_COMMAND_HANDLER(nrf51_flash_bank_command)
+{
+       return nrfx_flash_bank_command(bank, NRFX_FAMILY_51);
+}
+
+FLASH_BANK_COMMAND_HANDLER(nrf52_flash_bank_command)
+{
+       return nrfx_flash_bank_command(bank, NRFX_FAMILY_52);
+}
+
+FLASH_BANK_COMMAND_HANDLER(nrf91_flash_bank_command)
+{
+       return nrfx_flash_bank_command(bank, NRFX_FAMILY_91);
+}
+
+COMMAND_HANDLER(nrfx_handle_mass_erase_command)
 {
        int res;
        struct flash_bank *bank = NULL;
        struct target *target = get_current_target(CMD_CTX);
 
-       res = get_flash_bank_by_addr(target, NRF5_FLASH_BASE, true, &bank);
+       res = get_flash_bank_by_addr(target, NRFX_FLASH_BASE, true, &bank);
        if (res != ERROR_OK)
                return res;
 
        assert(bank);
 
-       struct nrf5_info *chip;
+       struct nrfx_info *chip;
 
-       res = nrf5_get_probed_chip_if_halted(bank, &chip);
+       res = nrfx_get_probed_chip_if_halted(bank, &chip);
        if (res != ERROR_OK)
                return res;
 
-       if (chip->features & NRF5_FEATURE_SERIES_51) {
+       if (chip->features & NRFX_FEATURE_SERIES_51) {
                uint32_t ppfc;
-               res = target_read_u32(target, NRF51_FICR_PPFC,
-                             &ppfc);
+               res = ficr_read(chip, NRFX_FICR_PPFC, &ppfc);
                if (res != ERROR_OK) {
                        LOG_ERROR("Couldn't read PPFC register");
                        return res;
@@ -1232,10 +1697,10 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command)
                }
        }
 
-       res = nrf5_erase_all(chip);
+       res = nrfx_erase_all(chip);
        if (res == ERROR_OK) {
                LOG_INFO("Mass erase completed.");
-               if (chip->features & NRF5_FEATURE_SERIES_51)
+               if (chip->features & NRFX_FEATURE_SERIES_51)
                        LOG_INFO("A reset or power cycle is required if the 
flash was protected before.");
 
        } else {
@@ -1245,149 +1710,208 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command)
        return res;
 }
 
-COMMAND_HANDLER(nrf5_handle_info_command)
+COMMAND_HANDLER(nrfx_handle_info_command)
 {
        int res;
        struct flash_bank *bank = NULL;
        struct target *target = get_current_target(CMD_CTX);
 
-       res = get_flash_bank_by_addr(target, NRF5_FLASH_BASE, true, &bank);
+       struct nrfx_info *chip;
+       uint32_t ficr[NRFX_FICR_NREGS];
+       uint32_t uicr[NRFX_UICR_NREGS];
+
+       res = get_flash_bank_by_addr(target, NRFX_FLASH_BASE, true, &bank);
        if (res != ERROR_OK)
                return res;
 
        assert(bank);
 
-       struct nrf5_info *chip;
-
-       res = nrf5_get_probed_chip_if_halted(bank, &chip);
+       res = nrfx_get_probed_chip_if_halted(bank, &chip);
        if (res != ERROR_OK)
                return res;
 
-       static struct {
-               const uint32_t address;
-               uint32_t value;
-       } ficr[] = {
-               { .address = NRF5_FICR_CODEPAGESIZE     },
-               { .address = NRF5_FICR_CODESIZE },
-               { .address = NRF51_FICR_CLENR0          },
-               { .address = NRF51_FICR_PPFC            },
-               { .address = NRF51_FICR_NUMRAMBLOCK     },
-               { .address = NRF51_FICR_SIZERAMBLOCK0   },
-               { .address = NRF51_FICR_SIZERAMBLOCK1   },
-               { .address = NRF51_FICR_SIZERAMBLOCK2   },
-               { .address = NRF51_FICR_SIZERAMBLOCK3   },
-               { .address = NRF5_FICR_CONFIGID },
-               { .address = NRF5_FICR_DEVICEID0        },
-               { .address = NRF5_FICR_DEVICEID1        },
-               { .address = NRF5_FICR_ER0              },
-               { .address = NRF5_FICR_ER1              },
-               { .address = NRF5_FICR_ER2              },
-               { .address = NRF5_FICR_ER3              },
-               { .address = NRF5_FICR_IR0              },
-               { .address = NRF5_FICR_IR1              },
-               { .address = NRF5_FICR_IR2              },
-               { .address = NRF5_FICR_IR3              },
-               { .address = NRF5_FICR_DEVICEADDRTYPE   },
-               { .address = NRF5_FICR_DEVICEADDR0      },
-               { .address = NRF5_FICR_DEVICEADDR1      },
-               { .address = NRF51_FICR_OVERRIDEN       },
-               { .address = NRF51_FICR_NRF_1MBIT0      },
-               { .address = NRF51_FICR_NRF_1MBIT1      },
-               { .address = NRF51_FICR_NRF_1MBIT2      },
-               { .address = NRF51_FICR_NRF_1MBIT3      },
-               { .address = NRF51_FICR_NRF_1MBIT4      },
-               { .address = NRF51_FICR_BLE_1MBIT0      },
-               { .address = NRF51_FICR_BLE_1MBIT1      },
-               { .address = NRF51_FICR_BLE_1MBIT2      },
-               { .address = NRF51_FICR_BLE_1MBIT3      },
-               { .address = NRF51_FICR_BLE_1MBIT4      },
-       }, uicr[] = {
-               { .address = NRF51_UICR_CLENR0,         },
-               { .address = NRF51_UICR_RBPCONF         },
-               { .address = NRF51_UICR_XTALFREQ        },
-               { .address = NRF51_UICR_FWID            },
-       };
-
-       for (size_t i = 0; i < ARRAY_SIZE(ficr); i++) {
-               res = target_read_u32(chip->target, ficr[i].address,
-                                     &ficr[i].value);
+       for (size_t i = 0; i < NRFX_FICR_NREGS; i++) {
+               res = ficr_read(chip, i, &ficr[i]);
+               if (res == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
+                       /* Register is not implemented, go on */
+                       continue;
                if (res != ERROR_OK) {
-                       LOG_ERROR("Couldn't read %" PRIx32, ficr[i].address);
+                       LOG_ERROR("Couldn't read %" PRIx32, 
chip->ficr_registers[i]);
                        return res;
                }
        }
 
-       for (size_t i = 0; i < ARRAY_SIZE(uicr); i++) {
-               res = target_read_u32(chip->target, uicr[i].address,
-                                     &uicr[i].value);
+       for (size_t i = 0; i < NRFX_UICR_NREGS; i++) {
+               res = uicr_read(chip, i, &uicr[i]);
+               if (res == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
+                       /* Register is not implemented, go on */
+                       continue;
                if (res != ERROR_OK) {
-                       LOG_ERROR("Couldn't read %" PRIx32, uicr[i].address);
+                       LOG_ERROR("Couldn't read %" PRIx32, 
chip->uicr_registers[i]);
                        return res;
                }
        }
 
-       command_print(CMD,
-                "\n[factory information control block]\n\n"
-                "code page size: %"PRIu32"B\n"
-                "code memory size: %"PRIu32"kB\n"
-                "code region 0 size: %"PRIu32"kB\n"
-                "pre-programmed code: %s\n"
-                "number of ram blocks: %"PRIu32"\n"
-                "ram block 0 size: %"PRIu32"B\n"
-                "ram block 1 size: %"PRIu32"B\n"
-                "ram block 2 size: %"PRIu32"B\n"
-                "ram block 3 size: %"PRIu32 "B\n"
-                "config id: %" PRIx32 "\n"
-                "device id: 0x%"PRIx32"%08"PRIx32"\n"
-                "encryption root: 
0x%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32"\n"
-                "identity root: 
0x%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32"\n"
-                "device address type: 0x%"PRIx32"\n"
-                "device address: 0x%"PRIx32"%08"PRIx32"\n"
-                "override enable: %"PRIx32"\n"
-                "NRF_1MBIT values: %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32" 
%"PRIx32"\n"
-                "BLE_1MBIT values: %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32" 
%"PRIx32"\n"
-                "\n[user information control block]\n\n"
-                "code region 0 size: %"PRIu32"kB\n"
-                "read back protection configuration: %"PRIx32"\n"
-                "reset value for XTALFREQ: %"PRIx32"\n"
-                "firmware id: 0x%04"PRIx32,
-                ficr[0].value,
-                (ficr[1].value * ficr[0].value) / 1024,
-                (ficr[2].value == 0xFFFFFFFF) ? 0 : ficr[2].value / 1024,
-                ((ficr[3].value & 0xFF) == 0x00) ? "present" : "not present",
-                ficr[4].value,
-                ficr[5].value,
-                (ficr[6].value == 0xFFFFFFFF) ? 0 : ficr[6].value,
-                (ficr[7].value == 0xFFFFFFFF) ? 0 : ficr[7].value,
-                (ficr[8].value == 0xFFFFFFFF) ? 0 : ficr[8].value,
-                ficr[9].value,
-                ficr[10].value, ficr[11].value,
-                ficr[12].value, ficr[13].value, ficr[14].value, ficr[15].value,
-                ficr[16].value, ficr[17].value, ficr[18].value, ficr[19].value,
-                ficr[20].value,
-                ficr[21].value, ficr[22].value,
-                ficr[23].value,
-                ficr[24].value, ficr[25].value, ficr[26].value, 
ficr[27].value, ficr[28].value,
-                ficr[29].value, ficr[30].value, ficr[31].value, 
ficr[32].value, ficr[33].value,
-                (uicr[0].value == 0xFFFFFFFF) ? 0 : uicr[0].value / 1024,
-                uicr[1].value & 0xFFFF,
-                uicr[2].value & 0xFF,
-                uicr[3].value & 0xFFFF);
-
+       command_print(CMD, "\n[factory information control block]\n");
+       if (ficr_is_implemented(chip, NRFX_FICR_INFO_PART))
+               command_print(CMD, "part: %" PRIx32,
+                                  ficr[reg_index(NRFX_FICR_INFO_PART)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_INFO_VARIANT)) {
+               union {
+                       uint32_t ul;
+                       char str[5];
+               } v;
+               v.str[4] = 0;
+               v.ul = ficr[reg_index(NRFX_FICR_INFO_VARIANT)];
+               command_print(CMD, "variant: %s", v.str);
+       }
+       if (ficr_is_implemented(chip, NRFX_FICR_INFO_PACKAGE))
+               command_print(CMD, "package: %s",
+                                  
nrfx_decode_info_package(ficr[reg_index(NRFX_FICR_INFO_PACKAGE)]));
+       if (ficr_is_implemented(chip, NRFX_FICR_INFO_RAM))
+               command_print(CMD, "total RAM: %uKB",
+                                  ficr[reg_index(NRFX_FICR_INFO_RAM)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_CODEPAGESIZE)) {
+               command_print(CMD, "code page size: %" PRIu32 "B",
+                                  ficr[reg_index(NRFX_FICR_CODEPAGESIZE)]);
+               if (ficr_is_implemented(chip, NRFX_FICR_CODESIZE))
+                       command_print(CMD, "code memory size: %" PRIu32 "KB",
+                                          
(ficr[reg_index(NRFX_FICR_CODEPAGESIZE)] *
+                                       ficr[reg_index(NRFX_FICR_CODESIZE)])
+                                          >> 10);
+       } else if (ficr_is_implemented(chip, NRFX_FICR_INFO_FLASH))
+               command_print(CMD, "code memory size: %uKB",
+                                  ficr[reg_index(NRFX_FICR_INFO_FLASH)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_CLENR0))
+               command_print(CMD, "code region 0 size: %" PRIu32 "kB",
+                                  (ficr[reg_index(NRFX_FICR_CLENR0)] ==
+                               0xFFFFFFFF) ? 0 :
+                                  ficr[reg_index(NRFX_FICR_CLENR0)] >> 10);
+       if (ficr_is_implemented(chip, NRFX_FICR_PPFC))
+               command_print(CMD, "pre-programmed code: %s",
+                                  ((ficr[reg_index(NRFX_FICR_PPFC)] & 0xFF) ==
+                               0x00) ?
+                                  "present" : "not present");
+       if (ficr_is_implemented(chip, NRFX_FICR_NUMRAMBLOCK))
+               command_print(CMD, "number of ram blocks: %" PRIu32,
+                                  ficr[reg_index(NRFX_FICR_NUMRAMBLOCK)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_SIZERAMBLOCK0))
+               command_print(CMD, "ram block 0 size: %" PRIu32 "B",
+                                  ficr[reg_index(NRFX_FICR_SIZERAMBLOCK0)] ==
+                                  0xFFFFFFFF ? 0 :
+                                  ficr[reg_index(NRFX_FICR_SIZERAMBLOCK0)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_SIZERAMBLOCK1))
+               command_print(CMD, "ram block 1 size: %" PRIu32 "B",
+                                  ficr[reg_index(NRFX_FICR_SIZERAMBLOCK1)] ==
+                                  0xFFFFFFFF ? 0 :
+                                  ficr[reg_index(NRFX_FICR_SIZERAMBLOCK1)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_SIZERAMBLOCK2))
+               command_print(CMD, "ram block 2 size: %" PRIu32 "B",
+                                  ficr[reg_index(NRFX_FICR_SIZERAMBLOCK2)] ==
+                                  0xFFFFFFFF ? 0 :
+                                  ficr[reg_index(NRFX_FICR_SIZERAMBLOCK2)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_SIZERAMBLOCK3))
+               command_print(CMD, "ram block 3 size: %" PRIu32 "B",
+                                  ficr[reg_index(NRFX_FICR_SIZERAMBLOCK3)] ==
+                                  0xFFFFFFFF ? 0 :
+                                  ficr[reg_index(NRFX_FICR_SIZERAMBLOCK3)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_CONFIGID))
+               command_print(CMD, "config id: %" PRIx32,
+                                  ficr[reg_index(NRFX_FICR_CONFIGID)] & 
0xFFFF);
+       if (ficr_is_implemented(chip, NRFX_FICR_DEVICEID0) &&
+               ficr_is_implemented(chip, NRFX_FICR_DEVICEID1))
+               command_print(CMD, "device id: 0x%" PRIx32 "%08" PRIx32,
+                                  ficr[reg_index(NRFX_FICR_DEVICEID0)],
+                                  ficr[reg_index(NRFX_FICR_DEVICEID1)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_ER0) &&
+               ficr_is_implemented(chip, NRFX_FICR_ER1) &&
+               ficr_is_implemented(chip, NRFX_FICR_ER2) &&
+               ficr_is_implemented(chip, NRFX_FICR_ER3))
+               command_print(CMD, "encryption root: 0x%08" PRIx32 "%08" PRIx32 
"%08" PRIx32 "%08" PRIx32,
+                                  ficr[reg_index(NRFX_FICR_ER0)],
+                                  ficr[reg_index(NRFX_FICR_ER1)],
+                                  ficr[reg_index(NRFX_FICR_ER2)],
+                                  ficr[reg_index(NRFX_FICR_ER3)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_IR0) &&
+               ficr_is_implemented(chip, NRFX_FICR_IR1) &&
+               ficr_is_implemented(chip, NRFX_FICR_IR2) &&
+               ficr_is_implemented(chip, NRFX_FICR_IR3))
+               command_print(CMD, "identity root: 0x%08" PRIx32 "%08" PRIx32 
"%08" PRIx32 "%08" PRIx32,
+                                  ficr[reg_index(NRFX_FICR_IR0)],
+                                  ficr[reg_index(NRFX_FICR_IR1)],
+                                  ficr[reg_index(NRFX_FICR_IR2)],
+                                  ficr[reg_index(NRFX_FICR_IR3)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_DEVICEADDRTYPE))
+               command_print(CMD, "device address type: 0x%" PRIx32,
+                                  ficr[reg_index(NRFX_FICR_DEVICEADDRTYPE)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_DEVICEADDR0) &&
+               ficr_is_implemented(chip, NRFX_FICR_DEVICEADDR1))
+               command_print(CMD, "device address: 0x%" PRIx32 "%08" PRIx32,
+                                  ficr[reg_index(NRFX_FICR_DEVICEADDR0)],
+                                  ficr[reg_index(NRFX_FICR_DEVICEADDR1)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_OVERRIDEN))
+               command_print(CMD, "override enable: %" PRIx32,
+                                  ficr[reg_index(NRFX_FICR_OVERRIDEN)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_NRF_1MBIT0) &&
+               ficr_is_implemented(chip, NRFX_FICR_NRF_1MBIT1) &&
+               ficr_is_implemented(chip, NRFX_FICR_NRF_1MBIT2) &&
+               ficr_is_implemented(chip, NRFX_FICR_NRF_1MBIT3) &&
+               ficr_is_implemented(chip, NRFX_FICR_NRF_1MBIT4))
+               command_print(CMD, "NRF_1MBIT values: %" PRIx32 " %" PRIx32 " 
%" PRIx32 " %" PRIx32 " %" PRIx32,
+                                  ficr[reg_index(NRFX_FICR_NRF_1MBIT0)],
+                                  ficr[reg_index(NRFX_FICR_NRF_1MBIT1)],
+                                  ficr[reg_index(NRFX_FICR_NRF_1MBIT2)],
+                                  ficr[reg_index(NRFX_FICR_NRF_1MBIT3)],
+                                  ficr[reg_index(NRFX_FICR_NRF_1MBIT4)]);
+       if (ficr_is_implemented(chip, NRFX_FICR_BLE_1MBIT0) &&
+               ficr_is_implemented(chip, NRFX_FICR_BLE_1MBIT1) &&
+               ficr_is_implemented(chip, NRFX_FICR_BLE_1MBIT2) &&
+               ficr_is_implemented(chip, NRFX_FICR_BLE_1MBIT3) &&
+               ficr_is_implemented(chip, NRFX_FICR_BLE_1MBIT4))
+               command_print(CMD, "BLE_1MBIT values: %" PRIx32 " %" PRIx32 " 
%" PRIx32 " %" PRIx32 " %" PRIx32,
+                                  ficr[reg_index(NRFX_FICR_BLE_1MBIT0)],
+                                  ficr[reg_index(NRFX_FICR_BLE_1MBIT1)],
+                                  ficr[reg_index(NRFX_FICR_BLE_1MBIT2)],
+                                  ficr[reg_index(NRFX_FICR_BLE_1MBIT3)],
+                                  ficr[reg_index(NRFX_FICR_BLE_1MBIT4)]);
+
+       command_print(CMD, "\n[user information control block]\n");
+       if (uicr_is_implemented(chip, NRFX_UICR_CLENR0))
+               command_print(CMD, "code region 0 size: %" PRIu32 "kB",
+                                  uicr[reg_index(NRFX_UICR_CLENR0)] == 
0xFFFFFFFF ?
+                                  0 : uicr[reg_index(NRFX_UICR_CLENR0)]);
+       if (uicr_is_implemented(chip, NRFX_UICR_RBPCONF))
+               command_print(CMD, "read back protection configuration: %" 
PRIx32,
+                                  uicr[reg_index(NRFX_UICR_RBPCONF)] & 0xFFFF);
+       if (uicr_is_implemented(chip, NRFX_UICR_RBPCONF))
+               command_print(CMD, "reset value for XTALFREQ: %" PRIx32,
+                                  uicr[reg_index(NRFX_UICR_RBPCONF)] & 0xFFFF);
+       if (uicr_is_implemented(chip, NRFX_UICR_FWID))
+               command_print(CMD, "firmware id: 0x%04" PRIx32,
+                                  uicr[reg_index(NRFX_UICR_FWID)] & 0xFFFF);
+       if (uicr_is_implemented(chip, NRFX_UICR_APPROTECT))
+               command_print(CMD, "APPROTECT: %" PRIx32,
+                                  uicr[reg_index(NRFX_UICR_APPROTECT)]);
+       if (uicr_is_implemented(chip, NRFX_UICR_SECUREAPPROTECT))
+               command_print(CMD, "SECUREAPPROTECT: %" PRIx32,
+                                  uicr[reg_index(NRFX_UICR_SECUREAPPROTECT)]);
+       if (uicr_is_implemented(chip, NRFX_UICR_ERASEPROTECT))
+               command_print(CMD, "ERASEPROTECT: %" PRIx32,
+                                  uicr[reg_index(NRFX_UICR_ERASEPROTECT)]);
        return ERROR_OK;
 }
 
-static const struct command_registration nrf5_exec_command_handlers[] = {
+static const struct command_registration nrfx_exec_command_handlers[] = {
        {
                .name           = "mass_erase",
-               .handler        = nrf5_handle_mass_erase_command,
+               .handler        = nrfx_handle_mass_erase_command,
                .mode           = COMMAND_EXEC,
                .help           = "Erase all flash contents of the chip.",
                .usage          = "",
        },
        {
                .name           = "info",
-               .handler        = nrf5_handle_info_command,
+               .handler        = nrfx_handle_info_command,
                .mode           = COMMAND_EXEC,
                .help           = "Show FICR and UICR info.",
                .usage          = "",
@@ -1401,14 +1925,25 @@ static const struct command_registration 
nrf5_command_handlers[] = {
                .mode   = COMMAND_ANY,
                .help   = "nrf5 flash command group",
                .usage  = "",
-               .chain  = nrf5_exec_command_handlers,
+               .chain  = nrfx_exec_command_handlers,
        },
        {
                .name   = "nrf51",
                .mode   = COMMAND_ANY,
                .help   = "nrf51 flash command group",
                .usage  = "",
-               .chain  = nrf5_exec_command_handlers,
+               .chain  = nrfx_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration nrf91_command_handlers[] = {
+       {
+               .name   = "nrf91",
+               .mode   = COMMAND_ANY,
+               .help   = "nrf91 flash command group",
+               .usage  = "",
+               .chain  = nrfx_exec_command_handlers,
        },
        COMMAND_REGISTRATION_DONE
 };
@@ -1417,16 +1952,16 @@ const struct flash_driver nrf5_flash = {
        .name                   = "nrf5",
        .commands               = nrf5_command_handlers,
        .flash_bank_command     = nrf5_flash_bank_command,
-       .info                   = nrf5_info,
-       .erase                  = nrf5_erase,
-       .protect                = nrf5_protect,
-       .write                  = nrf5_write,
+       .info                   = nrfx_info,
+       .erase                  = nrfx_erase,
+       .protect                = nrfx_protect,
+       .write                  = nrfx_write,
        .read                   = default_flash_read,
-       .probe                  = nrf5_probe,
-       .auto_probe             = nrf5_auto_probe,
+       .probe                  = nrfx_probe,
+       .auto_probe             = nrfx_auto_probe,
        .erase_check            = default_flash_blank_check,
-       .protect_check          = nrf5_protect_check,
-       .free_driver_priv       = nrf5_free_driver_priv,
+       .protect_check          = nrfx_protect_check,
+       .free_driver_priv       = nrfx_free_driver_priv,
 };
 
 /* We need to retain the flash-driver name as well as the commands
@@ -1434,15 +1969,47 @@ const struct flash_driver nrf5_flash = {
 const struct flash_driver nrf51_flash = {
        .name                   = "nrf51",
        .commands               = nrf5_command_handlers,
-       .flash_bank_command     = nrf5_flash_bank_command,
-       .info                   = nrf5_info,
-       .erase                  = nrf5_erase,
-       .protect                = nrf5_protect,
-       .write                  = nrf5_write,
+       .flash_bank_command     = nrf51_flash_bank_command,
+       .info                   = nrfx_info,
+       .erase                  = nrfx_erase,
+       .protect                = nrfx_protect,
+       .write                  = nrfx_write,
+       .read                   = default_flash_read,
+       .probe                  = nrfx_probe,
+       .auto_probe             = nrfx_auto_probe,
+       .erase_check            = default_flash_blank_check,
+       .protect_check          = nrfx_protect_check,
+       .free_driver_priv       = nrfx_free_driver_priv,
+};
+
+const struct flash_driver nrf52_flash = {
+       .name                   = "nrf52",
+       .commands               = nrf5_command_handlers,
+       .flash_bank_command     = nrf52_flash_bank_command,
+       .info                   = nrfx_info,
+       .erase                  = nrfx_erase,
+       .protect                = nrfx_protect,
+       .write                  = nrfx_write,
+       .read                   = default_flash_read,
+       .probe                  = nrfx_probe,
+       .auto_probe             = nrfx_auto_probe,
+       .erase_check            = default_flash_blank_check,
+       .protect_check          = nrfx_protect_check,
+       .free_driver_priv       = nrfx_free_driver_priv,
+};
+
+const struct flash_driver nrf91_flash = {
+       .name                   = "nrf91",
+       .commands               = nrf91_command_handlers,
+       .flash_bank_command     = nrf91_flash_bank_command,
+       .info                   = nrfx_info,
+       .erase                  = nrfx_erase,
+       .protect                = nrfx_protect,
+       .write                  = nrfx_write,
        .read                   = default_flash_read,
-       .probe                  = nrf5_probe,
-       .auto_probe             = nrf5_auto_probe,
+       .probe                  = nrfx_probe,
+       .auto_probe             = nrfx_auto_probe,
        .erase_check            = default_flash_blank_check,
-       .protect_check          = nrf5_protect_check,
-       .free_driver_priv       = nrf5_free_driver_priv,
+       .protect_check          = nrfx_protect_check,
+       .free_driver_priv       = nrfx_free_driver_priv,
 };
diff --git a/tcl/target/nrf91.cfg b/tcl/target/nrf91.cfg
new file mode 100644
index 0000000000..c42bc54b29
--- /dev/null
+++ b/tcl/target/nrf91.cfg
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+#
+# Nordic nRF9160 series: ARM Cortex-M33
+#
+
+source [find target/swj-dp.tcl]
+
+if { [info exists CHIPNAME] } {
+       set _CHIPNAME $CHIPNAME
+} else {
+       set _CHIPNAME nrf9160
+}
+
+# Work-area is a space in RAM used for flash programming
+# By default use 16kB
+if { [info exists WORKAREASIZE] } {
+   set _WORKAREASIZE $WORKAREASIZE
+} else {
+   set _WORKAREASIZE 0x4000
+}
+
+if { [info exists CPUTAPID] } {
+       set _CPUTAPID $CPUTAPID
+} else {
+       set _CPUTAPID 0x6ba02477
+}
+
+swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID
+dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
+
+set _TARGETNAME $_CHIPNAME.cpu
+target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap
+
+adapter speed 1000
+
+$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size 
$_WORKAREASIZE -work-area-backup 0
+
+if { ![using_hla] } {
+       cortex_m reset_config sysresetreq
+}
+
+flash bank $_CHIPNAME.flash nrf91 0x00000000 0 1 1 $_TARGETNAME
+flash bank $_CHIPNAME.uicr nrf91 0xff8000 0 1 1 $_TARGETNAME
+
+source [find target/nrf91_mfw.cfg]
\ No newline at end of file
diff --git a/tcl/target/nrf91_mfw.cfg b/tcl/target/nrf91_mfw.cfg
new file mode 100644
index 0000000000..2850bfb41c
--- /dev/null
+++ b/tcl/target/nrf91_mfw.cfg
@@ -0,0 +1,430 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Nordic nRF9160 Modem firmware series: ARM Cortex-M33
+#
+# Requires python, installed packge: 'pip install intelhex'
+# Usage:
+# -c 'source [find target/nrf91.cfg]' -c 'adapter speed 10000' '-c init' '-c 
targets' -c 'reset init' -c 'nrf91_flash_modem mfw_nrf9160_1.3.4.zip' -c 'reset 
run' -c shutdown
+#
+
+set MODEM_FIRMWARE_UPDATE_DEBUG 0
+set MODEM_FIRMWARE_UPDATE_RW_DEBUG 0
+
+set EVENT_NONE 0
+set EVENT_FAULT 1
+set EVENT_COMMAND 2
+set EVENT_DATA 3
+
+set FAULT_EVENT_REG 0x4002A100
+set COMMAND_EVENT_REG 0x4002A108
+set DATA_EVENT_REG 0x4002A110
+
+proc nrf91_mfw_read_memory {address width count} {
+       if {$::MODEM_FIRMWARE_UPDATE_RW_DEBUG} {
+               puts -nonewline [format "Read(0x%x) = " $address $count]
+       }
+       set RES [read_memory $address $width $count]
+       if {$::MODEM_FIRMWARE_UPDATE_RW_DEBUG} {
+               puts $RES
+       }
+       return $RES
+}
+
+proc nrf91_mfw_write_memory {address val} {
+       if {$::MODEM_FIRMWARE_UPDATE_RW_DEBUG} {
+               puts [format "Write(0x%x, 0x%x)" $address $val]
+       }
+       write_memory $address 32 $val
+}
+
+proc nrf91_clear_modem_ctrl_events {} {
+       nrf91_mfw_write_memory $::FAULT_EVENT_REG 0x0
+       nrf91_mfw_write_memory $::COMMAND_EVENT_REG 0x0
+       nrf91_mfw_write_memory $::DATA_EVENT_REG 0x0
+}
+
+proc nrf91_poll_modem_ctrl_event {} {
+       set RES [nrf91_mfw_read_memory $::FAULT_EVENT_REG 32 1]
+       if {$RES == 1} {
+               puts "Fault event recieved"
+               set res [nrf91_mfw_read_memory 0x2000000C 32 1]
+               if {[string match "0x5a*" $res]} {
+                       puts [format "Command Error: 0x%x" $res]
+                       return $::EVENT_FAULT
+               }
+
+               nrf91_mfw_write_memory $::FAULT_EVENT_REG 0x0
+               return $::EVENT_FAULT
+       }
+       set RES [nrf91_mfw_read_memory $::COMMAND_EVENT_REG 32 1]
+       if {$RES == 1} {
+               set res [nrf91_mfw_read_memory 0x2000000C 32 1]
+               if {[string match "0x5a*" $res]} {
+                       puts [format "Command Error: 0x%x" $res]
+                       return $::EVENT_FAULT
+               }
+               if {$::MODEM_FIRMWARE_UPDATE_DEBUG} {
+                       puts [format "Command Result: 0x%x" $res]
+               }
+
+               nrf91_mfw_write_memory $::COMMAND_EVENT_REG 0x0
+               return $::EVENT_COMMAND
+       }
+       set RES [nrf91_mfw_read_memory $::DATA_EVENT_REG 32 1]
+       if {$RES == 1} {
+               set res [nrf91_mfw_read_memory 0x2000000C 32 1]
+               nrf91_mfw_write_memory $::DATA_EVENT_REG 0x0
+               return $::EVENT_DATA
+       }
+       return $::EVENT_NONE
+}
+
+proc nrf91_wait_for_modem_event {} {
+       set EVT $::EVENT_FAULT
+       while {1} {
+               set EVT [nrf91_poll_modem_ctrl_event]
+               if {$EVT != $::EVENT_NONE} {
+                       break
+               }
+       }
+       return $EVT
+}
+
+proc nrf91_read_memory_padded {address size} {
+       set readStr [nrf91_mfw_read_memory $address 32 $size]
+       set wordList [regexp -inline -all -- {\S+} $readStr]
+       set output {}
+       foreach w $wordList {
+               set hex [scan $w %x]
+               lappend output [format "0x%08x" $hex]
+       }
+       return [join $output " "]
+}
+
+proc nrf91_modem_digest_read_prefix {} {
+       set hex [nrf91_read_memory_padded 0x20000010 1]
+       set prefix "0x"
+
+       set hexAlphaNumeric [regsub -all $prefix $hex ""]
+       set hexAlphaReversed ""
+       set hexAlphaNumericLen [string length $hexAlphaNumeric]
+       for {set i 0} {$i < [expr $hexAlphaNumericLen/2]} {incr i} {
+               set stInd [expr $hexAlphaNumericLen-($i+1)*2]
+               set endInd [expr $hexAlphaNumericLen-($i)*2-1]
+               set byteStr [string range $hexAlphaNumeric $stInd $endInd]
+               append hexAlphaReversed $byteStr
+       }
+       set hexResult [string toupper $hexAlphaReversed]
+       string range $hexResult 0 end-1
+}
+
+
+proc nrf91_modem_verify_digest_read {} {
+       set hex [nrf91_read_memory_padded 0x20000010 8]
+       set prefix "0x"
+       set hexAlphaNumeric [regsub -all $prefix $hex ""]
+       set hexAlphaNumericUnif [regsub -all " " $hexAlphaNumeric ""]
+       return [string toupper $hexAlphaNumericUnif]
+}
+
+proc load_image_hex {fname foffset address length } {
+    # Load data from fname filename at foffset offset to
+    # target at address. Load at most length bytes.
+       if {$::MODEM_FIRMWARE_UPDATE_DEBUG} {
+               puts [format "load_image %s %x ihex %x %x" $fname [expr 
{$address - $foffset}] $address $length]
+       }
+    load_image $fname [expr {$address - $foffset}] ihex $address $length
+}
+
+set NRF91_UTIL_PYTHON [find target/nrf91_mfw_utils.cfg]
+
+proc nrf91_probe_sections_info {SEGMENT_FILE} {
+    exec python $::NRF91_UTIL_PYTHON $SEGMENT_FILE
+}
+
+proc nrf91_probe_no_sections {SEGMENT_FILE} {
+    exec python $::NRF91_UTIL_PYTHON $SEGMENT_FILE -n -m
+}
+
+proc nrf91_probe_probe_section_address {SEGMENT_FILE SECTION} {
+    set res [exec python $::NRF91_UTIL_PYTHON $SEGMENT_FILE -i [format "%d" 
$SECTION] -m]
+       scan $res "%d %d" address size
+       return $address
+}
+
+proc nrf91_probe_probe_section_size {SEGMENT_FILE SECTION} {
+    set res [exec python $::NRF91_UTIL_PYTHON $SEGMENT_FILE -i [format "%d" 
$SECTION] -m]
+       scan $res "%d %d" address size
+       return $size
+}
+
+proc nrf91_upload_section_legacy {SEGMENT_FILE SECTION_START SECTION_LENGTH} {
+       
+       set currentBufferOffset 0
+       set curAddress 0
+       set blockSize 0x10000
+       
+       while {$curAddress < $SECTION_LENGTH} { 
+               if { $SECTION_LENGTH - $curAddress < $blockSize} {
+                       set blockSize [expr $SECTION_LENGTH-$curAddress]
+               }
+               set CURRENT_SECTION_START [expr $SECTION_START+$curAddress]
+               # Current chunk
+               set LRES [load_image_hex $SEGMENT_FILE $CURRENT_SECTION_START 
[expr 0x20000018] $blockSize]
+       
+               if {$::MODEM_FIRMWARE_UPDATE_DEBUG} {
+                       puts $LRES
+               }
+               set WRITTEN [scan $LRES %d]
+
+               nrf91_mfw_write_memory 0x20000010 $CURRENT_SECTION_START
+               nrf91_mfw_write_memory 0x20000014 $WRITTEN
+
+               #NVMC Write Enable -> True
+               nrf91_mfw_write_memory 0x50039504 0x1
+               nrf91_mfw_write_memory 0x50039504 0x1
+
+               #Write command to the modem
+               nrf91_mfw_write_memory 0x2000000C 0x03
+               #Start IPC
+               nrf91_mfw_write_memory 0x4002A004 0x01
+
+               if {$::MODEM_FIRMWARE_UPDATE_DEBUG} {
+                       puts [format "Started IPC 0x%x/0x%x -> 0x%x of 0x%x" 
$curAddress $SECTION_LENGTH 0x20000018 $CURRENT_SECTION_START]
+               }
+
+               #Wait for Event
+               set EVT $::EVENT_FAULT
+               while {1} {
+                       set EVT [nrf91_poll_modem_ctrl_event]
+                       if {$EVT != $::EVENT_NONE} {
+                               break
+                       }
+               }
+               if {$EVT == $::EVENT_FAULT} {
+                       error "Segment file upload failed"
+               }
+               if {$::MODEM_FIRMWARE_UPDATE_DEBUG} {
+                       puts [format "Confirmed IPC 0x%x/0x%x" $curAddress 
$SECTION_LENGTH]
+               }
+               set curAddress [expr $curAddress+$WRITTEN]
+       }
+}
+
+proc nrf91_upload_section {SEGMENT_FILE SECTION_START SECTION_LENGTH} {
+       
+       set currentBufferOffset 0
+       set curAddress 0
+       set blockSize 0xE000
+
+       if { $SECTION_LENGTH - $curAddress < $blockSize} {
+               set blockSize [expr $SECTION_LENGTH-$curAddress]
+       }
+       set CURRENT_SECTION_START [expr $SECTION_START+$curAddress]
+       set CURRENT_BUFFER [expr 0x2000001C+$currentBufferOffset]
+       set LRES [load_image_hex $SEGMENT_FILE $CURRENT_SECTION_START 
$CURRENT_BUFFER $blockSize]
+
+       if {$::MODEM_FIRMWARE_UPDATE_DEBUG} {
+               puts $LRES
+       }
+       set WRITTEN [scan $LRES %d]
+       
+       while {$curAddress < $SECTION_LENGTH} {
+               nrf91_clear_modem_ctrl_events
+               # Current chunk
+               nrf91_mfw_write_memory 0x20000010 $CURRENT_SECTION_START
+               nrf91_mfw_write_memory 0x20000014 $WRITTEN
+               nrf91_mfw_write_memory 0x20000018 $currentBufferOffset
+               nrf91_mfw_write_memory 0x2000000C 0x09
+               #Start IPC
+               nrf91_mfw_write_memory 0x4002A004 0x01
+
+               if {$::MODEM_FIRMWARE_UPDATE_DEBUG} {
+                       puts [format "Started IPC 0x%x/0x%x -> 0x%x of 0x%x" 
$curAddress $SECTION_LENGTH $CURRENT_BUFFER $CURRENT_SECTION_START]
+               }
+
+               set curAddress [expr $curAddress+$WRITTEN]
+               if {$curAddress < $SECTION_LENGTH} {
+                       if {$currentBufferOffset == 0x0} {
+                               set currentBufferOffset 0xE000
+                       } else {
+                               set currentBufferOffset 0
+                       }
+                       if { $SECTION_LENGTH - $curAddress < $blockSize} {
+                               set blockSize [expr $SECTION_LENGTH-$curAddress]
+                       }
+                       set CURRENT_SECTION_START [expr 
$SECTION_START+$curAddress]
+                       set CURRENT_BUFFER [expr 
0x2000001C+$currentBufferOffset]
+                       set LRES [load_image_hex $SEGMENT_FILE 
$CURRENT_SECTION_START $CURRENT_BUFFER $blockSize]
+
+                       if {$::MODEM_FIRMWARE_UPDATE_DEBUG} {
+                               puts $LRES
+                       }
+                       set WRITTEN [scan $LRES %d]
+               }
+
+               #Wait for Event
+               set EVT [nrf91_wait_for_modem_event]
+               if {$EVT == $::EVENT_FAULT} {
+                       error "Segment file upload failed"
+               }
+               if {$::MODEM_FIRMWARE_UPDATE_DEBUG} {
+                       puts [format "Confirmed IPC 0x%x/0x%x" $curAddress 
$SECTION_LENGTH]
+               }
+       }
+}
+
+proc nrf91_upload_segment {SEGMENT_FILE bufferedUpload} {
+       set SECTIONS [nrf91_probe_no_sections $SEGMENT_FILE]
+       puts [format "Uploading segment file %s" $SEGMENT_FILE]
+       puts [ nrf91_probe_sections_info $SEGMENT_FILE ]
+
+       for {set i 0} {$i < $SECTIONS} {incr i} {
+               puts [format "Uploading section %d/%d" [expr $i+1] $SECTIONS]
+               set SECTION_ADDRESS [ nrf91_probe_probe_section_address 
$SEGMENT_FILE $i ]
+               set SECTION_SIZE [ nrf91_probe_probe_section_size $SEGMENT_FILE 
$i ]
+               if {$bufferedUpload} {
+                       nrf91_upload_section $SEGMENT_FILE $SECTION_ADDRESS 
$SECTION_SIZE
+               } else {
+                       nrf91_upload_section_legacy $SEGMENT_FILE 
$SECTION_ADDRESS $SECTION_SIZE
+               }
+       }
+}
+
+proc nrf91_verify_segements { SEGMENT_VERIFY_FILE } {
+       set fp [open $SEGMENT_VERIFY_FILE r]
+       set SEGMENTS 0
+       set SEGMENTS_ADDRESES {}
+       set SEGMENTS_SIZES {}
+       set DIGEST {}
+
+       while { [gets $fp SEGMENT_VERIFY_DATA_LINE] >= 0 } {
+               set result [regexp {^Range: 
(0[xX][0-9a-fA-F]+)--(0[xX][0-9a-fA-F]+)\s+SHA256:\s+([0-9a-fA-F]+)} 
$SEGMENT_VERIFY_DATA_LINE whole_match M_START_ADDRESS M_END_ADDRESS M_DIGIEST]
+               if {$result == 1} {
+                       set M_START_ADDRESS_NUM [scan $M_START_ADDRESS %x]
+                       set M_END_ADDRESS_NUM [scan $M_END_ADDRESS %x]
+                       lappend SEGMENTS_ADDRESES $M_START_ADDRESS_NUM
+                       lappend SEGMENTS_SIZES [expr 
$M_END_ADDRESS_NUM+1-$M_START_ADDRESS_NUM]
+                       lappend DIGEST $M_DIGIEST
+                       incr SEGMENTS
+               }
+       }
+       close $fp
+       nrf91_clear_modem_ctrl_events
+
+       for {set i 0} {$i < $SEGMENTS} {incr i} {
+               nrf91_mfw_write_memory 0x2000000C 0x7
+               puts [format "Validating segment: 0x%x size: 0x%x" [lindex 
$SEGMENTS_ADDRESES $i] [lindex $SEGMENTS_SIZES $i]]
+               nrf91_mfw_write_memory [expr 0x20000014] [lindex 
$SEGMENTS_ADDRESES $i]
+               nrf91_mfw_write_memory [expr 0x20000018] [lindex 
$SEGMENTS_SIZES $i]
+
+               nrf91_mfw_write_memory 0x20000010 1
+               nrf91_mfw_write_memory 0x4002A004 0x1
+
+               set EVT [nrf91_wait_for_modem_event]
+               if {$EVT == $::EVENT_FAULT} {
+                       error "Verify Segment failed"
+               }
+
+               set MODEM_DIGEST [nrf91_modem_verify_digest_read]
+               set EXPECT_DIGEST [lindex $DIGEST $i]
+               if { $MODEM_DIGEST != $EXPECT_DIGEST} {
+                       error "Modem verification failed" [format "Expected 
digest: '%s' - Got: '%s'" $EXPECT_DIGEST $MODEM_DIGEST]
+               }
+       }
+       puts "Modem Verified"
+}
+
+proc nrf91_flash_ipc_loader {IPC_DFU_FILENAME} {
+       # Load image to RAM
+       load_image $IPC_DFU_FILENAME 0 ihex
+       nrf91_mfw_write_memory 0x4002A004 0x1
+       
+       #Wait for Event
+       set EVT [nrf91_wait_for_modem_event]
+
+       if {$EVT == $::EVENT_FAULT} {
+               error "Modem firmware IPC DFU failed"
+       }
+       puts "Modem firmware IPC DFU Done"
+}
+
+proc nrf91_flash_modem {MFW_FILE args} {
+       poll off
+
+       set bufferedUpload 0
+       if {"--buffered" in $args} {
+               set bufferedUpload 1
+       }
+
+       set MFW_FOLDER [exec mktemp -d]
+       exec unzip $MFW_FILE -d $MFW_FOLDER
+       set SEGMENT_FILES [glob [file join $MFW_FOLDER 
firmware.update.image.segments.*]]
+
+       #Setting up the Modem
+       # Step 1
+       nrf91_mfw_write_memory 0x500038A8 0x0
+
+       # Step 2
+       nrf91_mfw_write_memory 0x4002A514 0x00000002
+       nrf91_mfw_write_memory 0x4002A51C 0x00000008
+       nrf91_mfw_write_memory 0x4002A610 0x21000000
+       nrf91_mfw_write_memory 0x4002A614 0x00000000
+       nrf91_mfw_write_memory 0x4002A590 0x00000001
+       nrf91_mfw_write_memory 0x4002A598 0x00000004
+       nrf91_mfw_write_memory 0x4002A5A0 0x00000010
+
+       # Step 3 Mark ram non secure
+       for {set i 0} {$i < 32} {incr i} {
+               nrf91_mfw_write_memory [expr 0x50003700+$i*4] 0x7
+       }
+
+       # Step 4
+       nrf91_mfw_write_memory 0x20000000 0x80010000
+       nrf91_mfw_write_memory 0x20000004 0x2100000C
+       nrf91_mfw_write_memory 0x20000008 0x0003FC00
+
+       # # Step 5
+       nrf91_mfw_write_memory 0x50005610 0
+       nrf91_mfw_write_memory 0x50005614 1
+       nrf91_mfw_write_memory 0x50005610 1
+       nrf91_mfw_write_memory 0x50005614 0
+       nrf91_mfw_write_memory 0x50005610 0
+
+       # #HFXO SRC
+       # nrf91_mfw_write_memory 0x00FF801C 16 {0xE}
+       # #HFCO CNT
+       # nrf91_mfw_write_memory 0x00FF8020 16 0x20
+
+       nrf91_clear_modem_ctrl_events
+
+       set MODEM_DIGEST [ nrf91_modem_digest_read_prefix ]
+       set IPC_DFU_DILE [glob [format "%s/%s.ipc_dfu.signed_*" $MFW_FOLDER 
$MODEM_DIGEST]]
+       puts $IPC_DFU_DILE
+       set result [regexp {(\d+)\.(\d+)\.(\d+)\.ihex} $IPC_DFU_DILE 
whole_match M_IPC_MAJOR M_IPC_MINOR M_IPC_PATCH]
+       puts $result
+       if {$result != 1} {
+               error "Failed to detect IPC Loader version"
+       }
+       
+       set IPC_MAJOR [scan $M_IPC_MAJOR %d]
+       set IPC_MINOR [scan $M_IPC_MINOR %d]
+       set IPC_PATCH [scan $M_IPC_PATCH %d]
+
+       nrf91_flash_ipc_loader $IPC_DFU_DILE
+
+       if { ($IPC_MAJOR > 1) || (($IPC_MAJOR == 1) && ($IPC_MINOR >= 2)) } {
+               puts "Detected IPC Loader with buffered support enabling"
+               set bufferedUpload 1
+       }
+
+       foreach SEGMENT_FILE $SEGMENT_FILES {
+               nrf91_upload_segment $SEGMENT_FILE $bufferedUpload
+       }
+
+       # puts "Modem firmware Segments Done"
+       nrf91_verify_segements [format "%s/firmware.update.image.digest.txt" 
$MFW_FOLDER]
+       poll on
+}
+
+add_help_text nrf91_flash_modem "nRF91 update modem"
\ No newline at end of file
diff --git a/tcl/target/nrf91_mfw_utils.cfg b/tcl/target/nrf91_mfw_utils.cfg
new file mode 100644
index 0000000000..fe2abd74ff
--- /dev/null
+++ b/tcl/target/nrf91_mfw_utils.cfg
@@ -0,0 +1,81 @@
+import argparse
+from intelhex import IntelHex
+
+def align_address(address, page_size):
+    """Align the address to the nearest page boundary."""
+    return (address // page_size) * page_size
+
+def extract_contiguous_sections(hex_data, page_size):
+    sections = []
+    current_section_start = None
+    current_section_end = None
+
+    for start, stop in sorted(hex_data.segments()):
+        address = start
+        size = stop-start
+        if current_section_start is None:
+            current_section_start = align_address(address, page_size)
+            current_section_end = current_section_start + size
+        else:
+            if address > current_section_end:
+                sections.append((current_section_start, current_section_end - 
current_section_start))
+                current_section_start = align_address(address, page_size)
+                current_section_end = current_section_start + size
+            else:
+                current_section_end = max(current_section_end, address + 1)
+
+    if current_section_start is not None:
+        sections.append((current_section_start, current_section_end - 
current_section_start))
+
+    return sections
+
+def format_output(index, address, size, machine_readable):
+    if machine_readable:
+        return f"{address} {size}"
+    else:
+        return f"Section {index}:\nAddress: 0x{address:08X}\nSize:    {size / 
1024:.2f} KB\n"
+
+def print_selected_section(index, section, machine_readable):
+    print(format_output(index, section[0], section[1], machine_readable))
+
+def list_sections_only(sections, machine_readable):
+    if machine_readable:
+        print(f"{len(sections)}")
+    else:
+        print(f"Number of Sections: {len(sections)}")
+
+def main():
+    parser = argparse.ArgumentParser(description="Process HEX file and print 
contiguous sections.")
+    parser.add_argument("hex_file", help="Path to the HEX file")
+    parser.add_argument("-i", "--index", type=int, help="Optional index of the 
selected section to print")
+    parser.add_argument("-p", "--page", type=int, default=0x1000, help="Used 
to align the sections")
+    parser.add_argument("-m", "--machine-readable", action="store_true", 
help="Output in machine-readable format")
+    parser.add_argument("-n", "--list-sections-only", action="store_true", 
help="List only the number of sections")
+    args = parser.parse_args()
+
+    hex_file_path = args.hex_file
+    selected_index = args.index
+    machine_readable = args.machine_readable
+    list_sections_only_flag = args.list_sections_only
+    page_size = args.page
+
+    # Read the HEX file
+    hex_data = IntelHex(hex_file_path)
+
+    # Extract contiguous sections
+    sections = extract_contiguous_sections(hex_data, page_size)
+
+    # List only the number of sections
+    if list_sections_only_flag:
+        list_sections_only(sections, machine_readable)
+    else:
+        # Print selected section if specified
+        if selected_index is not None and selected_index < len(sections):
+            print_selected_section(selected_index, sections[selected_index], 
machine_readable)
+        else:
+            # Print all section information
+            for index, section in enumerate(sections, start=1):
+                print(format_output(index, section[0], section[1], 
machine_readable))
+
+if __name__ == "__main__":
+    main()

-- 

Reply via email to