From 625027a807f97eedf6339e033a7b10cadb56f415 Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Sat, 5 Feb 2022 14:44:13 +0100
Subject: [PATCH 01/16] Add HV UPDI pulse command

---
 src/jtag3.c         | 4 ++++
 src/jtag3_private.h | 8 ++++++++
 2 files changed, 12 insertions(+)

diff --git a/src/jtag3.c b/src/jtag3.c
index 1681a001..b0815986 100644
--- a/src/jtag3.c
+++ b/src/jtag3.c
@@ -1247,6 +1247,10 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
       }
     }
 
+    parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE;
+    if (jtag3_setparm(pgm, SCOPE_AVR, 3, PARM3_OPT_12V_UPDI_ENABLE, parm, 1) < 0)
+      return -1;
+
     u16_to_b2(xd.default_min_div1_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV1_VOLTAGE_MV);
     u16_to_b2(xd.default_min_div2_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV2_VOLTAGE_MV);
     u16_to_b2(xd.default_min_div4_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV4_VOLTAGE_MV);
diff --git a/src/jtag3_private.h b/src/jtag3_private.h
index a3e7fb08..3eeb61b3 100644
--- a/src/jtag3_private.h
+++ b/src/jtag3_private.h
@@ -236,6 +236,14 @@
 #define PARM3_OPT_12V_UPDI_ENABLE      0x06
 #define PARM3_OPT_CHIP_ERASE_TO_ENTER  0x07
 
+/*
+ * UPDI high-voltage enable modes
+ */
+#define PARM3_UPDI_HV_NONE              0x00  /* Do not use high-voltage */
+#define PARM3_UPDI_HV_SIMPLE_PULSE      0x01  /* Issue a single high-voltage pulse immediately*/
+#define PARM3_UPDI_HV_AUTO_POWER_TOGGLE 0x02  /* Toggle power automatically and then apply a high-voltage pulse */
+#define PARM3_UPDI_HV_USER_POWER_TOGGLE 0x03  /* The user toggles power, and the tool applies a high-voltage pulse on power-up */
+
 /* Xmega erase memory types, for CMND_XMEGA_ERASE */
 #define XMEGA_ERASE_CHIP        0x00
 #define XMEGA_ERASE_APP         0x01

From ba98e48880c030d90d9d4dd752a895fa29295607 Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Sun, 26 Jun 2022 00:11:51 +0200
Subject: [PATCH 02/16] add "hvupdi_variant" property to avrdude.conf

---
 src/avrdude.conf.in | 44 ++++++++++++++++++++++++++------------------
 src/config_gram.y   |  7 +++++++
 src/lexer.l         |  1 +
 src/libavrdude.h    |  1 +
 4 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in
index ba7f4f8e..2fc59ecd 100644
--- a/src/avrdude.conf.in
+++ b/src/avrdude.conf.in
@@ -17114,13 +17114,15 @@ part
 # AVR8X tiny family common values
 #------------------------------------------------------------
 
-part parent    ".avr8x"
-    id			= ".avr8x_tiny";
-    desc		= "AVR8X tiny family common values";
-    family_id	= "tinyAVR";
+part parent ".avr8x"
+    id			       = ".avr8x_tiny";
+    desc		       = "AVR8X tiny family common values";
+    family_id      = "tinyAVR";
+    # Shared UPDI pin, HV on UPDI pin
+    hvupdi_variant = 0;
 
     memory "userrow"
-        size		= 0x20;
+        size	  	= 0x20;
         offset		= 0x1300;
         page_size	= 0x20;
         readsize	= 0x100;
@@ -17135,13 +17137,15 @@ part parent    ".avr8x"
 # AVR8X mega family common values
 #------------------------------------------------------------
 
-part parent    ".avr8x"
-    id			= ".avr8x_mega";
-    desc		= "AVR8X mega family common values";
-    family_id	= "megaAVR";
+part parent ".avr8x"
+    id			       = ".avr8x_mega";
+    desc		       = "AVR8X mega family common values";
+    family_id	     = "megaAVR";
+    # Dedicated UPDI pin, no HV
+    hvupdi_variant = 1;
 
     memory "userrow"
-        size		= 0x40;
+        size		  = 0x40;
         offset		= 0x1300;
         page_size	= 0x40;
         readsize	= 0x100;
@@ -18240,11 +18244,13 @@ part parent    ".avr8x_mega"
 #------------------------------------------------------------
 
 part
-    id		= ".avrdx";
-    desc	= "AVR-Dx family common values";
-    has_updi	= yes;
-    nvm_base	= 0x1000;
-    ocd_base	= 0x0F80;
+    id             = ".avrdx";
+    desc           = "AVR-Dx family common values";
+    has_updi       = yes;
+    nvm_base       = 0x1000;
+    ocd_base       = 0x0F80;
+    # Dedicated UPDI pin, no HV
+    hvupdi_variant = 1;
 
     memory "signature"
         size		= 3;
@@ -19210,9 +19216,11 @@ part parent    ".avrdx"
 # AVR-Ex family common values
 #------------------------------------------------------------
 
-part parent    ".avrdx"
-    id			= ".avrex";
-    desc		= "AVR-Ex family common values";
+part parent ".avrdx"
+    id			       = ".avrex";
+    desc		       = "AVR-Ex family common values";
+    # Shared UPDI pin, HV on _RESET
+    hvupdi_variant = 2;
 
     memory "userrow"
         size      = 0x40;
diff --git a/src/config_gram.y b/src/config_gram.y
index a8416162..126b9b54 100644
--- a/src/config_gram.y
+++ b/src/config_gram.y
@@ -81,6 +81,7 @@ static int pin_name;
 %token K_DEFAULT_SERIAL
 %token K_DESC
 %token K_FAMILY_ID
+%token K_HVUPDI_VARIANT
 %token K_DEVICECODE
 %token K_STK500_DEVCODE
 %token K_AVR910_DEVCODE
@@ -676,6 +677,12 @@ part_parm :
       free_token($3);
     } |
 
