Index: avrdude.conf.in
===================================================================
--- avrdude.conf.in	(revision 1425)
+++ avrdude.conf.in	(working copy)
@@ -1222,6 +1222,15 @@
 ;
 
 programmer
+  id    = "atmelice_avr32";
+  desc  = "Atmel-ICE (ARM/AVR) in ISP mode";
+  type  = "jtagice3_avr32";
+  connection_type = usb;
+  usbpid = 0x2141;
+;
+
+
+programmer
   id    = "pavr";
   desc  = "Jason Kyle's pAVR Serial Programmer";
   type  = "avr910";
Index: jtag3.c
===================================================================
--- jtag3.c	(revision 1425)
+++ jtag3.c	(working copy)
@@ -70,6 +70,9 @@
   /* Start address of Xmega boot area */
   unsigned long boot_start;
 
+  /* AVR32 flashc address */
+  unsigned long flashc_start;
+
   /* Function to set the appropriate clock parameter */
   int (*set_sck)(PROGRAMMER *, unsigned char *);
 };
@@ -85,6 +88,7 @@
 #define PGM_FL_IS_JTAG          (0x0004)
 #define PGM_FL_IS_EDBG          (0x0008)
 #define PGM_FL_IS_UPDI          (0x0010)
+#define PGM_FL_IS_AVR32         (0x0020)
 
 static int jtag3_open(PROGRAMMER * pgm, char * port);
 static int jtag3_edbg_prepare(PROGRAMMER * pgm);
@@ -92,6 +96,10 @@
 static int jtag3_edbg_send(PROGRAMMER * pgm, unsigned char * data, size_t len);
 static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg);
 
+static int jtag3_avr32_busy(PROGRAMMER * pgm);
+static int jtag3_avr32_write_register(PROGRAMMER * pgm, Avr32SABAddressMap, unsigned int, unsigned int);
+static int jtag3_avr32_read_register(PROGRAMMER * pgm, Avr32SABAddressMap, unsigned int, unsigned int *);
+
 static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p);
 static int jtag3_chip_erase(PROGRAMMER * pgm, AVRPART * p);
 static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
@@ -215,6 +223,10 @@
       avrdude_message(MSG_INFO, "[AVR] ");
       break;
 
+    case SCOPE_AVR32:
+      avrdude_message(MSG_INFO, "[AVR32] ");
+      break;
+
     default:
       avrdude_message(MSG_INFO, "[scope 0x%02x] ", data[0]);
       break;
@@ -231,6 +243,65 @@
       {
 	char reason[50];
 	sprintf(reason, "0x%02x", data[3]);
+        
+        if (data[0]==SCOPE_AVR32)
+        {
+            char *str=0;
+            switch (data[3])
+            {
+              case AVR32_FAILURE_NACK: str="NACK received from target"; break;
+              case AVR32_FAILURE_LENGTH: str="Incorrect packet length"; break;
+              case AVR32_FAILURE_RECEIVE_TIMEOUT: str="Receive function timeout"; break;
+              case AVR32_FAILURE_RECEIVE_SYNC: str="Receive did not sync"; break;
+              case AVR32_FAILURE_RECEIVE_LENGTH: str="Incorrect packet length"; break;
+              case AVR32_FAILURE_TRANSMIT_OVERFLOW: str="Transmit buffer overflow"; break;
+              case AVR32_FAILURE_INVALID_MEMTYPE: str="Invalid memtype given"; break;
+              case AVR32_FAILURE_WRITE_ERROR: str="A write error occurred"; break;
+              case AVR32_FAILURE_WRITE_BUSY: str="Busy signal received"; break;
+              case AVR32_FAILURE_READ_SHORT: str="Short-packet received"; break;
+              case AVR32_FAILURE_ERASE_TIMEOUT: str="Erase command timeout"; break;
+              case AVR32_FAILURE_FLASHREADY_TIMEOUT: str="Flash controller busy"; break;
+              case AVR32_FAILURE_ILLEGAL_STATE: str="Illegal state specified"; break;
+              case AVR32_FAILURE_NOT_SUPPORTED: str="Feature not supported"; break;
+              case AVR32_FAILURE_PROGE: str="Programming error"; break;
+              case AVR32_FAILURE_LOCKE: str="Lock error"; break;
+              case AVR32_FAILURE_STEP_TIMEOUT: str="Single stepping timeout"; break;
+              case AVR32_FAILURE_READ_BUSY: str="Busy bit was set"; break;
+              case AVR32_FAILURE_READ_ERROR: str="Error bit was set"; break;
+              case AVR32_FAILURE_HARDWARE_ERROR: str="aWire hardware init error"; break;
+              case AVR32_FAILURE_NO_CONTACT: str="No response from aWire"; break;
+              case AVR32_FAILURE_NO_TARGET_POWER: str="No target power"; break;
+              case AVR32_FAILURE_NOT_IMPLEMENTED: str="Command not implemented"; break;
+              case AVR32_FAILURE_UNSUPPORTED_HARDWARE: str="Hardware not supported"; break;
+              case AVR32_FAILURE_JTAGM_INIT_ERROR: str="JTAG master init error"; break;
+              case AVR32_FAILURE_NO_DEVICE_FOUND: str="devices == 0!"; break;
+              case AVR32_FAILURE_JTAGM_ERROR: str="JTAG master error"; break;
+              case AVR32_FAILURE_INVALID_SIZE: str="Too many or too few bytes"; break;
+              case AVR32_FAILURE_INVALID_ADDRESS: str="Bad address requested"; break;
+              case AVR32_FAILURE_AWIRE_SET_BAUD_ERROR: str="Failure setting baud"; break;
+              case AVR32_FAILURE_INVALID_DATA: str="Data invalid, discard it"; break;
+              case AVR32_FAILURE_INVALID_PHYSICAL_MODE: str="Physical mode not valid"; break;
+              case AVR32_FAILURE_INVALID_CLOCK_SPEED: str="The clock is not valid"; break;
+              case AVR32_FAILURE_AWIRE_ERROR_RESPONSE: str="Error response received"; break;
+              case AVR32_FAILURE_AWIRE_OVERFLOW: str="Overflow data RX overflow/aWire master error"; break;
+              case AVR32_FAILURE_AWIRE_CRC: str="aWire CRC error"; break;
+              case AVR32_FAILURE_AWIRE_TUNE: str="aWire TUNE error"; break;
+              case AVR32_FAILURE_JTAGM_WAS_BUSY: str="JTAG master busy"; break;
+              case AVR32_FAILURE_JTAGM_TIMEOUT: str="JTAG master timeout"; break;
+              case AVR32_FAILURE_BAD_VALUE: str="Invalid parameter value"; break;
+              case AVR32_FAILURE_ERASE_ERROR: str="Erase error"; break;
+              case AVR32_FAILURE_CONFIG_ERROR: str="Insufficient config info"; break;
+              case AVR32_FAILURE_INVALID_EMULATOR_MODE: str="Mode is not valid"; break;
+              case AVR32_FAILURE_CPU_DIRTY_TIMEOUT: str="CPU wait timeout"; break;
+              case AVR32_FAILURE_CPU_MODE: str="CPU not in debug mode"; break;
+              case AVR32_FAILURE_CPU_DEBUG_MODE_TIMEOUT: str="CPU debug mode timeout"; break;
+              case AVR32_FAILURE_AWIRE_RW_STATUS: str="Unexpected status"; break;
+              case AVR32_FAILURE_TRANSMIT_TIMEOUT: str="Data TX timeout"; break;
+              case AVR32_FAILURE_INTERNAL_RESPONSE_ERROR: str="Near disaster"; break;
+            }
+            if (str) strcpy(reason, str);
+        } else
+        {
 	switch (data[3])
 	{
 	  case RSP3_FAIL_NO_ANSWER:
@@ -265,6 +336,7 @@
 	    strcpy(reason, "debugWIRE communication failed");
 	    break;
 	}
+        }
 	avrdude_message(MSG_INFO, ", reason: %s\n", reason);
       }
       else
@@ -284,7 +356,8 @@
 	if (isprint(data[i]))
 	  putc(data[i], stderr);
 	else
-	  avrdude_message(MSG_INFO, "\\%03o", data[i]);
+          //avrdude_message(MSG_INFO, "\\%03o", data[i]);
+          avrdude_message(MSG_INFO, "\\%02x", data[i]);
       }
       putc('\n', stderr);
       break;
@@ -302,6 +375,16 @@
       }
       break;
 
+    case AVR32_RSP_ID:
+      if (data[0]==SCOPE_AVR32)
+      {
+        avrdude_message(MSG_INFO, "Device ID returned:\n");
+        for (i = 3; i < len; i++)
+          avrdude_message(MSG_INFO, "\\%02x", data[i]);
+        putc('\n', stderr);
+        break;
+      }
+    
   default:
     avrdude_message(MSG_INFO, "unknown message 0x%02x\n", data[1]);
   }
@@ -434,7 +517,7 @@
 
 static int jtag3_edbg_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
 {
-  unsigned char buf[USBDEV_MAX_XFER_3];
+  unsigned char buf[USBDEV_MAX_XFER_3], i, c;
   unsigned char status[USBDEV_MAX_XFER_3];
   int rv;
 
@@ -447,6 +530,63 @@
   avrdude_message(MSG_DEBUG, "\n%s: jtag3_edbg_send(): sending %lu bytes\n",
 	    progname, (unsigned long)len);
 
+  if (len > (((USBDEV_MAX_XFER_3-4)*16)-4))
+  {
+    avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): data too long(%lubytes), cannot send!\n",
+                    progname, ((USBDEV_MAX_XFER_3-4)*16)-4);
+    return -1;
+  }
+  
+  for (i=0, c=((len+4+(USBDEV_MAX_XFER_3-5))/(USBDEV_MAX_XFER_3-4)); i<c; i++)
+  {
+    unsigned short l;
+    
+    l=USBDEV_MAX_XFER_3-(i?4:8);
+    if (l>len) l=len;
+    
+    avrdude_message(MSG_DEBUG, "%s: jtag3_edbg_send(): packet %d of %d, length %dbytes\n",
+                    progname, i+1, c, l);
+    
+    memset(buf, 0, sizeof(buf));
+    buf[0] = EDBG_VENDOR_AVR_CMD;
+    buf[1] = ((i+1) << 4) | c;	/* first out of a total of 1 fragments */
+    buf[2] = (l+(i?0:4)) >> 8;
+    buf[3] = (l+(i?0:4)) & 0xff;
+    
+    if (!i)
+    {
+      /* this is only sent in the first fragment */
+      buf[4] = TOKEN;
+      buf[5] = 0;                   /* dummy */
+      u16_to_b2(buf + 6, PDATA(pgm)->command_sequence);
+    }
+    
+    memcpy(buf + (i?4:8), data, l);
+    data+=l;
+    len-=l;
+
+    if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0)
+    {
+      avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): failed to send command to serial port\n",
+                       progname);
+       return -1;
+    }
+    rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
+ 
+    if (rv < 0)
+     {
+      /* timeout in receive */
+      avrdude_message(MSG_NOTICE2, "%s: jtag3_edbg_send(): Timeout receiving packet\n",
+                        progname);
+      return -1;
+    }
+    if (status[0] != EDBG_VENDOR_AVR_CMD || status[1] != ((i+1==c)?0x01:0x00))
+    {
+       /* what to do in this case? */
+       avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): Unexpected response 0x%02x, 0x%02x\n",
+                       progname, status[0], status[1]);
+     }
+#if 0
   /* 4 bytes overhead for CMD, fragment #, and length info */
   int max_xfer = pgm->fd.usb.max_xfer;
   int nfragments = (len + max_xfer - 1) / max_xfer;
