1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-26 14:42:36 +02:00

Add Altera USB-Blaster SPI programmer

Adds support for the Altera USB-Blaster programming dongle in Active
Serial (AS) mode. Tested on both original product and a clone dongle.

Corresponding to flashrom svn r1658.

Signed-off-by: James Laird <jhl@mafipulation.org>
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
Acked-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Acked-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
This commit is contained in:
James Laird 2013-03-27 13:00:23 +00:00 committed by Stefan Tauner
parent 226037da3d
commit c60de0e87f
6 changed files with 282 additions and 7 deletions

View File

@ -128,6 +128,11 @@ UNSUPPORTED_FEATURES += CONFIG_FT2232_SPI=yes
else else
override CONFIG_FT2232_SPI = no override CONFIG_FT2232_SPI = no
endif endif
ifeq ($(CONFIG_USBBLASTER_SPI), yes)
UNSUPPORTED_FEATURES += CONFIG_USBBLASTER_SPI=yes
else
override CONFIG_USBBLASTER_SPI = no
endif
endif endif
# FIXME: Should we check for Cygwin/MSVC as well? # FIXME: Should we check for Cygwin/MSVC as well?
@ -240,6 +245,11 @@ UNSUPPORTED_FEATURES += CONFIG_FT2232_SPI=yes
else else
override CONFIG_FT2232_SPI = no override CONFIG_FT2232_SPI = no
endif endif
ifeq ($(CONFIG_USBBLASTER_SPI), yes)
UNSUPPORTED_FEATURES += CONFIG_USBBLASTER_SPI=yes
else
override CONFIG_USBBLASTER_SPI = no
endif
endif endif
ifneq ($(TARGET_OS), Linux) ifneq ($(TARGET_OS), Linux)
@ -349,6 +359,9 @@ CONFIG_ATAHPT ?= no
# Always enable FT2232 SPI dongles for now. # Always enable FT2232 SPI dongles for now.
CONFIG_FT2232_SPI ?= yes CONFIG_FT2232_SPI ?= yes
# Always enable Altera USB-Blaster dongles for now.
CONFIG_USBBLASTER_SPI ?= yes
# Always enable dummy tracing for now. # Always enable dummy tracing for now.
CONFIG_DUMMY ?= yes CONFIG_DUMMY ?= yes
@ -474,12 +487,23 @@ NEED_PCI := yes
endif endif
ifeq ($(CONFIG_FT2232_SPI), yes) ifeq ($(CONFIG_FT2232_SPI), yes)
FTDILIBS := $(shell pkg-config --libs libftdi 2>/dev/null || printf "%s" "-lftdi -lusb")
# This is a totally ugly hack. # This is a totally ugly hack.
FEATURE_CFLAGS += $(shell LC_ALL=C grep -q "FTDISUPPORT := yes" .features && printf "%s" "-D'CONFIG_FT2232_SPI=1'") FEATURE_CFLAGS += $(shell LC_ALL=C grep -q "FTDISUPPORT := yes" .features && printf "%s" "-D'CONFIG_FT2232_SPI=1'")
NEED_FTDI := yes
PROGRAMMER_OBJS += ft2232_spi.o
endif
ifeq ($(CONFIG_USBBLASTER_SPI), yes)
# This is a totally ugly hack.
FEATURE_CFLAGS += $(shell LC_ALL=C grep -q "FTDISUPPORT := yes" .features && printf "%s" "-D'CONFIG_USBBLASTER_SPI=1'")
NEED_FTDI := yes
PROGRAMMER_OBJS += usbblaster_spi.o
endif
ifeq ($(NEED_FTDI), yes)
FTDILIBS := $(shell pkg-config --libs libftdi 2>/dev/null || printf "%s" "-lftdi -lusb")
FEATURE_CFLAGS += $(shell LC_ALL=C grep -q "FT232H := yes" .features && printf "%s" "-D'HAVE_FT232H=1'") FEATURE_CFLAGS += $(shell LC_ALL=C grep -q "FT232H := yes" .features && printf "%s" "-D'HAVE_FT232H=1'")
FEATURE_LIBS += $(shell LC_ALL=C grep -q "FTDISUPPORT := yes" .features && printf "%s" "$(FTDILIBS)") FEATURE_LIBS += $(shell LC_ALL=C grep -q "FTDISUPPORT := yes" .features && printf "%s" "$(FTDILIBS)")
PROGRAMMER_OBJS += ft2232_spi.o
# We can't set NEED_USB here because that would transform libftdi auto-enabling # We can't set NEED_USB here because that would transform libftdi auto-enabling
# into a hard requirement for libusb, defeating the purpose of auto-enabling. # into a hard requirement for libusb, defeating the purpose of auto-enabling.
endif endif
@ -799,7 +823,7 @@ export LINUX_SPI_TEST
features: compiler features: compiler
@echo "FEATURES := yes" > .features.tmp @echo "FEATURES := yes" > .features.tmp
ifeq ($(CONFIG_FT2232_SPI), yes) ifeq ($(NEED_FTDI), yes)
@printf "Checking for FTDI support... " @printf "Checking for FTDI support... "
@echo "$$FTDI_TEST" > .featuretest.c @echo "$$FTDI_TEST" > .featuretest.c
@$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) .featuretest.c -o .featuretest$(EXEC_SUFFIX) $(FTDILIBS) $(LIBS) >/dev/null 2>&1 && \ @$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) .featuretest.c -o .featuretest$(EXEC_SUFFIX) $(FTDILIBS) $(LIBS) >/dev/null 2>&1 && \