+  K_HVUPDI_VARIANT TKN_EQUAL TKN_NUMBER
+    {
+      current_part->hvupdi_variant = $3->value.number;
+      free_token($3);
+    } |
+
   K_DEVICECODE TKN_EQUAL TKN_NUMBER {
     {
       yyerror("devicecode is deprecated, use "
diff --git a/src/lexer.l b/src/lexer.l
index 0b31eb21..dd5c081a 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -159,6 +159,7 @@ hventerstabdelay { yylval=NULL; return K_HVENTERSTABDELAY; }
 hvleavestabdelay { yylval=NULL; return K_HVLEAVESTABDELAY; }
 hvsp_controlstack  { yylval=NULL; return K_HVSP_CONTROLSTACK; }
 hvspcmdexedelay  { yylval=NULL; return K_HVSPCMDEXEDELAY; }
+hvupdi_variant   { yylval=NULL; return K_HVUPDI_VARIANT; }
 id               { yylval=NULL; return K_ID; }
 idr              { yylval=NULL; return K_IDR; }
 io               { yylval=new_token(K_IO); return K_IO; }
diff --git a/src/libavrdude.h b/src/libavrdude.h
index ddb72b48..2b87ddf1 100644
--- a/src/libavrdude.h
+++ b/src/libavrdude.h
@@ -202,6 +202,7 @@ typedef struct avrpart {
   char          desc[AVR_DESCLEN];  /* long part name */
   char          id[AVR_IDLEN];      /* short part name */
   char          family_id[AVR_FAMILYIDLEN+1]; /* family id in the SIB (avr8x) */
+  int           hvupdi_variant;     /* 12V pulse on UPDI pin, no pin or RESET pin */
   int           stk500_devcode;     /* stk500 device code */
   int           avr910_devcode;     /* avr910 device code */
   int           chip_erase_delay;   /* microseconds */

From f67c35744e7522a61ff1d67efef4adc27278e1b0 Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Sun, 26 Jun 2022 00:13:56 +0200
Subject: [PATCH 03/16] add support for "-x hvupdi" that triggers HV UPDI

---
 src/jtag3.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/src/jtag3.c b/src/jtag3.c
index 4e3ef8c2..976291f4 100644
--- a/src/jtag3.c
+++ b/src/jtag3.c
@@ -71,6 +71,9 @@ struct pdata
   /* Start address of Xmega boot area */
   unsigned long boot_start;
 
+  /* Flag for triggering HV UPDI */
+  bool use_hvupdi;
+
   /* Function to set the appropriate clock parameter */
   int (*set_sck)(PROGRAMMER *, unsigned char *);
 };
@@ -1249,10 +1252,12 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
       }
     }
 
-    parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE;
-    if (jtag3_setparm(pgm, SCOPE_AVR, 3, PARM3_OPT_12V_UPDI_ENABLE, parm, 1) < 0)
-      return -1;
-
+    // Generate 12V UPDI pulse if user asks for it and  hardware supports it
+    if(p->flags & AVRPART_HAS_UPDI && PDATA(pgm)->use_hvupdi == true && p->hvupdi_variant == 0) {
+      parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE;
+      if (jtag3_setparm(pgm, SCOPE_AVR, 3, PARM3_OPT_12V_UPDI_ENABLE, parm, 1) < 0)
+        return -1;
+    }
     u16_to_b2(xd.default_min_div1_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV1_VOLTAGE_MV);
     u16_to_b2(xd.default_min_div2_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV2_VOLTAGE_MV);
     u16_to_b2(xd.default_min_div4_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV4_VOLTAGE_MV);
@@ -1477,6 +1482,10 @@ static int jtag3_parseextparms(PROGRAMMER * pgm, LISTID extparms)
 
       continue;
     }
+    else if (matches(extended_param, "hvupdi") || matches(extended_param, "hvupdi=1")) {
+      PDATA(pgm)->use_hvupdi = true;
+      continue;
+    }
 
     avrdude_message(MSG_INFO, "%s: jtag3_parseextparms(): invalid extended parameter '%s'\n",
                     progname, extended_param);
@@ -2601,6 +2610,7 @@ void jtag3_updi_initpgm(PROGRAMMER * pgm)
    * mandatory functions
    */
   pgm->initialize     = jtag3_initialize;
+  pgm->parseextparams = jtag3_parseextparms;
   pgm->display        = jtag3_display;
   pgm->enable         = jtag3_enable;
   pgm->disable        = jtag3_disable;

From e0683417163d1563cedbfeb0a2c23e4d783d4940 Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Sun, 26 Jun 2022 10:19:27 +0200
Subject: [PATCH 04/16] Make sure "-x hvupdi" is only valid for Pickit4 and
 Powerdebugger

---
 src/jtag3.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/jtag3.c b/src/jtag3.c
index 976291f4..5e971a28 100644
--- a/src/jtag3.c
+++ b/src/jtag3.c
@@ -1458,6 +1458,7 @@ static int jtag3_parseextparms(PROGRAMMER * pgm, LISTID extparms)
   LNODEID ln;
   const char *extended_param;
   int rv = 0;
+  avrdude_message(MSG_INFO, "id: %s, desc: %s, type: %s\n", ldata(lfirst(pgm->id)), pgm->desc, pgm->type);
 
   for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
     extended_param = ldata(ln);
@@ -1482,7 +1483,9 @@ static int jtag3_parseextparms(PROGRAMMER * pgm, LISTID extparms)
 
       continue;
     }
-    else if (matches(extended_param, "hvupdi") || matches(extended_param, "hvupdi=1")) {
+
+    else if ((matches(extended_param, "hvupdi") || matches(extended_param, "hvupdi=1")) &&
+      (matches(ldata(lfirst(pgm->id)), "pickit4_updi") || matches(ldata(lfirst(pgm->id)), "powerdebugger_updi"))) {
       PDATA(pgm)->use_hvupdi = true;
       continue;
     }

From 50220289bb8b369ccb89fade961f60d8c593d556 Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Sun, 26 Jun 2022 19:35:39 +0200
Subject: [PATCH 05/16] Add high-voltage UPDI info to docs

---
 src/avrdude.1        | 20 ++++++++++++++++----
 src/doc/avrdude.texi | 20 +++++++++++++++++---
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/src/avrdude.1 b/src/avrdude.1
index 81834d30..5ecccb6b 100644
--- a/src/avrdude.1
+++ b/src/avrdude.1
@@ -179,7 +179,7 @@ has a revision 1 hardware and firmware version of at least 5.37 (decimal).
 For ATxmega devices, the JTAGICE3 is supported in PDI mode.
 .Pp
 Atmel-ICE (ARM/AVR) is supported in all modes (JTAG, PDI for Xmega, debugWIRE,
-ISP).
+ISP, UPDI).
 .Pp
 Atmel's XplainedPro boards, using the EDBG protocol (CMSIS-DAP compatible),
 are supported using the "jtag3" programmer type.
