[LinuxBIOS] [PATCH] flashrom: add MX25L4005 erase/write support
Carl-Daniel Hailfinger
c-d.hailfinger.devel.2006 at gmx.net
Wed Oct 17 14:14:17 CEST 2007
On 15.10.2007 01:28, Harald Gutmann wrote:
> Am Montag, 15. Oktober 2007 01:06:00 schrieb Carl-Daniel Hailfinger:
>
>> Great, thanks! The code I have also is not polished, so even if your
>> code is ugly, it is better than no code. We can clean up that stuff
>> together.
>>
>
> yes, that's right!
> here it is.
>
> the patch is done with:
> Revision: 2850
>
I have rearranged some code, so your patch does no longer apply, but it
should be easy to fix.
> diff -ubrN ../../flashrom.original/board_enable.c flashrom.new/board_enable.c
> --- ../../flashrom.original/board_enable.c 2007-10-15 01:14:29.000000000 +0200
> +++ flashrom.new/board_enable.c 2007-10-14 20:28:41.000000000 +0200
>
This is now in spi.c
> @@ -37,7 +37,7 @@
> #define JEDEC_RDID_OUTSIZE 0x01
> #define JEDEC_RDID_INSIZE 0x03
>
> -static uint16_t it8716f_flashport = 0;
> +uint16_t it8716f_flashport = 0;
>
> /* Generic Super I/O helper functions */
> uint8_t regval(uint16_t port, uint8_t reg)
> @@ -111,7 +111,7 @@
> 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)
> +int it8716f_spi_command(uint16_t port, unsigned char writecnt, unsigned char readcnt, const unsigned char *writearr, unsigned char *readarr)
> {
> uint8_t busy, writeenc;
> do {
> diff -ubrN ../../flashrom.original/board_enable.h flashrom.new/board_enable.h
> --- ../../flashrom.original/board_enable.h 1970-01-01 01:00:00.000000000 +0100
> +++ flashrom.new/board_enable.h 2007-10-14 21:09:18.000000000 +0200
>
Perhaps move to spi.h?
> @@ -0,0 +1,7 @@
> +#ifndef boardenableh
> +#define boardenableh
> +uint16_t it8716f_flashport;
> +uint8_t regval(uint16_t port, uint8_t reg);
> +void regwrite(uint16_t port, uint8_t reg, uint8_t val);
> +int it8716f_spi_command(uint16_t port, unsigned char writecnt, unsigned char readcnt, const unsigned char *writearr, unsigned char *readarr);
> +#endif
> diff -ubrN ../../flashrom.original/flashchips.c flashrom.new/flashchips.c
> --- ../../flashrom.original/flashchips.c 2007-10-15 01:14:28.000000000 +0200
> +++ flashrom.new/flashchips.c 2007-10-15 01:24:58.000000000 +0200
> @@ -39,7 +39,7 @@
> {"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},
> + probe_spi, erase_25l4005, write_25l4005},
> {"SST29EE020A", SST_ID, SST_29EE020A, 256, 128,
> probe_jedec, erase_chip_jedec, write_jedec},
> {"SST28SF040A", SST_ID, SST_28SF040, 512, 256,
>
OK
> diff -ubrN ../../flashrom.original/flash.h flashrom.new/flash.h
> --- ../../flashrom.original/flash.h 2007-10-15 01:14:28.000000000 +0200
> +++ flashrom.new/flash.h 2007-10-14 19:13:52.000000000 +0200
> @@ -294,4 +294,10 @@
> /* w49f002u.c */
> int write_49f002(struct flashchip *flash, uint8_t *buf);
>
> +/* mx25l4005.c */
> +// probe
> +int write_25l4005(struct flashchip *flash, uint8_t *buf);
> +int erase_25l4005(struct flashchip *flash);
> +int read_25l4005(struct flashchip *flash, uint8_t *buf);
> +
> #endif /* !__FLASH_H__ */
>
OK
> diff -ubrN ../../flashrom.original/Makefile flashrom.new/Makefile
> --- ../../flashrom.original/Makefile 2007-10-15 01:14:29.000000000 +0200
> +++ flashrom.new/Makefile 2007-10-15 01:20:16.000000000 +0200
> @@ -24,7 +24,7 @@
> am29f040b.o mx29f002.o sst39sf020.o m29f400bt.o w49f002u.o \
> 82802ab.o msys_doc.o pm49fl004.o sst49lf040.o sst49lfxxxc.o \
> sst_fwhub.o layout.o lbtable.o flashchips.o flashrom.o \
> - sharplhf00l04.o w29ee011.o
> + sharplhf00l04.o w29ee011.o mx25l4005.o
>
> all: pciutils dep $(PROGRAM)
>
> @@ -33,7 +33,7 @@
> $(STRIP) $(STRIP_ARGS) $(PROGRAM)
>
> clean:
> - rm -f *.o *~
> + rm -f *.o *~ flashrom
>
> distclean: clean
> rm -f $(PROGRAM) .dependencies
>
Skip the make clean changes. We have make distclean.
> diff -ubrN ../../flashrom.original/mx25l4005.c flashrom.new/mx25l4005.c
> --- ../../flashrom.original/mx25l4005.c 1970-01-01 01:00:00.000000000 +0100
> +++ flashrom.new/mx25l4005.c 2007-10-15 01:17:56.000000000 +0200
> @@ -0,0 +1,57 @@
> +#include <stdint.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include "flash.h"
> +#include "board_enable.h"
> +
> +static void check_n_write_enable() {
> + uint8_t result[3] = {0, 0, 0};
> + uint8_t command[5] = {0x06, 0, 0, 0, 0};
> + // Send WREN (Write Enable)
> + it8716f_spi_command(it8716f_flashport, 1, 0, command, result);
>
generic_spi_command
> + uint8_t reg=regval(it8716f_flashport,0x24);
> + reg|=(1<<4);
> + regwrite(it8716f_flashport,0x24,reg);
>
I have absolutely no idea what you are trying to do here. According to
my data sheet, your code does the following:
* Enable multiple byte mode, set clock to 33/2 MHz, read the last JEDEC
command sent to the flash chip
* Set bit 4 of the last JEDEC command
* Enable multiple byte mode, set clock to 33/2 MHz, write the modified
JEDEC command
Please note that none of these three lines send or receive anything
from/to the chip.
> +
> +}
> +
> +static void write_disable() {
> + uint8_t result[3] = {0, 0, 0};
> + uint8_t command[5] = {0x04, 0, 0, 0, 0};
> + // Send WRDI (Write Disable)
> + it8716f_spi_command(it8716f_flashport, 1, 0, command, result);
>
generic_spi_command
> + uint8_t reg=regval(it8716f_flashport,0x24);
> + reg&=~(1<<4);
> + regwrite(it8716f_flashport,0x24,reg);
>
Same as above: What are you trying to do?
> +}
> +
> +void write256b(int block, uint8_t *buf, uint8_t *bios ) {
> + check_n_write_enable();
> + outb(0x06,it8716f_flashport+1);
> + outb((3<<4),it8716f_flashport);
> + int i;
> + for (i=0;i<256;++i) {
> + bios[256*block+i]=buf[256*block+i];
> + }
> + outb(0,it8716f_flashport);
> + write_disable();
> + usleep (1000);
>
Check the chip status register instead fo waiting.
> +}
>
OK, but we probably need a generic_spi_command_prepare and
generic_spi_command_stop
> +
> +int write_25l4005(struct flashchip *flash, uint8_t *buf) {
> + int total_size=1024*flash->total_size;
> + int i;
> + for (i=0;i<total_size/256;++i) {
> + write256b(i, buf, (uint8_t*)flash->virtual_memory);
> + }
> +return 0;
> +}
>
OK
> +
> +int erase_25l4005(struct flashchip *flash) {
> +check_n_write_enable();
> +uint8_t result[3]={0, 0, 0};
> +uint8_t command[5]={0xc7, 0, 0, 0, 0};
> +it8716f_spi_command(it8716f_flashport, 1, 0, command, result);
>
generic_spi_command
> +write_disable();
> +sleep (3);
> +// the chip needs some time, until it responses again.
> +return 0;
>
Can you instead read the flash chip status register in a loop? That way,
you don't have to hardcode the sleep duration.
> +}
>
Overall, I like it.
My version of the write patch follows. Please test.
Index: flash.h
===================================================================
--- flash.h (Revision 2864)
+++ flash.h (Arbeitskopie)
@@ -296,4 +296,10 @@
/* w49f002u.c */
int write_49f002(struct flashchip *flash, uint8_t *buf);
+/* mx25l4005.c */
+// probe
+int write_25l4005(struct flashchip *flash, uint8_t *buf);
+int erase_25l4005(struct flashchip *flash);
+int read_25l4005(struct flashchip *flash, uint8_t *buf);
+
#endif /* !__FLASH_H__ */
Index: flashchips.c
===================================================================
--- flashchips.c (Revision 2864)
+++ flashchips.c (Arbeitskopie)
@@ -39,7 +39,7 @@
{"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},
+ probe_spi, erase_25l4005, write_25l4005},
{"SST29EE020A", SST_ID, SST_29EE020A, 256, 128,
probe_jedec, erase_chip_jedec, write_jedec},
{"SST28SF040A", SST_ID, SST_28SF040, 512, 256,
Index: spi.c
===================================================================
--- spi.c (Revision 2864)
+++ spi.c (Arbeitskopie)
@@ -34,8 +34,16 @@
#define JEDEC_RDID_OUTSIZE 0x01
#define JEDEC_RDID_INSIZE 0x03
-static uint16_t it8716f_flashport = 0;
+#define JEDEC_WREN {0x06}
+#define JEDEC_WREN_OUTSIZE 0x01
+#define JEDEC_WREN_INSIZE 0x00
+#define JEDEC_WRDI {0x04}
+#define JEDEC_WRDI_OUTSIZE 0x01
+#define JEDEC_WRDI_INSIZE 0x00
+
+uint16_t it8716f_flashport = 0;
+
/* Generic Super I/O helper functions */
uint8_t regval(uint16_t port, uint8_t reg)
{
@@ -170,7 +178,7 @@
return 0;
}
-static int generic_spi_command(unsigned char writecnt, unsigned char readcnt, const unsigned char *writearr, unsigned char *readarr)
+int generic_spi_command(unsigned char writecnt, unsigned char readcnt, const unsigned char *writearr, unsigned char *readarr)
{
if (it8716f_flashport)
return it8716f_spi_command(it8716f_flashport, writecnt, readcnt, writearr, readarr);
@@ -188,6 +196,25 @@
return 0;
}
+void generic_spi_write_enable()
+{
+ const unsigned char cmd[] = JEDEC_WREN;
+ unsigned char result[] = {0, 0, 0};
+
+ // Send WREN (Write Enable)
+ generic_spi_command(JEDEC_WREN_OUTSIZE, JEDEC_WREN_INSIZE, cmd, result);
+
+}
+
+void generic_spi_write_disable()
+{
+ const unsigned char cmd[] = JEDEC_WRDI;
+ unsigned char result[] = {0, 0, 0};
+
+ // Send WRDI (Write Disable)
+ generic_spi_command(JEDEC_WRDI_OUTSIZE, JEDEC_WRDI_INSIZE, cmd, result);
+}
+
int probe_spi(struct flashchip *flash)
{
unsigned char readarr[3];
Index: Makefile
===================================================================
--- Makefile (Revision 2864)
+++ Makefile (Arbeitskopie)
@@ -24,7 +24,7 @@
am29f040b.o mx29f002.o sst39sf020.o m29f400bt.o w49f002u.o \
82802ab.o msys_doc.o pm49fl004.o sst49lf040.o sst49lfxxxc.o \
sst_fwhub.o layout.o lbtable.o flashchips.o flashrom.o \
- sharplhf00l04.o w29ee011.o spi.o
+ sharplhf00l04.o w29ee011.o spi.o mx25l4005.o
all: pciutils dep $(PROGRAM)
Index: spi.h
===================================================================
--- spi.h (Revision 0)
+++ spi.h (Revision 0)
@@ -0,0 +1,9 @@
+#ifndef __SPI_H__
+#define __SPI_H__ 1
+
+uint16_t it8716f_flashport;
+int generic_spi_command(unsigned char writecnt, unsigned char readcnt, const unsigned char *writearr, unsigned char *readarr);
+void generic_spi_write_enable();
+void generic_spi_write_disable();
+
+#endif
Index: mx25l4005.c
===================================================================
--- mx25l4005.c (Revision 0)
+++ mx25l4005.c (Revision 0)
@@ -0,0 +1,39 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "flash.h"
+#include "spi.h"
+
+
+void write256b(int block, uint8_t *buf, uint8_t *bios ) {
+ generic_spi_write_enable();
+ outb(0x06,it8716f_flashport+1);
+ outb((3<<4),it8716f_flashport);
+ int i;
+ for (i=0;i<256;++i) {
+ bios[256*block+i]=buf[256*block+i];
+ }
+ outb(0,it8716f_flashport);
+ generic_spi_write_disable();
+ usleep (1000);
+}
+
+int write_25l4005(struct flashchip *flash, uint8_t *buf) {
+ int total_size=1024*flash->total_size;
+ int i;
+ for (i=0;i<total_size/256;++i) {
+ write256b(i, buf, (uint8_t*)flash->virtual_memory);
+ }
+return 0;
+}
+
+int erase_25l4005(struct flashchip *flash) {
+ generic_spi_write_enable();
+ uint8_t result[3]={0, 0, 0};
+ uint8_t command[5]={0xc7, 0, 0, 0, 0};
+ generic_spi_command(1, 0, command, result);
+ generic_spi_write_disable();
+ // the chip needs some time, until it responses again.
+ sleep (3);
+ return 0;
+}
More information about the coreboot
mailing list