@@ -507,6 +647,7 @@
         }
       data += this_len;
       len -= this_len;
+#endif
     }
 
   return 0;
@@ -625,6 +766,147 @@
 }
 
 
+int jtag3_avr32_busy(PROGRAMMER * pgm)
+{
+  unsigned int count;
+  
+  /* wait until flash controller is ready */
+  count=3;
+  do
+  {
+    int status;
+    unsigned int value;
+    
+    status=jtag3_avr32_read_register(pgm, AVR32_SAB_HSB, PDATA(pgm)->flashc_start + 0x08, &value);
+    
+    if (status>=0)
+    {
+      if (value&4) avrdude_message(MSG_INFO, "%s: failed operation on locked region\n", progname);
+      if (value&8) avrdude_message(MSG_INFO, "%s: pragram error, invalid command/bad keyword\n", progname);
+      if (value&1) count--;
+    }
+  } while (count); //count++<2 || !(value&1));
+  
+  if (count) avrdude_message(MSG_INFO, "%s: failed to wait\n", progname);
+  
+  return count?-1:0;
+}
+
+
+int jtag3_avr32_write_register(PROGRAMMER * pgm, Avr32SABAddressMap region, unsigned int addr, unsigned int data)
+{
+  unsigned char i, buf[32], size, *resp, msg[64];
+  int rv, len;
+  
+  rv=-1;
+  size=0;
+  
+  avrdude_message(MSG_DEBUG, "%s: %s: register:0x%08x = 0x%08x\n",
+                  progname, __func__, addr, data);
+  
+  buf[size++] = SCOPE_AVR32;
+  buf[size++] = AVR32_CMD_WRITE;
+  buf[size++] = 0;
+  buf[size++] = AVR32_MEMTYPE_BLOCK;
+  
+  snprintf(msg, sizeof(msg), "write avr32 register %02x:0x%08x = 0x%08x", region, addr, data);
+  
+  for (i=0; i<sizeof(addr); i++)
+    buf[size++] = (addr>>(i<<3))&0xff;
+  
+  buf[size++] = region;
+  
+  for (i=0; i<sizeof(data); i++)
+    buf[size++] = sizeof(data)>>(i<<3);
+  
+  for (i=0; i<sizeof(data); i++, data>>=8)
+    buf[size++] = data&0xff;;
+  
+  len=jtag3_command(pgm, buf, size, &resp, msg);
+  if (len == 3)
+  {
+    char *str=0;
+    
+    switch (buf[len-1])
+    {
+      case AVR32_FAILURE_OK:
+        if (resp[0]==buf[0] && 
+          resp[1]==AVR32_RSP_OK && 
+          resp[2]==buf[2])
+        {
+          /* response correct */
+          rv=0;
+        }
+        break;
+      
+      default:
+          avrdude_message(MSG_INFO, "%s: %s: invalid response writing register:0x%08x, %02x\n",
+                          progname, __func__, addr, resp[len-1]);
+        break;
+      
+      case AVR32_FAILURE_NACK: str="NACK received from target"; break;
+      case AVR32_FAILURE_LENGTH: str="Incorrect packet length"; break;
+      case AVR32_FAILURE_RECEIVE_TIMEOUT: str="Receive function timeout"; break;
+      case AVR32_FAILURE_RECEIVE_SYNC: str="Receive did not sync"; break;
+      case AVR32_FAILURE_RECEIVE_LENGTH: str="Incorrect packet length"; break;
+      case AVR32_FAILURE_TRANSMIT_OVERFLOW: str="Transmit buffer overflow"; break;
+      case AVR32_FAILURE_INVALID_MEMTYPE: str="Invalid memtype given"; break;
+      case AVR32_FAILURE_WRITE_ERROR: str="A write error occurred"; break;
+      case AVR32_FAILURE_WRITE_BUSY: str="Busy signal received"; break;
+      case AVR32_FAILURE_READ_SHORT: str="Short-packet received"; break;
+      case AVR32_FAILURE_ERASE_TIMEOUT: str="Erase command timeout"; break;
+      case AVR32_FAILURE_FLASHREADY_TIMEOUT: str="Flash controller busy"; break;
+      case AVR32_FAILURE_ILLEGAL_STATE: str="Illegal state specified"; break;
+      case AVR32_FAILURE_NOT_SUPPORTED: str="Feature not supported"; break;
+      case AVR32_FAILURE_PROGE: str="Programming error"; break;
+      case AVR32_FAILURE_LOCKE: str="Lock error"; break;
+      case AVR32_FAILURE_STEP_TIMEOUT: str="Single stepping timeout"; break;
+      case AVR32_FAILURE_READ_BUSY: str="Busy bit was set"; break;
+      case AVR32_FAILURE_READ_ERROR: str="Error bit was set"; break;
+      case AVR32_FAILURE_HARDWARE_ERROR: str="aWire hardware init error"; break;
+      case AVR32_FAILURE_NO_CONTACT: str="No response from aWire"; break;
+      case AVR32_FAILURE_NO_TARGET_POWER: str="No target power"; break;
+      case AVR32_FAILURE_NOT_IMPLEMENTED: str="Command not implemented"; break;
+      case AVR32_FAILURE_UNSUPPORTED_HARDWARE: str="Hardware not supported"; break;
+      case AVR32_FAILURE_JTAGM_INIT_ERROR: str="JTAG master init error"; break;
+      case AVR32_FAILURE_NO_DEVICE_FOUND: str="devices == 0!"; break;
+      case AVR32_FAILURE_JTAGM_ERROR: str="JTAG master error"; break;
+      case AVR32_FAILURE_INVALID_SIZE: str="Too many or too few bytes"; break;
+      case AVR32_FAILURE_INVALID_ADDRESS: str="Bad address requested"; break;
+      case AVR32_FAILURE_AWIRE_SET_BAUD_ERROR: str="Failure setting baud"; break;
+      case AVR32_FAILURE_INVALID_DATA: str="Data invalid, discard it"; break;
+      case AVR32_FAILURE_INVALID_PHYSICAL_MODE: str="Physical mode not valid"; break;
+      case AVR32_FAILURE_INVALID_CLOCK_SPEED: str="The clock is not valid"; break;
+      case AVR32_FAILURE_AWIRE_ERROR_RESPONSE: str="Error response received"; break;
+      case AVR32_FAILURE_AWIRE_OVERFLOW: str="Overflow data RX overflow/aWire master error"; break;
+      case AVR32_FAILURE_AWIRE_CRC: str="aWire CRC error"; break;
+      case AVR32_FAILURE_AWIRE_TUNE: str="aWire TUNE error"; break;
+      case AVR32_FAILURE_JTAGM_WAS_BUSY: str="JTAG master busy"; break;
+      case AVR32_FAILURE_JTAGM_TIMEOUT: str="JTAG master timeout"; break;
+      case AVR32_FAILURE_BAD_VALUE: str="Invalid parameter value"; break;
+      case AVR32_FAILURE_ERASE_ERROR: str="Erase error"; break;
+      case AVR32_FAILURE_CONFIG_ERROR: str="Insufficient config info"; break;
+      case AVR32_FAILURE_INVALID_EMULATOR_MODE: str="Mode is not valid"; break;
+      case AVR32_FAILURE_CPU_DIRTY_TIMEOUT: str="CPU wait timeout"; break;
+      case AVR32_FAILURE_CPU_MODE: str="CPU not in debug mode"; break;
+      case AVR32_FAILURE_CPU_DEBUG_MODE_TIMEOUT: str="CPU debug mode timeout"; break;
+      case AVR32_FAILURE_AWIRE_RW_STATUS: str="Unexpected status"; break;
+      case AVR32_FAILURE_TRANSMIT_TIMEOUT: str="Data TX timeout"; break;
+      case AVR32_FAILURE_INTERNAL_RESPONSE_ERROR: str="Near disaster"; break;
+    }
+    if (str)
+      avrdude_message(MSG_INFO, "%s: %s: error writing register:0x%08x, %s\n", progname, __func__, addr, str);
+  } else
+    avrdude_message(MSG_INFO, "%s: %s: invalid response length %dbytes writing register:0x%08x\n", 
+      progname, __func__, len, addr);
+  
+  //if (len>=0) 
+  if (resp) free(resp);
+  
+  avrdude_message(MSG_DEBUG, "%s: %s: return %d\n", progname, __func__, rv);
+  return rv;
+}
+
 static int jtag3_drain(PROGRAMMER * pgm, int display)
 {
   return serial_drain(&pgm->fd, display);
@@ -640,6 +922,80 @@
  * Caller must eventually free the buffer.
  */
 static int jtag3_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
+  int rv, len, i, c, l;
+  unsigned char buf[USBDEV_MAX_XFER_3];
+  
+   avrdude_message(MSG_TRACE, "%s: jtag3_edbg_recv():\n", progname);
+  
+  //if ((buf = malloc(USBDEV_MAX_XFER_3)) == NULL) {
+  //  avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): out of memory\n",
+	//    progname);
+  //  return -1;
+  //}
+  
+  if (msg) *msg=0;
+  
+  for (i=0, c=1, len=0; i<c; i++)
+  {
+    memset(buf, 0, sizeof(buf));
+    buf[0] = EDBG_VENDOR_AVR_RSP;
+    
+    if (serial_send(&pgm->fd, buf, sizeof(buf)) != 0) {
+      avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): error sending CMSIS-DAP vendor command\n",
+                      progname);
+      return -1;
+    }
+ 
+    rv = serial_recv(&pgm->fd, buf, sizeof(buf));
+ 
+    if (rv < 0) {
+      /* timeout in receive */
+      avrdude_message(MSG_NOTICE2, "%s: jtag3_edbg_recv(): Timeout receiving packet\n",
+                        progname);
+      len=-1;
+      break;
+    }
+    
+    if (buf[0] != EDBG_VENDOR_AVR_RSP) {
+      avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected response 0x%02x, 0x%02x\n",
+                      progname, buf[0], buf[1]);
+      len=-1;
+      break;
+    }
+    
+    if ((buf[1]>>4)!=(i+1))
+    {
+      avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): fragment out of sequence got %d, expecting %d\n",
+                      progname, (buf[1]>>4), i+1);
+      len=-1;
+      break;
+    }
+    
+    /* allocate memory for large buffer once first packet is received */
+    if (msg && !*msg)
+    {
+      c=buf[1]&0x0f;
+      *msg=malloc(USBDEV_MAX_XFER_3*c);
+      memset(*msg, 0, USBDEV_MAX_XFER_3*c);
+    }
+    
+    /* copy packet buffer to larger buffer and update length */
+    l=(buf[2] << 8) | buf[3];
+    memcpy((*msg)+len, buf+4, l);
+    len += l;
+   }
+  
+  /*if (len > rv + 4) {
+    avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected length value (%d > %d)\n",
+                    progname, len, rv + 4);
+    len = rv + 4;
+  }
+  memmove(buf, buf + 4, len);*/
+  
+  if (len<0 && msg && *msg) {free(*msg); *msg=0;}
+  
+  return len;
+#if 0
   int rv;
   unsigned char *buf = NULL;
 
@@ -669,6 +1025,7 @@
   *msg = buf;
 
   return rv;
+#endif
 }
 
 static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
