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 1/2] 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 2/2] 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;