diff --git avrdude/Makefile.am avrdude/Makefile.am
index cd0388c..91315ca 100644
--- avrdude/Makefile.am
+++ avrdude/Makefile.am
@@ -104,6 +104,8 @@ libavrdude_a_SOURCES = \
 	fileio.c \
 	fileio.h \
 	freebsd_ppi.h \
+	goodfet.c \
+	goodfet.h \
 	jtagmkI.c \
 	jtagmkI.h \
 	jtagmkI_private.h \
diff --git avrdude/avrdude.conf.in avrdude/avrdude.conf.in
index 8790fff..e189cea 100644
--- avrdude/avrdude.conf.in
+++ avrdude/avrdude.conf.in
@@ -587,6 +587,13 @@ programmer
 ;
 
 programmer
+  id    = "goodfet";
+  desc  = "GoodFET";
+  baudrate = 115200;
+  type  = goodfet;
+;
+
+programmer
   id    = "pavr";
   desc  = "Jason Kyle's pAVR Serial Programmer";
   type  = avr910;
diff --git avrdude/config_gram.y avrdude/config_gram.y
index 2ff8452..340b0f4 100644
--- avrdude/config_gram.y
+++ avrdude/config_gram.y
@@ -104,6 +104,7 @@ static int parse_cmdbits(OPCODE * op);
 %token K_EEPROM
 %token K_ERRLED
 %token K_FLASH
+%token K_GOODFET
 %token K_ID
 %token K_IO
 %token K_JTAG_MKI
@@ -550,7 +551,11 @@ prog_parm :
       stk500v2_dragon_pp_initpgm(current_prog);
     }
   } |