@@ -791,8 +1148,8 @@
     rv &= USB_RECV_LENGTH_MASK;
     r_seqno = ((*msg)[2] << 8) | (*msg)[1];
     avrdude_message(MSG_DEBUG, "%s: jtag3_recv(): "
-	      "Got message seqno %d (command_sequence == %d)\n",
-	      progname, r_seqno, PDATA(pgm)->command_sequence);
+	      "Got message seqno %d (command_sequence == %d, size == %d)\n",
+	      progname, r_seqno, PDATA(pgm)->command_sequence, rv);
     if (r_seqno == PDATA(pgm)->command_sequence) {
       if (++(PDATA(pgm)->command_sequence) == 0xffff)
 	PDATA(pgm)->command_sequence = 0;
@@ -814,16 +1171,131 @@
   }
 }
 
- int jtag3_command(PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
+int jtag3_avr32_read_register(PROGRAMMER * pgm, Avr32SABAddressMap region, unsigned int addr, unsigned int *data)
+{
+  unsigned char i, buf[32], size, *resp, msg[64];
+  int rv, len;
+  
+  rv=-1;
+  size=0;
+  
+  buf[size++] = SCOPE_AVR32;
+  buf[size++] = AVR32_CMD_READ;
+  buf[size++] = 1;
+  buf[size++] = AVR32_MEMTYPE_BLOCK;
+  
+  for (i=0; i<sizeof(addr); i++)
+    buf[size++] = (addr>>(i<<3))&0xff;
+  
+  buf[size++] = region;
+  
+  for (i=0; i<sizeof(*data); i++)
+    buf[size++] = sizeof(*data)>>(i<<3);
+  
+  snprintf(msg, sizeof(msg), "read avr32 register %02x:0x%08x", region, addr);
+  len=jtag3_command(pgm, buf, size, &resp, msg);
+  if (len >= 4)
+  {
+    char *str=0;
+    
+    switch (resp[len-1])
+    {
+      case AVR32_FAILURE_OK:
+        if (resp[0]==buf[0] && 
+          resp[1]==AVR32_RSP_DATA && 
+          resp[2]==buf[2])
+        {
+          /* response correct */
+          for (i=0, *data=0; i<sizeof(*data); i++)
+            if (data) *data|=resp[3+i]<<(i<<3);
+
+          avrdude_message(MSG_DEBUG, "%s: %s: register:0x%08x = 0x%08x\n",
+                          progname, __func__, addr, *data);
+          rv=0;
+        } else 
+          avrdude_message(MSG_INFO, "%s: %s: invalid response reading register:0x%08x, %02x %02x %02x\n",
+                          progname, __func__, addr, resp[0], resp[1], resp[2]);
+        break;
+      
+      default:
+          avrdude_message(MSG_INFO, "%s: %s: invalid response reading register:0x%08x, %02x\n",
+                          progname, __func__, addr, resp[len-1]);
+        break;
+      
+      case AVR32_FAILURE_NACK: str="NACK received from target"; break;
+      case AVR32_FAILURE_LENGTH: str="Incorrect packet length"; break;
+      case AVR32_FAILURE_RECEIVE_TIMEOUT: str="Receive function timeout"; break;
+      case AVR32_FAILURE_RECEIVE_SYNC: str="Receive did not sync"; break;
+      case AVR32_FAILURE_RECEIVE_LENGTH: str="Incorrect packet length"; break;
+      case AVR32_FAILURE_TRANSMIT_OVERFLOW: str="Transmit buffer overflow"; break;
+      case AVR32_FAILURE_INVALID_MEMTYPE: str="Invalid memtype given"; break;
+      case AVR32_FAILURE_WRITE_ERROR: str="A write error occurred"; break;
+      case AVR32_FAILURE_WRITE_BUSY: str="Busy signal received"; break;
+      case AVR32_FAILURE_READ_SHORT: str="Short-packet received"; break;
+      case AVR32_FAILURE_ERASE_TIMEOUT: str="Erase command timeout"; break;
+      case AVR32_FAILURE_FLASHREADY_TIMEOUT: str="Flash controller busy"; break;
+      case AVR32_FAILURE_ILLEGAL_STATE: str="Illegal state specified"; break;
+      case AVR32_FAILURE_NOT_SUPPORTED: str="Feature not supported"; break;
+      case AVR32_FAILURE_PROGE: str="Programming error"; break;
+      case AVR32_FAILURE_LOCKE: str="Lock error"; break;
+      case AVR32_FAILURE_STEP_TIMEOUT: str="Single stepping timeout"; break;
+      case AVR32_FAILURE_READ_BUSY: str="Busy bit was set"; break;
+      case AVR32_FAILURE_READ_ERROR: str="Error bit was set"; break;
+      case AVR32_FAILURE_HARDWARE_ERROR: str="aWire hardware init error"; break;
+      case AVR32_FAILURE_NO_CONTACT: str="No response from aWire"; break;
+      case AVR32_FAILURE_NO_TARGET_POWER: str="No target power"; break;
+      case AVR32_FAILURE_NOT_IMPLEMENTED: str="Command not implemented"; break;
+      case AVR32_FAILURE_UNSUPPORTED_HARDWARE: str="Hardware not supported"; break;
+      case AVR32_FAILURE_JTAGM_INIT_ERROR: str="JTAG master init error"; break;
+      case AVR32_FAILURE_NO_DEVICE_FOUND: str="devices == 0!"; break;
+      case AVR32_FAILURE_JTAGM_ERROR: str="JTAG master error"; break;
+      case AVR32_FAILURE_INVALID_SIZE: str="Too many or too few bytes"; break;
+      case AVR32_FAILURE_INVALID_ADDRESS: str="Bad address requested"; break;
+      case AVR32_FAILURE_AWIRE_SET_BAUD_ERROR: str="Failure setting baud"; break;
+      case AVR32_FAILURE_INVALID_DATA: str="Data invalid, discard it"; break;
+      case AVR32_FAILURE_INVALID_PHYSICAL_MODE: str="Physical mode not valid"; break;
+      case AVR32_FAILURE_INVALID_CLOCK_SPEED: str="The clock is not valid"; break;
+      case AVR32_FAILURE_AWIRE_ERROR_RESPONSE: str="Error response received"; break;
+      case AVR32_FAILURE_AWIRE_OVERFLOW: str="Overflow data RX overflow/aWire master error"; break;
+      case AVR32_FAILURE_AWIRE_CRC: str="aWire CRC error"; break;
+      case AVR32_FAILURE_AWIRE_TUNE: str="aWire TUNE error"; break;
+      case AVR32_FAILURE_JTAGM_WAS_BUSY: str="JTAG master busy"; break;
+      case AVR32_FAILURE_JTAGM_TIMEOUT: str="JTAG master timeout"; break;
+      case AVR32_FAILURE_BAD_VALUE: str="Invalid parameter value"; break;
+      case AVR32_FAILURE_ERASE_ERROR: str="Erase error"; break;
+      case AVR32_FAILURE_CONFIG_ERROR: str="Insufficient config info"; break;
+      case AVR32_FAILURE_INVALID_EMULATOR_MODE: str="Mode is not valid"; break;
+      case AVR32_FAILURE_CPU_DIRTY_TIMEOUT: str="CPU wait timeout"; break;
+      case AVR32_FAILURE_CPU_MODE: str="CPU not in debug mode"; break;
+      case AVR32_FAILURE_CPU_DEBUG_MODE_TIMEOUT: str="CPU debug mode timeout"; break;
+      case AVR32_FAILURE_AWIRE_RW_STATUS: str="Unexpected status"; break;
+      case AVR32_FAILURE_TRANSMIT_TIMEOUT: str="Data TX timeout"; break;
+      case AVR32_FAILURE_INTERNAL_RESPONSE_ERROR: str="Near disaster"; break;
+    }
+    if (str)
+      avrdude_message(MSG_INFO, "%s: %s: error reading register 0x%08x: %s\n", progname, __func__, addr, str);
+  } else
+    avrdude_message(MSG_INFO, "%s: %s: invalid length %dbytes\n", progname, __func__, len);
+  
+  //if (len>=0) 
+  if (resp) free(resp);
+  
+  avrdude_message(MSG_DEBUG, "%s: %s: return %d\n", progname, __func__, rv);
+  return rv;
+}
+
+int jtag3_command(PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
 		   unsigned char **resp, const char *descr)
 {
   int status;
   unsigned char c;
+  char *str=0;
 
-  avrdude_message(MSG_NOTICE2, "%s: Sending %s command: ",
-	    progname, descr);
+  avrdude_message(MSG_NOTICE2, "%s: Sending %s command(%d bytes): ",
+	    progname, descr, cmdlen);
   jtag3_send(pgm, cmd, cmdlen);
 
+  *resp=0;
   status = jtag3_recv(pgm, resp);
   if (status <= 0) {
     if (verbose >= 2)
@@ -835,18 +1307,96 @@
     putc('\n', stderr);
     jtag3_prmsg(pgm, *resp, status);
   } else {
-    avrdude_message(MSG_NOTICE2, "0x%02x (%d bytes msg)\n", (*resp)[1], status);
+    avrdude_message(MSG_NOTICE2, "0x%02x (%d bytes msg:", (*resp)[1], status);
+    if ((*resp)[1]==0x84 && status>3 && status<32)
+    {
+      int i;
+      
+      avrdude_message(MSG_NOTICE2, " - ");
+      for (i=0; i<status; i++) 
+        avrdude_message(MSG_NOTICE2, "%02x ", (*resp)[i]);
+    }
+    avrdude_message(MSG_NOTICE2, ")\n");
   }
 
   c = (*resp)[1];
-  if ((c & RSP3_STATUS_MASK) != RSP3_OK) {
+  if ((c & RSP3_STATUS_MASK) == RSP3_OK) {
+    
+    if (status>3 &&
+        pgm->flag&PGM_FL_IS_AVR32 && 
+        (*resp)[0]==SCOPE_AVR32 && 
+        (*resp)[2]==1)
+    {
+      switch ((*resp)[status-1])
+      {
+        case AVR32_FAILURE_OK:
+            avrdude_message(MSG_NOTICE2, "%s: AVR32 %s command ok(received %d bytes)\n",
+                progname, descr, status);
+            return status;
+        
+        case AVR32_FAILURE_NACK: str="NACK received from target"; break;
+        case AVR32_FAILURE_LENGTH: str="Incorrect packet length"; break;
+        case AVR32_FAILURE_RECEIVE_TIMEOUT: str="Receive function timeout"; break;
+        case AVR32_FAILURE_RECEIVE_SYNC: str="Receive did not sync"; break;
+        case AVR32_FAILURE_RECEIVE_LENGTH: str="Incorrect packet length"; break;
+        case AVR32_FAILURE_TRANSMIT_OVERFLOW: str="Transmit buffer overflow"; break;
+        case AVR32_FAILURE_INVALID_MEMTYPE: str="Invalid memtype given"; break;
+        case AVR32_FAILURE_WRITE_ERROR: str="A write error occurred"; break;
+        case AVR32_FAILURE_WRITE_BUSY: str="Busy signal received"; break;
+        case AVR32_FAILURE_READ_SHORT: str="Short-packet received"; break;
+        case AVR32_FAILURE_ERASE_TIMEOUT: str="Erase command timeout"; break;
+        case AVR32_FAILURE_FLASHREADY_TIMEOUT: str="Flash controller busy"; break;
+        case AVR32_FAILURE_ILLEGAL_STATE: str="Illegal state specified"; break;
+        case AVR32_FAILURE_NOT_SUPPORTED: str="Feature not supported"; break;
+        case AVR32_FAILURE_PROGE: str="Programming error"; break;
+        case AVR32_FAILURE_LOCKE: str="Lock error"; break;
+        case AVR32_FAILURE_STEP_TIMEOUT: str="Single stepping timeout"; break;
+        case AVR32_FAILURE_READ_BUSY: str="Busy bit was set"; break;
+        case AVR32_FAILURE_READ_ERROR: str="Error bit was set"; break;
+        case AVR32_FAILURE_HARDWARE_ERROR: str="aWire hardware init error"; break;
+        case AVR32_FAILURE_NO_CONTACT: str="No response from aWire"; break;
+        case AVR32_FAILURE_NO_TARGET_POWER: str="No target power"; break;
+        case AVR32_FAILURE_NOT_IMPLEMENTED: str="Command not implemented"; break;
+        case AVR32_FAILURE_UNSUPPORTED_HARDWARE: str="Hardware not supported"; break;
+        case AVR32_FAILURE_JTAGM_INIT_ERROR: str="JTAG master init error"; break;
+        case AVR32_FAILURE_NO_DEVICE_FOUND: str="devices == 0!"; break;
+        case AVR32_FAILURE_JTAGM_ERROR: str="JTAG master error"; break;
+        case AVR32_FAILURE_INVALID_SIZE: str="Too many or too few bytes"; break;
+        case AVR32_FAILURE_INVALID_ADDRESS: str="Bad address requested"; break;
+        case AVR32_FAILURE_AWIRE_SET_BAUD_ERROR: str="Failure setting baud"; break;
+        case AVR32_FAILURE_INVALID_DATA: str="Data invalid, discard it"; break;
+        case AVR32_FAILURE_INVALID_PHYSICAL_MODE: str="Physical mode not valid"; break;
+        case AVR32_FAILURE_INVALID_CLOCK_SPEED: str="The clock is not valid"; break;
+        case AVR32_FAILURE_AWIRE_ERROR_RESPONSE: str="Error response received"; break;
+        case AVR32_FAILURE_AWIRE_OVERFLOW: str="Overflow data RX overflow/aWire master error"; break;
+        case AVR32_FAILURE_AWIRE_CRC: str="aWire CRC error"; break;
+        case AVR32_FAILURE_AWIRE_TUNE: str="aWire TUNE error"; break;
+        case AVR32_FAILURE_JTAGM_WAS_BUSY: str="JTAG master busy"; break;
+        case AVR32_FAILURE_JTAGM_TIMEOUT: str="JTAG master timeout"; break;
+        case AVR32_FAILURE_BAD_VALUE: str="Invalid parameter value"; break;
+        case AVR32_FAILURE_ERASE_ERROR: str="Erase error"; break;
+        case AVR32_FAILURE_CONFIG_ERROR: str="Insufficient config info"; break;
+        case AVR32_FAILURE_INVALID_EMULATOR_MODE: str="Mode is not valid"; break;
+        case AVR32_FAILURE_CPU_DIRTY_TIMEOUT: str="CPU wait timeout"; break;
+        case AVR32_FAILURE_CPU_MODE: str="CPU not in debug mode"; break;
+        case AVR32_FAILURE_CPU_DEBUG_MODE_TIMEOUT: str="CPU debug mode timeout"; break;
+        case AVR32_FAILURE_AWIRE_RW_STATUS: str="Unexpected status"; break;
+        case AVR32_FAILURE_TRANSMIT_TIMEOUT: str="Data TX timeout"; break;
+        case AVR32_FAILURE_INTERNAL_RESPONSE_ERROR: str="Near disaster"; break;
+      }
+    } else return status;
+    
+    if (str) avrdude_message(MSG_INFO, 
+      "%s: bad response to %s command: 0x%02x (%s, 0x%02x, %i)\n",
+      progname, descr, c, str, (*resp)[status-1], status);
+  } else {
     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);
+          "%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);
+          progname, descr, c);
     }
     status = (*resp)[3];
     free(*resp);
@@ -882,7 +1432,7 @@
   if (jtag3_command(pgm, buf, 3, &resp, "sign-on") < 0)
     return -1;
 
-  free(resp);
+  if (resp) free(resp);
 
   return 0;
 }