@@ -225,7 +225,7 @@ thus the name
 SerialUPDI programmer implementation is based on Microchip's
 .Em pymcuprog Li https://github.com/microchip-pic-avr-tools/pymcuprog
 utility, but it also contains some performance improvements included in
-Spence Kohde's
+Spence Konde's
 .Em DxCore
 Arduino core
 .Li https://github.com/SpenceKonde/DxCore .
@@ -959,9 +959,13 @@ versions of the bootloader.
 .It Ar JTAG ICE mkII
 .It Ar JTAGICE3
 .It Ar Atmel-ICE
+.It Ar Power Debugger
+.It Ar PICkit 4
+.It Ar MPLAB SNAP
 .It Ar AVR Dragon
-When using the JTAG ICE mkII, JTAGICE3, Atmel-ICE or AVR Dragon in JTAG mode, the
-following extended parameter is accepted:
+When using the JTAG ICE mkII, JTAGICE3, Atmel-ICE, PICkit 4, MPLAB SNAP,
+Power Debugger or AVR Dragon in JTAG mode, the following extended parameter
+is accepted:
 .Bl -tag -offset indent -width indent
 .It Ar jtagchain=UB,UA,BB,BA
 Setup the JTAG scan chain for
@@ -976,6 +980,14 @@ bits after the target AVR, respectively.
 Each AVR unit within the chain shifts by 4 bits.
 Other JTAG units might require a different bit shift count.
 .El
+.Pp
+The PICkit 4 and the Power Debugger also supports high-voltage UPDI programming.
+This is used to enable a UPDI pin that has previously been set to RESET or
+GPIO mode. High-voltage UPDI can be utilized by using an extended parameter:
+.Bl -tag -offset indent -width indent
+.It Ar hvupdi
+Enable high-voltage UPDI initialization for targets that supports this.
+.El
 .It Ar AVR910
 .Bl -tag -offset indent -width indent
 .It Ar devcode=VALUE
diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi
index 92cf4df4..20c8612a 100644
--- a/src/doc/avrdude.texi
+++ b/src/doc/avrdude.texi
@@ -250,7 +250,8 @@ See below for the limitations of debugWire.
 For ATxmega devices, the JTAG ICE mkII/3 is supported in PDI mode, provided it
 has a revision 1 hardware and firmware version of at least 5.37 (decimal).
 
-The Atmel-ICE (ARM/AVR) is supported (JTAG, PDI for Xmega, debugWIRE, ISP modes).
+The Atmel-ICE (ARM/AVR) is supported (JTAG, PDI for Xmega, debugWIRE, ISP,
+UPDI).
 
 Atmel's XplainedPro boards, using EDBG protocol (CMSIS-DAP compliant), are
 supported by the ``jtag3'' programmer type.
@@ -843,10 +844,15 @@ accepting extended parameters.
 @table @code
 
 @item JTAG ICE mkII/3
+@itemx Atmel-ICE
+@itemx PICkit 4
+@itemx MPLAB SNAP
+@itemx Power Debugger
 @itemx AVR Dragon
 
-When using the JTAG ICE mkII/3 or AVR Dragon in JTAG mode, the
-following extended parameter is accepted:
+When using the JTAG ICE mkII, JTAGICE3, Atmel-ICE, PICkit 4, MPLAB SNAP,
+Power Debugger or AVR Dragon in JTAG mode, the following extended parameter
+is accepted:
 @table @code
 @item @samp{jtagchain=UB,UA,BB,BA}
 Setup the JTAG scan chain for @var{UB} units before, @var{UA} units
@@ -856,6 +862,14 @@ Each AVR unit within the chain shifts by 4 bits.
 Other JTAG units might require a different bit shift count.
 @end table
 
+The PICkit 4 and the Power Debugger also supports high-voltage UPDI programming.
+This is used to enable a UPDI pin that has previously been set to RESET or
+GPIO mode. High-voltage UPDI can be utilized by using an extended parameter:
+@table @code
+@item @samp{hvupdi}
+Enable high-voltage UPDI initialization for targets that supports this.
+@end table
+
 @cindex @code{-x} AVR910
 @item AVR910
 

From 577856cf15700c048f1dd1cac7ca3a92d2f12b4d Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Sun, 26 Jun 2022 19:54:40 +0200
Subject: [PATCH 06/16] Use HV UPDI constants rather than arbitrary numbers

---
 src/jtag3.c      | 7 ++++---
 src/libavrdude.h | 4 ++++
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/jtag3.c b/src/jtag3.c
index 5e971a28..8eed8c29 100644
--- a/src/jtag3.c
+++ b/src/jtag3.c
@@ -1252,8 +1252,10 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
       }
     }
 
