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

Reply via email to