@@ -892,18 +1442,41 @@
  */
 static int jtag3_chip_erase(PROGRAMMER * pgm, AVRPART * p)
 {
-  unsigned char buf[8], *resp;
+  unsigned char buf[8], *resp, size;
 
-  buf[0] = SCOPE_AVR;
-  buf[1] = CMD3_ERASE_MEMORY;
-  buf[2] = 0;
-  buf[3] = XMEGA_ERASE_CHIP;
-  buf[4] = buf[5] = buf[6] = buf[7] = 0; /* page address */
+  size=0;
+  if (pgm->flag&PGM_FL_IS_AVR32)
+  {
+#if 0
+    return 0;
+#else
+    unsigned int value;
+    
+    do
+    {
+      if (jtag3_avr32_read_register(pgm, AVR32_SAB_HSB, PDATA(pgm)->flashc_start + 0x08, &value)<0) return -1;
+    } while (!(value&1));
 
-  if (jtag3_command(pgm, buf, 8, &resp, "chip erase") < 0)
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_ERASE;
+    buf[size++] = 0;
+#endif
+  } else
+  {
+    buf[size++] = SCOPE_AVR;
+    buf[size++] = CMD3_ERASE_MEMORY;
+    buf[size++] = 0;
+    buf[size++] = XMEGA_ERASE_CHIP;
+    buf[size++] = 0; /* page address */
+    buf[size++] = 0;
+    buf[size++] = 0;
+    buf[size++] = 0;
+  }
+  
+  if (jtag3_command(pgm, buf, size, &resp, "chip erase") < 0)
     return -1;
 
-  free(resp);
+  if (resp) free(resp);
   return 0;
 }
 