-    // Generate 12V UPDI pulse if user asks for it and  hardware supports it
-    if(p->flags & AVRPART_HAS_UPDI && PDATA(pgm)->use_hvupdi == true && p->hvupdi_variant == 0) {
+    // Generate 12V UPDI pulse if user asks for it and hardware supports it
+    if (p->flags & AVRPART_HAS_UPDI &&
+        PDATA(pgm)->use_hvupdi == true &&
+        p->hvupdi_variant == HV_UPDI_VARIANT_0) {
       parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE;
       if (jtag3_setparm(pgm, SCOPE_AVR, 3, PARM3_OPT_12V_UPDI_ENABLE, parm, 1) < 0)
         return -1;
@@ -1458,7 +1460,6 @@ static int jtag3_parseextparms(PROGRAMMER * pgm, LISTID extparms)
   LNODEID ln;
   const char *extended_param;
   int rv = 0;
-  avrdude_message(MSG_INFO, "id: %s, desc: %s, type: %s\n", ldata(lfirst(pgm->id)), pgm->desc, pgm->type);
 
   for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
     extended_param = ldata(ln);
diff --git a/src/libavrdude.h b/src/libavrdude.h
index 2b87ddf1..c3e89a7e 100644
--- a/src/libavrdude.h
+++ b/src/libavrdude.h
@@ -188,6 +188,10 @@ typedef struct opcode {
 #define AVRPART_IS_AT90S1200   0x1000  /* part is an AT90S1200 (needs special treatment) */
 #define AVRPART_HAS_UPDI       0x2000  /* part has UPDI i/f (AVR8X) */
 
+#define HV_UPDI_VARIANT_0      0 /* Shared UPDI/GPIO/RESET pin, HV on UPDI pin (tinyAVR0/1/2)*/
+#define HV_UPDI_VARIANT_1      1 /* Dedicated UPDI pin, no HV (megaAVR0/AVR-Dx) */
+#define HV_UPDI_VARIANT_2      2 /* Shared UPDI pin, HV on _RESET (AVR-Ex) */
+
 #define AVR_DESCLEN 64
 #define AVR_IDLEN   32
 #define AVR_FAMILYIDLEN 7

From 39008ac2c1008ca377cd605a754796ccc3cb3223 Mon Sep 17 00:00:00 2001
From: "Ruud, Jan Egil" <janegil.ruud@microchip.com>
Date: Tue, 28 Jun 2022 11:55:33 +0200
Subject: [PATCH 07/16] Add UPDI HV type to device description.

---
 src/jtag3.c         | 1 +
 src/jtag3_private.h | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/src/jtag3.c b/src/jtag3.c
index 8eed8c29..a371a6a9 100644
--- a/src/jtag3.c
+++ b/src/jtag3.c
@@ -1198,6 +1198,7 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
 
     u16_to_b2(xd.nvm_base_addr, p->nvm_base);
     u16_to_b2(xd.ocd_base_addr, p->ocd_base);
+    xd.hvupdi_variant = p->hvupdi_variant;
 
     for (ln = lfirst(p->mem); ln; ln = lnext(ln))
     {
diff --git a/src/jtag3_private.h b/src/jtag3_private.h
index 3eeb61b3..677d2289 100644
--- a/src/jtag3_private.h
+++ b/src/jtag3_private.h
@@ -400,5 +400,7 @@ struct updi_device_desc {
     unsigned char flash_page_size_msb;  // Extends flash_page_size, used in 24-bit mode
 
     unsigned char address_mode;  // 0x00 = 16-bit mode, 0x01 = 24-bit mode
+
+    unsigned char hvupdi_variant; // Indicates the target UPDI HV implementation
 };
 #endif /* JTAG3_PRIVATE_EXPORTED */

From 65763b5700c0f7dc627fece050f8c7369e47aadf Mon Sep 17 00:00:00 2001
From: "Ruud, Jan Egil" <janegil.ruud@microchip.com>
Date: Tue, 28 Jun 2022 12:21:45 +0200
Subject: [PATCH 08/16] Correct hvupdi_variant for AVR DD devices.

---
 src/avrdude.conf.in | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in
index 2fc59ecd..2e66c360 100644
--- a/src/avrdude.conf.in
+++ b/src/avrdude.conf.in
@@ -18932,6 +18932,7 @@ part parent    ".avrdx"
     id        = "avr16dd14";
     desc      = "AVR16DD14";
     signature = 0x1E 0x94 0x34;
+    hvupdi_variant = 2;
 
     memory "flash"
         size      = 0x4000;
@@ -18956,6 +18957,7 @@ part parent    ".avrdx"
     id        = "avr16dd20";
     desc      = "AVR16DD20";
     signature = 0x1E 0x94 0x33;
+    hvupdi_variant = 2;
 
     memory "flash"
         size      = 0x4000;
@@ -18980,6 +18982,7 @@ part parent    ".avrdx"
     id        = "avr16dd28";
     desc      = "AVR16DD28";
     signature = 0x1E 0x94 0x32;
+    hvupdi_variant = 2;
 
     memory "flash"
         size      = 0x4000;
@@ -19004,6 +19007,7 @@ part parent    ".avrdx"
     id        = "avr16dd32";
     desc      = "AVR16DD32";
     signature = 0x1E 0x94 0x31;
+    hvupdi_variant = 2;
 
     memory "flash"
         size      = 0x4000;
@@ -19028,6 +19032,7 @@ part parent    ".avrdx"
     id        = "avr32dd14";
     desc      = "AVR32DD14";
     signature = 0x1E 0x95 0x3B;
+    hvupdi_variant = 2;
 
     memory "flash"
         size      = 0x8000;
@@ -19052,6 +19057,7 @@ part parent    ".avrdx"
     id        = "avr32dd20";
     desc      = "AVR32DD20";
     signature = 0x1E 0x95 0x3A;
+    hvupdi_variant = 2;
 
     memory "flash"
         size      = 0x8000;
@@ -19076,6 +19082,7 @@ part parent    ".avrdx"
     id        = "avr32dd28";
     desc      = "AVR32DD28";
     signature = 0x1E 0x95 0x39;
+    hvupdi_variant = 2;
 
     memory "flash"
         size      = 0x8000;
@@ -19100,6 +19107,7 @@ part parent    ".avrdx"
     id        = "avr32dd32";
     desc      = "AVR32DD32";
     signature = 0x1E 0x95 0x38;
+    hvupdi_variant = 2;
 
     memory "flash"
         size      = 0x8000;
@@ -19124,6 +19132,7 @@ part parent    ".avrdx"
     id        = "avr64dd14";
     desc      = "AVR64DD14";
     signature = 0x1E 0x96 0x1D;
+    hvupdi_variant = 2;
 
     memory "flash"
         size      = 0x10000;
@@ -19148,6 +19157,7 @@ part parent    ".avrdx"
     id        = "avr64dd20";
     desc      = "AVR64DD20";
     signature = 0x1E 0x96 0x1C;
+    hvupdi_variant = 2;
 
     memory "flash"
         size      = 0x10000;
@@ -19172,6 +19182,7 @@ part parent    ".avrdx"
     id        = "avr64dd28";
     desc      = "AVR64DD28";
     signature = 0x1E 0x96 0x1B;
+    hvupdi_variant = 2;
 
     memory "flash"
         size      = 0x10000;
@@ -19196,6 +19207,7 @@ part parent    ".avrdx"
     id        = "avr64dd32";
     desc      = "AVR64DD32";
     signature = 0x1E 0x96 0x1A;
+    hvupdi_variant = 2;
 
     memory "flash"
         size      = 0x10000;

From 30c1b31b8d8c6572e608f379f7e6e00f6e45bf17 Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Tue, 28 Jun 2022 13:59:54 +0200
Subject: [PATCH 09/16] Send 12V pulse to HV_UPDI_VARIANT_2 targets as well

---
 src/jtag3.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/jtag3.c b/src/jtag3.c
index a371a6a9..f1cd2fc9 100644
--- a/src/jtag3.c
+++ b/src/jtag3.c
@@ -1256,7 +1256,8 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
     // Generate 12V UPDI pulse if user asks for it and hardware supports it
     if (p->flags & AVRPART_HAS_UPDI &&
         PDATA(pgm)->use_hvupdi == true &&
-        p->hvupdi_variant == HV_UPDI_VARIANT_0) {
+        (p->hvupdi_variant == HV_UPDI_VARIANT_0 ||
+        p->hvupdi_variant  == HV_UPDI_VARIANT_2)) {
       parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE;
       if (jtag3_setparm(pgm, SCOPE_AVR, 3, PARM3_OPT_12V_UPDI_ENABLE, parm, 1) < 0)
         return -1;

From 6473a6d71ab53e732babb90ed010d216d15b90c9 Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Wed, 29 Jun 2022 19:55:23 +0200
Subject: [PATCH 10/16] Add avrdude_message to verbose mode

---
 src/jtag3.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/jtag3.c b/src/jtag3.c
index f1cd2fc9..5a333991 100644
--- a/src/jtag3.c
+++ b/src/jtag3.c
@@ -1258,10 +1258,13 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
         PDATA(pgm)->use_hvupdi == true &&
         (p->hvupdi_variant == HV_UPDI_VARIANT_0 ||
         p->hvupdi_variant  == HV_UPDI_VARIANT_2)) {
+      avrdude_message(MSG_NOTICE, "%s: Sending HV pulse to %s pin\n",
+        progname, p->hvupdi_variant == HV_UPDI_VARIANT_0 ? "UPDI" : "RESET");
       parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE;
       if (jtag3_setparm(pgm, SCOPE_AVR, 3, PARM3_OPT_12V_UPDI_ENABLE, parm, 1) < 0)
         return -1;
     }
+
     u16_to_b2(xd.default_min_div1_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV1_VOLTAGE_MV);
     u16_to_b2(xd.default_min_div2_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV2_VOLTAGE_MV);
     u16_to_b2(xd.default_min_div4_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV4_VOLTAGE_MV);

From 9e5ea25b9e2d57c67decdbd524be1d4706ed124e Mon Sep 17 00:00:00 2001
From: "Ruud, Jan Egil" <janegil.ruud@microchip.com>
Date: Thu, 30 Jun 2022 16:15:24 +0200
Subject: [PATCH 11/16] Add HVUPDI_SUPPORT list for programmers.

---
 src/avrdude.conf.in | 11 +++++++++++
 src/config_gram.y   | 30 ++++++++++++++++++++++++++++++
 src/jtag3.c         | 18 ++++++++++++------
 src/lexer.l         |  1 +
 src/libavrdude.h    |  1 +
 5 files changed, 55 insertions(+), 6 deletions(-)

diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in
index 2e66c360..9d4f8dbd 100644
--- a/src/avrdude.conf.in
+++ b/src/avrdude.conf.in
@@ -40,6 +40,7 @@
 #       usbvendor = <vendorname>;                   # USB Vendor Name
 #       usbproduct = <productname>;                 # USB Product Name
 #       usbsn    = <serialno>;                      # USB Serial Number
+#       hvupdi_support = <num>, <num>, ...;         # UPDI HV Variants Support
 #
 #        To invert a bit, use = ~ <num>, the spaces are important.
 #        For a pin list all pins must be inverted.
@@ -630,6 +631,7 @@ programmer
   desc  = "SerialUPDI";
   type  = "serialupdi";
   connection_type = serial;
+  hvupdi_support = 1;
 ;
 
 programmer
@@ -1177,6 +1179,7 @@ programmer
   type  = "jtagice3_updi";
   connection_type = usb;
   usbpid = 0x2110, 0x2140;
+  hvupdi_support = 1;
 ;
 
 programmer
@@ -1209,6 +1212,7 @@ programmer
   type  = "jtagice3_updi";
   connection_type = usb;
   usbpid = 0x2111;
+  hvupdi_support = 1;
 ;
 
 programmer
@@ -1233,6 +1237,7 @@ programmer
   type  = "jtagice3_updi";
   connection_type = usb;
   usbpid = 0x2145;
+  hvupdi_support = 1;
 ;
 
 programmer
@@ -1257,6 +1262,7 @@ programmer
   type  = "jtagice3_updi";
   connection_type = usb;
   usbpid = 0x2141;
+  hvupdi_support = 1;
 ;
 
 programmer
@@ -1297,6 +1303,7 @@ programmer
   type  = "jtagice3_updi";
   connection_type = usb;
   usbpid = 0x2144;
+  hvupdi_support = 0, 1;
 ;
 
 programmer
@@ -1321,6 +1328,7 @@ programmer
   type  = "jtagice3_updi";
   connection_type = usb;
   usbpid = 0x2177, 0x2178, 0x2179;
+  hvupdi_support = 0, 1, 2;
 ;
 
 programmer
@@ -1345,6 +1353,7 @@ programmer
   type  = "jtagice3_updi";
   connection_type = usb;
   usbpid = 0x217F, 0x2180, 0x2181;
+  hvupdi_support = 1;
 ;
 
 programmer
@@ -1369,6 +1378,7 @@ programmer
   type  = "jtagice3_updi";
   connection_type = usb;
   usbpid = 0x2175;
+  hvupdi_support = 1;
 ;
 
 programmer
@@ -1737,6 +1747,7 @@ programmer
   type  = "jtagmkii_pdi";
   connection_type = serial;
   baudrate = 115200;
+  hvupdi_support = 1;
 ;
 
 #
diff --git a/src/config_gram.y b/src/config_gram.y
index 126b9b54..5db2a475 100644
--- a/src/config_gram.y
+++ b/src/config_gram.y
@@ -81,6 +81,7 @@ static int pin_name;
 %token K_DEFAULT_SERIAL
 %token K_DESC
 %token K_FAMILY_ID
+%token K_HVUPDI_SUPPORT
 %token K_HVUPDI_VARIANT
 %token K_DEVICECODE
 %token K_STK500_DEVCODE
@@ -547,6 +548,7 @@ prog_parm_usb:
       free_token($3);
     }
   }
+  K_HVUPDI_SUPPORT TKN_EQUAL hvupdi_support_list
 ;
 
 usb_pid_list:
@@ -577,6 +579,34 @@ usb_pid_list:
   }
 ;
 
+hvupdi_support_list:
+  TKN_NUMBER {
+    {
+      /* overwrite pids, so clear the existing entries */
+      ldestroy_cb(current_prog->hvupdi_support, free);
+      current_prog->hvupdi_support = lcreat(NULL, 0);
+    }
+    {
+      int *ip = malloc(sizeof(int));
+      if (ip) {
+        *ip = $1->value.number;
+        ladd(current_prog->hvupdi_support, ip);
+      }
+      free_token($1);
+    }
+  } |
+  hvupdi_support_list TKN_COMMA TKN_NUMBER {
+    {
+      int *ip = malloc(sizeof(int));
+      if (ip) {
+        *ip = $3->value.number;
+        ladd(current_prog->hvupdi_support, ip);
+      }
+      free_token($3);
+    }
+  }
+;
+
 pin_number_non_empty:
   TKN_NUMBER { if(0 != assign_pin(pin_name, $1, 0)) YYABORT;  }
   |
diff --git a/src/jtag3.c b/src/jtag3.c
index 5a333991..efb9b702 100644
--- a/src/jtag3.c
+++ b/src/jtag3.c
@@ -1253,14 +1253,20 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
       }
     }
 