4
README
View File

@ -45,8 +45,8 @@ Build Instructions
To build flashrom you need to install the following software: To build flashrom you need to install the following software:
* pciutils+libpci (if you want support for mainboard or PCI device flashing) * pciutils+libpci (if you want support for mainboard or PCI device flashing)
* libusb (if you want FT2232 or Dediprog support) * libusb (if you want FT2232, Dediprog or USB-Blaster support)
* libftdi (if you want FT2232 support) * libftdi (if you want FT2232 or USB-Blaster support)
Linux et al: Linux et al:

View File

@ -220,6 +220,8 @@ bitbanging adapter)
.sp .sp
.BR "* linux_spi" " (for SPI flash ROMs accessible via /dev/spidevX.Y on Linux)" .BR "* linux_spi" " (for SPI flash ROMs accessible via /dev/spidevX.Y on Linux)"
.sp .sp
.BR "* usbblaster_spi" " (for SPI flash ROMs attached to an Altera USB-Blaster compatible cable)"
.sp
Some programmers have optional or mandatory parameters which are described Some programmers have optional or mandatory parameters which are described
in detail in the in detail in the
.B PROGRAMMER SPECIFIC INFO .B PROGRAMMER SPECIFIC INFO
@ -837,7 +839,7 @@ needs TCP access to the network or userspace access to a serial port.
.B buspirate_spi .B buspirate_spi
needs userspace access to a serial port. needs userspace access to a serial port.
.sp .sp
.BR dediprog " and " ft2232_spi .BR dediprog ", " ft2232_spi " and " usbblaster_spi
need access to the USB device via libusb. need access to the USB device via libusb.
.sp .sp
.B dummy .B dummy
@ -847,7 +849,7 @@ needs no access permissions at all.
.BR gfxnvidia ", " drkaiser ", " satasii ", " satamv " and " atahpt .BR gfxnvidia ", " drkaiser ", " satasii ", " satamv " and " atahpt
have to be run as superuser/root, and need additional raw access permission. have to be run as superuser/root, and need additional raw access permission.
.sp .sp
.BR serprog ", " buspirate_spi ", " dediprog " and " ft2232_spi .BR serprog ", " buspirate_spi ", " dediprog ", " usbblaster_spi " and " ft2232_spi
can be run as normal user on most operating systems if appropriate device can be run as normal user on most operating systems if appropriate device
permissions are set. permissions are set.
.sp .sp

View File

