summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile23
-rw-r--r--flashrom.8.tmpl34
-rw-r--r--flashrom.c13
-rw-r--r--pickit2_spi.c505
-rw-r--r--programmer.h11
5 files changed, 582 insertions, 4 deletions
diff --git a/Makefile b/Makefile
index 93759c3..aaeca43 100644
--- a/Makefile
+++ b/Makefile
@@ -138,7 +138,7 @@ UNSUPPORTED_FEATURES += CONFIG_PONY_SPI=yes
else
override CONFIG_PONY_SPI = no
endif
-# Dediprog, USB-Blaster and FT2232 are not supported under DOS (missing USB support).
+# Dediprog, USB-Blaster, PICkit2 and FT2232 are not supported under DOS (missing USB support).
ifeq ($(CONFIG_DEDIPROG), yes)
UNSUPPORTED_FEATURES += CONFIG_DEDIPROG=yes
else
@@ -154,6 +154,11 @@ UNSUPPORTED_FEATURES += CONFIG_USBBLASTER_SPI=yes
else
override CONFIG_USBBLASTER_SPI = no
endif
+ifeq ($(CONFIG_PICKIT2_SPI), yes)
+UNSUPPORTED_FEATURES += CONFIG_PICKIT2_SPI=yes
+else
+override CONFIG_PICKIT2_SPI = no
+endif
endif
# FIXME: Should we check for Cygwin/MSVC as well?
@@ -277,7 +282,7 @@ UNSUPPORTED_FEATURES += CONFIG_PONY_SPI=yes
else
override CONFIG_PONY_SPI = no
endif
-# Dediprog, USB-Blaster and FT2232 are not supported with libpayload (missing libusb support)
+# Dediprog, USB-Blaster, PICkit2 and FT2232 are not supported with libpayload (missing libusb support)
ifeq ($(CONFIG_DEDIPROG), yes)
UNSUPPORTED_FEATURES += CONFIG_DEDIPROG=yes
else
@@ -293,6 +298,11 @@ UNSUPPORTED_FEATURES += CONFIG_USBBLASTER_SPI=yes
else
override CONFIG_USBBLASTER_SPI = no
endif
+ifeq ($(CONFIG_PICKIT2_SPI), yes)
+UNSUPPORTED_FEATURES += CONFIG_PICKIT2_SPI=yes
+else
+override CONFIG_PICKIT2_SPI = no
+endif
endif
ifneq ($(TARGET_OS), Linux)
@@ -429,6 +439,9 @@ CONFIG_USBBLASTER_SPI ?= yes
# MSTAR DDC support needs more tests/reviews/cleanups.
CONFIG_MSTARDDC_SPI ?= no
+# Always enable PICkit2 SPI dongles for now.
+CONFIG_PICKIT2_SPI ?= yes
+
# Always enable dummy tracing for now.
CONFIG_DUMMY ?= yes
@@ -614,6 +627,12 @@ NEED_FTDI := yes
PROGRAMMER_OBJS += usbblaster_spi.o
endif
+ifeq ($(CONFIG_PICKIT2_SPI), yes)
+FEATURE_CFLAGS += -D'CONFIG_PICKIT2_SPI=1'
+PROGRAMMER_OBJS += pickit2_spi.o
+NEED_USB := yes
+endif
+
ifeq ($(NEED_FTDI), yes)
FTDILIBS := $(shell ([ -n "$(PKG_CONFIG_LIBDIR)" ] && export PKG_CONFIG_LIBDIR="$(PKG_CONFIG_LIBDIR)" ); pkg-config --libs libftdi || printf "%s" "-lftdi -lusb")
FEATURE_CFLAGS += $(shell LC_ALL=C grep -q "FT232H := yes" .features && printf "%s" "-D'HAVE_FT232H=1'")
diff --git a/flashrom.8.tmpl b/flashrom.8.tmpl
index 799d5b9..8b5f98c 100644
--- a/flashrom.8.tmpl
+++ b/flashrom.8.tmpl
@@ -229,6 +229,8 @@ bitbanging adapter)
.sp
.BR "* mstarddc_spi" " (for SPI flash ROMs accessible through DDC in MSTAR-equipped displays)"
.sp
+.BR "* pickit2_spi" " (for SPI flash ROMs accessible via Microchip PICkit2)"
+.sp
Some programmers have optional or mandatory parameters which are described
in detail in the
.B PROGRAMMER-SPECIFIC INFORMATION
@@ -736,6 +738,34 @@ More information about the Bus Pirate pull-up resistors and their purpose is ava
.BR "http://dangerousprototypes.com/docs/Practical_guide_to_Bus_Pirate_pull-up_resistors " .
Only the external supply voltage (Vpu) is supported as of this writing.
.SS
+.BR "pickit2_spi " programmer
+An optional
+.B voltage
+parameter specifies the voltage the PICkit2 should use. The default unit is Volt if no unit is specified.
+You can use
+.BR mV ", " millivolt ", " V " or " Volt
+as unit specifier. Syntax is
+.sp
+.B " flashrom \-p pickit2_spi:voltage=value"
+.sp
+where
+.B value
+can be
+.BR 0V ", " 1.8V ", " 2.5V ", " 3.5V
+or the equivalent in mV.
+.sp
+An optional
+.B spispeed
+parameter specifies the frequency of the SPI bus. Syntax is
+.sp
+.B " flashrom \-p pickit2_spi:spispeed=frequency"
+.sp
+where
+.B frequency
+can be
+.BR 250k ", " 333k ", " 500k " or " 1M "
+(in Hz). The default is a frequency of 1 MHz.
+.SS
.BR "dediprog " programmer
An optional
.B voltage
@@ -992,7 +1022,7 @@ needs TCP access to the network or userspace access to a serial port.
.B buspirate_spi
needs userspace access to a serial port.
.sp
-.BR dediprog ", " ft2232_spi " and " usbblaster_spi
+.BR dediprog ", " ft2232_spi " and " usbblaster_spi and " pickit2_spi
need access to the USB device via libusb.
.sp
.B dummy
@@ -1002,7 +1032,7 @@ needs no access permissions at all.
.BR gfxnvidia ", " drkaiser ", " satasii ", " satamv ", " atahpt" and " atavia
have to be run as superuser/root, and need additional raw access permission.
.sp
-.BR serprog ", " buspirate_spi ", " dediprog ", " usbblaster_spi " and " ft2232_spi
+.BR serprog ", " buspirate_spi ", " dediprog ", " usbblaster_spi " and " ft2232_spi and " pickit2_spi
can be run as normal user on most operating systems if appropriate device
permissions are set.
.sp
diff --git a/flashrom.c b/flashrom.c
index e58f707..a389cb2 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -366,6 +366,19 @@ const struct programmer_entry programmer_table[] = {
},
#endif
+#if CONFIG_PICKIT2_SPI == 1
+ {
+ .name = "pickit2_spi",
+ .type = OTHER,
+ /* FIXME */
+ .devs.note = "Microchip PICkit2\n",
+ .init = pickit2_spi_init,
+ .map_flash_region = fallback_map,
+ .unmap_flash_region = fallback_unmap,
+ .delay = internal_delay,
+ },
+#endif
+
{0}, /* This entry corresponds to PROGRAMMER_INVALID. */
};
diff --git a/pickit2_spi.c b/pickit2_spi.c
new file mode 100644
index 0000000..fb03b02
--- /dev/null
+++ b/pickit2_spi.c
@@ -0,0 +1,505 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2010 Carl-Daniel Hailfinger
+ * Copyright (C) 2014 Justin Chevrier
+ *
+ * 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; version 2 of the License.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * Connections are as follows:
+ *
+ * +------+-----+----------+
+ * | SPI | Pin | PICkit2 |
+ * +------+-----+----------+
+ * | /CS | 1 | VPP/MCLR |
+ * | VCC | 2 | VDD |
+ * | GND | 3 | GND |
+ * | MISO | 4 | PGD |
+ * | SCLK | 5 | PDC |
+ * | MOSI | 6 | AUX |
+ * +------+-----+----------+
+ *
+ * Inspiration and some specifics of the interface came via the AVRDude
+ * PICkit2 code: https://github.com/steve-m/avrdude/blob/master/pickit2.c
+ */
+
+#include "platform.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+
+#if IS_WINDOWS
+#include <lusb0_usb.h>
+#else
+#include <usb.h>
+#endif
+
+#include "flash.h"
+#include "chipdrivers.h"
+#include "programmer.h"
+#include "spi.h"
+
+static usb_dev_handle *pickit2_handle;
+
+/* Default USB transaction timeout in ms */
+#define DFLT_TIMEOUT 10000
+
+#define CMD_LENGTH 64
+#define ENDPOINT_OUT 0x01
+#define ENDPOINT_IN 0x81
+
+#define PICKIT2_VID 0x04D8
+#define PICKIT2_PID 0x0033
+
+#define CMD_GET_VERSION 0x76
+#define CMD_SET_VDD 0xA0
+#define CMD_SET_VPP 0xA1
+#define CMD_READ_VDD_VPP 0xA3
+#define CMD_EXEC_SCRIPT 0xA6
+#define CMD_CLR_DLOAD_BUFF 0xA7
+#define CMD_DOWNLOAD_DATA 0xA8
+#define CMD_CLR_ULOAD_BUFF 0xA9
+#define CMD_UPLOAD_DATA 0xAA
+#define CMD_END_OF_BUFFER 0xAD
+
+#define SCR_SPI_READ_BUF 0xC5
+#define SCR_SPI_WRITE_BUF 0xC6
+#define SCR_SET_AUX 0xCF
+#define SCR_LOOP 0xE9
+#define SCR_SET_ICSP_CLK_PERIOD 0xEA
+#define SCR_SET_PINS 0xF3
+#define SCR_BUSY_LED_OFF 0xF4
+#define SCR_BUSY_LED_ON 0xF5
+#define SCR_MCLR_GND_OFF 0xF6
+#define SCR_MCLR_GND_ON 0xF7
+#define SCR_VPP_PWM_OFF 0xF8
+#define SCR_VPP_PWM_ON 0xF9
+#define SCR_VPP_OFF 0xFA
+#define SCR_VPP_ON 0xFB
+#define SCR_VDD_OFF 0xFE
+#define SCR_VDD_ON 0xFF
+
+/* Copied from dediprog.c */
+/* Might be useful for other USB devices as well. static for now. */
+/* device parameter allows user to specify one device of multiple installed */
+static struct usb_device *get_device_by_vid_pid(uint16_t vid, uint16_t pid, unsigned int device)
+{
+ struct usb_bus *bus;
+ struct usb_device *dev;
+
+ for (bus = usb_get_busses(); bus; bus = bus->next)
+ for (dev = bus->devices; dev; dev = dev->next)
+ if ((dev->descriptor.idVendor == vid) &&
+ (dev->descriptor.idProduct == pid)) {
+ if (device == 0)
+ return dev;
+ device--;
+ }
+
+ return NULL;
+}
+
+static int pickit2_get_firmware_version(void)
+{
+ int ret;
+ uint8_t command[CMD_LENGTH] = {CMD_GET_VERSION, CMD_END_OF_BUFFER};
+
+ ret = usb_interrupt_write(pickit2_handle, ENDPOINT_OUT, (char *)command, CMD_LENGTH, DFLT_TIMEOUT);
+ ret = usb_interrupt_read(pickit2_handle, ENDPOINT_IN, (char *)command, CMD_LENGTH, DFLT_TIMEOUT);
+
+ msg_pdbg("PICkit2 Firmware Version: %d.%d\n", (int)command[0], (int)command[1]);
+ if (ret != CMD_LENGTH) {
+ msg_perr("Command Get Firmware Version failed (%s)!\n", usb_strerror());
+ return 1;
+ }
+
+ return 0;
+}
+
+static int pickit2_set_spi_voltage(int millivolt)
+{
+ double voltage_selector;
+ switch (millivolt) {
+ case 0:
+ /* Admittedly this one is an assumption. */
+ voltage_selector = 0;
+ break;
+ case 1800:
+ voltage_selector = 1.8;
+ break;
+ case 2500:
+ voltage_selector = 2.5;
+ break;
+ case 3500:
+ voltage_selector = 3.5;
+ break;
+ default:
+ msg_perr("Unknown voltage %i mV! Aborting.\n", millivolt);
+ return 1;
+ }
+ msg_pdbg("Setting SPI voltage to %u.%03u V\n", millivolt / 1000,
+ millivolt % 1000);
+
+ uint8_t command[CMD_LENGTH] = {
+ CMD_SET_VDD,
+ voltage_selector * 2048 + 672,
+ (voltage_selector * 2048 + 672) / 256,
+ voltage_selector * 36,
+ CMD_SET_VPP,
+ 0x40,
+ voltage_selector * 18.61,
+ voltage_selector * 13,
+ CMD_END_OF_BUFFER
+ };
+
+ int ret = usb_interrupt_write(pickit2_handle, ENDPOINT_OUT, (char *)command, CMD_LENGTH, DFLT_TIMEOUT);
+
+ if (ret != CMD_LENGTH) {
+ msg_perr("Command Set Voltage failed (%s)!\n", usb_strerror());
+ return 1;
+ }
+
+ return 0;
+}
+
+struct pickit2_spispeeds {
+ const char *const name;
+ const int speed;
+};
+
+static const struct pickit2_spispeeds spispeeds[] = {
+ { "1M", 0x1 },
+ { "500k", 0x2 },
+ { "333k", 0x3 },
+ { "250k", 0x4 },
+ { NULL, 0x0 },
+};
+
+static int pickit2_set_spi_speed(unsigned int spispeed_idx)
+{
+ msg_pdbg("SPI speed is %sHz\n", spispeeds[spispeed_idx].name);
+
+ uint8_t command[CMD_LENGTH] = {
+ CMD_EXEC_SCRIPT,
+ 2,
+ SCR_SET_ICSP_CLK_PERIOD,
+ spispeed_idx,
+ CMD_END_OF_BUFFER
+ };
+
+ int ret = usb_interrupt_write(pickit2_handle, ENDPOINT_OUT, (char *)command, CMD_LENGTH, DFLT_TIMEOUT);
+
+ if (ret != CMD_LENGTH) {
+ msg_perr("Command Set SPI Speed failed (%s)!\n", usb_strerror());
+ return 1;
+ }
+
+ return 0;
+}
+
+static int pickit2_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr, unsigned char *readarr)
+{
+
+ /* Maximum number of bytes per transaction (including command overhead) is 64. Lets play it safe
+ * and always assume the worst case scenario of 20 bytes command overhead.
+ */
+ if (writecnt + readcnt + 20 > CMD_LENGTH) {
+ msg_perr("\nTotal packetsize (%i) is greater than 64 supported, aborting.\n",
+ writecnt + readcnt + 20);
+ return 1;
+ }
+
+ uint8_t buf[CMD_LENGTH] = {CMD_DOWNLOAD_DATA, writecnt};
+ int i = 2;
+ for (; i < writecnt + 2; i++) {
+ buf[i] = writearr[i - 2];
+ }
+
+ buf[i++] = CMD_CLR_ULOAD_BUFF;
+ buf[i++] = CMD_EXEC_SCRIPT;
+
+ /* Determine script length based on number of bytes to be read or written */
+ if (writecnt == 1 && readcnt == 1)
+ buf[i++] = 7;
+ else if (writecnt == 1 || readcnt == 1)
+ buf[i++] = 10;
+ else
+ buf[i++] = 13;
+
+ /* Assert CS# */
+ buf[i++] = SCR_VPP_OFF;
+ buf[i++] = SCR_MCLR_GND_ON;
+
+ buf[i++] = SCR_SPI_WRITE_BUF;
+
+ if (writecnt > 1) {
+ buf[i++] = SCR_LOOP;
+ buf[i++] = 1; /* Loop back one instruction */
+ buf[i++] = writecnt - 1; /* Number of times to loop */
+ }
+
+ if (readcnt)
+ buf[i++] = SCR_SPI_READ_BUF;
+
+ if (readcnt > 1) {
+ buf[i++] = SCR_LOOP;
+ buf[i++] = 1; /* Loop back one instruction */
+ buf[i++] = readcnt - 1; /* Number of times to loop */
+ }
+
+ /* De-assert CS# */
+ buf[i++] = SCR_MCLR_GND_OFF;
+ buf[i++] = SCR_VPP_PWM_ON;
+ buf[i++] = SCR_VPP_ON;
+
+ buf[i++] = CMD_UPLOAD_DATA;
+ buf[i++] = CMD_END_OF_BUFFER;
+
+ int ret = usb_interrupt_write(pickit2_handle, ENDPOINT_OUT, (char *)buf, CMD_LENGTH, DFLT_TIMEOUT);
+
+ if (ret != CMD_LENGTH) {
+ msg_perr("Send SPI failed, expected %i, got %i %s!\n", writecnt, ret, usb_strerror());
+ return 1;
+ }
+
+ if (readcnt) {
+ ret = usb_interrupt_read(pickit2_handle, ENDPOINT_IN, (char *)buf, CMD_LENGTH, DFLT_TIMEOUT);
+
+ if (ret != CMD_LENGTH) {
+ msg_perr("Receive SPI failed, expected %i, got %i %s!\n", readcnt, ret, usb_strerror());
+ return 1;
+ }
+
+ /* First byte indicates number of bytes transferred from upload buffer */
+ if (buf[0] != readcnt) {
+ msg_perr("Unexpected number of bytes transferred, expected %i, got %i!\n",
+ readcnt, ret);
+ return 1;
+ }
+
+ /* Actual data starts at byte number two */
+ memcpy(readarr, &buf[1], readcnt);
+ }
+
+ return 0;
+}
+
+/* Copied from dediprog.c */
+/* Might be useful for other USB devices as well. static for now. */
+static int parse_voltage(char *voltage)
+{
+ char *tmp = NULL;
+ int i;
+ int millivolt = 0, fraction = 0;
+
+ if (!voltage || !strlen(voltage)) {
+ msg_perr("Empty voltage= specified.\n");
+ return -1;
+ }
+ millivolt = (int)strtol(voltage, &tmp, 0);
+ voltage = tmp;
+ /* Handle "," and "." as decimal point. Everything after it is assumed
+ * to be in decimal notation.
+ */
+ if ((*voltage == '.') || (*voltage == ',')) {
+ voltage++;
+ for (i = 0; i < 3; i++) {
+ fraction *= 10;
+ /* Don't advance if the current character is invalid,
+ * but continue multiplying.
+ */
+ if ((*voltage < '0') || (*voltage > '9'))
+ continue;
+ fraction += *voltage - '0';
+ voltage++;
+ }
+ /* Throw away remaining digits. */
+ voltage += strspn(voltage, "0123456789");
+ }
+ /* The remaining string must be empty or "mV" or "V". */
+ tolower_string(voltage);
+
+ /* No unit or "V". */
+ if ((*voltage == '\0') || !strncmp(voltage, "v", 1)) {
+ millivolt *= 1000;
+ millivolt += fraction;
+ } else if (!strncmp(voltage, "mv", 2) ||
+ !strncmp(voltage, "millivolt", 9)) {
+ /* No adjustment. fraction is discarded. */
+ } else {
+ /* Garbage at the end of the string. */
+ msg_perr("Garbage voltage= specified.\n");
+ return -1;
+ }
+ return millivolt;
+}
+
+static const struct spi_master spi_master_pickit2 = {
+ .type = SPI_CONTROLLER_PICKIT2,
+ .max_data_read = 40,
+ .max_data_write = 40,
+ .command = pickit2_spi_send_command,
+ .multicommand = default_spi_send_multicommand,
+ .read = default_spi_read,
+ .write_256 = default_spi_write_256,
+ .write_aai = default_spi_write_aai,
+};
+
+static int pickit2_shutdown(void *data)
+{
+ /* Set all pins to float and turn voltages off */
+ uint8_t command[CMD_LENGTH] = {
+ CMD_EXEC_SCRIPT,
+ 8,
+ SCR_SET_PINS,
+ 3, /* Bit-0=1(PDC In), Bit-1=1(PGD In), Bit-2=0(PDC LL), Bit-3=0(PGD LL) */
+ SCR_SET_AUX,
+ 1, /* Bit-0=1(Aux In), Bit-1=0(Aux LL) */
+ SCR_MCLR_GND_OFF,
+ SCR_VPP_OFF,
+ SCR_VDD_OFF,
+ SCR_BUSY_LED_OFF,
+ CMD_END_OF_BUFFER
+ };
+
+ int ret = usb_interrupt_write(pickit2_handle, ENDPOINT_OUT, (char *)command, CMD_LENGTH, DFLT_TIMEOUT);
+
+ if (ret != CMD_LENGTH) {
+ msg_perr("Command Shutdown failed (%s)!\n", usb_strerror());
+ ret = 1;
+ }
+ if (usb_release_interface(pickit2_handle, 0) != 0) {
+ msg_perr("Could not release USB interface!\n");
+ ret = 1;
+ }
+ if (usb_close(pickit2_handle) != 0) {
+ msg_perr("Could not close USB device!\n");
+ ret = 1;
+ }
+ return ret;
+}
+
+int pickit2_spi_init(void)
+{
+ unsigned int usedevice = 0; // FIXME: allow to select one of multiple devices
+
+ uint8_t buf[CMD_LENGTH] = {
+ CMD_EXEC_SCRIPT,
+ 10, /* Script length */
+ SCR_SET_PINS,
+ 2, /* Bit-0=0(PDC Out), Bit-1=1(PGD In), Bit-2=0(PDC LL), Bit-3=0(PGD LL) */
+ SCR_SET_AUX,
+ 0, /* Bit-0=0(Aux Out), Bit-1=0(Aux LL) */
+ SCR_VDD_ON,
+ SCR_MCLR_GND_OFF, /* Let CS# float */
+ SCR_VPP_PWM_ON,
+ SCR_VPP_ON, /* Pull CS# high */
+ SCR_BUSY_LED_ON,
+ CMD_CLR_DLOAD_BUFF,
+ CMD_CLR_ULOAD_BUFF,
+ CMD_END_OF_BUFFER
+ };
+
+
+ int spispeed_idx = 0;
+ char *spispeed = extract_programmer_param("spispeed");
+ if (spispeed != NULL) {
+ int i = 0;
+ for (; spispeeds[i].name; i++) {
+ if (strcasecmp(spispeeds[i].name, spispeed) == 0) {
+ spispeed_idx = i;
+ break;
+ }
+ }
+ if (spispeeds[i].name == NULL) {
+ msg_perr("Error: Invalid 'spispeed' value.\n");
+ free(spispeed);
+ return 1;
+ }
+ free(spispeed);
+ }
+
+ int millivolt = 3500;
+ char *voltage = extract_programmer_param("voltage");
+ if (voltage != NULL) {
+ millivolt = parse_voltage(voltage);
+ free(voltage);
+ if (millivolt < 0)
+ return 1;
+ }
+
+ /* Here comes the USB stuff */
+ usb_init();
+ (void)usb_find_busses();
+ (void)usb_find_devices();
+ struct usb_device *dev = get_device_by_vid_pid(PICKIT2_VID, PICKIT2_PID, usedevice);
+ if (dev == NULL) {
+ msg_perr("Could not find a PICkit2 on USB!\n");
+ return 1;
+ }
+ msg_pdbg("Found USB device (%04x:%04x).\n", dev->descriptor.idVendor, dev->descriptor.idProduct);
+
+ pickit2_handle = usb_open(dev);
+ int ret = usb_set_configuration(pickit2_handle, 1);
+ if (ret != 0) {
+ msg_perr("Could not set USB device configuration: %i %s\n", ret, usb_strerror());
+ if (usb_close(pickit2_handle) != 0)
+ msg_perr("Could not close USB device!\n");
+ return 1;
+ }
+ ret = usb_claim_interface(pickit2_handle, 0);
+ if (ret != 0) {
+ msg_perr("Could not claim USB device interface %i: %i %s\n", 0, ret, usb_strerror());
+ if (usb_close(pickit2_handle) != 0)
+ msg_perr("Could not close USB device!\n");
+ return 1;
+ }
+
+ if (register_shutdown(pickit2_shutdown, NULL) != 0) {
+ return 1;
+ }
+
+ if (pickit2_get_firmware_version()) {
+ return 1;
+ }
+
+ /* Command Set SPI Speed */
+ if (pickit2_set_spi_speed(spispeed_idx)) {
+ return 1;
+ }
+
+ /* Command Set SPI Voltage */
+ msg_pdbg("Setting voltage to %i mV.\n", millivolt);
+ if (pickit2_set_spi_voltage(millivolt) != 0) {
+ return 1;
+ }
+
+ /* Perform basic setup.
+ * Configure pin directions and logic levels, turn Vdd on, turn busy LED on and clear buffers. */
+ ret = usb_interrupt_write(pickit2_handle, ENDPOINT_OUT, (char *)buf, CMD_LENGTH, DFLT_TIMEOUT);
+ if (ret != CMD_LENGTH) {
+ msg_perr("Command Setup failed (%s)!\n", usb_strerror());
+ return 1;
+ }
+
+ register_spi_master(&spi_master_pickit2);
+
+ return 0;
+}
diff --git a/programmer.h b/programmer.h
index c61f429..913522b 100644
--- a/programmer.h
+++ b/programmer.h
@@ -102,6 +102,9 @@ enum programmer {
#if CONFIG_MSTARDDC_SPI == 1
PROGRAMMER_MSTARDDC_SPI,
#endif
+#if CONFIG_PICKIT2_SPI == 1
+ PROGRAMMER_PICKIT2_SPI,
+#endif
PROGRAMMER_INVALID /* This must always be the last entry. */
};
@@ -480,6 +483,11 @@ extern const struct dev_entry devs_usbblasterspi[];
int mstarddc_spi_init(void);
#endif
+/* pickit2_spi.c */
+#if CONFIG_PICKIT2_SPI == 1
+int pickit2_spi_init(void);
+#endif
+
/* rayer_spi.c */
#if CONFIG_RAYER_SPI == 1
int rayer_spi_init(void);
@@ -564,6 +572,9 @@ enum spi_controller {
#if CONFIG_MSTARDDC_SPI == 1
SPI_CONTROLLER_MSTARDDC,
#endif
+#if CONFIG_PICKIT2_SPI == 1
+ SPI_CONTROLLER_PICKIT2,
+#endif
};
#define MAX_DATA_UNSPECIFIED 0
OpenPOWER on IntegriCloud