-    // Generate 12V UPDI pulse if user asks for it and hardware supports it
+    // Generate UPDI high-voltage pulse if user asks for it and hardware supports it
+    LNODEID hvupdi_support;
     if (p->flags & AVRPART_HAS_UPDI &&
         PDATA(pgm)->use_hvupdi == true &&
-        (p->hvupdi_variant == HV_UPDI_VARIANT_0 ||
-        p->hvupdi_variant  == HV_UPDI_VARIANT_2)) {
-      avrdude_message(MSG_NOTICE, "%s: Sending HV pulse to %s pin\n",
-        progname, p->hvupdi_variant == HV_UPDI_VARIANT_0 ? "UPDI" : "RESET");
-      parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE;
+        p->hvupdi_variant != HV_UPDI_VARIANT_1) {
+      for (hvupdi_support = lfirst(pgm->hvupdi_support); hvupdi_support != NULL; hvupdi_support = lnext(hvupdi_support)) {
+        unsigned int sup = (unsigned int)(*(int *)(ldata(hvupdi_support)));
+        if(sup == p->hvupdi_variant) {
+          avrdude_message(MSG_NOTICE, "%s: Sending HV pulse to targets %s pin\n",
+            progname, p->hvupdi_variant == HV_UPDI_VARIANT_0 ? "UPDI" : "RESET");
+          parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE;
+          break;
+        }
+      }
       if (jtag3_setparm(pgm, SCOPE_AVR, 3, PARM3_OPT_12V_UPDI_ENABLE, parm, 1) < 0)
         return -1;
     }