@ -308,6 +308,18 @@ const struct programmer_entry programmer_table[] = {
}, },
#endif #endif
#if CONFIG_USBBLASTER_SPI == 1
{
.name = "usbblaster_spi",
.type = USB,
.devs.dev = devs_usbblasterspi,
.init = usbblaster_spi_init,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.delay = internal_delay,
},
#endif
{0}, /* This entry corresponds to PROGRAMMER_INVALID. */ {0}, /* This entry corresponds to PROGRAMMER_INVALID. */
}; };

View File

@ -86,6 +86,9 @@ enum programmer {
#endif #endif
#if CONFIG_LINUX_SPI == 1 #if CONFIG_LINUX_SPI == 1
PROGRAMMER_LINUX_SPI, PROGRAMMER_LINUX_SPI,
#endif
#if CONFIG_USBBLASTER_SPI == 1
PROGRAMMER_USBBLASTER_SPI,
#endif #endif
PROGRAMMER_INVALID /* This must always be the last entry. */ PROGRAMMER_INVALID /* This must always be the last entry. */
}; };
@ -431,6 +434,12 @@ int ft2232_spi_init(void);
extern const struct dev_entry devs_ft2232spi[]; extern const struct dev_entry devs_ft2232spi[];
#endif #endif
/* usbblaster_spi.c */
#if CONFIG_USBBLASTER_SPI == 1
int usbblaster_spi_init(void);
extern const struct dev_entry devs_usbblasterspi[];
#endif
/* rayer_spi.c */ /* rayer_spi.c */
#if CONFIG_RAYER_SPI == 1 #if CONFIG_RAYER_SPI == 1
int rayer_spi_init(void); int rayer_spi_init(void);
@ -509,6 +518,9 @@ enum spi_controller {
#if CONFIG_SERPROG == 1 #if CONFIG_SERPROG == 1
SPI_CONTROLLER_SERPROG, SPI_CONTROLLER_SERPROG,
#endif #endif
#if CONFIG_USBBLASTER_SPI == 1
SPI_CONTROLLER_USBBLASTER,
#endif
}; };
#define MAX_DATA_UNSPECIFIED 0 #define MAX_DATA_UNSPECIFIED 0

225
usbblaster_spi.c Normal file
View File

