I bought a M29F040B 4 Mib flash chip for my EPIA-V motherboard today in
order to get LinuxBIOS on it, and found that flash_and_burn didn't
support it. So, I got the datasheet and modified a copy of the M29F400BT
driver to work with it.
I make no guarantees, of course, but it seems to Work For Me (TM), so I
thought you might want to include it. I haven't managed to get LinuxBIOS
working yet, though, but burning the original BIOS to it works and
boots.
I'm attaching the patch as MIME.
Fredrik Tolf
Index: util/flash_and_burn/flash.h
===================================================================
--- util/flash_and_burn/flash.h (revision 2100)
+++ util/flash_and_burn/flash.h (working copy)
@@ -53,6 +53,7 @@
#define ST_ID 0x20
#define ST_M29F400BT 0xD5
+#define ST_M29F040B 0xE2
#define MSYSTEMS_ID 0x156f
#define MSYSTEMS_MD2200 0xdb /* ? */
Index: util/flash_and_burn/m29f040b.c
===================================================================
--- util/flash_and_burn/m29f040b.c (revision 0)
+++ util/flash_and_burn/m29f040b.c (revision 0)
@@ -0,0 +1,171 @@
+/*
+ * m29f040b.c: driver for programming JEDEC standard flash parts
+ *
+ *
+ * Copyright 2000 Silicon Integrated System Corporation
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * Reference:
+ *
+ * $Id: m29f040b.c,v 1.1 2006/08/23 21:17:06 fredrik Exp $
+ */
+
+#include "flash.h"
+#include "m29f040b.h"
+
+void toggle_ready_m29f040b(volatile char *dst)
+{
+ unsigned int i = 0;
+ char tmp1, tmp2;
+
+ tmp1 = *dst & 0x40;
+
+ while (i++ < 0xFFFFFF) {
+ tmp2 = *dst & 0x40;
+ if (tmp1 == tmp2) {
+ break;
+ }
+ tmp1 = tmp2;
+ }
+}
+
+void data_polling_m29f040b(volatile char *dst,
+ unsigned char data)
+{
+ unsigned int i = 0;
+ char tmp;
+
+ data &= 0x80;
+
+ while (i++ < 0xFFFFFF) {
+ tmp = *dst & 0x80;
+ if (tmp == data) {
+ break;
+ }
+ }
+}
+
+void write_page_m29f040b(volatile char *bios, char *src,
+ volatile char *dst,
+ int page_size)
+{
+ int i;
+
+ for (i = 0; i < page_size; i++) {
+ *(volatile char *) (bios + 0x555) = 0xAA;
+ *(volatile char *) (bios + 0x2AA) = 0x55;
+ *(volatile char *) (bios + 0x555) = 0xA0;
+
+ /* transfer data from source to destination */
+ *dst = *src;
+ //*(volatile char *) (bios) = 0xF0;
+ /* usleep(5); */
+ toggle_ready_m29f040b(dst);
+ dst++;
+ src++;
+ }
+
+}
+
+int probe_m29f040b(struct flashchip *flash)
+{
+ volatile char *bios = flash->virt_addr;
+ unsigned char id1, id2;
+
+ *(volatile char *) (bios + 0x555) = 0xAA;
+ *(volatile char *) (bios + 0x2AA) = 0x55;
+ *(volatile char *) (bios + 0x555) = 0x90;
+
+ myusec_delay(10);
+
+ id1 = *(volatile unsigned char *) bios;
+ id2 = *(volatile unsigned char *) (bios + 0x01);
+
+ *(volatile char *) (bios + 0x555) = 0xAA;
+ *(volatile char *) (bios + 0x2AA) = 0x55;
+ *(volatile char *) (bios + 0x555) = 0xF0;
+
+ myusec_delay(10);
+
+ printf("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2);
+
+
+ if (id1 == flash->manufacture_id && id2 == flash->model_id)
+ return 1;
+
+ return 0;
+}
+
+int erase_m29f040b(struct flashchip *flash)
+{
+ volatile char *bios = flash->virt_addr;
+
+ *(volatile char *) (bios + 0x555) = 0xAA;
+ *(volatile char *) (bios + 0x2AA) = 0x55;
+ *(volatile char *) (bios + 0x555) = 0x80;
+
+ *(volatile char *) (bios + 0x555) = 0xAA;
+ *(volatile char *) (bios + 0x2AA) = 0x55;
+ *(volatile char *) (bios + 0x555) = 0x10;
+
+ myusec_delay(10);
+ toggle_ready_m29f040b(bios);
+
+ return (0);
+}
+
+int block_erase_m29f040b(volatile char *bios, volatile char *dst)
+{
+
+ *(volatile char *) (bios + 0x555) = 0xAA;
+ *(volatile char *) (bios + 0x2AA) = 0x55;
+ *(volatile char *) (bios + 0x555) = 0x80;
+
+ *(volatile char *) (bios + 0x555) = 0xAA;
+ *(volatile char *) (bios + 0x2AA) = 0x55;
+ //*(volatile char *) (bios + 0xAAA) = 0x10;
+ *dst = 0x30;
+
+ myusec_delay(10);
+ toggle_ready_m29f040b(bios);
+
+ return (0);
+}
+
+int write_m29f040b(struct flashchip *flash, unsigned char *buf)
+{
+ int i;
+ int total_size = flash->total_size * 1024, page_size =
+ flash->page_size;
+ volatile char *bios = flash->virt_addr;
+
+ //erase_m29f040b (flash);
+ printf("Programming Page:\n ");
+ printf("total_size/page_size = %d\n", total_size / page_size);
+ for (i = 0; i < total_size / page_size; i++) {
+ printf("%04d at address: 0x%08x\n", i, i * page_size);
+ block_erase_m29f040b(bios, bios + i * page_size);
+ write_page_m29f040b(bios, buf + i * page_size,
+ bios + i * page_size, page_size);
+ printf
+ ("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
+ }
+ printf("\n");
+ //protect_m29f040b (bios);
+
+ return (0);
+}
Index: util/flash_and_burn/m29f040b.h
===================================================================
--- util/flash_and_burn/m29f040b.h (revision 0)
+++ util/flash_and_burn/m29f040b.h (revision 0)
@@ -0,0 +1,13 @@
+#ifndef __M29F040B_H__
+#define __M29F040B_H__ 1
+
+#include <stdio.h>
+
+extern int probe_m29f040b(struct flashchip *flash);
+extern int erase_m29f040b(struct flashchip *flash);
+extern int block_erase_m29f040b(volatile char *bios, volatile char *dst);
+extern int write_m29f040b(struct flashchip *flash, unsigned char *buf);
+extern int write_linuxbios_m29f040b(struct flashchip *flash,
+ unsigned char *buf);
+
+#endif /* !__M29F040B_H__ */
Index: util/flash_and_burn/Makefile
===================================================================
--- util/flash_and_burn/Makefile (revision 2100)
+++ util/flash_and_burn/Makefile (working copy)
@@ -1,5 +1,5 @@
OBJS = flash_enable.o udelay.o jedec.o sst28sf040.o am29f040b.o mx29f002.c sst39sf020.o \
- m29f400bt.o w49f002u.o 82802ab.o msys_doc.o pm49fl004.o sst49lf040.o sst_fwhub.o
+ m29f400bt.o m29f040b.o w49f002u.o 82802ab.o msys_doc.o pm49fl004.o sst49lf040.o sst_fwhub.o
CC = gcc -O2 -g -Wall -Werror
all: flash_rom flash_on
@@ -15,12 +15,13 @@
flash_rom.o: flash_rom.c flash.h jedec.h \
82802ab.h am29f040b.h m29f400bt.h msys_doc.h mx29f002.h sst28sf040.h \
- sst39sf020.h w49f002u.h sst49lf040.h
+ sst39sf020.h w49f002u.h sst49lf040.h m29f040b.h
flash_on.o: flash_on.c
82802ab.o: 82802ab.c 82802ab.h flash.h
am29f040b.o: am29f040b.c am29f040b.h jedec.h flash.h
m29f400bt.o: m29f400bt.c m29f400bt.h flash.h
+m29f040b.o: m29f040b.c m29f040b.h flash.h
msys_doc.o: msys_doc.c msys_doc.h flash.h
mx29f002.o: mx29f002.c mx29f002.h jedec.h flash.h
sst28sf040.o: sst28sf040.c sst28sf040.h jedec.h flash.h
Index: util/flash_and_burn/flash_rom.c
===================================================================
--- util/flash_and_burn/flash_rom.c (revision 2100)
+++ util/flash_and_burn/flash_rom.c (working copy)
@@ -39,6 +39,7 @@
#include "flash.h"
#include "jedec.h"
#include "m29f400bt.h"
+#include "m29f040b.h"
#include "82802ab.h"
#include "msys_doc.h"
#include "am29f040b.h"
@@ -87,6 +88,8 @@
probe_jedec, erase_chip_jedec, write_49f002, NULL},
{"M29F400BT", ST_ID, ST_M29F400BT, NULL, 512, 64 * 1024,
probe_m29f400bt, erase_m29f400bt, write_linuxbios_m29f400bt, NULL},
+ {"M29F040B", ST_ID, ST_M29F040B, NULL, 512, 65536,
+ probe_m29f040b, erase_m29f040b, write_m29f040b, NULL},
{"82802ab", 137, 173, NULL, 512, 64 * 1024,
probe_82802ab, erase_82802ab, write_82802ab, NULL},
{"82802ac", 137, 172, NULL, 1024, 64 * 1024,
--
linuxbios mailing list
[email protected]
http://www.openbios.org/mailman/listinfo/linuxbios