diff --git a/src/lexer.l b/src/lexer.l
index dd5c081a..1693886c 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -159,6 +159,7 @@ hventerstabdelay { yylval=NULL; return K_HVENTERSTABDELAY; }
 hvleavestabdelay { yylval=NULL; return K_HVLEAVESTABDELAY; }
 hvsp_controlstack  { yylval=NULL; return K_HVSP_CONTROLSTACK; }
 hvspcmdexedelay  { yylval=NULL; return K_HVSPCMDEXEDELAY; }
+hvupdi_support   { yylval=NULL; return K_HVUPDI_SUPPORT; }
 hvupdi_variant   { yylval=NULL; return K_HVUPDI_VARIANT; }
 id               { yylval=NULL; return K_ID; }
 idr              { yylval=NULL; return K_IDR; }
diff --git a/src/libavrdude.h b/src/libavrdude.h
index c3e89a7e..4a7a66b0 100644
--- a/src/libavrdude.h
+++ b/src/libavrdude.h
@@ -719,6 +719,7 @@ typedef struct programmer_t {
   int  lineno;                /* config file line number */
   void *cookie;		      /* for private use by the programmer */
   char flag;		      /* for private use of the programmer */
+  LISTID hvupdi_support;  /* List of UPDI HV variants the tool supports. See HV_UPDI_VARIANT_ */
 } PROGRAMMER;
 
 #ifdef __cplusplus

From 91310e6f505c1e8eba9c739ee9b0d0a93c790b03 Mon Sep 17 00:00:00 2001
From: Jan Egil Ruud <janegil.ruud@microchip.com>
Date: Thu, 7 Jul 2022 12:23:05 +0200
Subject: [PATCH 12/16] Move hvupdi_support list to a new prog_parm_updi group,
 and initialize the list.

---
 src/avrdude.conf.in |  2 +-
 src/config_gram.y   | 10 +++++++---
 src/jtag3.c         |  9 +++++++++
 src/libavrdude.h    |  2 +-
 src/pgm.c           |  1 +
 5 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in