@ -0,0 +1,225 @@
/*
* This file is part of the flashrom project.
*
* Copyright (C) 2012 James Laird <jhl@mafipulation.org>
*
* 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
*/
/*
* Device should be connected as per "active serial" mode:
*
* +---------+------+-----------+
* | SPI | Pin | Altera |
* +---------+------+-----------+
* | SCLK | 1 | DCLK |
* | GND | 2,10 | GND |
* | VCC | 4 | VCC(TRGT) |
* | MISO | 7 | DATAOUT |
* | /CS | 8 | nCS |
* | MOSI | 9 | ASDI |
* +---------+------+-----------+
*
* See also the USB-Blaster Download Cable User Guide: http://www.altera.com/literature/ug/ug_usb_blstr.pdf
*/
#if CONFIG_USBBLASTER_SPI == 1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <ftdi.h>
#include "flash.h"
#include "programmer.h"
#include "spi.h"
/* Please keep sorted by vendor ID, then device ID. */
#define ALTERA_VID 0x09fb
#define ALTERA_USBBLASTER_PID 0x6001
const struct dev_entry devs_usbblasterspi[] = {
{ALTERA_VID, ALTERA_USBBLASTER_PID, OK, "Altera", "USB-Blaster"},
{}
};
static const struct spi_programmer spi_programmer_usbblaster;
static struct ftdi_context ftdic;
// command bytes
#define BIT_BYTE (1<<7) // byte mode (rather than bitbang)
#define BIT_READ (1<<6) // read request
#define BIT_LED (1<<5)
#define BIT_CS (1<<3)
#define BIT_TMS (1<<1)
#define BIT_CLK (1<<0)
#define BUF_SIZE 64
/* The programmer shifts bits in the wrong order for SPI, so we use this method to reverse the bits when needed.
* http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits */
uint8_t reverse(uint8_t b)
{
return ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
}
/* Returns 0 upon success, a negative number upon errors. */
int usbblaster_spi_init(void)
{
uint8_t buf[BUF_SIZE + 1];
if (ftdi_init(&ftdic) < 0)
return -1;
if (ftdi_usb_open(&ftdic, ALTERA_VID, ALTERA_USBBLASTER_PID) < 0) {
msg_perr("Failed to open USB-Blaster: %s\n", ftdic.error_str);
return -1;
}
if (ftdi_usb_reset(&ftdic) < 0) {
msg_perr("USB-Blaster reset failed\n");
return -1;
}
if (ftdi_set_latency_timer(&ftdic, 2) < 0) {
msg_perr("USB-Blaster set latency timer failed\n");
return -1;
}
if (ftdi_write_data_set_chunksize(&ftdic, 4096) < 0 ||
ftdi_read_data_set_chunksize(&ftdic, BUF_SIZE) < 0) {
msg_perr("USB-Blaster set chunk size failed\n");
return -1;
}
memset(buf, 0, sizeof(buf));
buf[sizeof(buf)-1] = BIT_LED | BIT_CS;
if (ftdi_write_data(&ftdic, buf, sizeof(buf)) < 0) {
msg_perr("USB-Blaster reset write failed\n");
return -1;
}
if (ftdi_read_data(&ftdic, buf, sizeof(buf)) < 0) {
msg_perr("USB-Blaster reset read failed\n");
return -1;
}
register_spi_programmer(&spi_programmer_usbblaster);
return 0;
}
static int send_write(unsigned int writecnt, const unsigned char *writearr)
{
int i;
uint8_t buf[BUF_SIZE];
memset(buf, 0, sizeof(buf));
while (writecnt) {
unsigned int n_write = min(writecnt, BUF_SIZE - 1);
msg_pspew("writing %d-byte packet\n", n_write);
buf[0] = BIT_BYTE | (uint8_t)n_write;
for (i = 0; i < n_write; i++) {
buf[i+1] = reverse(writearr[i]);
}
if (ftdi_write_data(&ftdic, buf, n_write + 1) < 0) {
msg_perr("USB-Blaster write failed\n");
return -1;
}
writearr += n_write;
writecnt -= n_write;
}
return 0;
}
static int send_read(unsigned int readcnt, unsigned char *readarr)
{
int i;
unsigned int n_read;
uint8_t buf[BUF_SIZE];
memset(buf, 0, sizeof(buf));
n_read = readcnt;
while (n_read) {
unsigned int payload_size = min(n_read, BUF_SIZE - 1);
msg_pspew("reading %d-byte packet\n", payload_size);
buf[0] = BIT_BYTE | BIT_READ | (uint8_t)payload_size;
if (ftdi_write_data(&ftdic, buf, payload_size + 1) < 0) {
msg_perr("USB-Blaster write failed\n");
return -1;
}
n_read -= payload_size;
};
n_read = readcnt;
while (n_read) {
int ret = ftdi_read_data(&ftdic, readarr, n_read);
if (ret < 0) {
msg_perr("USB-Blaster read failed\n");
return -1;
}
for (i = 0; i < ret; i++) {
readarr[i] = reverse(readarr[i]);
}
n_read -= ret;
readarr += ret;
}
return 0;
}
/* Returns 0 upon success, a negative number upon errors. */
static int usbblaster_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr)
{
uint8_t cmd;
int ret = 0;
cmd = BIT_LED; // asserts /CS
if (ftdi_write_data(&ftdic, &cmd, 1) < 0) {
msg_perr("USB-Blaster enable chip select failed\n");
ret = -1;
}
if (!ret && writecnt)
ret = send_write(writecnt, writearr);
if (!ret && readcnt)
ret = send_read(readcnt, readarr);
cmd = BIT_CS;
if (ftdi_write_data(&ftdic, &cmd, 1) < 0) {
msg_perr("USB-Blaster disable chip select failed\n");
ret = -1;
}
return ret;
}
static const struct spi_programmer spi_programmer_usbblaster = {
.type = SPI_CONTROLLER_USBBLASTER,
.max_data_read = 256,
.max_data_write = 256,
.command = usbblaster_spi_send_command,
.multicommand = default_spi_send_multicommand,
.read = default_spi_read,
.write_256 = default_spi_write_256,
.write_aai = default_spi_write_aai,
};
#endif