@@ -954,41 +1527,112 @@
 
 static int jtag3_program_enable(PROGRAMMER * pgm)
 {
-  unsigned char buf[3], *resp;
+  unsigned char buf[64], *resp, size;
   int status;
 
   if (PDATA(pgm)->prog_enabled)
     return 0;
 
-  buf[0] = SCOPE_AVR;
-  buf[1] = CMD3_ENTER_PROGMODE;
-  buf[2] = 0;
-
-  if ((status = jtag3_command(pgm, buf, 3, &resp, "enter progmode")) >= 0) {
-    free(resp);
-    PDATA(pgm)->prog_enabled = 1;
-
-    return 0;
+  size=0;
+  if (pgm->flag&PGM_FL_IS_AVR32)
+  {
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_SET;
+    buf[size++] = 0;
+    buf[size++] = AVR32_CTXT_SESSION;
+    buf[size++] = 0;
+    buf[size++] = 1;
+    buf[size++] = 1;
+    status = jtag3_command(pgm, buf, size, &resp, "Activate session");
+    if (resp) free(resp);
+    if (status < 0) return status;
+    
+    size=0;
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_RESET;
+    buf[size++] = 0;
+    buf[size++] = 0x07;
+    status = jtag3_command(pgm, buf, size, &resp, "CPU reset avr32");
+  } else
+  {
+    buf[size++] = SCOPE_AVR;
+    buf[size++] = CMD3_ENTER_PROGMODE;
+    buf[size++] = 0;
+    status = jtag3_command(pgm, buf, 3, &resp, "enter progmode");
   }
-
+  
+  if (resp) free(resp);
+  if (status < 0) return status;
+  
+  PDATA(pgm)->prog_enabled = 1;
+  
   return status;
 }
 
 static int jtag3_program_disable(PROGRAMMER * pgm)
 {
-  unsigned char buf[3], *resp;
+  unsigned char buf[8], *resp, size;
 
   if (!PDATA(pgm)->prog_enabled)
     return 0;
 
-  buf[0] = SCOPE_AVR;
-  buf[1] = CMD3_LEAVE_PROGMODE;
-  buf[2] = 0;
+  size=0;
+  if (pgm->flag&PGM_FL_IS_AVR32)
+  {
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_HALT;
+    buf[size++] = 0;
+    buf[size++] = 0;
+    if (jtag3_command(pgm, buf, size, &resp, "un-halt") >= 0)
+      free(resp);
+    
+    /*size=0;
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_RESET;
+    buf[size++] = 0;
+    buf[size++] = AVR32_CTXT_PHYSICAL;
+    buf[size++] = AVR32_PHY_EXT_RESET;
+    buf[size++] = 1;
+    if (jtag3_command(pgm, buf, size, &resp, "Set reset") >= 0)
+      free(resp);
+    
+    size=0;
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_RESET;
+    buf[size++] = 0;
+    buf[size++] = AVR32_CTXT_PHYSICAL;
+    buf[size++] = AVR32_PHY_EXT_RESET;
+    buf[size++] = 0;
+    if (jtag3_command(pgm, buf, size, &resp, "Clear reset") >= 0)
+      free(resp);*/
+    
+    size=0;
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_RESET;
+    buf[size++] = 0;
+    buf[size++] = 0x1F;
+    if (jtag3_command(pgm, buf, size, &resp, "Full reset avr32") >= 0)
+      if (resp) free(resp);
+    
+    size=0;
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_RESET;
+    buf[size++] = 0;
+    buf[size++] = 0x00;
+    //if (jtag3_command(pgm, buf, size, &resp, "CPU reset avr32") >= 0)
+    //  free(resp);
 
-  if (jtag3_command(pgm, buf, 3, &resp, "leave progmode") < 0)
+  } else
+  {
+    buf[size++] = SCOPE_AVR;
+    buf[size++] = CMD3_LEAVE_PROGMODE;
+    buf[size++] = 0;
+  }
+
+  if (jtag3_command(pgm, buf, size, &resp, "leave progmode") < 0)
     return -1;
 
-  free(resp);
+  if (resp) free(resp);
 
   PDATA(pgm)->prog_enabled = 0;
 
@@ -1018,7 +1662,7 @@
 {
   unsigned char conn = 0, parm[4];
   const char *ifname;
-  unsigned char cmd[4], *resp;
+  unsigned char cmd[32], *resp;
   int status;
 
   /*
@@ -1061,7 +1705,7 @@
     if (p->flags & AVRPART_HAS_UPDI)
       conn = PARM3_CONN_UPDI;
   } else {
-    ifname = "JTAG";
+    ifname = (pgm->flag & PGM_FL_IS_AVR32)?"JTAGavr32":"JTAG";
     if (p->flags & AVRPART_HAS_JTAG)
       conn = PARM3_CONN_JTAG;
   }
@@ -1273,16 +1917,104 @@
   }
 
   int use_ext_reset;
+	unsigned char size;
+  
+  if (pgm->flag&PGM_FL_IS_AVR32)
+  {
+    //unsigned int speed=7500;
+    unsigned int speed=4000;
+    
+    size=0;
+    cmd[size++] = SCOPE_AVR32;
+    cmd[size++] = AVR32_CMD_SET;
+    cmd[size++] = 0;
+    cmd[size++] = AVR32_CTXT_PHYSICAL;
+    cmd[size++] = AVR32_PHY_JTAG_CLOCK;
+    cmd[size++] = 2;
+    cmd[size++] = speed&0xff;
+    cmd[size++] = (speed>>8)&0xff;
+    //cmd[size++] = (speed>>16)&0xff;
+    //cmd[size++] = (speed>>24)&0xff;
+    if (jtag3_command(pgm, cmd, size, &resp, "Set avr32 JTAG clock") >= 0)
+      if (resp) free(resp);
+    
+    size=0;
+    cmd[size++] = SCOPE_AVR32;
+    cmd[size++] = AVR32_CMD_SET;
+    cmd[size++] = 0;
+    cmd[size++] = AVR32_CTXT_PHYSICAL;
+    cmd[size++] = AVR32_PHY_DAISY;
+    cmd[size++] = 4;
+    cmd[size++] = 0;
+    cmd[size++] = 0;
+    cmd[size++] = 0;
+    cmd[size++] = 0;
+    if (jtag3_command(pgm, cmd, size, &resp, "Clear avr32 JTAG daisy chain") >= 0)
+      if (resp) free(resp);
+    
+    size=0;
+    cmd[size++] = SCOPE_AVR32;
+    cmd[size++] = AVR32_CMD_SET;
+    cmd[size++] = 0;
+    cmd[size++] = AVR32_CTXT_PHYSICAL;
+    cmd[size++] = AVR32_PHY_PHYSICAL;
+    cmd[size++] = 1;
+    cmd[size++] = AVR32_PHYSICAL_INTERFACE_JTAG;
+    if (jtag3_command(pgm, cmd, size, &resp, "Set avr32 interface to JTAG") >= 0)
+      if (resp) free(resp);
+    
+    size=0;
+    cmd[size++] = SCOPE_AVR32;
+    cmd[size++] = AVR32_CMD_SET;
+    cmd[size++] = 0;
+    cmd[size++] = AVR32_CTXT_DEVICE;
+    cmd[size++] = 0;
+    cmd[size++] = 0x14;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x14;
+    cmd[size++] = 0xfe;
+    cmd[size++] = 0xff;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x02;
+    cmd[size++] = 0x01;
+    cmd[size++] = 0x01;
+    cmd[size++] = 0x05;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x04;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    if (jtag3_command(pgm, cmd, size, &resp, "Set avr32 device context") >= 0)
+      if (resp) free(resp);
+//     13 01 00 82 00 14 00 00 00 14 FE FF 00 02 01 01 05 00 04 00
+  }
 
   for (use_ext_reset = 0; use_ext_reset <= 1; use_ext_reset++) {
-    cmd[0] = SCOPE_AVR;
-    cmd[1] = CMD3_SIGN_ON;
-    cmd[2] = 0;
-    cmd[3] = use_ext_reset;			/* external reset */
+    size=0;
+    if (pgm->flag&PGM_FL_IS_AVR32)
+    {
+      cmd[size++] = SCOPE_AVR32;
+      cmd[size++] = AVR32_CMD_ACTIVATE_PHYSICAL;
+    } else
+    {
+      cmd[size++] = SCOPE_AVR;
+      cmd[size++] = CMD3_SIGN_ON;
+    }
+    cmd[size++] = 0;
+    cmd[size++] = use_ext_reset;			/* external reset */
 
-    if ((status = jtag3_command(pgm, cmd, 4, &resp, "AVR sign-on")) >= 0)
+
+    if ((status = jtag3_command(pgm, cmd, size, &resp, "AVR sign-on")) >= 0)
+    {
+      //if (resp) free(resp);
       break;
-
+    }
     avrdude_message(MSG_INFO, "%s: retrying with external reset applied\n",
 		    progname);
   }
@@ -1308,14 +2040,147 @@
     if (p->flags & AVRPART_HAS_UPDI) {
       /* Partial Family_ID has been returned */
       avrdude_message(MSG_NOTICE, "%s: Partial Family_ID returned: \"%c%c%c%c\"\n",
-	      progname, resp[3], resp[4], resp[5], resp[6]);
-    }
-    else
+        progname, resp[3], resp[4], resp[5], resp[6]);
+    } else if (pgm->flag & PGM_FL_IS_AVR32) {
+      unsigned int value;
+      
+      // on the AVR32 use the JTAG ID to determine the FLASHC module address
+      if (((resp[3] | (resp[4]<<8))&0x0fff)>>1 == 0x01f) // identifies ATMEL
+      {
+        // check 16bit part number and assign address location
+        switch (((unsigned long)(resp[4] | (resp[5]<<8) | (resp[6]<<16))>>4)&0xFFFF)
+        {
+          // assume 0xfffe1400 address, there doesn't seem to be a pattern to
+          // the part numbering, it might be worth adding the address to the
+          // avrdude.conf processor config as a part argument
+          default:
+          
+          // a0 a1 a3 a4 b0 b1
+          // d3 d4 - flashcdw
+          case 0x1EDC: // AT32UC3A0512
+          case 0x1EDF: // AT32UC3A0256
+          case 0x1EE2: // AT32UC3A0128
+          case 0x1EDD: // AT32UC3A1512
+          case 0x1EE0: // AT32UC3A1256
+          case 0x1EE3: // AT32UC3A1128
+          
+          case 0x2050: // AT32UC3B0512
+          case 0x2052: // AT32UC3B1512
+          case 0x1EE4: // AT32UC3B0256
+          case 0x1EE5: // AT32UC3B1256
+          case 0x1EE6: // AT32UC3B0128
+          case 0x1EE9: // AT32UC3B1128
+          case 0x1EEA: // AT32UC3B064
+          case 0x1EEB: // AT32UC3B164
+
+          case 0x2020: // AT32UC3A3256S
+          case 0x2021: // AT32UC3A3128S
+          case 0x2022: // AT32UC3A364S
+          case 0x2026: // AT32UC3A3256
+          case 0x2027: // AT32UC3A3128
+          case 0x2028: // AT32UC3A364
+          case 0x2029: // AT32UC3A4256S
+          case 0x202a: // AT32UC3A4128S
+          case 0x202b: // AT32UC3A464S
+          case 0x202c: // AT32UC3A4256
+          case 0x202d: // AT32UC3A128
+          case 0x202e: // AT32UC3A64
+          
+          case 0x2123: // ATUC256D3
+          case 0x2120: // ATUC128D3
+          case 0x2121: // ATUC64D3
+          case 0x2133: // ATUC256D4
+          case 0x2130: // ATUC128D4
+          case 0x2131: // ATUC64D4
+            
+            PDATA(pgm)->flashc_start = 0xfffe1400;
+            break;
+          
+          
+          // c0 c1 c2
+          // l0 l1 l2 l3 l4 - flashcdw
+          case 0x2000: // AT32UC3C0512C
+          case 0x2001: // AT32UC3C0256C
+          case 0x2002: // AT32UC3C0128C
+          case 0x2003: // AT32UC3C064C
+          case 0x2004: // AT32UC3C1512C
+          case 0x2005: // AT32UC3C1256C
+          case 0x2006: // AT32UC3C1128C
+          case 0x2007: // AT32UC3C164C
+          case 0x2008: // AT32UC3C2512C
+          case 0x2009: // AT32UC3C2256C
+          case 0x200A: // AT32UC3C2128C
+          case 0x200B: // AT32UC3C264C
+          
+          case 0x21C9: // AT32UC3L0256
+          case 0x21CA: // AT32UC3L0128
+          
+          case 0x21C3: // ATUC256L3U
+          case 0x21C4: // ATUC128L3U
+          case 0x21C5: // ATUC64L3U
+          case 0x21C6: // ATUC256L4U
+          case 0x21C7: // ATUC128L4U
+          case 0x21C8: // ATUC64L4U
+          
+            PDATA(pgm)->flashc_start = 0xfffe0000;
+            break;
+        }
+      }
+      
+      free(resp);
+      
+      do
+      {
+        if (jtag3_avr32_read_register(pgm, AVR32_SAB_HSB, PDATA(pgm)->flashc_start + 0x08, &value)<0) return -1;
+      } while (!(value&1));
+      
+      cmd[size++] = SCOPE_AVR32;
+      cmd[size++] = AVR32_CMD_IS_PROTECTED;
+      cmd[size++] = 0;
+      jtag3_command(pgm, cmd, size, &resp, "Check avr32 is protected");
+      if (resp) free(resp);
+      
+      size=0;
+      cmd[size++] = SCOPE_AVR32;
+      cmd[size++] = AVR32_CMD_RESET;
+      cmd[size++] = 0;
+      cmd[size++] = 0x07;
+      jtag3_command(pgm, cmd, size, &resp, "Full reset avr32");
+      if (resp) free(resp);
+      
+      jtag3_avr32_write_register(pgm, AVR32_SAB_OCD, 0x00000008, 0x00003000);
+      
+      size=0;
+      cmd[size++] = SCOPE_AVR32;
+      cmd[size++] = AVR32_CMD_GET_ID;
+      cmd[size++] = 0;
+      jtag3_command(pgm, cmd, size, &resp, "Get ID");
+      if (resp) free(resp);
+      
+      do
+      {
+        if (jtag3_avr32_read_register(pgm, AVR32_SAB_HSB, PDATA(pgm)->flashc_start + 0x08, &value)<0) return -1;
+      } while (!(value&1));
+      
+      size=0;
+      cmd[size++] = SCOPE_AVR32;
+      cmd[size++] = AVR32_CMD_HALT;
+      cmd[size++] = 0;
+      cmd[size++] = 1;
+      jtag3_command(pgm, cmd, size, &resp, "Halt avr32");
+      
+      do
+      {
+        if (jtag3_avr32_read_register(pgm, AVR32_SAB_HSB, PDATA(pgm)->flashc_start + 0x08, &value)<0) return -1;
+      } while (!(value&1));
+    } else
+    {
       /* JTAG ID has been returned */
       avrdude_message(MSG_NOTICE, "%s: JTAG ID returned: 0x%02x 0x%02x 0x%02x 0x%02x\n",
-	      progname, resp[3], resp[4], resp[5], resp[6]);
+        progname, resp[3], resp[4], resp[5], resp[6]);
+    }
   }
-
+  
   free(resp);
 
   PDATA(pgm)->boot_start = ULONG_MAX;
@@ -1561,22 +2426,30 @@
 
 void jtag3_close(PROGRAMMER * pgm)
 {
-  unsigned char buf[4], *resp;
+  unsigned char buf[4], *resp, size;
 
   avrdude_message(MSG_NOTICE2, "%s: jtag3_close()\n", progname);
 
-  buf[0] = SCOPE_AVR;
-  buf[1] = CMD3_SIGN_OFF;
-  buf[2] = buf[3] = 0;
+  size=0;
+  if (pgm->flag&PGM_FL_IS_AVR32)
+  {
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_DEACTIVATE_PHYSICAL;
+  } else
+  {
+    buf[size++] = SCOPE_AVR;
+    buf[size++] = CMD3_SIGN_OFF;
+    buf[size++] = 0;
+  }
+ 
+  jtag3_command(pgm, buf, size, &resp, "AVR sign-off");
+  if (resp) free(resp);
 
-  if (jtag3_command(pgm, buf, 3, &resp, "AVR sign-off") >= 0)
-    free(resp);
-
   buf[0] = SCOPE_GENERAL;
   buf[1] = CMD3_SIGN_OFF;
 
-  if (jtag3_command(pgm, buf, 4, &resp, "sign-off") >= 0)
-    free(resp);
+  jtag3_command(pgm, buf, 4, &resp, "sign-off");
+  if (resp) free(resp);
 
   /* XplainedMini boards do not need this, and early revisions had a
    * firmware bug where they complained about it. */
@@ -1631,7 +2504,7 @@
   if (jtag3_command(pgm, cmd, 8, &resp, "page erase") < 0)
     return -1;
 
-  free(resp);
+  if (resp) free(resp);
   return 0;
 }
 
