diff --git a/avrdude/avr.c b/avrdude/avr.c
index fa46f49..7bebff5 100644
--- a/avrdude/avr.c
+++ b/avrdude/avr.c
@@ -1195,6 +1195,15 @@ int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p)
   return rc;
 }
 
+int avr_unlock(PROGRAMMER * pgm, AVRPART * p)
+{
+  int rc;
+
+  rc = pgm->unlock(pgm, p);
+
+  return rc;
+}
+
 /*
  * Report the progress of a read or write operation from/to the
  * device.
diff --git a/avrdude/jtag3.c b/avrdude/jtag3.c
index 1dbf328..4db9cec 100644
--- a/avrdude/jtag3.c
+++ b/avrdude/jtag3.c
@@ -842,8 +842,8 @@ int jtag3_recv(PROGRAMMER * pgm, unsigned char **msg) {
   if ((c & RSP3_STATUS_MASK) != RSP3_OK) {
     if ((c == RSP3_FAILED) && ((*resp)[3] == RSP3_FAIL_OCD_LOCKED)) {
       avrdude_message(MSG_INFO,
-		      "%s: Device is locked! Chip erase required to unlock.\n",
-		      progname);
+             "\n%s: Device is locked! Chip erase required to unlock.\n",
+             progname);
     } else {
       avrdude_message(MSG_INFO, "%s: bad response to %s command: 0x%02x\n",
 		      progname, descr, c);
@@ -865,8 +865,11 @@ int jtag3_getsync(PROGRAMMER * pgm, int mode) {
   avrdude_message(MSG_DEBUG, "%s: jtag3_getsync()\n", progname);
 
   if (pgm->flag & PGM_FL_IS_EDBG) {
-    if (jtag3_edbg_prepare(pgm) < 0)
-      return -1;
+    if (strcmp(pgm->id, "xplainedmini_updi") != 0) {
+      if (jtag3_edbg_prepare(pgm) < 0) {
+        return -1;
+      }
+    }
   }
 
   /* Get the sign-on information. */
@@ -903,9 +906,9 @@ static int jtag3_chip_erase(PROGRAMMER * pgm, AVRPART * p)
 }
 
 /*
- * UPDI 'chip erase' -> 'enter progmode' with chip erase key
+ * UPDI 'unlock' -> 'enter progmode' with chip erase key
  */
-static int jtag3_chip_erase_updi(PROGRAMMER * pgm, AVRPART * p)
+static int jtag3_unlock_erase_key(PROGRAMMER * pgm, AVRPART * p)
 {
   unsigned char buf[8], *resp;
 
@@ -1573,8 +1576,11 @@ void jtag3_close(PROGRAMMER * pgm)
   if (jtag3_command(pgm, buf, 4, &resp, "sign-off") >= 0)
     free(resp);
 
-  if (pgm->flag & PGM_FL_IS_EDBG)
-    jtag3_edbg_signoff(pgm);
+  if (pgm->flag & PGM_FL_IS_EDBG) {
+    if (strcmp(pgm->id, "xplainedmini_updi") != 0) {
+      jtag3_edbg_signoff(pgm);
+    }
+  }
 
   serial_close(&pgm->fd);
   pgm->fd.ifd = -1;
@@ -1636,8 +1642,13 @@ static int jtag3_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
   int status, dynamic_memtype = 0;
   long otimeout = serial_recv_timeout;
 
-  avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_write(.., %s, %d, %d)\n",
-	    progname, m->desc, page_size, n_bytes);
+  avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_write(.., %s, %d, 0x%lx, %d)\n",
+	    progname, m->desc, page_size, addr, n_bytes);
+
+  block_size = jtag3_memaddr(pgm, p, m, addr);
+  if(block_size != addr)
+    avrdude_message(MSG_NOTICE2, "          mapped to address: 0x%lx\n", block_size);
+  block_size = 0;
 
   if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0)
     return -1;
@@ -1679,6 +1690,8 @@ static int jtag3_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
     PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
   } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
     cmd[3] = MTYPE_USERSIG;
