Hi,
this new thread is here just to get some early testing and info on the GA-M57SLI SPI flash.
The IT8716F is indeed used for LPC-to-SPI translation as I supected.
LDN 0x0, reg 0x24: val=0x1a serial flash interface at pin 29 LPC write to serial flash enabled 512kByte of flash are mapped at top of 4GByte 128kByte of flash are mapped at top of 1MByte (1152kByte can be mapped at most)
LDN 0x7, reg 0x64/0x65: val=0x08/0x20 serial flash interface base addr 0x0820 (that's an I/O port)
What I need: * Byte reads from all ports between 0x0820-0x0827 on the SPI version of the GA-M57SLI under factory BIOS. Should be harmless. * Exact type of SPI flash chip (datasheet link would be nice) * Volunteer who can reflash manually once my writing code is ready.
Carl-Daniel
On 23.09.2007 18:39, Carl-Daniel Hailfinger wrote:
Hi,
this new thread is here just to get some early testing and info on the GA-M57SLI SPI flash.
The IT8716F is indeed used for LPC-to-SPI translation as I supected.
LDN 0x0, reg 0x24: val=0x1a serial flash interface at pin 29 LPC write to serial flash enabled 512kByte of flash are mapped at top of 4GByte 128kByte of flash are mapped at top of 1MByte (1152kByte can be mapped at most)
LDN 0x7, reg 0x64/0x65: val=0x08/0x20 serial flash interface base addr 0x0820 (that's an I/O port)
What I need:
- Byte reads from all ports between 0x0820-0x0827 on the SPI version of
the GA-M57SLI under factory BIOS. Should be harmless.
- Exact type of SPI flash chip (datasheet link would be nice)
MX25L4005 from Macronix http://www.macronix.com/QuickPlace/hq/PageLibrary48256F5500439ED0.nsf/h_CE4C...
- Volunteer who can reflash manually once my writing code is ready.
Carl-Daniel
Can somebody with the GA-M57SLI v2.0 try the following code snippet and post the output? Code may not compile/link etc.
#include <stdint.h> #include <stdio.h> int main(int argc, char *argv[]) { uint8_t busy, data0, data1, data2; do { busy = inb(0x0820) & 0x80; } while (busy); /* RDID */ outb(0x0820+1, 0x9f); /* Start IO, 33MHz, 3 input bytes, 0 output bytes*/ outb(0x0820, (0x5<<4)|(0x3<<2)|(0x0)); data0 = inb(0x0820+5); data1 = inb(0x0820+6); data2 = inb(0x0820+7); printf("RDID returned %02x %02x %02x\n", data0, data1, data2); return 0; }
Carl-Daniel
On 23.09.2007 22:30, Carl-Daniel Hailfinger wrote:
Can somebody with the GA-M57SLI v2.0 try the following code snippet and post the output? Code may not compile/link etc.
Forget the code in my previous mail. It was simply too late for me to write working code without a compiler handy.
Try the patch below and post output to the list: --- util/flashrom/board_enable.c (Revision 2802) +++ util/flashrom/board_enable.c (Arbeitskopie) @@ -4,6 +4,7 @@ * Copyright (C) 2005-2007 coresystems GmbH stepan@coresystems.de * Copyright (C) 2006 Uwe Hermann uwe@hermann-uwe.de * Copyright (C) 2007 Luc Verhaegen libv@skynet.be + * Copyright (C) 2007 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 @@ -29,6 +30,105 @@ #include <string.h> #include "flash.h"
+/* Generic Super I/O helper functions */ +uint8_t regval(uint16_t port, uint8_t reg) +{ + outb(reg, port); + return inb(port + 1); +} + +void regwrite(uint16_t port, uint8_t reg, uint8_t val) +{ + outb(reg, port); + outb(val, port + 1); +} + +/* Helper functions for most recent ITE IT87xx Super I/O chips */ +#define CHIP_ID_BYTE1_REG 0x20 +#define CHIP_ID_BYTE2_REG 0x21 +#define CHIP_VERSION_REG 0x22 +static void enter_conf_mode_ite(uint16_t port) +{ + outb(0x87, port); + outb(0x01, port); + outb(0x55, port); + if (port == 0x2e) + outb(0x55, port); + else + outb(0xaa, port); +} + +static void exit_conf_mode_ite(uint16_t port) +{ + regwrite(port, 0x02, 0x02); +} + +static uint16_t find_ite_serial_flash_port(uint16_t port) +{ + uint8_t tmp = 0; + uint16_t id, flashport = 0; + + enter_conf_mode_ite(port); + + id = regval(port, CHIP_ID_BYTE1_REG) << 8; + id |= regval(port, CHIP_ID_BYTE2_REG); + + if (id == 0x8716) { + /* LDN 0x0, reg 0x24, mask out lowest bit (suspend) */ + regwrite(port, 0x07, 0x0); + tmp = regval(port, 0x24) & 0xFE; + printf("Serial flash segment 0x%08x-0x%08x %sabled\n", + 0xFFFE0000, 0xFFFFFFFF, (tmp & 1 << 1) ? "en" : "dis"); + printf("Serial flash segment 0x%08x-0x%08x %sabled\n", + 0x000E0000, 0x000FFFFF, (tmp & 1 << 1) ? "en" : "dis"); + printf("Serial flash segment 0x%08x-0x%08x %sabled\n", + 0xFFEE0000, 0xFFEFFFFF, (tmp & 1 << 2) ? "en" : "dis"); + printf("Serial flash segment 0x%08x-0x%08x %sabled\n", + 0xFFF80000, 0xFFFEFFFF, (tmp & 1 << 3) ? "en" : "dis"); + printf("LPC write to serial flash %sabled\n", + (tmp & 1 << 4) ? "en" : "dis"); + printf("serial flash pin %i\n", (tmp & 1 << 5) ? 87 : 29); + /* LDN 0x7, reg 0x64/0x65 */ + regwrite(port, 0x07, 0x7); + flashport = regval(port, 0x64) << 8; + flashport |= regval(port, 0x65); + } + exit_conf_mode_ite(port); + return flashport; +} + +static void it8716_serial_rdid(uint16_t port) +{ + uint8_t busy, data0, data1, data2; + do { + busy = inb(0x0820) & 0x80; + } while (busy); + /* RDID */ + outb(0x9f, 0x0820 + 1); + /* Start IO, 33MHz, 3 input bytes, 0 output bytes*/ + outb((0x5<<4)|(0x3<<2)|(0x0), 0x0820); + do { + busy = inb(0x0820) & 0x80; + } while (busy); + data0 = inb(0x0820 + 5); + data1 = inb(0x0820 + 6); + data2 = inb(0x0820 + 7); + printf("RDID returned %02x %02x %02x\n", data0, data1, data2); + return; +} + +static int gam57sli_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); + return 0; +} + /* * Helper functions for many Winbond Super I/Os of the W836xx range. */ @@ -314,6 +414,8 @@ };
struct board_pciid_enable board_pciid_enables[] = { + {0x10de, 0x0360, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + "gigabyte", "gam57sli", "Gigabyte GA-M57SLI", gam57sli_probe_serial_flash}, {0x1022, 0x7468, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, "iwill", "dk8_htx", "IWILL DK8-HTX", w83627hf_gpio24_raise}, {0x1022, 0x746B, 0x1022, 0x36C0, 0x0000, 0x0000, 0x0000, 0x0000,
You have to use the "--mainboard gigabyte:gam57sli" switch for flashrom.
Carl-Daniel
On Mon, Sep 24, 2007 at 12:10:15PM +0200, Carl-Daniel Hailfinger wrote:
+uint8_t regval(uint16_t port, uint8_t reg)
Why not regread() btw? Just a minor issue.
- if (id == 0x8716) {
/* LDN 0x0, reg 0x24, mask out lowest bit (suspend) */
regwrite(port, 0x07, 0x0);
tmp = regval(port, 0x24) & 0xFE;
Why LDN 0? Isn't that for floppy stuff? 0x24 can be manipulated regardless of any LDN, IIRC.
+static void it8716_serial_rdid(uint16_t port) +{
- uint8_t busy, data0, data1, data2;
- do {
busy = inb(0x0820) & 0x80;
- } while (busy);
- /* RDID */
- outb(0x9f, 0x0820 + 1);
Should this be a #define?
- /* Start IO, 33MHz, 3 input bytes, 0 output bytes*/
- outb((0x5<<4)|(0x3<<2)|(0x0), 0x0820);
- do {
busy = inb(0x0820) & 0x80;
- } while (busy);
- data0 = inb(0x0820 + 5);
- data1 = inb(0x0820 + 6);
- data2 = inb(0x0820 + 7);
#defines? SPI_IDATA0 etc.
- printf("RDID returned %02x %02x %02x\n", data0, data1, data2);
- return;
Not needed, the function returns void.
+static int gam57sli_probe_serial_flash(const char *name)
Let's use the full/correct name for the board. In this case: ga_m57sli_s4_probe_serial_flash or gam57slis4_probe_serial_flash (I think the first version is more readable)
+{
- 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);
- return 0;
If the function always returns the same value, maybe we should make it return void?
struct board_pciid_enable board_pciid_enables[] = {
- {0x10de, 0x0360, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
"gigabyte", "gam57sli", "Gigabyte GA-M57SLI", gam57sli_probe_serial_flash},
"gigabyte", "ga-m57sli-s4", "GIGABYTE GA-M57SLI-S4", ga_m57sli_s4_probe_serial_flash},
(or similar, depending on the above function name)
GIGABYTE is all-caps as they use that form on their website.
Uwe.
On 25.09.2007 01:17, Uwe Hermann wrote:
On Mon, Sep 24, 2007 at 12:10:15PM +0200, Carl-Daniel Hailfinger wrote:
+uint8_t regval(uint16_t port, uint8_t reg)
Why not regread() btw? Just a minor issue.
Straight copy from flashrom. Besides that, val is shorter and sounds nicer.
- if (id == 0x8716) {
/* LDN 0x0, reg 0x24, mask out lowest bit (suspend) */
regwrite(port, 0x07, 0x0);
tmp = regval(port, 0x24) & 0xFE;
Why LDN 0? Isn't that for floppy stuff? 0x24 can be manipulated regardless of any LDN, IIRC.
superiotool output was a bit misleading. LDN 0 isn't needed.
+static void it8716_serial_rdid(uint16_t port) +{
- uint8_t busy, data0, data1, data2;
- do {
busy = inb(0x0820) & 0x80;
- } while (busy);
- /* RDID */
- outb(0x9f, 0x0820 + 1);
Should this be a #define?
No. Old code version. Will send new patch.
- /* Start IO, 33MHz, 3 input bytes, 0 output bytes*/
- outb((0x5<<4)|(0x3<<2)|(0x0), 0x0820);
- do {
busy = inb(0x0820) & 0x80;
- } while (busy);
- data0 = inb(0x0820 + 5);
- data1 = inb(0x0820 + 6);
- data2 = inb(0x0820 + 7);
#defines? SPI_IDATA0 etc.
- printf("RDID returned %02x %02x %02x\n", data0, data1, data2);
- return;
Not needed, the function returns void.
Explicit return statements are nice and this will return a value in the future.
+static int gam57sli_probe_serial_flash(const char *name)
Let's use the full/correct name for the board. In this case: ga_m57sli_s4_probe_serial_flash or gam57slis4_probe_serial_flash (I think the first version is more readable)
This works for all boards with SPI hanging off IT8716F, so more generic name needed.
+{
- 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);
- return 0;
If the function always returns the same value, maybe we should make it return void?
Function must return int unless you change all other probe functions.
struct board_pciid_enable board_pciid_enables[] = {
- {0x10de, 0x0360, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
"gigabyte", "gam57sli", "Gigabyte GA-M57SLI", gam57sli_probe_serial_flash},
"gigabyte", "ga-m57sli-s4", "GIGABYTE GA-M57SLI-S4", ga_m57sli_s4_probe_serial_flash},
(or similar, depending on the above function name)
GIGABYTE is all-caps as they use that form on their website.
ok, done.
Updated patch attached. This one was unfortunately an old version of the code.
Carl-Daniel
Index: util/flashrom/board_enable.c =================================================================== --- util/flashrom/board_enable.c (Revision 2802) +++ util/flashrom/board_enable.c (Arbeitskopie) @@ -4,6 +4,7 @@ * Copyright (C) 2005-2007 coresystems GmbH stepan@coresystems.de * Copyright (C) 2006 Uwe Hermann uwe@hermann-uwe.de * Copyright (C) 2007 Luc Verhaegen libv@skynet.be + * Copyright (C) 2007 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 @@ -29,6 +30,104 @@ #include <string.h> #include "flash.h"
+/* Generic Super I/O helper functions */ +uint8_t regval(uint16_t port, uint8_t reg) +{ + outb(reg, port); + return inb(port + 1); +} + +void regwrite(uint16_t port, uint8_t reg, uint8_t val) +{ + outb(reg, port); + outb(val, port + 1); +} + +/* Helper functions for most recent ITE IT87xx Super I/O chips */ +#define CHIP_ID_BYTE1_REG 0x20 +#define CHIP_ID_BYTE2_REG 0x21 +static void enter_conf_mode_ite(uint16_t port) +{ + outb(0x87, port); + outb(0x01, port); + outb(0x55, port); + if (port == 0x2e) + outb(0x55, port); + else + outb(0xaa, port); +} + +static void exit_conf_mode_ite(uint16_t port) +{ + regwrite(port, 0x02, 0x02); +} + +static uint16_t find_ite_serial_flash_port(uint16_t port) +{ + uint8_t tmp = 0; + uint16_t id, flashport = 0; + + enter_conf_mode_ite(port); + + id = regval(port, CHIP_ID_BYTE1_REG) << 8; + id |= regval(port, CHIP_ID_BYTE2_REG); + + /* TODO: Handle more IT87xx if they support flash translation */ + if (id == 0x8716) { + /* NOLDN, reg 0x24, mask out lowest bit (suspend) */ + tmp = regval(port, 0x24) & 0xFE; + printf("Serial flash segment 0x%08x-0x%08x %sabled\n", + 0xFFFE0000, 0xFFFFFFFF, (tmp & 1 << 1) ? "en" : "dis"); + printf("Serial flash segment 0x%08x-0x%08x %sabled\n", + 0x000E0000, 0x000FFFFF, (tmp & 1 << 1) ? "en" : "dis"); + printf("Serial flash segment 0x%08x-0x%08x %sabled\n", + 0xFFEE0000, 0xFFEFFFFF, (tmp & 1 << 2) ? "en" : "dis"); + printf("Serial flash segment 0x%08x-0x%08x %sabled\n", + 0xFFF80000, 0xFFFEFFFF, (tmp & 1 << 3) ? "en" : "dis"); + printf("LPC write to serial flash %sabled\n", + (tmp & 1 << 4) ? "en" : "dis"); + printf("serial flash pin %i\n", (tmp & 1 << 5) ? 87 : 29); + /* LDN 0x7, reg 0x64/0x65 */ + regwrite(port, 0x07, 0x7); + flashport = regval(port, 0x64) << 8; + flashport |= regval(port, 0x65); + } + exit_conf_mode_ite(port); + return flashport; +} + +static void it8716_serial_rdid(uint16_t port) +{ + uint8_t busy, data0, data1, data2; + 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); + 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; +} + +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); + return 0; +} + /* * Helper functions for many Winbond Super I/Os of the W836xx range. */ @@ -314,6 +413,8 @@ };
struct board_pciid_enable board_pciid_enables[] = { + {0x10de, 0x0360, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + "gigabyte", "ga-m57sli", "GIGABYTE GA-M57SLI", it87xx_probe_serial_flash}, {0x1022, 0x7468, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, "iwill", "dk8_htx", "IWILL DK8-HTX", w83627hf_gpio24_raise}, {0x1022, 0x746B, 0x1022, 0x36C0, 0x0000, 0x0000, 0x0000, 0x0000,
Hi Carl-Daniel,
On Tue, Sep 25, 2007 at 03:00:55AM +0200, Carl-Daniel Hailfinger wrote:
Updated patch attached. This one was unfortunately an old version of the code.
This certainly does something!
# ./flashrom --mainboard gigabyte:ga-m57sli Calibrating delay loop... ok No LinuxBIOS table found. Found chipset "NVIDIA MCP55": Enabling flash write... OK. Found board "GIGABYTE GA-M57SLI": Enabling flash write... Serial flash segment 0xfffe0000-0xffffffff enabled Serial flash segment 0x000e0000-0x000fffff enabled Serial flash segment 0xffee0000-0xffefffff disabled Serial flash segment 0xfff80000-0xfffeffff enabled LPC write to serial flash enabled serial flash pin 29 RDID returned c2 20 13 OK. No EEPROM/flash device found.
Suggestion: can we change the board identifier to m57sli, instead of ga-m57sli?
Thanks, Ward.
On 27.09.2007 02:38, Ward Vandewege wrote:
Hi Carl-Daniel,
On Tue, Sep 25, 2007 at 03:00:55AM +0200, Carl-Daniel Hailfinger wrote:
Updated patch attached. This one was unfortunately an old version of the code.
This certainly does something!
# ./flashrom --mainboard gigabyte:ga-m57sli Calibrating delay loop... ok No LinuxBIOS table found. Found chipset "NVIDIA MCP55": Enabling flash write... OK. Found board "GIGABYTE GA-M57SLI": Enabling flash write... Serial flash segment 0xfffe0000-0xffffffff enabled Serial flash segment 0x000e0000-0x000fffff enabled Serial flash segment 0xffee0000-0xffefffff disabled Serial flash segment 0xfff80000-0xfffeffff enabled LPC write to serial flash enabled serial flash pin 29 RDID returned c2 20 13
Great! About 100 lines left to write for flashing support, but I know how to write them and probably can do it without hardware.
OK. No EEPROM/flash device found.
Don't let yourself be irritated by that.
Suggestion: can we change the board identifier to m57sli, instead of ga-m57sli?
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
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, Ward.
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; }
On Fri, Sep 28, 2007 at 03:35:54PM +0200, Carl-Daniel Hailfinger wrote:
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
Yep, Signed-off-by missing for this one (yeah, there's one for the older version, but still)...
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
Maybe we should separate out the IDs for SPI chips in a different section of the header file (to not confuse people into assuing they're LPC parts or so)?
#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);
Can be int probe_spi(const struct flashchip *flash); I think.
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
IT8716F please, as per datasheet. AFAICS all ITEs should have the F at the end of the name. Applies to several places in the code and comments.
- 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)
If the size of writecnt/readcnt/writearr/readarr etc. is fixed/specified in the datasheet then please make it uint16_t etc. instead of the "generic" unsigned char and friends.
+static int it8716_serial_rdid(uint16_t port, unsigned char *readarr) +{
- /* RDID is 0x9f */
- const unsigned char cmd[] = {0x9f};
#define RDID 0x9f
at the top of the file?
- 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;
Move this to the top of the file, please.
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);
#defines for 0x2e and 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;
}
Looks good otherwise, but should be tested of course.
Uwe.
On 28.09.2007 16:55, Uwe Hermann wrote:
On Fri, Sep 28, 2007 at 03:35:54PM +0200, Carl-Daniel Hailfinger wrote:
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
Yep, Signed-off-by missing for this one (yeah, there's one for the older version, but still)...
Intentional. Was not ready to be applied.
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
Maybe we should separate out the IDs for SPI chips in a different section of the header file (to not confuse people into assuing they're LPC parts or so)?
All SPI parts have 16-bit device IDs, I'll add a comment about that.
#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);
Can be int probe_spi(const struct flashchip *flash); I think.
Maybe, but that's a separate cleanup. This function prototype matches the others.
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
IT8716F please, as per datasheet. AFAICS all ITEs should have the F at the end of the name. Applies to several places in the code and comments.
OK.
- 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)
If the size of writecnt/readcnt/writearr/readarr etc. is fixed/specified in the datasheet then please make it uint16_t etc. instead of the "generic" unsigned char and friends.
{read,write}cnt are between 0 and 5, so they could as well be int. No datasheet specification for their variable size. {read,write}arr are just helper constructs to abstract the horrible datasheet variable types. Or do you honestly want a 24-bit type?
+static int it8716_serial_rdid(uint16_t port, unsigned char *readarr) +{
- /* RDID is 0x9f */
- const unsigned char cmd[] = {0x9f};
#define RDID 0x9f
at the top of the file?
Can do, but it will get messy very soon because there is no way to sensibly specify command value, input size, output size in one #define. Furthermore, depending on the state of the chip, the commands change values/input/output size. So I'd prefer to keep it that way right now until we figure out a better abstraction which doesn't complicate stuff.
- 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;
Move this to the top of the file, please.
OK.
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);
#defines for 0x2e and 0x4e.
OK.
- 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;
}
Looks good otherwise, but should be tested of course.
Yes, looking for testers.
Carl-Daniel
This patch aims to restructure SPI flash support in a more reasonable way. It introduces a generic SPI host driver for the IT8716F Super I/O which will enable easy SPI programming without having to care for the peculiarities of the SPI host.
To activate probing for the IT8716F, you have to use the gigabyte:m57sli mainboard override. SPI support will then use the gathered SPI host data to access the SPI flash.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Tests welcome!
Index: util/flashrom/flash.h =================================================================== --- util/flashrom/flash.h (Revision 2814) +++ util/flashrom/flash.h (Arbeitskopie) @@ -55,6 +55,8 @@ /* Please keep this list sorted alphabetically by manufacturer. The first * entry of each section should be the manufacturer ID, followed by the * list of devices from that manufacturer (sorted by device IDs). + * All LPC/FWH parts (parallel flash) have 8-bit device IDs. + * All SPI parts have 16-bit device IDs. */
#define AMD_ID 0x01 /* AMD */ @@ -68,8 +70,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 +207,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 2814) +++ util/flashrom/board_enable.c (Arbeitskopie) @@ -30,6 +30,15 @@ #include <string.h> #include "flash.h"
+#define ITE_SUPERIO_PORT1 0x2e +#define ITE_SUPERIO_PORT2 0x4e + +#define JEDEC_RDID {0x9f} +#define JEDEC_RDID_OUTSIZE 0x01 +#define JEDEC_RDID_INSIZE 0x03 + +static uint16_t it8716f_flashport = 0; + /* Generic Super I/O helper functions */ uint8_t regval(uint16_t port, uint8_t reg) { @@ -51,7 +60,7 @@ outb(0x87, port); outb(0x01, port); outb(0x55, port); - if (port == 0x2e) + if (port == ITE_SUPERIO_PORT1) outb(0x55, port); else outb(0xaa, port); @@ -96,35 +105,97 @@ return flashport; }
-static void it8716_serial_rdid(uint16_t port) +/* The IT8716F 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 IT8716F 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 it8716f_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 it8716f_serial_rdid(uint16_t port, unsigned char *readarr) +{ + const unsigned char cmd[] = JEDEC_RDID; + + if (it8716f_spi_command(port, JEDEC_RDID_OUTSIZE, JEDEC_RDID_INSIZE, cmd, readarr)) + return 1; + printf("RDID returned %02x %02x %02x\n", readarr[0], readarr[1], readarr[2]); + return 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); + it8716f_flashport = find_ite_serial_flash_port(ITE_SUPERIO_PORT1); + if (!it8716f_flashport) + it8716f_flashport = find_ite_serial_flash_port(ITE_SUPERIO_PORT2); + return (!it8716f_flashport); +} + +int probe_spi(struct flashchip *flash) +{ + unsigned char readarr[3]; + uint8_t manuf_id; + uint16_t model_id; + if (it8716f_flashport) { + it8716f_serial_rdid(it8716f_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; }
* Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net [070929 04:08]:
+#define ITE_SUPERIO_PORT1 0x2e +#define ITE_SUPERIO_PORT2 0x4e
This has nothing to do with the IDE. All PC SuperIOs are on 2e or 4e.
+int probe_spi(struct flashchip *flash) +{
- unsigned char readarr[3];
This should be a struct imho
typedef struct spi_id { unsigned char vendor_id; unsigned short device_id; } spi_id_t;
The driver does only probe so far, right?
what about the other SPI commands?
On 29.09.2007 15:59, Stefan Reinauer wrote:
- Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net [070929 04:08]:
+#define ITE_SUPERIO_PORT1 0x2e +#define ITE_SUPERIO_PORT2 0x4e
This has nothing to do with the IDE. All PC SuperIOs are on 2e or 4e.
+int probe_spi(struct flashchip *flash) +{
- unsigned char readarr[3];
This should be a struct imho
typedef struct spi_id { unsigned char vendor_id; unsigned short device_id; } spi_id_t;
Yes, but the underlying generic SPI function uses an array for commands and results. Once I add write/erase support, it will become obvious why I used unsigned char arrays.
The driver does only probe so far, right?
Yes.
what about the other SPI commands?
Will be implemented once this patch has been tested.
Carl-Daniel
Carl-Daniel Hailfinger wrote:
+int probe_spi(struct flashchip *flash) +{
- unsigned char readarr[3];
This should be a struct imho
typedef struct spi_id { unsigned char vendor_id; unsigned short device_id; } spi_id_t;
Yes, but the underlying generic SPI function uses an array for commands and results. Once I add write/erase support, it will become obvious why I used unsigned char arrays.
Ah, so maybe it should be a union?
what about the other SPI commands?
Will be implemented once this patch has been tested.
Cool. I'll wait.
On 01.10.2007 12:54, Stefan Reinauer wrote:
Carl-Daniel Hailfinger wrote:
+int probe_spi(struct flashchip *flash) +{
- unsigned char readarr[3];
This should be a struct imho
typedef struct spi_id { unsigned char vendor_id; unsigned short device_id; } spi_id_t;
Yes, but the underlying generic SPI function uses an array for commands and results. Once I add write/erase support, it will become obvious why I used unsigned char arrays.
Ah, so maybe it should be a union?
That's an option. I'll consider this once I refine the code.
Carl-Daniel
On Mon, Oct 01, 2007 at 12:28:46PM +0200, Carl-Daniel Hailfinger wrote:
Will be implemented once this patch has been tested.
Ah, yes, sorry, here's the output:
# ./flashrom Calibrating delay loop... ok No LinuxBIOS table found. Found chipset "NVIDIA MCP55": Enabling flash write... OK. No EEPROM/flash device found.
# ./flashrom -v Calibrating delay loop... ok No LinuxBIOS table found. Found chipset "NVIDIA MCP55": Enabling flash write... OK. No EEPROM/flash device found.
# ./flashrom -v -m gigabyte:m57sli Calibrating delay loop... ok No LinuxBIOS table found. Found chipset "NVIDIA MCP55": Enabling flash write... OK. Found board "GIGABYTE GA-M57SLI": Enabling flash write... Serial flash segment 0xfffe0000-0xffffffff enabled Serial flash segment 0x000e0000-0x000fffff enabled Serial flash segment 0xffee0000-0xffefffff disabled Serial flash segment 0xfff80000-0xfffeffff enabled LPC write to serial flash enabled serial flash pin 29 OK. No EEPROM/flash device found.
Does that look good?
Thanks, Ward.
On 01.10.2007 14:25, Ward Vandewege wrote:
On Mon, Oct 01, 2007 at 12:28:46PM +0200, Carl-Daniel Hailfinger wrote:
Will be implemented once this patch has been tested.
Ah, yes, sorry, here's the output:
Thanks!
# ./flashrom Calibrating delay loop... ok No LinuxBIOS table found. Found chipset "NVIDIA MCP55": Enabling flash write... OK. No EEPROM/flash device found.
# ./flashrom -v Calibrating delay loop... ok No LinuxBIOS table found. Found chipset "NVIDIA MCP55": Enabling flash write... OK. No EEPROM/flash device found.
# ./flashrom -v -m gigabyte:m57sli Calibrating delay loop... ok No LinuxBIOS table found. Found chipset "NVIDIA MCP55": Enabling flash write... OK. Found board "GIGABYTE GA-M57SLI": Enabling flash write... Serial flash segment 0xfffe0000-0xffffffff enabled Serial flash segment 0x000e0000-0x000fffff enabled Serial flash segment 0xffee0000-0xffefffff disabled Serial flash segment 0xfff80000-0xfffeffff enabled LPC write to serial flash enabled serial flash pin 29 OK. No EEPROM/flash device found.
Does that look good?
Unfortunately not. Hmm... you used -v (verify) instead of -V (verbose). And my patch was incomplete.
Can you try "flashrom -V -m gigabyte:m57sli" with the attached patch (against current svn) and report back?
Thanks, Carl-Daniel
Index: util/flashrom/flash.h =================================================================== --- util/flashrom/flash.h (Revision 2814) +++ util/flashrom/flash.h (Arbeitskopie) @@ -55,6 +55,8 @@ /* Please keep this list sorted alphabetically by manufacturer. The first * entry of each section should be the manufacturer ID, followed by the * list of devices from that manufacturer (sorted by device IDs). + * All LPC/FWH parts (parallel flash) have 8-bit device IDs. + * All SPI parts have 16-bit device IDs. */
#define AMD_ID 0x01 /* AMD */ @@ -68,8 +70,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 +207,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 2814) +++ util/flashrom/board_enable.c (Arbeitskopie) @@ -30,6 +30,15 @@ #include <string.h> #include "flash.h"
+#define ITE_SUPERIO_PORT1 0x2e +#define ITE_SUPERIO_PORT2 0x4e + +#define JEDEC_RDID {0x9f} +#define JEDEC_RDID_OUTSIZE 0x01 +#define JEDEC_RDID_INSIZE 0x03 + +static uint16_t it8716f_flashport = 0; + /* Generic Super I/O helper functions */ uint8_t regval(uint16_t port, uint8_t reg) { @@ -51,7 +60,7 @@ outb(0x87, port); outb(0x01, port); outb(0x55, port); - if (port == 0x2e) + if (port == ITE_SUPERIO_PORT1) outb(0x55, port); else outb(0xaa, port); @@ -96,35 +105,97 @@ return flashport; }
-static void it8716_serial_rdid(uint16_t port) +/* The IT8716F 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 IT8716F 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 it8716f_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 it8716f_serial_rdid(uint16_t port, unsigned char *readarr) +{ + const unsigned char cmd[] = JEDEC_RDID; + + if (it8716f_spi_command(port, JEDEC_RDID_OUTSIZE, JEDEC_RDID_INSIZE, cmd, readarr)) + return 1; + printf("RDID returned %02x %02x %02x\n", readarr[0], readarr[1], readarr[2]); + return 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); + it8716f_flashport = find_ite_serial_flash_port(ITE_SUPERIO_PORT1); + if (!it8716f_flashport) + it8716f_flashport = find_ite_serial_flash_port(ITE_SUPERIO_PORT2); + return (!it8716f_flashport); +} + +int probe_spi(struct flashchip *flash) +{ + unsigned char readarr[3]; + uint8_t manuf_id; + uint16_t model_id; + if (it8716f_flashport) { + it8716f_serial_rdid(it8716f_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; }
Index: util/flashrom/flashchips.c =================================================================== --- util/flashrom/flashchips.c (Revision 2814) +++ util/flashrom/flashchips.c (Arbeitskopie) @@ -38,6 +38,8 @@ probe_jedec, erase_chip_jedec, write_jedec}, {"Mx29f002", MX_ID, MX_29F002, 256, 64 * 1024, probe_29f002, erase_29f002, write_29f002}, + {"MX25L4005", MX_ID, MX_25L4005, 512, 4 * 1024, + probe_spi, NULL, NULL}, {"SST29EE020A", SST_ID, SST_29EE020A, 256, 128, probe_jedec, erase_chip_jedec, write_jedec}, {"SST28SF040A", SST_ID, SST_28SF040, 512, 256,
On Mon, Oct 01, 2007 at 02:53:35PM +0200, Carl-Daniel Hailfinger wrote:
Unfortunately not. Hmm... you used -v (verify) instead of -V (verbose).
Woops - that's what happens when you try to do stuff before coffee.
And my patch was incomplete.
Can you try "flashrom -V -m gigabyte:m57sli" with the attached patch (against current svn) and report back?
Yes, this looks a lot better:
# ./flashrom -V -m gigabyte:m57sli Calibrating delay loop... 283M loops per second. ok No LinuxBIOS table found. Found chipset "NVIDIA MCP55": Enabling flash write... OK. Found board "GIGABYTE GA-M57SLI": Enabling flash write... Serial flash segment 0xfffe0000-0xffffffff enabled Serial flash segment 0x000e0000-0x000fffff enabled Serial flash segment 0xffee0000-0xffefffff disabled Serial flash segment 0xfff80000-0xfffeffff enabled LPC write to serial flash enabled serial flash pin 29 OK. Probing for Am29F040B, 512 KB probe_29f040b: id1 0x49, id2 0x4d Probing for Am29F016D, 2048 KB probe_29f040b: id1 0xff, id2 0xff Probing for AE49F2008, 256 KB probe_jedec: id1 0x83, id2 0x83 Probing for At29C040A, 512 KB probe_jedec: id1 0x49, id2 0x4d Probing for At29C020, 256 KB probe_jedec: id1 0x83, id2 0x83 Probing for Mx29f002, 256 KB probe_29f002: id1 0x83, id2 0x83 Probing for MX25L4005, 512 KB RDID returned c2 20 13 probe_spi: id1 0xc2, id2 0x2013 MX25L4005 found at physical address: 0xfff80000 Flash part is MX25L4005 (512 KB) OK, only ENABLING flash write, but NOT FLASHING.
Thanks, Ward.
On 01.10.2007 15:00, Ward Vandewege wrote:
On Mon, Oct 01, 2007 at 02:53:35PM +0200, Carl-Daniel Hailfinger wrote:
Unfortunately not. Hmm... you used -v (verify) instead of -V (verbose).
Woops - that's what happens when you try to do stuff before coffee.
And my patch was incomplete.
Can you try "flashrom -V -m gigabyte:m57sli" with the attached patch (against current svn) and report back?
Yes, this looks a lot better:
# ./flashrom -V -m gigabyte:m57sli Calibrating delay loop... 283M loops per second. ok No LinuxBIOS table found. Found chipset "NVIDIA MCP55": Enabling flash write... OK. Found board "GIGABYTE GA-M57SLI": Enabling flash write... Serial flash segment 0xfffe0000-0xffffffff enabled Serial flash segment 0x000e0000-0x000fffff enabled Serial flash segment 0xffee0000-0xffefffff disabled Serial flash segment 0xfff80000-0xfffeffff enabled LPC write to serial flash enabled serial flash pin 29 OK. Probing for Am29F040B, 512 KB probe_29f040b: id1 0x49, id2 0x4d Probing for Am29F016D, 2048 KB probe_29f040b: id1 0xff, id2 0xff Probing for AE49F2008, 256 KB probe_jedec: id1 0x83, id2 0x83 Probing for At29C040A, 512 KB probe_jedec: id1 0x49, id2 0x4d Probing for At29C020, 256 KB probe_jedec: id1 0x83, id2 0x83 Probing for Mx29f002, 256 KB probe_29f002: id1 0x83, id2 0x83 Probing for MX25L4005, 512 KB RDID returned c2 20 13 probe_spi: id1 0xc2, id2 0x2013 MX25L4005 found at physical address: 0xfff80000 Flash part is MX25L4005 (512 KB) OK, only ENABLING flash write, but NOT FLASHING.
Great! Can you ack/commit with the following changelog? ------------------------------------------------------------------------
This patch aims to restructure SPI flash support in a more reasonable way. It introduces a generic SPI host driver for the IT8716F Super I/O which will enable easy SPI programming without having to care for the peculiarities of the SPI host.
To activate probing for the IT8716F, you have to use the gigabyte:m57sli mainboard override. SPI support will then use the gathered SPI host data to access the SPI flash.
This has been tested sucessfully by Ward Vandewege ward@gnu.org on the GA-M57SLI v2.0, which has a MX25L4005 SPI flash part.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
------------------------------------------------------------------------
Thanks, Carl-Daniel
On Mon, Oct 01, 2007 at 03:13:12PM +0200, Carl-Daniel Hailfinger wrote:
Great! Can you ack/commit with the following changelog?
This patch aims to restructure SPI flash support in a more reasonable way. It introduces a generic SPI host driver for the IT8716F Super I/O which will enable easy SPI programming without having to care for the peculiarities of the SPI host.
To activate probing for the IT8716F, you have to use the gigabyte:m57sli mainboard override. SPI support will then use the gathered SPI host data to access the SPI flash.
This has been tested sucessfully by Ward Vandewege ward@gnu.org on the GA-M57SLI v2.0, which has a MX25L4005 SPI flash part.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Acked-by: Ward Vandewege ward@gnu.org
And committed in r2817
Thanks, Ward.
On Mon, Oct 01, 2007 at 02:53:35PM +0200, Carl-Daniel Hailfinger wrote:
Index: util/flashrom/flash.h
--- util/flashrom/flash.h (Revision 2814) +++ util/flashrom/flash.h (Arbeitskopie) @@ -55,6 +55,8 @@ /* Please keep this list sorted alphabetically by manufacturer. The first
- entry of each section should be the manufacturer ID, followed by the
- list of devices from that manufacturer (sorted by device IDs).
- All LPC/FWH parts (parallel flash) have 8-bit device IDs.
*/
- All SPI parts have 16-bit device IDs.
#define AMD_ID 0x01 /* AMD */ @@ -68,8 +70,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 */
id -> ID
+#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 */
id -> ID
+#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 +207,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 2814) +++ util/flashrom/board_enable.c (Arbeitskopie) @@ -30,6 +30,15 @@ #include <string.h> #include "flash.h"
+#define ITE_SUPERIO_PORT1 0x2e +#define ITE_SUPERIO_PORT2 0x4e
+#define JEDEC_RDID {0x9f} +#define JEDEC_RDID_OUTSIZE 0x01 +#define JEDEC_RDID_INSIZE 0x03
+static uint16_t it8716f_flashport = 0;
/* Generic Super I/O helper functions */ uint8_t regval(uint16_t port, uint8_t reg) { @@ -51,7 +60,7 @@ outb(0x87, port); outb(0x01, port); outb(0x55, port);
- if (port == 0x2e)
- if (port == ITE_SUPERIO_PORT1) outb(0x55, port); else outb(0xaa, port);
@@ -96,35 +105,97 @@ return flashport; }
-static void it8716_serial_rdid(uint16_t port) +/* The IT8716F 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 IT8716F 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. */
Please make all multi-line comments look the same as in the rest of the code:
/* Foo * Bar */
Or, if we want to use the exact Linux-style:
/* * Foo * Bar */
+static int it8716f_spi_command(uint16_t port, unsigned char writecnt, unsigned char readcnt, const unsigned char *writearr, unsigned char *readarr)
As per another mail, writecnt/readcnt/writearr/readarr seems to have a dont-care size, so I think we can make them all 'int' (or 'unsigned int' if they can't or shouldn't get negative).
I think using the "native" int type is the best solution in general, it gives the compiler maximum freedom to optimize (not that it would matter much here).
Index: util/flashrom/flashchips.c
--- util/flashrom/flashchips.c (Revision 2814) +++ util/flashrom/flashchips.c (Arbeitskopie) @@ -38,6 +38,8 @@ probe_jedec, erase_chip_jedec, write_jedec}, {"Mx29f002", MX_ID, MX_29F002, 256, 64 * 1024, probe_29f002, erase_29f002, write_29f002},
- {"MX25L4005", MX_ID, MX_25L4005, 512, 4 * 1024,
probe_spi, NULL, NULL},
All the other chips from above are not added?
{"SST29EE020A", SST_ID, SST_29EE020A, 256, 128, probe_jedec, erase_chip_jedec, write_jedec}, {"SST28SF040A", SST_ID, SST_28SF040, 512, 256,
With the above fixes: Acked-by: Uwe Hermann uwe@hermann-uwe.de
Uwe.