mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-30 00:13:43 +02:00
This patch adds support for a new SPI programmer, based on the FT2232H/4232H chip from FTDI
FTDI support is autodetected during compilation. Paul writes: There are certainly possible improvements: The code has hard-coded values for which interface of the ftdi chip to use (interface B was chosen because libftdi seems to have trouble with A right now), what clock rate use for the SPI interface (I've been running at 30Mhz, but the patch sets it to 10Mhz), and possibly others. I think this means that per-programmer options might be a good idea at some point. Carl-Daniel writes: There is one additional FIXME comment in the code, but AFAICS that problem is not solvable with current libftdi. Corresponding to flashrom svn r598. Signed-off-by: Paul Fox <pgf@laptop.org> Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Acked-by: Uwe Hermann <uwe@hermann-uwe.de>
This commit is contained in:
parent
4cb7a96153
commit
05dfbe67d6
36
Makefile
36
Makefile
@ -22,6 +22,7 @@ PROGRAM = flashrom
|
|||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
STRIP = strip
|
STRIP = strip
|
||||||
INSTALL = install
|
INSTALL = install
|
||||||
|
DIFF = diff
|
||||||
PREFIX ?= /usr/local
|
PREFIX ?= /usr/local
|
||||||
MANDIR ?= $(PREFIX)/share/man
|
MANDIR ?= $(PREFIX)/share/man
|
||||||
CFLAGS ?= -Os -Wall -Werror
|
CFLAGS ?= -Os -Wall -Werror
|
||||||
@ -48,9 +49,9 @@ OBJS = chipset_enable.o board_enable.o udelay.o jedec.o stm50flw0x0x.o \
|
|||||||
sst49lfxxxc.o sst_fwhub.o layout.o cbtable.o flashchips.o physmap.o \
|
sst49lfxxxc.o sst_fwhub.o layout.o cbtable.o flashchips.o physmap.o \
|
||||||
flashrom.o w39v080fa.o sharplhf00l04.o w29ee011.o spi.o it87spi.o \
|
flashrom.o w39v080fa.o sharplhf00l04.o w29ee011.o spi.o it87spi.o \
|
||||||
ichspi.o w39v040c.o sb600spi.o wbsio_spi.o m29f002.o internal.o \
|
ichspi.o w39v040c.o sb600spi.o wbsio_spi.o m29f002.o internal.o \
|
||||||
dummyflasher.o pcidev.o nic3com.o satasii.o
|
dummyflasher.o pcidev.o nic3com.o satasii.o ft2232_spi.o
|
||||||
|
|
||||||
all: pciutils dep $(PROGRAM)
|
all: pciutils .features dep $(PROGRAM)
|
||||||
|
|
||||||
# Set the flashrom version string from the highest revision number
|
# Set the flashrom version string from the highest revision number
|
||||||
# of the checked out flashrom files.
|
# of the checked out flashrom files.
|
||||||
@ -63,16 +64,19 @@ VERSION := 0.9.0-r$(SVNVERSION)
|
|||||||
SVNDEF := -D'FLASHROM_VERSION="$(VERSION)"'
|
SVNDEF := -D'FLASHROM_VERSION="$(VERSION)"'
|
||||||
|
|
||||||
$(PROGRAM): $(OBJS)
|
$(PROGRAM): $(OBJS)
|
||||||
$(CC) $(LDFLAGS) -o $(PROGRAM) $(OBJS) $(LIBS)
|
$(CC) $(LDFLAGS) -o $(PROGRAM) $(OBJS) $(LIBS) $(FEATURE_LIBS)
|
||||||
|
|
||||||
flashrom.o: flashrom.c
|
flashrom.o: flashrom.c
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< $(SVNDEF)
|
$(CC) $(CFLAGS) $(CPPFLAGS) $(FEATURE_CFLAGS) -c -o $@ $< $(SVNDEF)
|
||||||
|
|
||||||
|
%.o: %.c .features
|
||||||
|
$(CC) $(CFLAGS) $(CPPFLAGS) $(FEATURE_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(PROGRAM) *.o
|
rm -f $(PROGRAM) *.o
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
rm -f .dependencies
|
rm -f .dependencies .features
|
||||||
|
|
||||||
dep:
|
dep:
|
||||||
@$(CC) $(CPPFLAGS) $(SVNDEF) -MM *.c > .dependencies
|
@$(CC) $(CPPFLAGS) $(SVNDEF) -MM *.c > .dependencies
|
||||||
@ -81,7 +85,7 @@ strip: $(PROGRAM)
|
|||||||
$(STRIP) $(STRIP_ARGS) $(PROGRAM)
|
$(STRIP) $(STRIP_ARGS) $(PROGRAM)
|
||||||
|
|
||||||
compiler:
|
compiler:
|
||||||
@echo; printf "Checking for a C compiler... "
|
@printf "Checking for a C compiler... "
|
||||||
@$(shell ( echo "int main(int argc, char **argv)"; \
|
@$(shell ( echo "int main(int argc, char **argv)"; \
|
||||||
echo "{ return 0; }"; ) > .test.c )
|
echo "{ return 0; }"; ) > .test.c )
|
||||||
@$(CC) $(CFLAGS) $(LDFLAGS) .test.c -o .test >/dev/null && \
|
@$(CC) $(CFLAGS) $(LDFLAGS) .test.c -o .test >/dev/null && \
|
||||||
@ -89,8 +93,10 @@ compiler:
|
|||||||
rm -f .test.c .test; exit 1)
|
rm -f .test.c .test; exit 1)
|
||||||
@rm -f .test.c .test
|
@rm -f .test.c .test
|
||||||
|
|
||||||
pciutils: compiler
|
# We don't specify compiler as requirement because the compiler is already
|
||||||
@echo; printf "Checking for pciutils and zlib... "
|
# checked during makefile remake through .features
|
||||||
|
pciutils:
|
||||||
|
@printf "Checking for pciutils and zlib... "
|
||||||
@$(shell ( echo "#include <pci/pci.h>"; \
|
@$(shell ( echo "#include <pci/pci.h>"; \
|
||||||
echo "struct pci_access *pacc;"; \
|
echo "struct pci_access *pacc;"; \
|
||||||
echo "int main(int argc, char **argv)"; \
|
echo "int main(int argc, char **argv)"; \
|
||||||
@ -102,6 +108,19 @@ pciutils: compiler
|
|||||||
rm -f .test.c .test; exit 1)
|
rm -f .test.c .test; exit 1)
|
||||||
@rm -f .test.c .test
|
@rm -f .test.c .test
|
||||||
|
|
||||||
|
.features: compiler
|
||||||
|
@printf "Checking for FTDI support... "
|
||||||
|
@$(shell ( echo "#include <ftdi.h>"; \
|
||||||
|
echo "struct ftdi_context *ftdic = NULL;"; \
|
||||||
|
echo "int main(int argc, char **argv)"; \
|
||||||
|
echo "{ return ftdi_init(ftdic); }"; ) > .featuretest.c )
|
||||||
|
@$(CC) $(CFLAGS) $(LDFLAGS) .featuretest.c -o .featuretest $(LIBS) -lftdi >/dev/null 2>&1 && \
|
||||||
|
( echo "found."; echo FEATURE_CFLAGS := -D'FT2232_SPI_SUPPORT=1' > .features.tmp; \
|
||||||
|
echo FEATURE_LIBS := -lftdi >> .features.tmp) || \
|
||||||
|
( echo "not found."; echo "" > .features.tmp )
|
||||||
|
@$(DIFF) -q .features.tmp .features >/dev/null 2>&1 && rm .features.tmp || mv .features.tmp .features
|
||||||
|
@rm -f .featuretest.c .featuretest
|
||||||
|
|
||||||
install: $(PROGRAM)
|
install: $(PROGRAM)
|
||||||
mkdir -p $(DESTDIR)$(PREFIX)/sbin
|
mkdir -p $(DESTDIR)$(PREFIX)/sbin
|
||||||
mkdir -p $(DESTDIR)$(MANDIR)/man8
|
mkdir -p $(DESTDIR)$(MANDIR)/man8
|
||||||
@ -122,3 +141,4 @@ tarball: export
|
|||||||
.PHONY: all clean distclean dep compiler pciutils export tarball
|
.PHONY: all clean distclean dep compiler pciutils export tarball
|
||||||
|
|
||||||
-include .dependencies
|
-include .dependencies
|
||||||
|
-include .features
|
||||||
|
9
flash.h
9
flash.h
@ -86,6 +86,7 @@ extern int programmer;
|
|||||||
#define PROGRAMMER_NIC3COM 0x02
|
#define PROGRAMMER_NIC3COM 0x02
|
||||||
#define PROGRAMMER_SATASII 0x03
|
#define PROGRAMMER_SATASII 0x03
|
||||||
#define PROGRAMMER_IT87SPI 0x04
|
#define PROGRAMMER_IT87SPI 0x04
|
||||||
|
#define PROGRAMMER_FT2232SPI 0x05
|
||||||
|
|
||||||
struct programmer_entry {
|
struct programmer_entry {
|
||||||
const char *vendor;
|
const char *vendor;
|
||||||
@ -358,6 +359,13 @@ void satasii_chip_writeb(uint8_t val, chipaddr addr);
|
|||||||
uint8_t satasii_chip_readb(const chipaddr addr);
|
uint8_t satasii_chip_readb(const chipaddr addr);
|
||||||
extern struct pcidev_status satas_sii[];
|
extern struct pcidev_status satas_sii[];
|
||||||
|
|
||||||
|
/* ft2232_spi.c */
|
||||||
|
int ft2232_spi_init(void);
|
||||||
|
int ft2232_spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr);
|
||||||
|
int ft2232_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len);
|
||||||
|
int ft2232_spi_write1(struct flashchip *flash, uint8_t *buf);
|
||||||
|
int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf);
|
||||||
|
|
||||||
/* flashrom.c */
|
/* flashrom.c */
|
||||||
extern int verbose;
|
extern int verbose;
|
||||||
#define printf_debug(x...) { if (verbose) printf(x); }
|
#define printf_debug(x...) { if (verbose) printf(x); }
|
||||||
@ -388,6 +396,7 @@ enum spi_controller {
|
|||||||
SPI_CONTROLLER_SB600,
|
SPI_CONTROLLER_SB600,
|
||||||
SPI_CONTROLLER_VIA,
|
SPI_CONTROLLER_VIA,
|
||||||
SPI_CONTROLLER_WBSIO,
|
SPI_CONTROLLER_WBSIO,
|
||||||
|
SPI_CONTROLLER_FT2232,
|
||||||
SPI_CONTROLLER_DUMMY,
|
SPI_CONTROLLER_DUMMY,
|
||||||
};
|
};
|
||||||
extern enum spi_controller spi_controller;
|
extern enum spi_controller spi_controller;
|
||||||
|
@ -136,6 +136,8 @@ Specify the programmer device. Currently supported are:
|
|||||||
.sp
|
.sp
|
||||||
.BR "* it87spi" " (for flash ROMs behind an ITE IT87xx Super I/O LPC/SPI translation unit)"
|
.BR "* it87spi" " (for flash ROMs behind an ITE IT87xx Super I/O LPC/SPI translation unit)"
|
||||||
.sp
|
.sp
|
||||||
|
.BR "* ft2232spi" " (for flash ROMs attached to a FT2232H/FT4232H based USB SPI programmer)"
|
||||||
|
.sp
|
||||||
The dummy programmer has an optional parameter specifying the bus types it
|
The dummy programmer has an optional parameter specifying the bus types it
|
||||||
should support. For that you have to use the
|
should support. For that you have to use the
|
||||||
.B "flashrom -p dummy=type"
|
.B "flashrom -p dummy=type"
|
||||||
|
20
flashrom.c
20
flashrom.c
@ -116,6 +116,22 @@ const struct programmer_entry programmer_table[] = {
|
|||||||
.delay = internal_delay,
|
.delay = internal_delay,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
.init = ft2232_spi_init,
|
||||||
|
.shutdown = dummy_shutdown,
|
||||||
|
.map_flash_region = dummy_map,
|
||||||
|
.unmap_flash_region = dummy_unmap,
|
||||||
|
.chip_readb = dummy_chip_readb,
|
||||||
|
.chip_readw = fallback_chip_readw,
|
||||||
|
.chip_readl = fallback_chip_readl,
|
||||||
|
.chip_readn = fallback_chip_readn,
|
||||||
|
.chip_writeb = dummy_chip_writeb,
|
||||||
|
.chip_writew = fallback_chip_writew,
|
||||||
|
.chip_writel = fallback_chip_writel,
|
||||||
|
.chip_writen = fallback_chip_writen,
|
||||||
|
.delay = internal_delay,
|
||||||
|
},
|
||||||
|
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -589,7 +605,7 @@ void usage(const char *name)
|
|||||||
" -i | --image <name>: only flash image name from flash layout\n"
|
" -i | --image <name>: only flash image name from flash layout\n"
|
||||||
" -L | --list-supported: print supported devices\n"
|
" -L | --list-supported: print supported devices\n"
|
||||||
" -p | --programmer <name>: specify the programmer device\n"
|
" -p | --programmer <name>: specify the programmer device\n"
|
||||||
" (internal, dummy, nic3com, satasii, it87spi)\n"
|
" (internal, dummy, nic3com, satasii, it87spi, ft2232spi)\n"
|
||||||
" -h | --help: print this help text\n"
|
" -h | --help: print this help text\n"
|
||||||
" -R | --version: print the version (release)\n"
|
" -R | --version: print the version (release)\n"
|
||||||
"\nYou can specify one of -E, -r, -w, -v or no operation.\n"
|
"\nYou can specify one of -E, -r, -w, -v or no operation.\n"
|
||||||
@ -747,6 +763,8 @@ int main(int argc, char *argv[])
|
|||||||
pcidev_bdf = strdup(optarg + 8);
|
pcidev_bdf = strdup(optarg + 8);
|
||||||
} else if (strncmp(optarg, "it87spi", 7) == 0) {
|
} else if (strncmp(optarg, "it87spi", 7) == 0) {
|
||||||
programmer = PROGRAMMER_IT87SPI;
|
programmer = PROGRAMMER_IT87SPI;
|
||||||
|
} else if (strncmp(optarg, "ft2232spi", 9) == 0) {
|
||||||
|
programmer = PROGRAMMER_FT2232SPI;
|
||||||
} else {
|
} else {
|
||||||
printf("Error: Unknown programmer.\n");
|
printf("Error: Unknown programmer.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
284
ft2232_spi.c
Normal file
284
ft2232_spi.c
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the flashrom project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Paul Fox <pgf@laptop.org>
|
||||||
|
* Copyright (C) 2009 Carl-Daniel Hailfinger
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "flash.h"
|
||||||
|
#include "spi.h"
|
||||||
|
|
||||||
|
#if FT2232_SPI_SUPPORT == 1
|
||||||
|
|
||||||
|
#include <ftdi.h>
|
||||||
|
|
||||||
|
/* the 'H' chips can run internally at either 12Mhz or 60Mhz.
|
||||||
|
* the non-H chips can only run at 12Mhz. */
|
||||||
|
#define CLOCK_5X 1
|
||||||
|
|
||||||
|
/* in either case, the divisor is a simple integer clock divider.
|
||||||
|
* if CLOCK_5X is set, this divisor divides 30Mhz, else it
|
||||||
|
* divides 6Mhz */
|
||||||
|
#define DIVIDE_BY 3 // e.g. '3' will give either 10Mhz or 2Mhz spi clock
|
||||||
|
|
||||||
|
|
||||||
|
static struct ftdi_context ftdic_context;
|
||||||
|
|
||||||
|
int send_buf(struct ftdi_context *ftdic, const unsigned char *buf, int size)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
r = ftdi_write_data(ftdic, (unsigned char *) buf, size);
|
||||||
|
if (r < 0) {
|
||||||
|
fprintf(stderr, "ftdi_write_data: %d, %s\n", r,
|
||||||
|
ftdi_get_error_string(ftdic));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_buf(struct ftdi_context *ftdic, const unsigned char *buf, int size)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
r = ftdi_read_data(ftdic, (unsigned char *) buf, size);
|
||||||
|
if (r < 0) {
|
||||||
|
fprintf(stderr, "ftdi_read_data: %d, %s\n", r,
|
||||||
|
ftdi_get_error_string(ftdic));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft2232_spi_init(void)
|
||||||
|
{
|
||||||
|
int f;
|
||||||
|
struct ftdi_context *ftdic = &ftdic_context;
|
||||||
|
unsigned char buf[512];
|
||||||
|
unsigned char port_val = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if (ftdi_init(ftdic) < 0) {
|
||||||
|
fprintf(stderr, "ftdi_init failed\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// f = ftdi_usb_open(ftdic, 0x0403, 0x6010); // FT2232
|
||||||
|
f = ftdi_usb_open(ftdic, 0x0403, 0x6011); // FT4232
|
||||||
|
|
||||||
|
if (f < 0 && f != -5) {
|
||||||
|
fprintf(stderr, "Unable to open ftdi device: %d (%s)\n", f,
|
||||||
|
ftdi_get_error_string(ftdic));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftdi_set_interface(ftdic, INTERFACE_B) < 0) {
|
||||||
|
fprintf(stderr, "Unable to select FT2232 channel B: %s\n",
|
||||||
|
ftdic->error_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftdi_usb_reset(ftdic) < 0) {
|
||||||
|
fprintf(stderr, "Unable to reset ftdi device\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftdi_set_latency_timer(ftdic, 2) < 0) {
|
||||||
|
fprintf(stderr, "Unable to set latency timer\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftdi_write_data_set_chunksize(ftdic, 512)) {
|
||||||
|
fprintf(stderr, "Unable to set chunk size\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftdi_set_bitmode(ftdic, 0x00, 2) < 0) {
|
||||||
|
fprintf(stderr, "Unable to set bitmode\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CLOCK_5X
|
||||||
|
printf_debug("Disable divide-by-5 front stage\n");
|
||||||
|
buf[0] = 0x8a; /* disable divide-by-5 */
|
||||||
|
if (send_buf(ftdic, buf, 1))
|
||||||
|
return -1;
|
||||||
|
#define MPSSE_CLK 60.0
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define MPSSE_CLK 12.0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
printf_debug("Set clock divisor\n");
|
||||||
|
buf[0] = 0x86; /* command "set divisor" */
|
||||||
|
/* valueL/valueH are (desired_divisor - 1) */
|
||||||
|
buf[1] = (DIVIDE_BY-1) & 0xff;
|
||||||
|
buf[2] = ((DIVIDE_BY-1) >> 8) & 0xff;
|
||||||
|
if (send_buf(ftdic, buf, 3))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
printf("SPI clock is %fMHz\n",
|
||||||
|
(double)(MPSSE_CLK / (((DIVIDE_BY-1) + 1) * 2)));
|
||||||
|
|
||||||
|
/* Disconnect TDI/DO to TDO/DI for Loopback */
|
||||||
|
printf_debug("No loopback of tdi/do tdo/di\n");
|
||||||
|
buf[0] = 0x85;
|
||||||
|
if (send_buf(ftdic, buf, 1))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
printf_debug("Set data bits\n");
|
||||||
|
/* Set data bits low-byte command:
|
||||||
|
* value: 0x08 CS=high, DI=low, DO=low, SK=low
|
||||||
|
* dir: 0x0b CS=output, DI=input, DO=output, SK=output
|
||||||
|
*/
|
||||||
|
#define CS_BIT 0x08
|
||||||
|
|
||||||
|
buf[0] = SET_BITS_LOW;
|
||||||
|
buf[1] = (port_val = CS_BIT);
|
||||||
|
buf[2] = 0x0b;
|
||||||
|
if (send_buf(ftdic, buf, 3))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
printf_debug("\nft2232 chosen\n");
|
||||||
|
|
||||||
|
buses_supported = CHIP_BUSTYPE_SPI;
|
||||||
|
spi_controller = SPI_CONTROLLER_FT2232;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft2232_spi_command(unsigned int writecnt, unsigned int readcnt,
|
||||||
|
const unsigned char *writearr, unsigned char *readarr)
|
||||||
|
{
|
||||||
|
struct ftdi_context *ftdic = &ftdic_context;
|
||||||
|
static unsigned char *buf = NULL;
|
||||||
|
unsigned char port_val = 0;
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
buf = realloc(buf, writecnt + readcnt + 100);
|
||||||
|
if (!buf) {
|
||||||
|
fprintf(stderr, "Out of memory!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
/* minimize USB transfers by packing as many commands
|
||||||
|
* as possible together. if we're not expecting to
|
||||||
|
* read, we can assert CS, write, and deassert CS all
|
||||||
|
* in one shot. if reading, we do three separate
|
||||||
|
* operations. */
|
||||||
|
printf_debug("Assert CS#\n");
|
||||||
|
buf[i++] = SET_BITS_LOW;
|
||||||
|
buf[i++] = (port_val &= ~CS_BIT);
|
||||||
|
buf[i++] = 0x0b;
|
||||||
|
|
||||||
|
if (writecnt) {
|
||||||
|
buf[i++] = 0x11;
|
||||||
|
buf[i++] = (writecnt - 1) & 0xff;
|
||||||
|
buf[i++] = ((writecnt - 1) >> 8) & 0xff;
|
||||||
|
memcpy(buf+i, writearr, writecnt);
|
||||||
|
i += writecnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* optionally terminate this batch of commands with a
|
||||||
|
* read command, then do the fetch of the results.
|
||||||
|
*/
|
||||||
|
if (readcnt) {
|
||||||
|
buf[i++] = 0x20;
|
||||||
|
buf[i++] = (readcnt - 1) & 0xff;
|
||||||
|
buf[i++] = ((readcnt - 1) >> 8) & 0xff;
|
||||||
|
ret = send_buf(ftdic, buf, i);
|
||||||
|
i = 0;
|
||||||
|
if (ret) goto deassert_cs;
|
||||||
|
|
||||||
|
/* FIXME: This is unreliable. There's no guarantee that we read
|
||||||
|
* the response directly after sending the read command.
|
||||||
|
* We may be scheduled out etc.
|
||||||
|
*/
|
||||||
|
ret = get_buf(ftdic, readarr, readcnt);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
deassert_cs:
|
||||||
|
printf_debug("De-assert CS#\n");
|
||||||
|
buf[i++] = SET_BITS_LOW;
|
||||||
|
buf[i++] = (port_val |= CS_BIT);
|
||||||
|
buf[i++] = 0x0b;
|
||||||
|
if (send_buf(ftdic, buf, i))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft2232_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
|
||||||
|
{
|
||||||
|
/* Maximum read length is 64k bytes. */
|
||||||
|
return spi_read_chunked(flash, buf, start, len, 64 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf)
|
||||||
|
{
|
||||||
|
int total_size = 1024 * flash->total_size;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf_debug("total_size is %d\n", total_size);
|
||||||
|
for (i = 0; i < total_size; i += 256) {
|
||||||
|
int l, r;
|
||||||
|
if (i + 256 <= total_size)
|
||||||
|
l = 256;
|
||||||
|
else
|
||||||
|
l = total_size - i;
|
||||||
|
|
||||||
|
spi_write_enable();
|
||||||
|
if ((r = spi_nbyte_program(i, &buf[i], l))) {
|
||||||
|
fprintf(stderr, "%s: write fail %d\n", __FUNCTION__, r);
|
||||||
|
// spi_write_disable(); chip does this for us
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
|
||||||
|
/* loop */;
|
||||||
|
}
|
||||||
|
// spi_write_disable(); chip does this for us
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
int ft2232_spi_init(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "FT2232 SPI support was not compiled in\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft2232_spi_command(unsigned int writecnt, unsigned int readcnt,
|
||||||
|
const unsigned char *writearr, unsigned char *readarr)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "FT2232 SPI support was not compiled in\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft2232_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "FT2232 SPI support was not compiled in\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "FT2232 SPI support was not compiled in\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
7
spi.c
7
spi.c
@ -47,6 +47,8 @@ int spi_command(unsigned int writecnt, unsigned int readcnt,
|
|||||||
return sb600_spi_command(writecnt, readcnt, writearr, readarr);
|
return sb600_spi_command(writecnt, readcnt, writearr, readarr);
|
||||||
case SPI_CONTROLLER_WBSIO:
|
case SPI_CONTROLLER_WBSIO:
|
||||||
return wbsio_spi_command(writecnt, readcnt, writearr, readarr);
|
return wbsio_spi_command(writecnt, readcnt, writearr, readarr);
|
||||||
|
case SPI_CONTROLLER_FT2232:
|
||||||
|
return ft2232_spi_command(writecnt, readcnt, writearr, readarr);
|
||||||
case SPI_CONTROLLER_DUMMY:
|
case SPI_CONTROLLER_DUMMY:
|
||||||
return dummy_spi_command(writecnt, readcnt, writearr, readarr);
|
return dummy_spi_command(writecnt, readcnt, writearr, readarr);
|
||||||
default:
|
default:
|
||||||
@ -212,6 +214,7 @@ int probe_spi_rdid4(struct flashchip *flash)
|
|||||||
case SPI_CONTROLLER_VIA:
|
case SPI_CONTROLLER_VIA:
|
||||||
case SPI_CONTROLLER_SB600:
|
case SPI_CONTROLLER_SB600:
|
||||||
case SPI_CONTROLLER_WBSIO:
|
case SPI_CONTROLLER_WBSIO:
|
||||||
|
case SPI_CONTROLLER_FT2232:
|
||||||
case SPI_CONTROLLER_DUMMY:
|
case SPI_CONTROLLER_DUMMY:
|
||||||
return probe_spi_rdid_generic(flash, 4);
|
return probe_spi_rdid_generic(flash, 4);
|
||||||
default:
|
default:
|
||||||
@ -726,6 +729,8 @@ int spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len)
|
|||||||
return ich_spi_read(flash, buf, start, len);
|
return ich_spi_read(flash, buf, start, len);
|
||||||
case SPI_CONTROLLER_WBSIO:
|
case SPI_CONTROLLER_WBSIO:
|
||||||
return wbsio_spi_read(flash, buf, start, len);
|
return wbsio_spi_read(flash, buf, start, len);
|
||||||
|
case SPI_CONTROLLER_FT2232:
|
||||||
|
return ft2232_spi_read(flash, buf, start, len);
|
||||||
default:
|
default:
|
||||||
printf_debug
|
printf_debug
|
||||||
("%s called, but no SPI chipset/strapping detected\n",
|
("%s called, but no SPI chipset/strapping detected\n",
|
||||||
@ -774,6 +779,8 @@ int spi_chip_write_256(struct flashchip *flash, uint8_t *buf)
|
|||||||
return ich_spi_write_256(flash, buf);
|
return ich_spi_write_256(flash, buf);
|
||||||
case SPI_CONTROLLER_WBSIO:
|
case SPI_CONTROLLER_WBSIO:
|
||||||
return wbsio_spi_write_1(flash, buf);
|
return wbsio_spi_write_1(flash, buf);
|
||||||
|
case SPI_CONTROLLER_FT2232:
|
||||||
|
return ft2232_spi_write_256(flash, buf);
|
||||||
default:
|
default:
|
||||||
printf_debug
|
printf_debug
|
||||||
("%s called, but no SPI chipset/strapping detected\n",
|
("%s called, but no SPI chipset/strapping detected\n",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user