+  } else if ( ( strcmp(m->desc, "userrow") == 0 ) ) {
+    cmd[3] = MTYPE_USERSIG;
   } else if ( ( strcmp(m->desc, "boot") == 0 ) ) {
     cmd[3] = MTYPE_BOOT_FLASH;
   } else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) {
@@ -1740,8 +1753,13 @@ static int jtag3_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
   int status, dynamic_memtype = 0;
   long otimeout = serial_recv_timeout;
 
-  avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_load(.., %s, %d, %d)\n",
-	    progname, m->desc, page_size, n_bytes);
+  avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_load(.., %s, %d, 0x%lx, %d)\n",
+	    progname, m->desc, page_size, addr, n_bytes);
+
+  block_size = jtag3_memaddr(pgm, p, m, addr);
+  if(block_size != addr)
+    avrdude_message(MSG_NOTICE2, "          mapped to address: 0x%lx\n", block_size);
+  block_size = 0;
 
   if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0)
     return -1;
@@ -1765,6 +1783,8 @@ static int jtag3_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
     cmd[3] = MTYPE_PRODSIG;
   } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
     cmd[3] = MTYPE_USERSIG;
+  } else if ( ( strcmp(m->desc, "userrow") == 0 ) ) {
+    cmd[3] = MTYPE_USERSIG;
   } else if ( ( strcmp(m->desc, "boot") == 0 ) ) {
     cmd[3] = MTYPE_BOOT_FLASH;
   } else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) {
@@ -1819,6 +1839,11 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
   avrdude_message(MSG_NOTICE2, "%s: jtag3_read_byte(.., %s, 0x%lx, ...)\n",
 	    progname, mem->desc, addr);
 
+  paddr = jtag3_memaddr(pgm, p, mem, addr);
+  if(paddr != addr)
+    avrdude_message(MSG_NOTICE2, "          mapped to address: 0x%lx\n", paddr);
+  paddr = 0;
+
   if (!(pgm->flag & PGM_FL_IS_DW))
     if ((status = jtag3_program_enable(pgm)) < 0)
       return status;
@@ -1828,8 +1853,6 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
   cmd[2] = 0;
 
   cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE;
-  if (p->flags & AVRPART_HAS_UPDI)
-      addr += mem->offset;
   if (strcmp(mem->desc, "flash") == 0 ||
       strcmp(mem->desc, "application") == 0 ||
       strcmp(mem->desc, "apptable") == 0 ||
@@ -1874,6 +1897,8 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
       addr = mem->offset & 7;
   } else if (strcmp(mem->desc, "usersig") == 0) {
     cmd[3] = MTYPE_USERSIG;
+  } else if (strcmp(mem->desc, "userrow") == 0) {
+    cmd[3] = MTYPE_USERSIG;
   } else if (strcmp(mem->desc, "prodsig") == 0) {
     cmd[3] = MTYPE_PRODSIG;
   } else if (strcmp(mem->desc, "calibration") == 0) {
@@ -1892,11 +1917,7 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
      * harm for other connection types either.
      */
     u32_to_b4(cmd + 8, 3);
-    u32_to_b4(cmd + 4, mem->offset);
-
-    if (p->flags & AVRPART_HAS_UPDI){
-        addr -= mem->offset;
-    }
+    u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, addr));
 
     if (addr == 0) {
       if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
@@ -1942,10 +1963,11 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
 
   if (pagesize) {
     u32_to_b4(cmd + 8, pagesize);
-    u32_to_b4(cmd + 4, paddr);
+    u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, paddr));
+
   } else {
     u32_to_b4(cmd + 8, 1);
-    u32_to_b4(cmd + 4, addr);
+    u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, addr));
   }
 
   if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
@@ -1978,16 +2000,19 @@ static int jtag3_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
   unsigned char *cache_ptr = 0;
   int status, unsupp = 0;
   unsigned int pagesize = 0;
+  unsigned long mapped_addr;
 
   avrdude_message(MSG_NOTICE2, "%s: jtag3_write_byte(.., %s, 0x%lx, ...)\n",
 	    progname, mem->desc, addr);
 
