diff --git a/avrdude/avr.c b/avrdude/avr.c
index 8df586a..1152b15 100644
--- a/avrdude/avr.c
+++ b/avrdude/avr.c
@@ -309,7 +309,7 @@ int avr_mem_hiaddr(AVRMEM * mem)
 int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype,
              AVRPART * v)
 {
-  unsigned long    i, lastaddr;
+  unsigned long    i, lastaddr, offsetaddr;
   unsigned char    cmd[4];
   AVRMEM * mem, * vmem = NULL;
   int rc;
@@ -432,11 +432,17 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype,
     }
   }
 
-  for (i=0; i < mem->size; i++) {
+  if (p->flags & AVRPART_HAS_UPDI) {
+      offsetaddr = mem->offset & 0xFFFF;
+  }
+  else {
+      offsetaddr = 0;
+  }
+  for (i = 0; i < mem->size; i++) {
     if (vmem == NULL ||
 	(vmem->tags[i] & TAG_ALLOCATED) != 0)
     {
-      rc = pgm->read_byte(pgm, p, mem, i, mem->buf + i);
+      rc = pgm->read_byte(pgm, p, mem, offsetaddr + i, mem->buf + i);
       if (rc != 0) {
 	avrdude_message(MSG_INFO, "avr_read(): error reading address 0x%04lx\n", i);
 	if (rc == -1)
diff --git a/avrdude/avrdude.conf.in b/avrdude/avrdude.conf.in
index b247e52..7250467 100644
--- a/avrdude/avrdude.conf.in
+++ b/avrdude/avrdude.conf.in
@@ -55,6 +55,7 @@
 #       has_jtag         = <yes/no> ;             # part has JTAG i/f
 #       has_debugwire    = <yes/no> ;             # part has debugWire i/f
 #       has_pdi          = <yes/no> ;             # part has PDI i/f
+#       has_updi         = <yes/no> ;             # part has UPDI i/f
 #       has_tpi          = <yes/no> ;             # part has TPI i/f
 #       devicecode       = <num> ;            # deprecated, use stk500_devcode
 #       stk500_devcode   = <num> ;                # numeric
@@ -1104,6 +1105,14 @@ programmer
   usbpid = 0x2111;
 ;
 
+programmer
+  id    = "xplainedpro_updi";
+  desc  = "Atmel AVR XplainedPro in UPDI mode";
+  type  = "jtagice3_updi";
+  connection_type = usb;
+  usbpid = 0x2111;
+;
+
 programmer
   id    = "xplainedmini";
   desc  = "Atmel AVR XplainedMini in ISP mode";
@@ -1136,6 +1145,14 @@ programmer
   usbpid = 0x2141;
 ;
 
+programmer
+  id    = "atmelice_updi";
+  desc  = "Atmel-ICE (ARM/AVR) in UPDI mode";
+  type  = "jtagice3_updi";
+  connection_type = usb;
+  usbpid = 0x2141;
+;
+
 programmer
   id    = "atmelice_dw";
   desc  = "Atmel-ICE (ARM/AVR) in debugWIRE mode";
@@ -8695,6 +8712,14 @@ part parent "m328"
     ocdrev              = 1;
 ;
 
+part parent "m328"
+    id			= "m328pb";
+    desc		= "ATmega328PB";
+    signature		= 0x1e 0x95 0x16;
+
+    ocdrev              = 1;
+;
+
 #------------------------------------------------------------
 # ATmega32m1
 #------------------------------------------------------------
@@ -14981,4 +15006,131 @@ part
     ;
 ;
 
+#------------------------------------------------------------
+# AVR8X family common values
+#------------------------------------------------------------
+
+part
+    id		= ".avr8x";
+    desc	= "AVR8X family common values";
+    has_updi	= yes;
+    nvm_base	= 0x01c0;
+    mcu_base	= 0x0090;
+
+    memory "signature"
+        size		= 3;
+        offset		= 0x1100;
+    ;
+
+    memory "userrow"
+        size        = 0x20;
+        offset      = 0x801300;
+        page_size   = 0x20;
+        readsize	= 0x100;
+    ;
+
+    memory "prodsig"
+        size		= 0x3D;
+        offset		= 0x801103;
+        page_size	= 0x3D;
+        readsize	= 0x3D;
+    ;
+
+    memory "fuse0"
+        size		= 1;
+        offset		= 0x801280;
+    ;
+
+    memory "fuse1"
+        size		= 1;
+        offset		= 0x801281;
+    ;
+
+    memory "fuse2"
+        size		= 1;
+        offset		= 0x801282;
+    ;
+
+    memory "fuse4"
+        size		= 1;
+        offset		= 0x801284;
+    ;
+
+    memory "fuse5"
+        size		= 1;
+        offset		= 0x801285;
+    ;
 
+    memory "fuse6"
+        size		= 1;
+        offset		= 0x801286;
+    ;
+
+    memory "fuse7"
+        size		= 1;
+        offset		= 0x801287;
+    ;
+
+    memory "fuse8"
+        size		= 1;
+        offset		= 0x801288;
+    ;
+
+    memory "lock"
+        size		= 1;
+        offset		= 0x80128a;
+    ;
+
+    memory "data"
+        # SRAM, only used to supply the offset
+        offset		= 0x1000000;
+    ;
+;
+
+#------------------------------------------------------------
+# ATtiny1617
+#------------------------------------------------------------
+
+part parent ".avr8x"
+    id		= "tn1617";
+    desc	= "ATtiny1617";
+    signature	= 0x1e 0x94 0x20;
+
+    memory "eeprom"
+        size		= 0x0100;
+        offset		= 0x0801400;
+        page_size	= 0x20;
+        readsize	= 0x100;
+    ;
+
+    memory "flash"
+        size		= 0x4000;
+        offset		= 0x0800000;
+        page_size	= 0x40;
+        readsize	= 0x100;
+    ;
+;
+
+#------------------------------------------------------------
+# ATtiny817
+#------------------------------------------------------------
+
+part parent ".avr8x"
+    id		= "tn817";
+    desc	= "ATtiny817";
+    signature	= 0x1e 0x93 0x20;
+
+    memory "eeprom"
+        size		= 0x0100;
+        offset		= 0x0801400;
+        page_size	= 0x20;
+        readsize	= 0x100;
+    ;
+
+    memory "flash"
+        size		= 0x2000;
+        offset		= 0x0800000;
+        page_size	= 0x40;
+        readsize	= 0x100;
+    ;
+;
diff --git a/avrdude/config_gram.y b/avrdude/config_gram.y
index 0aa95a8..25c87ce 100644
--- a/avrdude/config_gram.y
+++ b/avrdude/config_gram.y
@@ -183,6 +183,7 @@ static int pin_name;
 %token K_HAS_JTAG		/* MCU has JTAG i/f. */
 %token K_HAS_DW			/* MCU has debugWire i/f. */
 %token K_HAS_PDI                /* MCU has PDI i/f rather than ISP (ATxmega). */
+%token K_HAS_UPDI               /* MCU has UPDI i/f (AVR8X). */
 %token K_HAS_TPI                /* MCU has TPI i/f rather than ISP (ATtiny4/5/9/10). */
 %token K_IDR			/* address of OCD register in IO space */
 %token K_IS_AT90S1200		/* chip is an AT90S1200 (needs special treatment) */
@@ -1062,6 +1063,16 @@ part_parm :
       free_token($3);
     } |
 
+  K_HAS_UPDI TKN_EQUAL yesno
+    {
+      if ($3->primary == K_YES)
+        current_part->flags |= AVRPART_HAS_UPDI;
+      else if ($3->primary == K_NO)
+        current_part->flags &= ~AVRPART_HAS_UPDI;
+
+      free_token($3);
+    } |
+
   K_HAS_TPI TKN_EQUAL yesno
     {
       if ($3->primary == K_YES)
diff --git a/avrdude/doc/avrdude.texi b/avrdude/doc/avrdude.texi
index 6941389..161c647 100644
--- a/avrdude/doc/avrdude.texi
+++ b/avrdude/doc/avrdude.texi
@@ -1440,6 +1440,7 @@ part
     has_jtag         = <yes/no> ;             # part has JTAG i/f
     has_debugwire    = <yes/no> ;             # part has debugWire i/f
     has_pdi          = <yes/no> ;             # part has PDI i/f
+    has_updi         = <yes/no> ;             # part has UPDI i/f
     has_tpi          = <yes/no> ;             # part has TPI i/f
     devicecode       = <num> ;                # numeric
     stk500_devcode   = <num> ;                # numeric
diff --git a/avrdude/jtag3.c b/avrdude/jtag3.c
index 3084c32..a8d4cee 100644
--- a/avrdude/jtag3.c
+++ b/avrdude/jtag3.c
@@ -84,6 +84,7 @@ struct pdata
 #define PGM_FL_IS_PDI           (0x0002)
 #define PGM_FL_IS_JTAG          (0x0004)
 #define PGM_FL_IS_EDBG          (0x0008)
+#define PGM_FL_IS_UPDI          (0x0010)
 
 static int jtag3_open(PROGRAMMER * pgm, char * port);
 static int jtag3_edbg_prepare(PROGRAMMER * pgm);
@@ -1014,6 +1015,10 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
     ifname = "PDI";
     if (p->flags & AVRPART_HAS_PDI)
       conn = PARM3_CONN_PDI;
+  } else if (pgm->flag & PGM_FL_IS_UPDI) {
+    ifname = "UPDI";
+    if (p->flags & AVRPART_HAS_UPDI)
+      conn = PARM3_CONN_UPDI;
   } else {
     ifname = "JTAG";
     if (p->flags & AVRPART_HAS_JTAG)
@@ -1028,6 +1033,8 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
 
   if (p->flags & AVRPART_HAS_PDI)
     parm[0] = PARM3_ARCH_XMEGA;
+  else if (p->flags & AVRPART_HAS_UPDI)
+    parm[0] = PARM3_ARCH_UPDI;
   else if (p->flags & AVRPART_HAS_DW)
     parm[0] = PARM3_ARCH_TINY;
   else
@@ -1043,7 +1050,7 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
   if (jtag3_setparm(pgm, SCOPE_AVR, 1, PARM3_CONNECTION, parm, 1) < 0)
     return -1;
 
-  if (conn == PARM3_CONN_PDI)
+  if (conn == PARM3_CONN_PDI || conn == PARM3_CONN_UPDI)
     PDATA(pgm)->set_sck = jtag3_set_sck_xmega_pdi;
   else if (conn == PARM3_CONN_JTAG) {
     if (p->flags & AVRPART_HAS_PDI)
@@ -1119,6 +1126,68 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
     if (jtag3_setparm(pgm, SCOPE_AVR, 2, PARM3_DEVICEDESC, (unsigned char *)&xd, sizeof xd) < 0)
       return -1;
   }
+  else if ((p->flags & AVRPART_HAS_UPDI))
+  {
+    struct updi_device_desc xd;
+    LNODEID ln;
+    AVRMEM *m;
+
+    u16_to_b2(xd.nvm_base_addr, p->nvm_base);
+    u16_to_b2(xd.mcu_base_addr, p->mcu_base);
+
+    for (ln = lfirst(p->mem); ln; ln = lnext(ln))
+    {
+      m = ldata(ln);
+      if (strcmp(m->desc, "flash") == 0)
+      {
+        if (m->readsize != 0 && m->readsize < m->page_size)
+          PDATA(pgm)->flash_pagesize = m->readsize;
+        else
+          PDATA(pgm)->flash_pagesize = m->page_size;
+        xd.flash_page_size = m->page_size;
+      }
+      else if (strcmp(m->desc, "eeprom") == 0)
+      {
+        PDATA(pgm)->eeprom_pagesize = m->page_size;
+        xd.eeprom_page_size = m->page_size;
+        u32_to_b4(xd.nvm_eeprom_offset, m->offset & 0x0FFFF);
+      }
+      else if (strcmp(m->desc, "fuse0") == 0)
+      {
+        u32_to_b4(xd.nvm_fuse_offset, m->offset & 0x0FFFF);
+      }
+      else if (strcmp(m->desc, "lock") == 0)
+      {
+        u32_to_b4(xd.nvm_lock_offset, m->offset & 0x0FFFF);
+      }
+      else if (strcmp(m->desc, "userrow") == 0)
+      {
+        u32_to_b4(xd.nvm_user_sig_offset, m->offset & 0x0FFFF);
+      }
+      else if (strcmp(m->desc, "prodsig") == 0)
+      {
+        u32_to_b4(xd.nvm_prod_sig_offset, m->offset & 0x0FFFF);
+      }
+    }
+    
+    xd.prog_base[1] = 0x80;
+    xd.prog_base[0] = 0;
+
+    avrdude_message(MSG_NOTICE2, "UPDI SET: \n\t"
+      "xd->prog_base=%x %x\n\t"
+      "xd->flash_page_size=%x\n\t"
+      "xd->eeprom_page_size=%x\n\t"      
+      "xd->nvmctrl=%x %x\n\t"
+      "xd->ocd=%x %x\n",
+      xd.prog_base[0], xd.prog_base[1],
+      xd.flash_page_size,
+      xd.eeprom_page_size,
+      xd.nvm_base_addr[0], xd.nvm_base_addr[1], 
+      xd.mcu_base_addr[0], xd.mcu_base_addr[1]);
+
+    if (jtag3_setparm(pgm, SCOPE_AVR, 2, PARM3_DEVICEDESC, (unsigned char *)&xd, sizeof xd) < 0)
+      return -1;
+  }
   else
   {
     struct mega_device_desc md;
@@ -1443,6 +1512,18 @@ static int jtag3_open_pdi(PROGRAMMER * pgm, char * port)
   return 0;
 }
 
+static int jtag3_open_updi(PROGRAMMER * pgm, char * port)
+{
+  avrdude_message(MSG_NOTICE2, "%s: jtag3_open_updi()\n", progname);
+
+  if (jtag3_open_common(pgm, port) < 0)
+    return -1;
+
+  if (jtag3_getsync(pgm, PARM3_CONN_UPDI) < 0)
+    return -1;
+
+  return 0;
+}
 
 void jtag3_close(PROGRAMMER * pgm)
 {
@@ -1716,7 +1797,7 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
   cmd[1] = CMD3_READ_MEMORY;
   cmd[2] = 0;
 
-  cmd[3] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE;
+  cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE;
   if (strcmp(mem->desc, "flash") == 0 ||
       strcmp(mem->desc, "application") == 0 ||
       strcmp(mem->desc, "apptable") == 0 ||
@@ -1727,7 +1808,7 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
     paddr_ptr = &PDATA(pgm)->flash_pageaddr;
     cache_ptr = PDATA(pgm)->flash_pagecache;
   } else if (strcmp(mem->desc, "eeprom") == 0) {
-    if ( (pgm->flag & PGM_FL_IS_DW) || ( p->flags & AVRPART_HAS_PDI ) ) {
+    if ( (pgm->flag & PGM_FL_IS_DW) || ( p->flags & AVRPART_HAS_PDI ) || ( p->flags & AVRPART_HAS_UPDI ) ) {
       cmd[3] = MTYPE_EEPROM;
     } else {
       cmd[3] = MTYPE_EEPROM_PAGE;
@@ -1778,7 +1859,11 @@ 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, 0);
+    u32_to_b4(cmd + 4, mem->offset);
+
+    if (p->flags & AVRPART_HAS_UPDI){
+        addr -= mem->offset;
+    }
 
     if (addr == 0) {
       if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
@@ -1867,7 +1952,7 @@ static int jtag3_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
   cmd[0] = SCOPE_AVR;
   cmd[1] = CMD3_WRITE_MEMORY;
   cmd[2] = 0;
-  cmd[3] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_FLASH : MTYPE_SPM;
+  cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_FLASH : MTYPE_SPM;
   if (strcmp(mem->desc, "flash") == 0) {
      cache_ptr = PDATA(pgm)->flash_pagecache;
      pagesize = PDATA(pgm)->flash_pagesize;
@@ -1902,6 +1987,8 @@ static int jtag3_write_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 (strncmp(mem->desc, "lock", 4) == 0) {
@@ -2284,3 +2371,37 @@ void jtag3_pdi_initpgm(PROGRAMMER * pgm)
   pgm->flag           = PGM_FL_IS_PDI;
 }
 
+const char jtag3_updi_desc[] = "Atmel JTAGICE3 in UPDI mode";
+
+void jtag3_updi_initpgm(PROGRAMMER * pgm)
+{
+  strcpy(pgm->type, "JTAGICE3_UPDI");
+
+  /*
+   * mandatory functions
+   */
+  pgm->initialize     = jtag3_initialize;
+  pgm->display        = jtag3_display;
+  pgm->enable         = jtag3_enable;
+  pgm->disable        = jtag3_disable;
+  pgm->program_enable = jtag3_program_enable_dummy;
+  pgm->chip_erase     = jtag3_chip_erase;
+  pgm->open           = jtag3_open_updi;
+  pgm->close          = jtag3_close;
+  pgm->read_byte      = jtag3_read_byte;
+  pgm->write_byte     = jtag3_write_byte;
+
+  /*
+   * optional functions
+   */
+  pgm->paged_write    = jtag3_paged_write;
+  pgm->paged_load     = jtag3_paged_load;
+  pgm->page_erase     = jtag3_page_erase;
+  pgm->print_parms    = jtag3_print_parms;
+  pgm->set_sck_period = jtag3_set_sck_period;
+  pgm->setup          = jtag3_setup;
+  pgm->teardown       = jtag3_teardown;
+  pgm->page_size      = 256;
+  pgm->flag           = PGM_FL_IS_UPDI;
+}
+
diff --git a/avrdude/jtag3.h b/avrdude/jtag3.h
index fef3be0..4e49c58 100644
--- a/avrdude/jtag3.h
+++ b/avrdude/jtag3.h
@@ -41,9 +41,11 @@ int jtag3_command(PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
 extern const char jtag3_desc[];
 extern const char jtag3_dw_desc[];
 extern const char jtag3_pdi_desc[];
+extern const char jtag3_updi_desc[];
 void jtag3_initpgm (PROGRAMMER * pgm);
 void jtag3_dw_initpgm (PROGRAMMER * pgm);
 void jtag3_pdi_initpgm (PROGRAMMER * pgm);
+void jtag3_updi_initpgm (PROGRAMMER * pgm);
 
 /*
  * These functions are referenced from stk500v2.c for JTAGICE3 in
diff --git a/avrdude/jtag3_private.h b/avrdude/jtag3_private.h
index 8ee3750..e319673 100644
--- a/avrdude/jtag3_private.h
+++ b/avrdude/jtag3_private.h
@@ -109,6 +109,7 @@
 #define CMD3_GET_PARAMETER         0x02
 #define CMD3_SIGN_ON               0x10
 #define CMD3_SIGN_OFF              0x11 /* takes one parameter? */
+#define CMD3_GET_ID                0x12
 #define CMD3_START_DW_DEBUG        0x13
 #define CMD3_MONCON_DISABLE        0x17
 
@@ -165,6 +166,7 @@
 #define MTYPE_EEPROM_XMEGA 0xc4	/* xmega EEPROM in debug mode - undocumented in AVR067 */
 #define MTYPE_USERSIG     0xc5	/* xmega user signature - undocumented in AVR067 */
 #define MTYPE_PRODSIG     0xc6	/* xmega production signature - undocumented in AVR067 */
+#define MTYPE_SIB         0xD3  /* AVR8X System Information Block */
 
 /*
  * Parameters are divided into sections, where the section number
@@ -189,6 +191,7 @@
 #  define PARM3_ARCH_TINY   1   /* also small megaAVR with ISP/DW only */
 #  define PARM3_ARCH_MEGA   2
 #  define PARM3_ARCH_XMEGA  3
+#  define PARM3_ARCH_UPDI   5   /* AVR devices with UPDI i/f */
 
 #define PARM3_SESS_PURPOSE 0x01 /* section 0, AVR scope, 1 byte */
 #  define PARM3_SESS_PROGRAMMING 1
@@ -199,6 +202,7 @@
 #  define PARM3_CONN_JTAG   4
 #  define PARM3_CONN_DW     5
 #  define PARM3_CONN_PDI    6
+#  define PARM3_CONN_UPDI   8
 
 
 #define PARM3_JTAGCHAIN   0x01  /* JTAG chain info, AVR scope (units
@@ -316,4 +320,18 @@ struct xmega_device_desc {
     unsigned char nvm_base_addr[2];	// IO space base address of NVM controller
     unsigned char mcu_base_addr[2];	// IO space base address of MCU control
 };
+
+/* UPDI device descriptor */
+struct updi_device_desc {
+    unsigned char prog_base[2];
+    unsigned char flash_page_size;
+    unsigned char eeprom_page_size;
+    unsigned char nvm_base_addr[2];
+    unsigned char mcu_base_addr[2];
+    unsigned char nvm_eeprom_offset[4]; // NVM offset for EEPROM
+    unsigned char nvm_fuse_offset[4];	// NVM offset for fuses
+    unsigned char nvm_lock_offset[4];	// NVM offset for lock bits
+    unsigned char nvm_user_sig_offset[4]; // NVM offset for user signature row
+    unsigned char nvm_prod_sig_offset[4]; // NVM offset for production sign. row
+};
 #endif /* JTAG3_PRIVATE_EXPORTED */
diff --git a/avrdude/lexer.l b/avrdude/lexer.l
index 34af33d..2ddd90a 100644
--- a/avrdude/lexer.l
+++ b/avrdude/lexer.l
@@ -151,6 +151,7 @@ flash_instr      { yylval=NULL; return K_FLASH_INSTR; }
 has_debugwire    { yylval=NULL; return K_HAS_DW; }
 has_jtag         { yylval=NULL; return K_HAS_JTAG; }
 has_pdi          { yylval=NULL; return K_HAS_PDI; }
+has_updi         { yylval=NULL; return K_HAS_UPDI; }
 has_tpi          { yylval=NULL; return K_HAS_TPI; }
 hventerstabdelay { yylval=NULL; return K_HVENTERSTABDELAY; }
 hvleavestabdelay { yylval=NULL; return K_HVLEAVESTABDELAY; }
diff --git a/avrdude/libavrdude.h b/avrdude/libavrdude.h
index d5f32e4..e40e9b3 100644
--- a/avrdude/libavrdude.h
+++ b/avrdude/libavrdude.h
@@ -199,6 +199,7 @@ typedef struct opcode {
 #define AVRPART_WRITE          0x0400  /* at least one write operation specified */
 #define AVRPART_HAS_TPI        0x0800  /* part has TPI i/f rather than ISP (ATtiny4/5/9/10) */
 #define AVRPART_IS_AT90S1200   0x1000  /* part is an AT90S1200 (needs special treatment) */
+#define AVRPART_HAS_UPDI       0x2000  /* part has UPDI i/f (AVR8X) */
 
 #define AVR_DESCLEN 64
 #define AVR_IDLEN   32
diff --git a/avrdude/pgm_type.c b/avrdude/pgm_type.c
index 7724987..9b6bdcc 100644
--- a/avrdude/pgm_type.c
+++ b/avrdude/pgm_type.c
@@ -77,6 +77,7 @@ const PROGRAMMER_TYPE programmers_types[] = {
         {"jtagmkii_pdi", jtagmkII_pdi_initpgm, jtagmkII_pdi_desc},
         {"jtagice3", jtag3_initpgm, jtag3_desc},
         {"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc},
+        {"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc},
         {"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc},
         {"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc},
         {"linuxgpio", linuxgpio_initpgm, linuxgpio_desc},