-
+  K_TYPE TKN_EQUAL K_GOODFET {
+    {
+      goodfet_initpgm(current_prog);
+    }
+  } |
   K_DESC TKN_EQUAL TKN_STRING {
     strncpy(current_prog->desc, $3->value.string, PGM_DESCLEN);
     current_prog->desc[PGM_DESCLEN-1] = 0;
diff --git avrdude/goodfet.c avrdude/goodfet.c
new file mode 100644
index 0000000..43f6469
--- /dev/null
+++ avrdude/goodfet.c
@@ -0,0 +1,304 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ *
+ * avrdude support for Travis Goodspeed's GoodFET
+ *
+ * Copyright (C) 2010 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * GoodFET           AVR Chip
+ * -----------       --------
+ *     GND (9)  <->  GND
+ *     +5V (2)  <->  Vcc
+ *      CS (5)  <->  RESET
+ *    MOSI (3)  <->  MOSI
+ *    MISO (1)  <->  MISO
+ * SCL/CLK (7)  <->  SCK
+ *
+ * Tested with GoodFet20 running web firmware as of 28 Oct 2010, programming ATmega328P
+ */
+
+/* $Id$ */
+
+#include "ac_cfg.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#if defined(WIN32NATIVE)
+#  include <malloc.h>  /* for alloca() */
+#endif
+#include <assert.h>
+
+#include "avrdude.h"
+#include "avr.h"
+#include "pgm.h"
+#include "serial.h"
+
+/* ====== Private data structure ====== */
+/* CS and AUX pin bitmasks in
+ * 0100wxyz - Configure peripherals command */
+
+#define GF_APP_MONITOR 0x00
+#define GF_APP_SPI     0x01
+#define GF_APP_AVR     0x32
+
+#define GF_VERB_READ   0x00
+#define GF_VERB_SETUP  0x10
+#define GF_VERB_START  0x20
+struct pdata
+{
+	int	spifreq;		/* 0..7 - see buspirate manual for what freq each value means */
+	int	reset;			/* See BP_RESET_* above */
+};
+
+typedef struct goodfet_message {
+	char app;
+	char verb;
+	int len;
+	unsigned char *data;
+} goodfet_message_t;
+
+#define PDATA(pgm) ((struct pdata *)(pgm->cookie))
+
+/* ====== Serial talker functions - binmode ====== */
+
+static void dump_mem(char *buf, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i<len; i++) {
+		if (i % 8 == 0)
+			fprintf(stderr, "\t");
+		fprintf(stderr, "0x%02x ", (unsigned)buf[i] & 0xFF);
+		if (i % 8 == 3)
+			fprintf(stderr, "  ");
+		else if (i % 8 == 7)
+			fprintf(stderr, "\n");
+	}
+	if (i % 8 != 7)
+		fprintf(stderr, "\n");
+}
+
+static void goodfet_send_message(struct programmer_t *pgm,
+				 goodfet_message_t *msg,
+				 goodfet_message_t *response) {
+	unsigned char buf[4];
+	buf[0] = msg->app;
+	buf[1] = msg->verb;
+	buf[2] = msg->len & 0xff;
+	buf[3] = (msg->len >> 8) & 0xff;
+
+	serial_send(&pgm->fd, buf, 4);
+	if (msg->len > 0)
+		serial_send(&pgm->fd, msg->data, msg->len);
+	serial_recv(&pgm->fd, buf, 4);
+	response->app = buf[0];
+	response->verb = buf[1];
+	response->len = buf[2] | (buf[3] << 8);
+	if (response->data)
+		free(response->data);
+	if (response->len > 0) {
+		response->data = malloc(response->len);
+		memset(response->data, 0, response->len);
+		serial_recv(&pgm->fd, response->data, response->len);
+	} else
+		response->data = NULL;
+}
+
+static void goodfet_spi_exchange(struct programmer_t *pgm, unsigned char* data, int len) {
+	goodfet_message_t msg, resp;
+	msg.app = GF_APP_AVR;
+	msg.verb = GF_VERB_READ;
+	msg.len = len;
+	msg.data = data;
+
+	resp.data = NULL;
+	goodfet_send_message(pgm, &msg, &resp);
+	assert(len == resp.len);
+	if (verbose) {
+		int i;
+		fprintf(stderr, "\x1b[1;32m");
+		for (i = 0; i < len; i++)
+			fprintf(stderr, "%02x.", data[i]);
+		fprintf(stderr, "\x1b[1;31m");
+		for (i = 0; i < len; i++)
+			fprintf(stderr, "%02x.", resp.data[i]);
+		fprintf(stderr, "\x1b[0m\n");
+	}
+	memcpy(data, resp.data, resp.len);
+	free(resp.data);
+}
+
+/* ====== Do-nothing functions ====== */
+static void goodfet_dummy_6(struct programmer_t *pgm,
+                            const char *p)
+{
+}
+
+/* ====== Config / parameters handling functions ====== */
+
+/* ====== Programmer methods ======= */
+static int goodfet_open(struct programmer_t *pgm, char * port)
+{
+	int len;
+	char *dbuf;
+	unsigned char hbuf[4];
+	/* Goodfet runs at 115200 by default */
+	if(pgm->baudrate == 0)
+		pgm->baudrate = 115200;
+
+	strcpy(pgm->port, port);
+	if (serial_open(port, pgm->baudrate, &pgm->fd)==-1) {
+	  return -1;
+	}
+
+	/* drain any extraneous input */
+	serial_drain(&pgm->fd, 0);
+	// drop DTR to start goodfet
+	serial_set_dtr_rts(&pgm->fd, 1);
+	usleep(50 * 1000);
+	serial_set_dtr_rts(&pgm->fd, 0);
+
+	/* Read the initialization string */
+
+	serial_recv(&pgm->fd, hbuf, 4);
+	len = hbuf[2] | (hbuf[3] << 8);
+	if (len > 0) {
+		dbuf = malloc(len);
+		serial_recv(&pgm->fd, dbuf, len);
+		free(dbuf);
+	}
+
+	return 0;
+}
+
+static void goodfet_close(struct programmer_t *pgm)
+{
+	serial_close(&pgm->fd);
+	pgm->fd.ifd = -1;
+}
+
+static void goodfet_enable(struct programmer_t *pgm)
+{
+}
+
+static void goodfet_disable(struct programmer_t *pgm)
+{
+}
+
+static int goodfet_initialize(struct programmer_t *pgm, AVRPART * p)
+{
+	goodfet_message_t cmd, resp;
+	cmd.app = GF_APP_AVR;
+	cmd.verb = GF_VERB_START;
+	cmd.len = 0;
+	cmd.data = resp.data = NULL;
+	goodfet_send_message(pgm, &cmd, &resp);
+
+	//return pgm->program_enable(pgm, p);
+}
+
+static int goodfet_cmd(struct programmer_t *pgm,
+				unsigned char cmd[4],
+				unsigned char res[4])
+{
+	memcpy(res, cmd, 4);
+	goodfet_spi_exchange(pgm, res, 4);
+	return 0;
+}
+
+static int goodfet_program_enable(struct programmer_t *pgm, AVRPART * p)
+{
+	unsigned char cmd[4];
+	unsigned char res[4];
+
+	if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
+		fprintf(stderr,
+			"program enable instruction not defined for part \"%s\"\n",
+			p->desc);
+		return -1;
+	}
+
+	memset(cmd, 0, sizeof(cmd));
+	avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd);
+	pgm->cmd(pgm, cmd, res);
+
+	if (res[2] != cmd[1])
+		return -2;
+
+	return 0;
+}
+
+static int goodfet_chip_erase(struct programmer_t *pgm, AVRPART * p)
+{
+	unsigned char cmd[4];
+	unsigned char res[4];
+
+	if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
+		fprintf(stderr,
+			"chip erase instruction not defined for part \"%s\"\n",
+			p->desc);
+		return -1;
+	}
+
+	pgm->pgm_led(pgm, ON);
+
+	memset(cmd, 0, sizeof(cmd));
+
+	avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
+	pgm->cmd(pgm, cmd, res);
+	usleep(p->chip_erase_delay);
+	pgm->initialize(pgm, p);
+
+	pgm->pgm_led(pgm, OFF);
+
+	return 0;
+}
+
+void goodfet_initpgm(struct programmer_t *pgm)
+{
+	strcpy(pgm->type, "GoodFET");
+
+	pgm->display        = goodfet_dummy_6;
+
+	/* Goodfet itself related methods */
+	pgm->open           = goodfet_open;
+	pgm->close          = goodfet_close;
+	pgm->enable         = goodfet_enable;
+	pgm->disable        = goodfet_disable;
+	pgm->initialize     = goodfet_initialize;
+
+	/* Chip related methods */
+	pgm->program_enable = goodfet_program_enable;
+	pgm->chip_erase     = goodfet_chip_erase;
+	pgm->cmd            = goodfet_cmd;
+	pgm->read_byte      = avr_read_byte_default;
+	pgm->write_byte     = avr_write_byte_default;
+
+	/* Support functions */
+	//pgm->parseextparams = goodfet_parseextparms;
+
+	/* Allocate private data */
+	if ((pgm->cookie = calloc(1, sizeof(struct pdata))) == 0) {
+		fprintf(stderr, "%s: goodfet_initpgm(): Out of memory allocating private data\n",
+			progname);
+		exit(1);
+	}
+}
diff --git avrdude/goodfet.h avrdude/goodfet.h
new file mode 100644
index 0000000..d72dad7
--- /dev/null
+++ avrdude/goodfet.h
@@ -0,0 +1,30 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ *
+ * avrdude support for Travis Goodspeed's GoodFET
+ *
+ * Copyright (C) 2010 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* $Id$ */
+
+#ifndef goodfet_h
+#define goodfet_h
+
+void goodfet_initpgm (struct programmer_t *pgm);
+
+#endif
diff --git avrdude/lexer.l avrdude/lexer.l
index 926aca1..8135dc3 100644
--- avrdude/lexer.l
+++ avrdude/lexer.l
@@ -146,6 +146,7 @@ eeprom           { yylval=NULL; return K_EEPROM; }
 enablepageprogramming { yylval=NULL; return K_ENABLEPAGEPROGRAMMING; }
 errled           { yylval=NULL; return K_ERRLED; }
 flash            { yylval=NULL; return K_FLASH; }
+goodfet          { yylval=NULL; return K_GOODFET; }
 has_jtag         { yylval=NULL; return K_HAS_JTAG; }
 has_debugwire    { yylval=NULL; return K_HAS_DW; }
 has_pdi          { yylval=NULL; return K_HAS_PDI; }