index 9d4f8dbd..6cb314da 100644
--- a/src/avrdude.conf.in
+++ b/src/avrdude.conf.in
@@ -40,7 +40,7 @@
 #       usbvendor = <vendorname>;                   # USB Vendor Name
 #       usbproduct = <productname>;                 # USB Product Name
 #       usbsn    = <serialno>;                      # USB Serial Number
-#       hvupdi_support = <num>, <num>, ...;         # UPDI HV Variants Support
+#       hvupdi_support = <num> [, <num>, ... ] ;    # UPDI HV Variants Support
 #
 #        To invert a bit, use = ~ <num>, the spaces are important.
 #        For a pin list all pins must be inverted.
diff --git a/src/config_gram.y b/src/config_gram.y
index 5db2a475..b0a8e36e 100644
--- a/src/config_gram.y
+++ b/src/config_gram.y
@@ -477,7 +477,8 @@ prog_parm :
       current_prog->baudrate = $3->value.number;
       free_token($3);
     }
-  }
+  } |
+  prog_parm_updi
 ;
 
 prog_parm_type:
@@ -548,7 +549,6 @@ prog_parm_usb:
       free_token($3);
     }
   }
-  K_HVUPDI_SUPPORT TKN_EQUAL hvupdi_support_list
 ;
 
 usb_pid_list:
@@ -579,10 +579,14 @@ usb_pid_list:
   }
 ;
 
