diff -urN jtag.old/libbrux/flash/detectflash.c jtag.dev/libbrux/flash/detectflash.c --- jtag.old/libbrux/flash/detectflash.c 2003-11-02 23:41:18.000000000 +0100 +++ jtag.dev/libbrux/flash/detectflash.c 2007-05-18 03:18:06.000000000 +0200 @@ -39,6 +39,7 @@ #include #include #include +#include "noncfi.h" cfi_array_t *cfi_array = NULL; @@ -60,6 +61,12 @@ bus_prepare( bus ); + if (spiflash_probe(bus, adr, &cfi_array)) + return; + + cfi_array_free( cfi_array ); + cfi_array = NULL; + if (cfi_detect( bus, adr, &cfi_array )) { cfi_array_free( cfi_array ); cfi_array = NULL; diff -urN jtag.old/libbrux/flash/noncfi.h jtag.dev/libbrux/flash/noncfi.h --- jtag.old/libbrux/flash/noncfi.h 1970-01-01 01:00:00.000000000 +0100 +++ jtag.dev/libbrux/flash/noncfi.h 2007-05-17 22:43:55.000000000 +0200 @@ -0,0 +1,4 @@ + +#define CFI_VENDOR_STM 0xff01 + +int spiflash_probe(bus_t *bus, uint32_t adr, cfi_array_t **cfi_array); diff -urN jtag.old/libbrux/flash/spiflash.c jtag.dev/libbrux/flash/spiflash.c --- jtag.old/libbrux/flash/spiflash.c 1970-01-01 01:00:00.000000000 +0100 +++ jtag.dev/libbrux/flash/spiflash.c 2007-05-18 03:18:06.000000000 +0200 @@ -0,0 +1,273 @@ +/* + * Flash driver for spiflash on Atheros WiSoC + * Copyright (C) 2007 Felix Fietkau + * + * 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. + */ + +#include "sysdep.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "noncfi.h" + +static int dbg = 0; + +static int spiflash_erase_block( cfi_array_t *cfi_array, uint32_t adr ); +static int spiflash_unlock_block( cfi_array_t *cfi_array, uint32_t adr ); +static int spiflash_program( cfi_array_t *cfi_array, uint32_t adr, uint32_t data ); +static void spiflash_read_array( cfi_array_t *cfi_array ); + +static int o; + +#define SPIFLASH_ADDR 0x51300000 +#define SPIFLASH_MAP 0x48000000 + +#define SPI_CTL_START 0x00000100 +#define SPI_CTL_BUSY 0x00010000 +#define SPI_CTL_TXCNT_MASK 0x0000000f +#define SPI_CTL_RXCNT_MASK 0x000000f0 +#define SPI_CTL_TX_RX_CNT_MASK 0x000000ff +#define SPI_CTL_SIZE_MASK 0x00060000 +#define SPI_CTL_CLK_SEL_MASK 0x03000000 + +enum { + REG_CTL = 0x00, + REG_DATA1 = 0x04, + REG_DATA2 = 0x08, +}; + +struct spiflash_op { + uint8_t opcode; + uint8_t txlen; + uint8_t rxlen; +}; + +enum { + OP_RDSIG, + OP_WRITE, + OP_WREN, + OP_ERASE, + OP_RDSTATUS, +}; + + +static struct spiflash_op ops[] = { + [OP_WRITE] = {0x02, 7, 0}, + [OP_RDSTATUS] = {0x05, 0, 1}, + [OP_WREN] = {0x06, 0, 0}, + [OP_RDSIG] = {0xab, 3, 1}, + [OP_ERASE] = {0xd8, 3, 0}, +}; + +/* XXX: assumes little endian flash access on big endian machine */ +static uint64_t spiflash_cmd(struct spiflash_op *op, uint32_t tx1, uint32_t tx2) +{ + uint32_t reg; + uint64_t res = 0; + + /* wait for the flash chip to become ready */ + do { + reg = bus_read(bus, SPIFLASH_ADDR + REG_CTL); + } while (reg & SPI_CTL_BUSY); + + bus_write(bus, SPIFLASH_ADDR + REG_DATA1, op->opcode | (tx1 << 8)); + if (op->txlen > 3) + bus_write(bus, SPIFLASH_ADDR + REG_DATA2, tx2); + + reg &= ~SPI_CTL_TX_RX_CNT_MASK; + reg |= (op->txlen + 1) | (op->rxlen << 4); + reg |= SPI_CTL_START; + +#ifdef DEBUG + printf("request: 0x%08x, 0x%08x, 0x%08x\n", reg, bus_read(bus, SPIFLASH_ADDR + REG_DATA1), bus_read(bus, SPIFLASH_ADDR + REG_DATA2)); +#endif + + /* start the spi transaction */ + bus_write(bus, SPIFLASH_ADDR + REG_CTL, reg); + + /* wait for the flash chip to complete the transaction */ + do { + reg = bus_read(bus, SPIFLASH_ADDR + REG_CTL); + } while (reg & SPI_CTL_BUSY); + +#ifdef DEBUG + printf("result: 0x%08x, 0x%08x\n", bus_read(bus, SPIFLASH_ADDR + REG_DATA1), bus_read(bus, SPIFLASH_ADDR + REG_DATA2)); +#endif + + if (op->rxlen > 0) { + int i = 3; + res = bus_read(bus, SPIFLASH_ADDR + REG_DATA2); + + if (op->rxlen < i) { + i = op->rxlen; + res &= (1 << (i * 8)) - 1; + } + + if (op->rxlen > 4) { + res <<= (op->rxlen - 4) * 8; + + reg = bus_read(bus, SPIFLASH_ADDR + REG_DATA1); + if (op->rxlen < 8) + res &= (1 << (1 + (op->rxlen - 4) * 8)) - 1; + + res |= reg; + } + } + + return res; +} + + +int spiflash_probe(bus_t *bus, uint32_t adr, cfi_array_t **cfi_array) +{ + uint32_t sig, size; + cfi_query_structure_t *cfi; + + if (!cfi_array || !bus) + return 0; /* invalid parameters */ + + /* default mapping for spiflash on atheros */ + if (adr != SPIFLASH_ADDR) + return 0; + + *cfi_array = calloc( 1, sizeof (cfi_array_t) ); + if (!*cfi_array) + return 0; /* out of memory */ + + (*cfi_array)->bus = bus; + (*cfi_array)->address = SPIFLASH_MAP; + (*cfi_array)->bus_width = 4; + (*cfi_array)->cfi_chips = calloc(1, sizeof(cfi_chip_t *)); + (*cfi_array)->cfi_chips[0] = calloc(1, sizeof(cfi_chip_t)); + cfi = &((*cfi_array)->cfi_chips[0]->cfi); + + printf("Probing for flash chip at 0x%08x...\n", SPIFLASH_MAP); + sig = (uint32_t) spiflash_cmd(&ops[OP_RDSIG], 0, 0); + printf("Signature: 0x%08x\n", sig); + + + cfi->device_geometry.erase_block_regions = malloc(sizeof (cfi_erase_block_region_t)); + if (sig >= 0x13 && sig <= 0x17) { + cfi->identification_string.pri_id_code = CFI_VENDOR_STM; + cfi->device_geometry.erase_block_regions[0].erase_block_size = 1 << 16; /* 64k */ + size = (1 << (sig - 0x13)) << 4; /* number of eraseblocks */ + } else { + printf("Unknown flash chip.\n"); + return 0; + } + cfi->device_geometry.erase_block_regions[0].number_of_erase_blocks = size; + + return 1; +} + +static int +spiflash_autodetect( cfi_array_t *cfi_array ) +{ + return (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code == CFI_VENDOR_STM); +} + + +static void +spiflash_print_info( cfi_array_t *cfi_array ) +{ + int mid, cid, prot; + bus_t *bus = cfi_array->bus; + uint32_t address = cfi_array->address; + + printf("Unimplemented.\n"); +} + +static int +spiflash_erase_block( cfi_array_t *cfi_array, uint32_t adr ) +{ + bus_t *bus = cfi_array->bus; + uint32_t address = cfi_array->address; + uint32_t reg; + +#ifdef DEBUG + printf("flash_erase_block 0x%08X\n", adr); +#endif + + adr &= ( + ~((1 << 16) - 1) & /* mask out the offset inside the eraseblock */ + ((16 << 20) - 1) /* 16 mb limit, mask out memory offset */ + ); + + /* enable writes */ + spiflash_cmd(&ops[OP_WREN], adr, 0); + spiflash_cmd(&ops[OP_ERASE], adr, 0); + do { + reg = (uint32_t) spiflash_cmd(&ops[OP_RDSTATUS], 0, 0); + } while (reg & 0x01); /* work in progress */ + + return 0; +} + +static int +spiflash_unlock_block( cfi_array_t *cfi_array, uint32_t adr ) +{ + return 0; +} + +static int +spiflash_program( cfi_array_t *cfi_array, uint32_t adr, uint32_t data ) +{ + uint32_t address = cfi_array->address; + uint32_t reg; + + /* 16 mb limit, mask out memory offset */ + adr &= ((16 << 20) - 1); +//#ifdef DEBUG + printf("\nflash_program 0x%08X = 0x%08X\n", adr, data); +//#endif + + + spiflash_cmd(&ops[OP_WREN], adr, 0); + spiflash_cmd(&ops[OP_WRITE], adr, data); + do { + reg = (uint32_t) spiflash_cmd(&ops[OP_RDSTATUS], 0, 0); + } while (reg & 0x01); /* work in progress */ + + return 0; +} + +static void +spiflash_read_array( cfi_array_t *cfi_array ) +{ +} + + +flash_driver_t spiflash_driver = { + 4, /* buswidth */ + N_("SPIFLASH chip"), + N_("."), + spiflash_autodetect, + spiflash_print_info, + spiflash_erase_block, + spiflash_unlock_block, + spiflash_program, + spiflash_read_array, +}; diff -urN jtag.old/libbrux/Makefile.in jtag.dev/libbrux/Makefile.in --- jtag.old/libbrux/Makefile.in 2005-11-13 01:08:27.000000000 +0100 +++ jtag.dev/libbrux/Makefile.in 2007-05-17 22:47:43.000000000 +0200 @@ -136,7 +136,7 @@ libbrux_a_AR = $(AR) $(ARFLAGS) libbrux_a_LIBADD = am_libbrux_a_OBJECTS = cmd.$(OBJEXT) help.$(OBJEXT) quit.$(OBJEXT) \ - cmd_detectflash.$(OBJEXT) cfi.$(OBJEXT) jedec.$(OBJEXT) \ + cmd_detectflash.$(OBJEXT) cfi.$(OBJEXT) jedec.$(OBJEXT) spiflash.$(OBJEXT) \ detectflash.$(OBJEXT) amd.$(OBJEXT) intel.$(OBJEXT) libbrux_a_OBJECTS = $(am_libbrux_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I. @@ -278,6 +278,7 @@ cmd/help.c \ cmd/quit.c \ cmd/cmd_detectflash.c \ + flash/spiflash.c \ flash/cfi.c \ flash/jedec.c \ flash/detectflash.c \ @@ -440,6 +441,13 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cfi.o `test -f 'flash/cfi.c' || echo '$(srcdir)/'`flash/cfi.c +spiflash.o: flash/spiflash.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spiflash.o -MD -MP -MF "$(DEPDIR)/spiflash.Tpo" -c -o spiflash.o `test -f 'flash/spiflash.c' || echo '$(srcdir)/'`flash/spiflash.c; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/spiflash.Tpo" "$(DEPDIR)/spiflash.Po"; else rm -f "$(DEPDIR)/spiflash.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='flash/spiflash.c' object='spiflash.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spiflash.o `test -f 'flash/spiflash.c' || echo '$(srcdir)/'`flash/spiflash.c + cfi.obj: flash/cfi.c @am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cfi.obj -MD -MP -MF "$(DEPDIR)/cfi.Tpo" -c -o cfi.obj `if test -f 'flash/cfi.c'; then $(CYGPATH_W) 'flash/cfi.c'; else $(CYGPATH_W) '$(srcdir)/flash/cfi.c'; fi`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/cfi.Tpo" "$(DEPDIR)/cfi.Po"; else rm -f "$(DEPDIR)/cfi.Tpo"; exit 1; fi diff -urN jtag.old/src/flash.c jtag.dev/src/flash.c --- jtag.old/src/flash.c 2005-12-26 18:46:36.000000000 +0100 +++ jtag.dev/src/flash.c 2007-05-18 00:16:49.000000000 +0200 @@ -46,6 +46,7 @@ #include "flash.h" #include "jtag.h" +extern flash_driver_t spiflash_driver; extern flash_driver_t amd_32_flash_driver; extern flash_driver_t amd_16_flash_driver; extern flash_driver_t amd_8_flash_driver; @@ -54,6 +55,7 @@ extern flash_driver_t intel_8_flash_driver; flash_driver_t *flash_drivers[] = { + &spiflash_driver, &amd_32_flash_driver, &amd_16_flash_driver, &amd_8_flash_driver,