This is a bitbanging SPI driver without hardware support. If you want support for a particular piece of hardware, just fill in a few functions. That's it.
Tested, trace looks OK.
Not 0.9.1 material. If I get an ack, I'll commit after 0.9.1.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-bitbang_spi/flash.h =================================================================== --- flashrom-bitbang_spi/flash.h (Revision 682) +++ flashrom-bitbang_spi/flash.h (Arbeitskopie) @@ -90,6 +90,7 @@ #if SERPROG_SUPPORT == 1 PROGRAMMER_SERPROG, #endif + PROGRAMMER_BITBANGSPI, PROGRAMMER_INVALID /* This must always be the last entry. */ };
@@ -390,6 +391,12 @@ int ft2232_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf);
+/* bitbang_spi.c */ +int bitbang_spi_init(void); +int bitbang_spi_send_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr); +int bitbang_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); +int bitbang_spi_write_256(struct flashchip *flash, uint8_t *buf); + /* flashrom.c */ extern char *programmer_param; extern int verbose; @@ -428,6 +435,7 @@ SPI_CONTROLLER_WBSIO, SPI_CONTROLLER_FT2232, SPI_CONTROLLER_DUMMY, + SPI_CONTROLLER_BITBANG, }; struct spi_command { unsigned int writecnt; Index: flashrom-bitbang_spi/bitbang_spi.c =================================================================== --- flashrom-bitbang_spi/bitbang_spi.c (Revision 0) +++ flashrom-bitbang_spi/bitbang_spi.c (Revision 0) @@ -0,0 +1,183 @@ +/* + * This file is part of the flashrom project. + * + * 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 <ctype.h> +#include "flash.h" +#include "spi.h" + +#if BITBANG_SPI_SUPPORT == 1 + +/* Length of half a clock period in usecs */ +int bitbang_half_period = 0; + +/* Empty functions, need to be replaced with actual driver implementation. */ +void bitbang_set_cs(int val) +{ +} + +void bitbang_set_sck(int val) +{ +} + +void bitbang_set_mosi(int val) +{ +} + +int bitbang_get_miso(void) +{ + return 1; +} + +int bitbang_spi_init(void) +{ + bitbang_set_cs(1); + bitbang_set_sck(0); + + buses_supported = CHIP_BUSTYPE_SPI; + spi_controller = SPI_CONTROLLER_BITBANG; + + return 0; +} + +uint8_t bitbang_spi_readwrite_byte(uint8_t val) +{ + uint8_t ret = 0; + int i; + + for (i = 7; i >= 0; i--) { + bitbang_set_mosi((val >> i) & 1); + programmer_delay(bitbang_half_period); + bitbang_set_sck(1); + ret <<= 1; + ret |= bitbang_get_miso(); + programmer_delay(bitbang_half_period); + bitbang_set_sck(0); + } + return ret; +} + +int bitbang_spi_send_command(unsigned int writecnt, unsigned int readcnt, + const unsigned char *writearr, unsigned char *readarr) +{ + static unsigned char *bufout = NULL; + static unsigned char *bufin = NULL; + static int oldbufsize = 0; + int bufsize = max(writecnt + readcnt, 260); + int i; + + /* Arbitrary size limitation here. We're only constrained by memory. */ + if (writecnt > 65536 || readcnt > 65536) + return SPI_INVALID_LENGTH; + + if (bufsize != oldbufsize) { + bufout = realloc(bufout, bufsize); + if (!bufout) { + fprintf(stderr, "Out of memory!\n"); + if (bufin) + free(bufin); + exit(1); + } + bufin = realloc(bufout, bufsize); + if (!bufin) { + fprintf(stderr, "Out of memory!\n"); + if (bufout) + free(bufout); + exit(1); + } + } + + memcpy(bufout, writearr, writecnt); + /* Shift out 0x00 while reading data. */ + memset(bufout + writecnt, 0x00, readcnt); + /* Make sure any non-read data is 0xff. */ + memset(bufin + writecnt, 0xff, readcnt); + + bitbang_set_cs(0); + for (i = 0; i < readcnt + writecnt; i++) { + bufin[i] = bitbang_spi_readwrite_byte(bufout[i]); + } + programmer_delay(bitbang_half_period); + bitbang_set_cs(1); + programmer_delay(bitbang_half_period); + memcpy(readarr, bufin + writecnt, readcnt); + + return 0; +} + +int bitbang_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len) +{ + /* Maximum read length is unlimited, use 64k bytes. */ + return spi_read_chunked(flash, buf, start, len, 64 * 1024); +} + +int bitbang_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; + + if ((r = spi_nbyte_program(i, &buf[i], l))) { + fprintf(stderr, "%s: write fail %d\n", __FUNCTION__, r); + return 1; + } + + while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) + /* loop */; + } + + return 0; +} + +#else +int bitbang_spi_init(void) +{ + fprintf(stderr, "Bitbanging SPI support was not compiled in\n"); + exit(1); +} + +int bitbang_spi_send_command(unsigned int writecnt, unsigned int readcnt, + const unsigned char *writearr, unsigned char *readarr) +{ + fprintf(stderr, "Bitbanging SPI support was not compiled in\n"); + exit(1); +} + +int bitbang_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len) +{ + fprintf(stderr, "Bitbanging SPI support was not compiled in\n"); + exit(1); +} + +int bitbang_spi_write_256(struct flashchip *flash, uint8_t *buf) +{ + fprintf(stderr, "Bitbanging SPI support was not compiled in\n"); + exit(1); +} +#endif Index: flashrom-bitbang_spi/spi.c =================================================================== --- flashrom-bitbang_spi/spi.c (Revision 682) +++ flashrom-bitbang_spi/spi.c (Arbeitskopie) @@ -95,6 +95,13 @@ .read = NULL, .write_256 = NULL, }, + + { /* SPI_CONTROLLER_BITBANG */ + .command = bitbang_spi_send_command, + .multicommand = default_spi_send_multicommand, + .read = bitbang_spi_read, + .write_256 = bitbang_spi_write_256, + }, };
Index: flashrom-bitbang_spi/Makefile =================================================================== --- flashrom-bitbang_spi/Makefile (Revision 682) +++ flashrom-bitbang_spi/Makefile (Arbeitskopie) @@ -67,11 +67,19 @@ # Always enable serprog for now. Needs to be disabled on Windows. CONFIG_SERPROG = yes
+# Bitbanging SPI is not yet ready. +CONFIG_BITBANG_SPI = yes + ifeq ($(CONFIG_SERPROG), yes) FEATURE_CFLAGS += -D'SERPROG_SUPPORT=1' OBJS += serprog.o endif
+ifeq ($(CONFIG_BITBANG_SPI), yes) +FEATURE_CFLAGS += -D'BITBANG_SPI_SUPPORT=1' +OBJS += bitbang_spi.o +endif + FEATURE_CFLAGS += $(shell LC_ALL=C grep -q "FTDISUPPORT := yes" .features && printf "%s" "-D'FT2232_SPI_SUPPORT=1'")
FEATURE_LIBS += $(shell LC_ALL=C grep -q "FTDISUPPORT := yes" .features && printf "%s" "-lftdi") Index: flashrom-bitbang_spi/flashrom.c =================================================================== --- flashrom-bitbang_spi/flashrom.c (Revision 682) +++ flashrom-bitbang_spi/flashrom.c (Arbeitskopie) @@ -158,6 +158,23 @@ }, #endif
+ { + .name = "bitbangspi", + .init = bitbang_spi_init, + .shutdown = fallback_shutdown, + .map_flash_region = fallback_map, + .unmap_flash_region = fallback_unmap, + .chip_readb = dummy_chip_readb, + .chip_readw = fallback_chip_readw, + .chip_readl = fallback_chip_readl, + .chip_readn = fallback_chip_readn, + .chip_writeb = fallback_chip_writeb, + .chip_writew = fallback_chip_writew, + .chip_writel = fallback_chip_writel, + .chip_writen = fallback_chip_writen, + .delay = internal_delay, + }, + {}, /* This entry corresponds to PROGRAMMER_INVALID. */ };
@@ -512,7 +529,7 @@ " -z | --list-supported-wiki: print supported devices in wiki syntax\n" " -p | --programmer <name>: specify the programmer device\n" " (internal, dummy, nic3com, satasii,\n" - " it87spi, ft2232spi, serprog)\n" + " it87spi, ft2232spi, serprog, bitbangspi)\n" " -h | --help: print this help text\n" " -R | --version: print the version (release)\n" "\nYou can specify one of -E, -r, -w, -v or no operation. If no operation is\n"