@@ -1639,7 +2512,7 @@
                                 unsigned int page_size,
                                 unsigned int addr, unsigned int n_bytes)
 {
-  unsigned int block_size;
+  unsigned int block_size, size;
   unsigned int maxaddr = addr + n_bytes;
   unsigned char *cmd;
   unsigned char *resp;
@@ -1659,18 +2532,25 @@
 
   if (page_size == 0) page_size = 256;
 
-  if ((cmd = malloc(page_size + 13)) == NULL) {
+  if ((cmd = malloc(page_size + 32)) == NULL) {
     avrdude_message(MSG_INFO, "%s: jtag3_paged_write(): Out of memory\n",
 	    progname);
     return -1;
   }
 
-  cmd[0] = SCOPE_AVR;
-  cmd[1] = CMD3_WRITE_MEMORY;
-  cmd[2] = 0;
+  size=0;
+  if (pgm->flag&PGM_FL_IS_AVR32)
+  {
+    /* wait until flash controller is ready */
+    if (jtag3_avr32_busy(pgm)<0) return -1;
+  } else
+  {
+    cmd[size++] = SCOPE_AVR;
+    cmd[size++] = CMD3_WRITE_MEMORY;
+    cmd[size++] = 0;
   if (strcmp(m->desc, "flash") == 0) {
     PDATA(pgm)->flash_pageaddr = (unsigned long)-1L;
-    cmd[3] = jtag3_memtype(pgm, p, addr);
+      cmd[size++] = jtag3_memtype(pgm, p, addr);
     if (p->flags & AVRPART_HAS_PDI)
       /* dynamically decide between flash/boot memtype */
       dynamic_memtype = 1;
@@ -1701,6 +2581,8 @@
   } else {
     cmd[3] = MTYPE_SPM;
   }
+  }
+  
   serial_recv_timeout = 100;
   for (; addr < maxaddr; addr += page_size) {
     if ((maxaddr - addr) < page_size)
@@ -1714,9 +2596,139 @@
     if (dynamic_memtype)
       cmd[3] = jtag3_memtype(pgm, p, addr);
 
-    u32_to_b4(cmd + 8, page_size);
-    u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, m, addr));
-    cmd[12] = 0;
+    
+    /* erase flash page */
+    if (pgm->flag&PGM_FL_IS_AVR32)
+    {
+      int erase,write,blank;
+      unsigned int i;
+      
+      if (jtag3_avr32_busy(pgm)<0) return -1;
+      
+      cmd[0] = SCOPE_AVR32;
+      cmd[1] = AVR32_CMD_READ;
+      cmd[2] = 1;
+      cmd[3] = AVR32_MEMTYPE_BLOCK;
+      size=4;
+      u32_to_b4(&cmd[size], jtag3_memaddr(pgm, p, m, 0x80000000|addr));
+      size+=4;
+      cmd[size++]=AVR32_SAB_HSB;
+      u32_to_b4(&cmd[size], page_size);
+      size+=4;
+      
+      erase=page_size;
+      write=page_size;
+      blank=0;
+      
+      //if (jtag3_avr32_read_register(pgm, AVR32_SAB_HSB, 0x80000000|addr, &value)<0) return -1;
+      while ((status = jtag3_command(pgm, cmd, size, &resp, "read memory")) < 0);
+      
+      
+      if (resp[0]==SCOPE_AVR32 && 
+        resp[1]==AVR32_RSP_DATA && 
+        resp[2]==cmd[2] && 
+        status==4+page_size &&
+        resp[status-1]==0x00)
+      {
+        for (i=0; i<page_size; i++)
+        {
+          unsigned char want,have,diff;
+          
+          // there is a difference
+          //ch=resp[3+i];
+          
+          // if blank counts to zero then the page is blank and does
+          // not need to be written after an erase
+          want=m->buf[addr+(i&0xfffffffc)+(3-(i&0x3))];
+          have=resp[3+i];
+          
+          if (want==0xff) blank++;
+          
+          // get the difference between what we want and what we have
+          diff=want^have;
+          
+          // match, so decrement write, otherwise check if we need to erase
+          if (!diff) write--;
+          if (!(diff&want)) erase--;
+        }
+      }
+      if (resp) free(resp);
+      
+      
+      if (write || erase)
+        avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_write(): "
+            "address:0x%08x size:%d write:%d erase:%d\n",
+            progname, addr, page_size, write, erase);
+      
+      /* clear page */
+      if (write || erase)
+      {
+        while (jtag3_avr32_write_register(pgm, AVR32_SAB_HSB, PDATA(pgm)->flashc_start + 0x04, 0xa5000002|(((addr/page_size)&0xffff)<<8))<0);
+        
+        if (jtag3_avr32_busy(pgm)<0) return -1;
+      }
+      
+      if (blank!=page_size && write)
+      {
+        /* clear page buffer */
+        while (jtag3_avr32_write_register(pgm, AVR32_SAB_HSB, PDATA(pgm)->flashc_start + 0x04, 0xa5000003)<0);
+        
+        /* wait until flash controller is ready */
+        if (jtag3_avr32_busy(pgm)<0) return -1;
+        
+        cmd[0] = SCOPE_AVR32;
+        cmd[1] = AVR32_CMD_WRITE;
+        cmd[2] = 0;
+        cmd[3] = AVR32_MEMTYPE_BLOCK;
+        size=4;
+        
+        u32_to_b4(&cmd[size], jtag3_memaddr(pgm, p, m, 0x80000000|addr));
+        size+=4;
+        cmd[size++]=AVR32_SAB_HSB;
+        u32_to_b4(&cmd[size], page_size);
+        size+=4;
+        
+        for (i=0; i<page_size; i++)
+          cmd[size++]=m->buf[addr+(i&0xfffffffc)+(3-(i&0x3))];
+        
+        avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_write(): "
+          "write %lubytes to address:0x%08x\n",
+          progname, size, addr);
+        
+        /* write block to flash page buffer */
+        while ((status = jtag3_command(pgm, cmd, size,
+            &resp, "write memory")) < 0);
+        //{
+        //  free(cmd);
+        //  serial_recv_timeout = otimeout;
+        //  return -1;
+        //}
+        if (resp) free(resp);
+        
+        /* wait until flash controller is ready */
+        if (jtag3_avr32_busy(pgm)<0) return -1;
+        
+        /* write page buffer to flash */
+        while (jtag3_avr32_write_register(pgm, AVR32_SAB_HSB, PDATA(pgm)->flashc_start + 0x04, 0xa5000001|(((addr/page_size)&0xffff)<<8))<0);
+        
+        /*{
+          avrdude_message(MSG_INFO, "%s: jtag3_paged_write(): error writing buffer to memory\n",
+            progname);
+          
+          free(cmd);
+          return -1;
+        }*/
+        
+        if (jtag3_avr32_busy(pgm)<0) return -1;
+      }
+    }
+    else
+    {
+      u32_to_b4(&cmd[size], jtag3_memaddr(pgm, p, m, addr));
+      size+=4;
+      u32_to_b4(&cmd[size], page_size);
+      size+=4;
+      cmd[size++] = 0;
 
     /*
      * The JTAG ICE will refuse to write anything but a full page, at
@@ -1725,10 +2737,10 @@
      * the existing contents instead before?  Doesn't matter much, as
      * bits cannot be written to 1 anyway.)
      */
-    memset(cmd + 13, 0xff, page_size);
-    memcpy(cmd + 13, m->buf + addr, block_size);
+      memset(cmd + size, 0xff, page_size);
+      memcpy(cmd + size, m->buf + addr, block_size);
 
-    if ((status = jtag3_command(pgm, cmd, page_size + 13,
+      if ((status = jtag3_command(pgm, cmd, page_size + size,
 				&resp, "write memory")) < 0) {
       free(cmd);
       serial_recv_timeout = otimeout;
@@ -1735,7 +2747,8 @@
       return -1;
     }
 
-    free(resp);
+      if (resp) free(resp);
+    }
   }
 
   free(cmd);
@@ -1750,7 +2763,7 @@
 {
   unsigned int block_size;
   unsigned int maxaddr = addr + n_bytes;
-  unsigned char cmd[12];
+  unsigned char cmd[16], size;
   unsigned char *resp;
   int status, dynamic_memtype = 0;
   long otimeout = serial_recv_timeout;
@@ -1768,30 +2781,43 @@
 
   page_size = m->readsize;
 
-  cmd[0] = SCOPE_AVR;
-  cmd[1] = CMD3_READ_MEMORY;
-  cmd[2] = 0;
-
-  if (strcmp(m->desc, "flash") == 0) {
-    cmd[3] = jtag3_memtype(pgm, p, addr);
-    if (p->flags & AVRPART_HAS_PDI)
-      /* dynamically decide between flash/boot memtype */
-      dynamic_memtype = 1;
-  } else if (strcmp(m->desc, "eeprom") == 0) {
-    cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE;
-    if (pgm->flag & PGM_FL_IS_DW)
-      return -1;
-  } else if ( ( strcmp(m->desc, "prodsig") == 0 ) ) {
-    cmd[3] = MTYPE_PRODSIG;
-  } else if ( ( strcmp(m->desc, "usersig") == 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 ) {
-    cmd[3] = MTYPE_FLASH;
-  } else {
-    cmd[3] = MTYPE_SPM;
+  size=0;
+ 
+  if (pgm->flag&PGM_FL_IS_AVR32)
+  {
+    cmd[size++] = SCOPE_AVR32;
+    cmd[size++] = AVR32_CMD_READ;
+    cmd[size++] = 1;
+    
+    cmd[size++] = AVR32_MEMTYPE_BLOCK;
+  } else
+  {
+    cmd[size++] = SCOPE_AVR;
+    cmd[size++] = CMD3_READ_MEMORY;
+    cmd[size++] = 0;
+    
+    if (strcmp(m->desc, "flash") == 0) {
+      cmd[size++] = jtag3_memtype(pgm, p, addr);
+      if (p->flags & AVRPART_HAS_PDI)
+        /* dynamically decide between flash/boot memtype */
+        dynamic_memtype = 1;
+    } else if (strcmp(m->desc, "eeprom") == 0) {
+      cmd[size++] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE;
+      if (pgm->flag & PGM_FL_IS_DW)
+        return -1;
+    } else if ( ( strcmp(m->desc, "prodsig") == 0 ) ) {
+      cmd[size++] = MTYPE_PRODSIG;
+    } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
+      cmd[size++] = MTYPE_USERSIG;
+    } else if ( ( strcmp(m->desc, "boot") == 0 ) ) {
+      cmd[size++] = MTYPE_BOOT_FLASH;
+    } else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) {
+      cmd[size++] = MTYPE_FLASH;
+    } else {
+      cmd[size++] = MTYPE_SPM;
+    }
   }
+  
   serial_recv_timeout = 100;
   for (; addr < maxaddr; addr += page_size) {
     if ((maxaddr - addr) < page_size)
@@ -1803,24 +2829,44 @@
 	      progname, addr, block_size);
 
     if (dynamic_memtype)
-      cmd[3] = jtag3_memtype(pgm, p, addr);
+      cmd[size-1] = jtag3_memtype(pgm, p, addr);
 
-    u32_to_b4(cmd + 8, block_size);
-    u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, m, addr));
+    if (pgm->flag&PGM_FL_IS_AVR32)
+    {
+      u32_to_b4(&cmd[size], jtag3_memaddr(pgm, p, m, 0x80000000|addr));
+      size+=4;
+      cmd[size++]=AVR32_SAB_HSB;
+      u32_to_b4(&cmd[size], block_size);
+      size+=4;
+    } else
+    {
+      u32_to_b4(&cmd[size], jtag3_memaddr(pgm, p, m, addr));
+      size+=4;
+      u32_to_b4(&cmd[size], block_size);
+      size+=4;
+    }
 
-    if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
-      return -1;
+    while ((status = jtag3_command(pgm, cmd, size, &resp, "read memory")) < 0);
+      //return -1;
 
     if (resp[1] != RSP3_DATA ||
 	status < block_size + 4) {
-      avrdude_message(MSG_INFO, "%s: wrong/short reply to read memory command\n",
-	      progname);
+      avrdude_message(MSG_INFO, "%s: wrong/short reply to read memory command (read %dbytes, expected %dbytes)\n",
+	      progname, status, block_size+4);
       serial_recv_timeout = otimeout;
-      free(resp);
+      if (resp) free(resp);
       return -1;
     }
+    if (pgm->flag&PGM_FL_IS_AVR32)
+    {
+      unsigned int i;
+      for (i=0; i<status - 4; i++)
+        m->buf[addr+i]=resp[3+(i&0xfffffffc)+(3-(i&3))];
+    } else
+    {
     memcpy(m->buf + addr, resp + 3, status - 4);
-    free(resp);
+    }
+    if (resp) free(resp);
   }
   serial_recv_timeout = otimeout;
 