+  mapped_addr = jtag3_memaddr(pgm, p, mem, addr);
+  if(mapped_addr != addr)
+    avrdude_message(MSG_NOTICE2, "          mapped to address: 0x%lx\n", mapped_addr);
+
   cmd[0] = SCOPE_AVR;
   cmd[1] = CMD3_WRITE_MEMORY;
   cmd[2] = 0;
   cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_FLASH : MTYPE_SPM;
-  if (p->flags & AVRPART_HAS_UPDI)
-      addr += mem->offset;
   if (strcmp(mem->desc, "flash") == 0) {
      cache_ptr = PDATA(pgm)->flash_pagecache;
      pagesize = PDATA(pgm)->flash_pagesize;
@@ -2070,7 +2095,7 @@ static int jtag3_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
     return -1;
 
   u32_to_b4(cmd + 8, 1);
-  u32_to_b4(cmd + 4, addr);
+  u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, addr));
   cmd[12] = 0;
   cmd[13] = data;
 
@@ -2325,7 +2350,13 @@ static unsigned int jtag3_memaddr(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, uns
    * Non-Xmega device.
    */
   if (p->flags & AVRPART_HAS_UPDI) {
-    if (strcmp(m->desc, "flash") != 0) {
+    if (strcmp(m->desc, "fuses") == 0) {
+        addr += m->offset;
+    }
+    else if (strncmp(m->desc, "fuse", strlen("fuse")) == 0) {
+        addr = m->offset;
+    }
+    else if (strcmp(m->desc, "flash") != 0) {
         addr += m->offset;
     }
   }
@@ -2448,7 +2479,7 @@ void jtag3_updi_initpgm(PROGRAMMER * pgm)
   pgm->enable         = jtag3_enable;
   pgm->disable        = jtag3_disable;
   pgm->program_enable = jtag3_program_enable_dummy;
-  pgm->chip_erase     = jtag3_chip_erase_updi;
+  pgm->chip_erase     = jtag3_chip_erase;
   pgm->open           = jtag3_open_updi;
   pgm->close          = jtag3_close;
   pgm->read_byte      = jtag3_read_byte;
@@ -2466,6 +2497,7 @@ void jtag3_updi_initpgm(PROGRAMMER * pgm)
   pgm->teardown       = jtag3_teardown;
   pgm->page_size      = 256;
   pgm->flag           = PGM_FL_IS_UPDI;
+  pgm->unlock         = jtag3_unlock_erase_key;
   pgm->read_sib       = jtag3_read_sib;
 }
 
diff --git a/avrdude/libavrdude.h b/avrdude/libavrdude.h
index 7ba3a71..b80ad79 100644
--- a/avrdude/libavrdude.h
+++ b/avrdude/libavrdude.h
@@ -647,6 +647,7 @@ typedef struct programmer_t {
   void (*powerdown)      (struct programmer_t * pgm);
   int  (*program_enable) (struct programmer_t * pgm, AVRPART * p);
   int  (*chip_erase)     (struct programmer_t * pgm, AVRPART * p);
+  int  (*unlock)         (struct programmer_t * pgm, AVRPART * p);
   int  (*cmd)            (struct programmer_t * pgm, const unsigned char *cmd,
                           unsigned char *res);
   int  (*cmd_tpi)        (struct programmer_t * pgm, const unsigned char *cmd,
@@ -764,6 +765,8 @@ int avr_mem_hiaddr(AVRMEM * mem);
 
 int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p);
 
+int avr_unlock(PROGRAMMER * pgm, AVRPART * p);
+
 void report_progress (int completed, int total, char *hdr);
 
 #ifdef __cplusplus
diff --git a/avrdude/main.c b/avrdude/main.c
index 4521aea..1de907c 100644
--- a/avrdude/main.c
+++ b/avrdude/main.c
@@ -1077,7 +1077,7 @@ int main(int argc, char * argv [])
               if (quell_progress < 2) {
                 avrdude_message(MSG_INFO, "%s: erasing chip\n", progname);
               }
-              exitrc = avr_chip_erase(pgm, p);
+              exitrc = avr_unlock(pgm, p);
               if(exitrc) goto main_exit;
               goto sig_again;
             }
