On 27.09.2007 16:30, Ward Vandewege wrote:
On Thu, Sep 27, 2007 at 11:31:14AM +0200, Carl-Daniel Hailfinger wrote:
No problem. Can you commit with your changes? Changelog follows:
Add preliminary SPI flash identification support for SPI chips attached to ITE IT8716F Super I/O. Right now this is hardcoded to the Gigabyte M57SLI board. It works only with rev 2.0 of the board, but it will bail out on earlier versions, so no damage can occur.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Acked-by: Ward Vandewege ward@gnu.org
and committed in r2811
Thanks for committing!
Here is a patch against current svn which aims to restructure SPI flash support in a more reasonable way. Please note that the patch is not ready to be committed, but it should work much better than the existing one, namely without the dirty "do everything in board_enable functions" hack. Functions still have to be moved to another file, but for initial testing, this should be fine.
Regards, Carl-Daniel
Index: util/flashrom/flash.h =================================================================== --- util/flashrom/flash.h (Revision 2811) +++ util/flashrom/flash.h (Arbeitskopie) @@ -68,8 +68,31 @@ #define AT_29C040A 0xA4 #define AT_29C020 0xDA
+#define EON_ID 0x1C +/* EN25 chips are SPI, first byte of device id is memory type, + second byte of device id is log(bitsize)-9 */ +#define EN_25B05 0x2010 /* 2^19 kbit or 2^16 kByte */ +#define EN_25B10 0x2011 +#define EN_25B20 0x2012 +#define EN_25B40 0x2013 +#define EN_25B80 0x2014 +#define EN_25B16 0x2015 +#define EN_25B32 0x2016 + #define MX_ID 0xC2 /* Macronix (MX) */ #define MX_29F002 0xB0 +/* MX25L chips are SPI, first byte of device id is memory type, + second byte of device id is log(bitsize)-9 */ +#define MX_25L512 0x2010 /* 2^19 kbit or 2^16 kByte */ +#define MX_25L1005 0x2011 +#define MX_25L2005 0x2012 +#define MX_25L4005 0x2013 /* MX25L4005{,A} */ +#define MX_25L8005 0x2014 +#define MX_25L1605 0x2015 /* MX25L1605{,A,D} */ +#define MX_25L3205 0x2016 /* MX25L3205{,A} */ +#define MX_25L6405 0x2017 /* MX25L3205{,D} */ +#define MX_25L1635D 0x2415 +#define MX_25L3235D 0x2416
#define SHARP_ID 0xB0 /* Sharp */ #define SHARP_LHF00L04 0xCF @@ -182,6 +205,8 @@ int linuxbios_init(void); extern char *lb_part, *lb_vendor;
+int probe_spi(struct flashchip *flash); + /* 82802ab.c */ int probe_82802ab(struct flashchip *flash); int erase_82802ab(struct flashchip *flash); Index: util/flashrom/board_enable.c =================================================================== --- util/flashrom/board_enable.c (Revision 2811) +++ util/flashrom/board_enable.c (Arbeitskopie) @@ -96,35 +96,100 @@ return flashport; }
-static void it8716_serial_rdid(uint16_t port) +/* The IT8716 only supports commands with length 1,2,4,5 bytes including + command byte and can not read more than 3 bytes from the device. + This function expects writearr[0] to be the first byte sent to the device, + whereas the IT8716 splits commands internally into address and non-address + commands with the address in inverse wire order. That's why the register + ordering in case 4 and 5 may seem strange. */ +static int it8716_spi_command(uint16_t port, unsigned char writecnt, unsigned char readcnt, const unsigned char *writearr, unsigned char *readarr) { - uint8_t busy, data0, data1, data2; + uint8_t busy, writeenc; do { busy = inb(port) & 0x80; } while (busy); - /* RDID */ - outb(0x9f, port + 1); - /* Start IO, 33MHz, 3 input bytes, 0 output bytes*/ - outb((0x5<<4)|(0x3<<2)|(0x0), port); + if (readcnt > 3) { + printf("%s called with unsupported readcnt %i\n", + __FUNCTION__, readcnt); + return 1; + } + switch (writecnt) { + case 1: + outb(writearr[0], port + 1); + writeenc = 0x0; + break; + case 2: + outb(writearr[0], port + 1); + outb(writearr[1], port + 7); + writeenc = 0x1; + break; + case 4: + outb(writearr[0], port + 1); + outb(writearr[1], port + 4); + outb(writearr[2], port + 3); + outb(writearr[3], port + 2); + writeenc = 0x2; + break; + case 5: + outb(writearr[0], port + 1); + outb(writearr[1], port + 4); + outb(writearr[2], port + 3); + outb(writearr[3], port + 2); + outb(writearr[4], port + 7); + writeenc = 0x3; + break; + default: + printf("%s called with unsupported writecnt %i\n", + __FUNCTION__, writecnt); + return 1; + } + /* Start IO, 33MHz, readcnt input bytes, writecnt output bytes. Note: + We can't use writecnt directly, but have to use a strange encoding */ + outb((0x5 << 4) | ((readcnt & 0x3) << 2) | (writeenc), port); do { busy = inb(port) & 0x80; } while (busy); - data0 = inb(port + 5); - data1 = inb(port + 6); - data2 = inb(port + 7); - printf("RDID returned %02x %02x %02x\n", data0, data1, data2); - return; + readarr[0] = inb(port + 5); + readarr[1] = inb(port + 6); + readarr[2] = inb(port + 7); + return 0; }
+static int it8716_serial_rdid(uint16_t port, unsigned char *readarr) +{ + /* RDID is 0x9f */ + const unsigned char cmd[] = {0x9f}; + + if (it8716_spi_command(port, 1, 3, cmd, readarr)) + return 1; + printf("RDID returned %02x %02x %02x\n", readarr[0], readarr[1], readarr[2]); + return 0; +} + +static uint16_t it8716_flashport = 0; + static int it87xx_probe_serial_flash(const char *name) { - uint16_t flashport; - flashport = find_ite_serial_flash_port(0x2e); - if (flashport) - it8716_serial_rdid(flashport); - flashport = find_ite_serial_flash_port(0x4e); - if (flashport) - it8716_serial_rdid(flashport); + it8716_flashport = find_ite_serial_flash_port(0x2e); + if (!it8716_flashport) + it8716_flashport = find_ite_serial_flash_port(0x4e); + return (!it8716_flashport); +} + +int probe_spi(struct flashchip *flash) +{ + unsigned char readarr[3]; + uint8_t manuf_id; + uint16_t model_id; + if (it8716_flashport) { + it8716_serial_rdid(it8716_flashport, readarr); + manuf_id = readarr[0]; + model_id = (readarr[1] << 8) | readarr[2]; + printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, manuf_id, model_id); + if (manuf_id == flash->manufacture_id && model_id == flash->model_id) + return 1; + } + return 0; }