@@ -1919,7 +2965,7 @@
 
     if (addr == 0) {
       if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
-	return status;
+        return status;
 
       signature_cache[0] = resp[4];
       signature_cache[1] = resp[5];
@@ -2098,7 +3144,7 @@
   if ((status = jtag3_command(pgm, cmd, 14, &resp, "write memory")) < 0)
     return status;
 
-  free(resp);
+  if (resp) free(resp);
 
   return 0;
 }
@@ -2162,13 +3208,13 @@
     avrdude_message(MSG_INFO, "%s: jtag3_getparm(): "
                     "bad response to %s\n",
                     progname, descr);
-    free(resp);
+    if (resp) free(resp);
     return -1;
   }
 
   status -= 3;
   memcpy(value, resp + 3, (length < status? length: status));
-  free(resp);
+  if (resp) free(resp);
 
   return 0;
 }
@@ -2208,7 +3254,7 @@
 
   free(buf);
   if (status > 0)
-    free(resp);
+    if (resp) free(resp);
 
   return status;
 }
@@ -2264,7 +3310,7 @@
   if (c != RSP3_INFO) {
     avrdude_message(MSG_INFO, "%s: jtag3_display(): response is not RSP3_INFO\n",
                     progname);
-    free(resp);
+    if (resp) free(resp);
     return;
   }
   memmove(resp, resp + 3, status - 3);
@@ -2275,7 +3321,7 @@
 	  parms[1], parms[2],
 	  (parms[3] | (parms[4] << 8)));
   avrdude_message(MSG_INFO, "%sSerial number   : %s\n", p, resp);
-  free(resp);
+  if (resp) free(resp);
 
   jtag3_print_parms1(pgm, p);
 }
@@ -2497,3 +3543,37 @@
   pgm->read_sib       = jtag3_read_sib;
 }
 
+
+const char jtag3_avr32_desc[] = "Atmel JTAGICE3 in AVR32 mode";
+
+void jtag3_avr32_initpgm(PROGRAMMER * pgm)
+{
+  strcpy(pgm->type, "JTAGICE3_AVR32");
+
+  /*
+   * 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;
+  pgm->close          = jtag3_close;
+  pgm->read_byte      = 0;
+  pgm->write_byte     = 0;
+
+  /*
+   * 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->setup          = jtag3_setup;
+  pgm->teardown       = jtag3_teardown;
+  pgm->page_size      = 256;
+  pgm->flag           = PGM_FL_IS_AVR32;
+}
+
Index: jtag3.h
===================================================================
--- jtag3.h	(revision 1425)
+++ jtag3.h	(working copy)
@@ -42,10 +42,12 @@
 extern const char jtag3_dw_desc[];
 extern const char jtag3_pdi_desc[];
 extern const char jtag3_updi_desc[];
+extern const char jtag3_avr32_desc[];
 void jtag3_initpgm (PROGRAMMER * pgm);
 void jtag3_dw_initpgm (PROGRAMMER * pgm);
 void jtag3_pdi_initpgm (PROGRAMMER * pgm);
 void jtag3_updi_initpgm (PROGRAMMER * pgm);
+void jtag3_avr32_initpgm (PROGRAMMER * pgm);
 
 /*
  * These functions are referenced from stk500v2.c for JTAGICE3 in
Index: jtag3_private.h
===================================================================
--- jtag3_private.h	(revision 1425)
+++ jtag3_private.h	(working copy)
@@ -96,6 +96,9 @@
 #define SCOPE_GENERAL              0x01
 #define SCOPE_AVR_ISP              0x11
 #define SCOPE_AVR                  0x12
+#define SCOPE_AVR32                0x13
+#define SCOPE_TPI                  0x14
+#define SCOPE_EDBG                 0x20
 
 /* Info scope */
 #define CMD3_GET_INFO              0x00
@@ -347,3 +350,292 @@
     unsigned char ocd_base_addr[2];
 };
 #endif /* JTAG3_PRIVATE_EXPORTED */