+prog_parm_updi:
+  K_HVUPDI_SUPPORT TKN_EQUAL hvupdi_support_list
+;
+
 hvupdi_support_list:
   TKN_NUMBER {
     {
-      /* overwrite pids, so clear the existing entries */
+      /* overwrite list entries, so clear the existing entries */
       ldestroy_cb(current_prog->hvupdi_support, free);
       current_prog->hvupdi_support = lcreat(NULL, 0);
     }
diff --git a/src/jtag3.c b/src/jtag3.c
index efb9b702..1c003a82 100644
--- a/src/jtag3.c
+++ b/src/jtag3.c
@@ -1649,6 +1649,15 @@ static int jtag3_open_updi(PROGRAMMER * pgm, char * port)
 {
   avrdude_message(MSG_NOTICE2, "%s: jtag3_open_updi()\n", progname);
 
+  LNODEID ln;
+  unsigned int hv_sup;
+  avrdude_message(MSG_NOTICE2, "%s: HV UPDI support:", progname);
+  for (ln = lfirst(pgm->hvupdi_support); ln; ln = lnext(ln)) {
+    hv_sup = (unsigned int)(*(int *)ldata(ln));
+    avrdude_message(MSG_NOTICE2, " %d", hv_sup);
+  }
+  avrdude_message(MSG_NOTICE2, "\n", progname);
+
   if (jtag3_open_common(pgm, port) < 0)
     return -1;
 
diff --git a/src/libavrdude.h b/src/libavrdude.h
index 4a7a66b0..1259977f 100644
--- a/src/libavrdude.h
+++ b/src/libavrdude.h
@@ -206,7 +206,7 @@ typedef struct avrpart {
   char          desc[AVR_DESCLEN];  /* long part name */
   char          id[AVR_IDLEN];      /* short part name */
   char          family_id[AVR_FAMILYIDLEN+1]; /* family id in the SIB (avr8x) */
-  int           hvupdi_variant;     /* 12V pulse on UPDI pin, no pin or RESET pin */
+  int           hvupdi_variant;     /* HV pulse on UPDI pin, no pin or RESET pin */
   int           stk500_devcode;     /* stk500 device code */
   int           avr910_devcode;     /* avr910 device code */
   int           chip_erase_delay;   /* microseconds */
diff --git a/src/pgm.c b/src/pgm.c
index 851ac5a8..4580cbbd 100644
--- a/src/pgm.c
+++ b/src/pgm.c
@@ -83,6 +83,7 @@ PROGRAMMER * pgm_new(void)
   pgm->lineno = 0;
   pgm->baudrate = 0;
   pgm->initpgm = NULL;
+  pgm->hvupdi_support = lcreat(NULL, 0);
 
   for (i=0; i<N_PINS; i++) {
     pgm->pinno[i] = 0;

From 173b4f9d0ac90924764d8c3174ad3e3ab934a0cd Mon Sep 17 00:00:00 2001
From: Jan Egil Ruud <janegil.ruud@microchip.com>
Date: Mon, 11 Jul 2022 14:07:45 +0200
Subject: [PATCH 13/16] Clean up and simplify hvupdi handling, and set default
 hvupdi_variant to -1.

---
 src/avrpart.c |  1 +
 src/jtag3.c   | 13 ++++---------
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/src/avrpart.c b/src/avrpart.c
index dc6def44..5a192e2d 100644
--- a/src/avrpart.c
+++ b/src/avrpart.c
@@ -573,6 +573,7 @@ AVRPART * avr_new_part(void)
   memset(p->signature, 0xFF, 3);
   p->ctl_stack_type = CTL_STACK_NONE;
   p->ocdrev = -1;
+  p->hvupdi_variant = -1;
 
   p->mem = lcreat(NULL, 0);
   p->mem_alias = lcreat(NULL, 0);
diff --git a/src/jtag3.c b/src/jtag3.c
index 1c003a82..ae5d1912 100644
--- a/src/jtag3.c
+++ b/src/jtag3.c
@@ -1259,8 +1259,7 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
         PDATA(pgm)->use_hvupdi == true &&
         p->hvupdi_variant != HV_UPDI_VARIANT_1) {
       for (hvupdi_support = lfirst(pgm->hvupdi_support); hvupdi_support != NULL; hvupdi_support = lnext(hvupdi_support)) {
-        unsigned int sup = (unsigned int)(*(int *)(ldata(hvupdi_support)));
-        if(sup == p->hvupdi_variant) {
+        if(*(int *) ldata(hvupdi_support) == p->hvupdi_variant) {
           avrdude_message(MSG_NOTICE, "%s: Sending HV pulse to targets %s pin\n",
             progname, p->hvupdi_variant == HV_UPDI_VARIANT_0 ? "UPDI" : "RESET");
           parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE;
@@ -1496,8 +1495,7 @@ static int jtag3_parseextparms(PROGRAMMER * pgm, LISTID extparms)
       continue;
     }
 
-    else if ((matches(extended_param, "hvupdi") || matches(extended_param, "hvupdi=1")) &&
-      (matches(ldata(lfirst(pgm->id)), "pickit4_updi") || matches(ldata(lfirst(pgm->id)), "powerdebugger_updi"))) {
+    else if (matches(extended_param, "hvupdi")) {
       PDATA(pgm)->use_hvupdi = true;
       continue;
     }
@@ -1650,12 +1648,9 @@ static int jtag3_open_updi(PROGRAMMER * pgm, char * port)
   avrdude_message(MSG_NOTICE2, "%s: jtag3_open_updi()\n", progname);
 
   LNODEID ln;
-  unsigned int hv_sup;
   avrdude_message(MSG_NOTICE2, "%s: HV UPDI support:", progname);
-  for (ln = lfirst(pgm->hvupdi_support); ln; ln = lnext(ln)) {
-    hv_sup = (unsigned int)(*(int *)ldata(ln));
-    avrdude_message(MSG_NOTICE2, " %d", hv_sup);
-  }
+  for (ln = lfirst(pgm->hvupdi_support); ln; ln = lnext(ln))
+    avrdude_message(MSG_NOTICE2, " %d", *(int *) ldata(ln));
   avrdude_message(MSG_NOTICE2, "\n", progname);
 
   if (jtag3_open_common(pgm, port) < 0)

From 2478c1874591693ccff4c689e39238687bc2bc93 Mon Sep 17 00:00:00 2001
From: Jan Egil Ruud <janegil.ruud@microchip.com>
Date: Mon, 11 Jul 2022 15:26:41 +0200
Subject: [PATCH 14/16] Do not let the hvupdi extended option take any
 configuration values. The hvupdi type is implied by the part configuration.

---
 src/jtag3.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/jtag3.c b/src/jtag3.c
index ae5d1912..f07e0319 100644
--- a/src/jtag3.c
+++ b/src/jtag3.c
@@ -1495,7 +1495,7 @@ static int jtag3_parseextparms(PROGRAMMER * pgm, LISTID extparms)
       continue;
     }
 
-    else if (matches(extended_param, "hvupdi")) {
+    else if (strcmp(extended_param, "hvupdi") == 0) {
       PDATA(pgm)->use_hvupdi = true;
       continue;
     }

From 69ee5da6130471d62bf170735b7f82cc93128107 Mon Sep 17 00:00:00 2001
From: Jan Egil Ruud <janegil.ruud@microchip.com>
Date: Tue, 12 Jul 2022 12:01:17 +0200
Subject: [PATCH 15/16] Improve error handling for devices that does not
 support HVUPDI.

---
 src/jtag3.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/src/jtag3.c b/src/jtag3.c
index f07e0319..becfd8a1 100644
--- a/src/jtag3.c
+++ b/src/jtag3.c
@@ -1254,17 +1254,21 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
     }
 
     // Generate UPDI high-voltage pulse if user asks for it and hardware supports it
-    LNODEID hvupdi_support;
+    LNODEID support;
     if (p->flags & AVRPART_HAS_UPDI &&
         PDATA(pgm)->use_hvupdi == true &&
         p->hvupdi_variant != HV_UPDI_VARIANT_1) {
-      for (hvupdi_support = lfirst(pgm->hvupdi_support); hvupdi_support != NULL; hvupdi_support = lnext(hvupdi_support)) {
-        if(*(int *) ldata(hvupdi_support) == p->hvupdi_variant) {
+      parm[0] = PARM3_UPDI_HV_NONE;
+      for (support = lfirst(pgm->hvupdi_support); support != NULL; support = lnext(support)) {
+        if(*(int *) ldata(support) == p->hvupdi_variant) {
           avrdude_message(MSG_NOTICE, "%s: Sending HV pulse to targets %s pin\n",
             progname, p->hvupdi_variant == HV_UPDI_VARIANT_0 ? "UPDI" : "RESET");
           parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE;
           break;
         }
+        if (parm[0] == PARM3_UPDI_HV_NONE)
+          avrdude_message(MSG_INFO, "%s: %s does not support sending HV pulse to target %s\n",
+            progname, pgm->desc, p->desc);
       }
       if (jtag3_setparm(pgm, SCOPE_AVR, 3, PARM3_OPT_12V_UPDI_ENABLE, parm, 1) < 0)
         return -1;
@@ -1495,7 +1499,8 @@ static int jtag3_parseextparms(PROGRAMMER * pgm, LISTID extparms)
       continue;
     }
 
-    else if (strcmp(extended_param, "hvupdi") == 0) {
+    else if ((strcmp(extended_param, "hvupdi") == 0) &&
+             (lsize(pgm->hvupdi_support) > 1)) {
       PDATA(pgm)->use_hvupdi = true;
       continue;
     }

From dde35018eb7a3bf26af3f64d5549cb8ceb66583d Mon Sep 17 00:00:00 2001
From: MCUdude <hansibull@gmail.com>
Date: Wed, 13 Jul 2022 23:49:14 +0200
Subject: [PATCH 16/16] Exit if programmer can't send HV pulse to target

---
 src/jtag3.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/jtag3.c b/src/jtag3.c
index becfd8a1..5ce6769c 100644
--- a/src/jtag3.c
+++ b/src/jtag3.c
@@ -1266,9 +1266,11 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
           parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE;
           break;
         }
-        if (parm[0] == PARM3_UPDI_HV_NONE)
+        if (parm[0] == PARM3_UPDI_HV_NONE) {
           avrdude_message(MSG_INFO, "%s: %s does not support sending HV pulse to target %s\n",
             progname, pgm->desc, p->desc);
+          return -1;
+        }
       }
       if (jtag3_setparm(pgm, SCOPE_AVR, 3, PARM3_OPT_12V_UPDI_ENABLE, parm, 1) < 0)
         return -1;