From d46b2e880ca289f8e135b1728c48ba82c4becf1b Mon Sep 17 00:00:00 2001
From: hweisbach <hweisbach@81a1dc3b-b13d-400b-aceb-764788c761c2>
Date: Mon, 6 May 2013 12:43:47 +0000
Subject: [PATCH] avr.c: Add generic TPI chip erase function

git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1166 81a1dc3b-b13d-400b-aceb-764788c761c2
---
 ChangeLog |  1 +
 avr.c     | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 089a3ba8..9d108810 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -45,6 +45,7 @@
 	* avrftdi_tpi.c: Do all I/O in terms of pgm->cmd_tpi()-calls instead of
 	avrftdi_tpi_[read,write]_byte().
 	Remove unnecessary set_pin call to set MOSI high, speeds up I/O.
+	* avr.c: Adds avr_tpi_chip_erase() generic TPI chip erase function.
 
 2013-05-02  Hannes Weisbach <hannes_weisbach@gmx.net>
 
diff --git a/avr.c b/avr.c
index e79de0ef..07ab8e03 100644
--- a/avr.c
+++ b/avr.c
@@ -54,6 +54,55 @@ int avr_tpi_poll_nvmbsy(PROGRAMMER *pgm)
   return (res & TPI_IOREG_NVMCSR_NVMBSY);
 }
 
+/* TPI chip erase sequence */
+int avr_tpi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
+{
+	int err;
+  AVRMEM *mem;
+
+  if (p->flags & AVRPART_HAS_TPI) {
+    pgm->pgm_led(pgm, ON);
+
+    /* Set Pointer Register */
+    mem = avr_locate_mem(p, "flash");
+    if (mem == NULL) {
+      fprintf(stderr, "No flash memory to erase for part %s\n",
+          p->desc);
+      return -1;
+    }
+
+		unsigned char cmd[] = {
+			/* write pointer register high byte */
+			(TPI_CMD_SSTPR | 0),
+			((mem->offset & 0xFF) | 1),
+			/* and low byte */
+			(TPI_CMD_SSTPR | 1),
+			((mem->offset >> 8) & 0xFF),
+	    /* write CHIP_ERASE command to NVMCMD register */
+			(TPI_CMD_SOUT | TPI_SIO_ADDR(TPI_IOREG_NVMCMD)),
+			TPI_NVMCMD_CHIP_ERASE,
+			/* write dummy value to start erase */
+			TPI_CMD_SST,
+			0xFF
+		};
+
+    while (avr_tpi_poll_nvmbsy(pgm));
+
+		err = pgm->cmd_tpi(pgm, cmd, sizeof(cmd), NULL, 0);
+		if(err)
+			return err;
+
+    while (avr_tpi_poll_nvmbsy(pgm));
+
+    pgm->pgm_led(pgm, OFF);
+
+    return 0;
+  } else {
+		fprintf(stderr, "%s called for a part that has no TPI\n", __func__);
+		return -1;
+	}
+}
+
 /* TPI: setup NVMCMD register and pointer register (PR) for read/write/erase */
 static int avr_tpi_setup_rw(PROGRAMMER * pgm, AVRMEM * mem,
 			    unsigned long addr, unsigned char nvmcmd)