+
+
+
+/* avr32 programming interface, this overlays edbg interface */
+enum Avr32GenericCommands {
+    AVR32_CMD_QUERY                 = 0x00, //! Capability discovery 
+    AVR32_CMD_SET                   = 0x01, //! Set parameters
+    AVR32_CMD_GET                   = 0x02, //! Get parameters
+    AVR32_CMD_ACTIVATE_PHYSICAL     = 0x03, //! Connect physically
+    AVR32_CMD_DEACTIVATE_PHYSICAL   = 0x04, //! Disconnect physically
+    AVR32_CMD_GET_ID                = 0x10, //! Read the ID
+    AVR32_CMD_ERASE                 = 0x11, //! Erase the device
+    AVR32_CMD_HALT                  = 0x12, //! Stop or start execution
+    AVR32_CMD_RESET                 = 0x13, //! Apply or release reset
+    AVR32_CMD_STEP                  = 0x14, //! Single step
+    AVR32_CMD_READ                  = 0x15, //! Read memory
+    AVR32_CMD_WRITE                 = 0x16, //! Write memory
+    AVR32_CMD_TAP                   = 0x17, //! Low-level JTAG commands
+    AVR32_CMD_IS_PROTECTED          = 0x18, //! Check protected bit
+    AVR32_CMD_ERASE_SECTION         = 0x19  //! Partial erase
+};
+
+enum Avr32GenericResponses {
+    AVR32_RSP_FAILED                = 0xA0, //! Execution failed
+    AVR32_RSP_OK                    = 0x80, //! All OK
+    AVR32_RSP_LIST                  = 0x81, //! List of items returned
+    AVR32_RSP_ID                    = 0x82, //! ID value returned
+    AVR32_RSP_PC                    = 0x83, //! PC value returned
+    AVR32_RSP_DATA                  = 0x84  //! Data returned
+};
+
+enum Avr32GenericQueryContexts {
+    AVR32_QUERY_COMMANDS             = 0x00, //! Supported command list
+    AVR32_QUERY_CONFIGURATION        = 0x05, //! Supported configuration list
+    AVR32_QUERY_READ_MEMTYPES        = 0x06, //! Supported read memtypes list
+    AVR32_QUERY_WRITE_MEMTYPES       = 0x07, //! Supported write memtypes list
+    AVR32_QUERY_COMMAND_VERSIONS     = 0x08  //! Version map of command list
+};
+ 
+enum Avr32GenericSetGetContexts {
+    AVR32_CTXT_USB                  = 0x03, //! Transport-related settings
+    AVR32_CTXT_SESSION              = 0x04, //! Session-related settings
+    AVR32_CTXT_PHYSICAL             = 0x80, //! Physical interface related
+    AVR32_CTXT_DEVICE                = 0x82, //! Device specific settings
+};
+
+enum Avr32GenericSessionContextParameters {
+    AVR32_SESS_RUN_LED              = 0x00, //! Control the LED
+};
+
+enum Avr32GenericUsbContextParameters {
+    AVR32_USB_MAX_READ              = 0x00, //! Read payload size
+    AVR32_USB_MAX_WRITE             = 0x01  //! Write payload size
+};
+
+enum Avr32GenericPhysicalContextParameters {
+    AVR32_PHY_PHYSICAL              = 0x00, //! Physical interface selector
+    AVR32_PHY_JTAG_CLOCK            = 0x01, //! JTAG clock value
+    AVR32_PHY_AW_MAXBAUD            = 0x02, //! Maximum aWire baud
+    AVR32_PHY_DAISY                 = 0x03, //! JTAG daisy chain settings
+    AVR32_PHY_AWIRE_BAUD            = 0x04, //! Current aWire baud
+    AVR32_PHY_AWIRE_VERSION         = 0x05, //! aWire slave version
+    AVR32_PHY_EXT_RESET             = 0x0C, //! External reset control
+};
+
+enum Avr32GenericDeviceContext {
+    AVR32_FLASH_CTRL_BASE           = 0x02, //! Flash controller base address
+    AVR32_FLASH_PAGEBYTES           = 0x06, //! Number of bytes in one flash page
+    AVR32_RESET_DOMAINS         = 0x0A, //! Number of reset domains
+    AVR32_FLASH_PAGES               = 0x0B, //! Number of pages in the flash block
+    AVR32_AWIRE_BASE                = 0x10  //! Base address for aWire module
+};
+
+enum Avr32GenericMemoryTypes {
+    AVR32_MEMTYPE_SAB               = 0x80, //! Service Access Bus (SAB) word access
+    AVR32_MEMTYPE_NEXUS             = 0x81, //! Nexus mode access to SAB
+    AVR32_MEMTYPE_MEMORY_SERVICE    = 0x82, //! Memory Service mode access to SAB
+    AVR32_MEMTYPE_BLOCK             = 0x83, //! Block access to SAB
+    AVR32_MEMTYPE_BYTE              = 0x84, //! 8-bit access to SAB
+    AVR32_MEMTYPE_HALF_WORD         = 0x85, //! 16-bit access to SAB
+    AVR32_MEMTYPE_INTERNAL_FLASH    = 0x90, //! Write access to internal FLASH
+    AVR32_MEMTYPE_SYSREG            = 0x91, //! Access to system registers
+    AVR32_MEMTYPE_REGFILE           = 0x92, //! Access to register file
+    AVR32_MEMTYPE_USER_PAGE         = 0x93  //! Access to User Page in flash
+};
+
+enum Avr32GenericPhysicalInterfaces {
+    AVR32_PHYSICAL_INTERFACE_NONE   = 0x00, //! No physical
+    AVR32_PHYSICAL_INTERFACE_JTAG   = 0x04, //! JTAG physical
+    AVR32_PHYSICAL_INTERFACE_AWIRE  = 0x07  //! aWire physical
+};
+
+enum Avr32TapCommands {
+    AVR32_TAP_IR                    = 0x00, //! JTAG Instruction Register access
+    AVR32_TAP_DR                    = 0x01  //! JTAG Data Register access
+};
+
+typedef enum Avr32SABAddressMap {
+	AVR32_SAB_OCD					= 0x01,
+	AVR32_SAB_HSB_CPU				= 0x04,
+	AVR32_SAB_HSB					= 0x05,
+	AVR32_SAB_MSU					= 0x06
+} Avr32SABAddressMap;
+
+enum Avr32GenericFailureCodes {
+    AVR32_FAILURE_OK                        = 0x00, //! All OK
+    AVR32_FAILURE_NACK                      = 0x01, //! NACK received from target
+    AVR32_FAILURE_LENGTH                    = 0x02, //! Incorrect packet length
+    AVR32_FAILURE_RECEIVE_TIMEOUT           = 0x03, //! Receive function timeout
+    AVR32_FAILURE_RECEIVE_SYNC              = 0x04, //! Receive did not sync
+    AVR32_FAILURE_RECEIVE_LENGTH            = 0x05, //! Incorrect packet length
+    AVR32_FAILURE_TRANSMIT_OVERFLOW         = 0x06, //! Transmit buffer overflow
+    AVR32_FAILURE_INVALID_MEMTYPE           = 0x07, //! Invalid memtype given
+    AVR32_FAILURE_WRITE_ERROR               = 0x08, //! A write error occurred 
+    AVR32_FAILURE_WRITE_BUSY                = 0x09, //! Busy signal received
+    AVR32_FAILURE_READ_SHORT                = 0x0A, //! Short-packet received
+    AVR32_FAILURE_ERASE_TIMEOUT             = 0x0B, //! Erase command timeout 
+    AVR32_FAILURE_FLASHREADY_TIMEOUT        = 0x0C, //! Flash controller busy
+    AVR32_FAILURE_ILLEGAL_STATE             = 0x0D, //! Illegal state specified
+    AVR32_FAILURE_NOT_SUPPORTED             = 0x0E, //! Feature not supported
+    AVR32_FAILURE_PROGE                     = 0x0F, //! Programming error
+    AVR32_FAILURE_LOCKE                     = 0x10, //! Lock error
+    AVR32_FAILURE_STEP_TIMEOUT              = 0x11, //! Single stepping timeout
+    AVR32_FAILURE_READ_BUSY                 = 0x12, //! Busy bit was set
+    AVR32_FAILURE_READ_ERROR                = 0x13, //! Error bit was set
+    AVR32_FAILURE_HARDWARE_ERROR            = 0x14, //! aWire hardware init error
+    AVR32_FAILURE_NO_CONTACT                = 0x15, //! No response from aWire 
+    AVR32_FAILURE_NO_TARGET_POWER           = 0x16, //! No target power 
+    AVR32_FAILURE_NOT_IMPLEMENTED           = 0x17, //! Command not implemented
+    AVR32_FAILURE_UNSUPPORTED_HARDWARE      = 0x18, //! Hardware not supported
+    AVR32_FAILURE_JTAGM_INIT_ERROR          = 0x19, //! JTAG master init error
+    AVR32_FAILURE_NO_DEVICE_FOUND           = 0x1A, //! devices == 0!    
+    AVR32_FAILURE_JTAGM_ERROR               = 0x1B, //! JTAG master error
+    AVR32_FAILURE_INVALID_SIZE              = 0x1D, //! Too many or too few bytes
+    AVR32_FAILURE_INVALID_ADDRESS           = 0x1E, //! Bad address requested
+    AVR32_FAILURE_AWIRE_SET_BAUD_ERROR      = 0x1F, //! Failure setting baud   
+    AVR32_FAILURE_INVALID_DATA              = 0x20, //! Data invalid, discard it
+    AVR32_FAILURE_INVALID_PHYSICAL_MODE     = 0x21, //! Physical mode not valid  
+    AVR32_FAILURE_INVALID_CLOCK_SPEED       = 0x22, //! The clock is not valid
+    AVR32_FAILURE_AWIRE_ERROR_RESPONSE      = 0x23, //! Error response received
+    AVR32_FAILURE_AWIRE_OVERFLOW            = 0x24, //! Overflow data RX overflow
+    AVR32_FAILURE_AWM_ERROR                 = 0x24, //! aWire master error
+    AVR32_FAILURE_AWIRE_CRC                 = 0x25, //! aWire CRC error
+    AVR32_FAILURE_AWIRE_TUNE                = 0x26, //! aWire TUNE error
+    AVR32_FAILURE_JTAGM_WAS_BUSY            = 0x29, //! JTAG master busy 
+    AVR32_FAILURE_JTAGM_TIMEOUT             = 0x2A, //! JTAG master timeout
+    AVR32_FAILURE_BAD_VALUE                 = 0x2B, //! Invalid parameter value
+    AVR32_FAILURE_ERASE_ERROR               = 0x2C, //! Erase error
+    AVR32_FAILURE_CONFIG_ERROR              = 0x2D, //! Insufficient config info
+    AVR32_FAILURE_INVALID_EMULATOR_MODE     = 0x2E, //! Mode is not valid 
+    AVR32_FAILURE_CPU_DIRTY_TIMEOUT         = 0x2F, //! CPU wait timeout
+    AVR32_FAILURE_CPU_MODE                  = 0x30, //! CPU not in debug mode 
+    AVR32_FAILURE_CPU_DEBUG_MODE_TIMEOUT    = 0x31, //! CPU debug mode timeout
+    AVR32_FAILURE_AWIRE_RW_STATUS           = 0x32, //! Unexpected status
+    AVR32_FAILURE_TRANSMIT_TIMEOUT          = 0x33, //! Data TX timeout
+    AVR32_FAILURE_INTERNAL_RESPONSE_ERROR   = 0xFE, //! Near disaster
+    AVR32_FAILURE_UNKNOWN                   = 0xFF, //! Disaster
+};
+
+
+
+
+enum EdbgCommands {
+    //**********************************************************
+    // Protocol commands
+    //**********************************************************
+
+    // Basics
+    EDBG_CMD_QUERY                                      = 0x00,
+    EDBG_CMD_SET                                        = 0x01,
+    EDBG_CMD_GET                                        = 0x02,
+};
+
+enum EdbgResponses {
+    //**********************************************************
+    // Protocol responses
+    //**********************************************************
+
+    EDBG_RSP_OK                                         = 0x80,
+    EDBG_RSP_LIST                                       = 0x81,
+    EDBG_RSP_DATA                                       = 0x84,
+    EDBG_RSP_FAILED                                     = 0xA0
+};
+
+
+enum EdbgFailureCodes {
+    //**********************************************************
+    // Failure response codes (RSP_FAILED)
+    //**********************************************************
+
+    EDBG_FAILED_OK                                      = 0x00,
+    EDBG_FAILED_NOT_SUPPORTED                           = 0x01,
+    EDBG_FAILED_ILLEGAL_GPIO_PIN                        = 0x10,
+    EDBG_FAILED_ILLEGAL_GPIO_MODE                       = 0x11,
+    EDBG_FAILED_ILLEGAL_VOLTAGE_RANGE                   = 0x12,
+    EDBG_FAILED_ILLEGAL_INTERVAL                        = 0x13,
+    EDBG_FAILED_ILLEGAL_MAX_THRESHOLD                   = 0x14,
+    EDBG_FAILED_ILLEGAL_MIN_THRESHOLD                   = 0x15,
+    EDBG_FAILED_ILLEGAL_ACTION                          = 0x16,
+    EDBG_FAILED_ILLEGAL_FREQUENCY                       = 0x17,
+    EDBG_FAILED_ILLEGAL_MODE                            = 0x18,
+    EDBG_FAILED_ILLEGAL_FLAGS                           = 0x19,
+    EDBG_FAILED_FLASH_WRITE                             = 0x20,
+    EDBG_FAILED_OVERFLOW                                = 0x30,
+    EDBG_FAILED_UNKNOWN                                 = 0xFF
+};
+
+enum EdbgConfigTypes {
+    EDBG_CONFIGTYPE_CHAR                                = 0x00,
+    EDBG_CONFIGTYPE_SHORT                               = 0x01,
+    EDBG_CONFIGTYPE_WORD                                = 0x02,
+    EDBG_CONFIGTYPE_BIT                                 = 0x03,
+    EDBG_CONFIGTYPE_STRING                              = 0x10,
+    EDBG_CONFIGTYPE_ARRAY                               = 0x20,
+};
+
+enum EdbgConfigTags {
+    //**********************************************************
+    // EDBG Configuration Tags
+    //**********************************************************
+
+    EDBG_CONFIG_VERSION                                 = 0x00,
+    EDBG_CONFIG_SERIAL_NUMBER                           = 0x01,
+    EDBG_CONFIG_BOARD_NAME                              = 0x02,
+    EDBG_CONFIG_MANUFACTURER_NAME                       = 0x03,
+    EDBG_CONFIG_TARGET_NAME                             = 0x04,
+    EDBG_CONFIG_TARGET_SIGNATURE                        = 0x05,
+    EDBG_CONFIG_TARGET_JTAGID                           = 0x06,
+    EDBG_CONFIG_TARGET_CHIPID                           = 0x07,
+    EDBG_CONFIG_INTERFACES                              = 0x08,
+    EDBG_CONFIG_DGI_GPIO_MAP                            = 0x09,
+    EDBG_CONFIG_EXTENSION_MAP                           = 0x0A,
+    EDBG_CONFIG_EXTENSION_STATUS                        = 0x0B,
+    EDBG_CONFIG_EXTENSION_MANUFACTURER                  = 0x0C,
+    EDBG_CONFIG_EXTENSION_PRODUCT                       = 0x0D,
+    EDBG_CONFIG_EXTENSION_REVISION                      = 0x0E,
+    EDBG_CONFIG_EXTENSION_SERIAL                        = 0x0F,
+    EDBG_CONFIG_EXTENSION_MIN_VOLTAGE                   = 0x10,
+    EDBG_CONFIG_EXTENSION_MAX_VOLTAGE                   = 0x11,
+    EDBG_CONFIG_EXTENSION_CURRENT                       = 0x12,
+    EDBG_CONFIG_BOARD_TYPE                              = 0x13,
+    EDBG_CONFIG_FAMILY_NAME                             = 0x14,
+    EDBG_CONFIG_TVS                                     = 0x15,
+    EDBG_CONFIG_VERSION_MINOR                           = 0x16,
+    EDBG_CONFIG_USB_ID                                  = 0x17,
+    EDBG_CONFIG_KIT_DATA                                = 0x20,
+};
+
+enum EdbgInterfaces {
+    //**********************************************************
+    // EDBG Configuration Tags
+    //********************************************************** 
+    // GPIO, USART, UART, TWI, SPI, CDC
+    // SWD, ARMJTAG, AVRJTAG, aW, dW, PDI, ISP, DBG_EN
+
+    EDBG_IF_DBG_EN                                      = 15,
+    EDBG_IF_DBG_ISP                                     = 14,
+    EDBG_IF_DBG_PDI                                     = 13,
+    EDBG_IF_DBG_DW                                      = 12,
+    EDBG_IF_DBG_AW                                      = 11,
+    EDBG_IF_DBG_AVRJTAG                                 = 10,
+    EDBG_IF_DBG_ARMJTAG                                 = 9,
+    EDBG_IF_DBG_SWD                                     = 8,
+    
+    EDBG_IF_DGI_SPI                                     = 0,
+    EDBG_IF_DGI_TWI                                     = 1,
+    EDBG_IF_DGI_UART                                    = 2,
+    EDBG_IF_DGI_USART                                   = 3,
+    EDBG_IF_DGI_GPIO                                    = 4,
+    EDBG_IF_CDC                                         = 5,
+    
+    EDBG_IF_ERASE_PIN                                   = 7,
+};
+enum EDBGQueryContexts {
+    // QUERY types on this protocol
+    EDBG_QUERY_COMMANDS                                 = 0x00
+};
+    
+enum EDBGSetGetContexts {
+    EDBG_CONTEXT_CONTROL                                = 0x00,
+    EDBG_CONTEXT_CONFIG0                                = 0x10,
+    EDBG_CONTEXT_CONFIG1                                = 0x11,
+}; 
+
+enum EDBGControlContextParameters {
+    EDBG_CONTROL_LED_USAGE                              = 0x00,
+    EDBG_CONTROL_EXT_PROG                               = 0x01,
+    EDBG_CONTROL_TARGET_POWER                           = 0x10
+};
Index: pgm_type.c
===================================================================
--- pgm_type.c	(revision 1425)
+++ pgm_type.c	(working copy)
@@ -80,6 +80,7 @@
         {"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc},
         {"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc},
         {"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc},
+        {"jtagice3_avr32", jtag3_avr32_initpgm, jtag3_avr32_desc},
         {"linuxgpio", linuxgpio_initpgm, linuxgpio_desc},
         {"par", par_initpgm, par_desc},
         {"pickit2", pickit2_initpgm, pickit2_desc},
