diff options
| author | Ronald G. Minnich <rminnich@gmail.com> | 2004-09-30 16:37:01 +0000 | 
|---|---|---|
| committer | Ronald G. Minnich <rminnich@gmail.com> | 2004-09-30 16:37:01 +0000 | 
| commit | 1f4d653d8cb34ad17de722eef45bc9db9bbb1aa3 (patch) | |
| tree | 41b598f0e40964f48d3a66944954b452d37496da | |
| parent | 9ffaf0b42308d26cfc7bf2711ea1c662c3093e0d (diff) | |
| download | flashrom-1f4d653d8cb34ad17de722eef45bc9db9bbb1aa3.tar.gz flashrom-1f4d653d8cb34ad17de722eef45bc9db9bbb1aa3.tar.bz2 flashrom-1f4d653d8cb34ad17de722eef45bc9db9bbb1aa3.zip | |
Support for sst firmware hub
Corresponding to flashrom svn r25 and coreboot v2 svn r1651.
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | flash_rom.c | 3 | ||||
| -rw-r--r-- | jedec.c | 29 | ||||
| -rw-r--r-- | jedec.h | 3 | ||||
| -rw-r--r-- | sst_fwhub.c | 178 | ||||
| -rw-r--r-- | sst_fwhub.h | 48 | 
6 files changed, 261 insertions, 2 deletions
| @@ -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 +	m29f400bt.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 diff --git a/flash_rom.c b/flash_rom.c index 6abd4898..3fd56e31 100644 --- a/flash_rom.c +++ b/flash_rom.c @@ -46,6 +46,7 @@  #include "sst49lf040.h"  #include "pm49fl004.h"  #include "mx29f002.h" +#include "sst_fwhub.h"  struct flashchip flashchips[] = {  	{"Am29F040B",	AMD_ID, 	AM_29F040B,	NULL, 512, 64 * 1024, @@ -73,7 +74,7 @@ struct flashchip flashchips[] = {  	{"SST49LF004A", SST_ID,		SST_49LF004A,	NULL, 512, 4096,  	 probe_jedec,	erase_chip_jedec, write_49lf040,NULL},  	{"SST49LF008A", SST_ID,		SST_49LF008A, 	NULL, 1024, 4096, -	 probe_jedec, 	erase_chip_jedec, write_49lf040,NULL}, +	 probe_sst_fwhub, erase_sst_fwhub, write_sst_fwhub, NULL},  	{"Pm49FL004",	PMC_ID,		PMC_49FL004,	NULL, 512, 64 * 1024,  	 probe_jedec,	erase_chip_jedec, write_49fl004,NULL},  	{"W29C011",	WINBOND_ID,	W_29C011,	NULL, 128, 128, @@ -89,6 +89,35 @@ int erase_sector_jedec(volatile unsigned char *bios, unsigned int page)  	return (0);  } +int erase_block_jedec(volatile unsigned char *bios, unsigned int block) +{ +	volatile unsigned char *Temp; + +	/*  Issue the Sector Erase command   */ +	Temp = bios + 0x5555;	/* set up address to be BASE:5555h      */ +	*Temp = 0xAA;		/* write data 0xAA to the address       */ +	myusec_delay(10); +	Temp = bios + 0x2AAA;	/* set up address to be BASE:2AAAh      */ +	*Temp = 0x55;		/* write data 0x55 to the address       */ +	myusec_delay(10); +	Temp = bios + 0x5555;	/* set up address to be BASE:5555h      */ +	*Temp = 0x80;		/* write data 0x80 to the address       */ +	myusec_delay(10); +	Temp = bios + 0x5555;	/* set up address to be BASE:5555h      */ +	*Temp = 0xAA;		/* write data 0xAA to the address       */ +	myusec_delay(10); +	Temp = bios + 0x2AAA;	/* set up address to be BASE:2AAAh      */ +	*Temp = 0x55;		/* write data 0x55 to the address       */ +	myusec_delay(10); +	Temp = bios + block;	/* set up address to be the current sector */ +	*Temp = 0x50;		/* write data 0x30 to the address       */ +	myusec_delay(10); + +	/* wait for Toggle bit ready         */ +	toggle_ready_jedec(bios); + +	return (0); +}  int erase_chip_jedec(struct flashchip *flash)  { @@ -1,10 +1,13 @@  #ifndef __JEDEC_H__  #define __JEDEC_H__ 1 +int write_byte_program_jedec(volatile unsigned char *bios, unsigned char *src, +			     volatile unsigned char *dst);  extern int probe_jedec(struct flashchip *flash);  extern int erase_chip_jedec(struct flashchip *flash);  extern int write_jedec(struct flashchip *flash, unsigned char *buf);  extern int erase_sector_jedec(volatile unsigned char *bios, unsigned int page); +extern int erase_block_jedec(volatile unsigned char *bios, unsigned int page);  extern int write_sector_jedec(volatile unsigned char *bios, unsigned char *src,  			      volatile unsigned char *dst,  			      unsigned int page_size); diff --git a/sst_fwhub.c b/sst_fwhub.c new file mode 100644 index 00000000..7ab6bdba --- /dev/null +++ b/sst_fwhub.c @@ -0,0 +1,178 @@ +/* + * adapted from the Intel FW hub stuff for 82802ax 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. + * + * + * $Id$ + */ + +#include <errno.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/io.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> + +#include "flash.h" +#include "jedec.h" +#include "sst_fwhub.h" + +// I need that Berkeley bit-map printer +void print_sst_fwhub_status(unsigned char status) +{ +	printf("%s", status & 0x80 ? "Ready:" : "Busy:"); +	printf("%s", status & 0x40 ? "BE SUSPEND:" : "BE RUN/FINISH:"); +	printf("%s", status & 0x20 ? "BE ERROR:" : "BE OK:"); +	printf("%s", status & 0x10 ? "PROG ERR:" : "PROG OK:"); +	printf("%s", status & 0x8 ? "VP ERR:" : "VPP OK:"); +	printf("%s", status & 0x4 ? "PROG SUSPEND:" : "PROG RUN/FINISH:"); +	printf("%s", status & 0x2 ? "WP|TBL#|WP#,ABORT:" : "UNLOCK:"); +} + +/* probe_jedec works fine for probing */ + +int probe_sst_fwhub(struct flashchip *flash) +{ +	volatile unsigned char *bios = flash->virt_addr; +	unsigned char id1, id2; +	size_t size = flash->total_size * 1024; +	/* Issue JEDEC Product ID Entry command */ +	*(volatile char *) (bios + 0x5555) = 0xAA; +	myusec_delay(10); +	*(volatile char *) (bios + 0x2AAA) = 0x55; +	myusec_delay(10); +	*(volatile char *) (bios + 0x5555) = 0x90; +	myusec_delay(10); + +	/* Read product ID */ +	id1 = *(volatile unsigned char *) bios; +	id2 = *(volatile unsigned char *) (bios + 0x01); + +	/* Issue JEDEC Product ID Exit command */ +	*(volatile char *) (bios + 0x5555) = 0xAA; +	myusec_delay(10); +	*(volatile char *) (bios + 0x2AAA) = 0x55; +	myusec_delay(10); +	*(volatile char *) (bios + 0x5555) = 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 0; + +	myusec_delay(10); + + + +	// we need to mmap the write-protect space.  +	bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED, +		    flash->fd_mem, (off_t) (0 - 0x400000 - size)); +	if (bios == MAP_FAILED) { +	  // it's this part but we can't map it ... +	  perror("Error MMAP /dev/mem"); +	  exit(1); +	} + +	flash->virt_addr_2 = bios; +	return 1; +} + +unsigned char wait_sst_fwhub(volatile unsigned char *bios) +{ + + + +	toggle_ready_jedec(bios); +	return 0; +} + +int erase_sst_fwhub_block(struct flashchip *flash, int offset) +{ +	volatile unsigned char *bios = flash->virt_addr + offset; +	volatile unsigned char *wrprotect = +	    flash->virt_addr_2 + offset + 2; +	unsigned char status; + +	// clear status register +	printf("Erase at %p\n", bios); +	// clear write protect +	printf("write protect is at %p\n", (wrprotect)); +	printf("write protect is 0x%x\n", *(wrprotect)); +	*(wrprotect) = 0; +	printf("write protect is 0x%x\n", *(wrprotect)); + +	erase_block_jedec(flash->virt_addr, offset); +	status = wait_sst_fwhub(flash->virt_addr); +	//print_sst_fwhub_status(status); +	printf("DONE BLOCK 0x%x\n", offset); +	return (0); +} + +int erase_sst_fwhub(struct flashchip *flash) +{ +	int i; +	unsigned int total_size = flash->total_size * 1024; + +	printf("total_size is %d; flash->page_size is %d\n", +	       total_size, flash->page_size); +	for (i = 0; i < total_size; i += flash->page_size) +		erase_sst_fwhub_block(flash, i); +	printf("DONE ERASE\n"); +	return (0); +} + +void write_page_sst_fwhub(volatile char *bios, char *src, volatile char *dst, +			int page_size) +{ +	int i; + +	for (i = 0; i < page_size; i++) { +		/* transfer data from source to destination */ +	  write_byte_program_jedec(bios, src, dst); +	  src++; +	  dst++; +	} + +} + +int write_sst_fwhub(struct flashchip *flash, unsigned char *buf) +{ +	int i; +	int total_size = flash->total_size * 1024, page_size = +	    flash->page_size; +	volatile unsigned char *bios = flash->virt_addr; + +	erase_sst_fwhub(flash); +	if (*bios != 0xff) { +		printf("ERASE FAILED\n"); +		return -1; +	} +	printf("Programming Page: "); +	for (i = 0; i < total_size / page_size; i++) { +		printf("%04d at address: 0x%08x", i, i * page_size); +		write_page_sst_fwhub(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_sst_fwhub(bios); +	return (0); +} diff --git a/sst_fwhub.h b/sst_fwhub.h new file mode 100644 index 00000000..35691305 --- /dev/null +++ b/sst_fwhub.h @@ -0,0 +1,48 @@ +#ifndef __SST_FWHUB_H__ +#define __SST_FWHUB_H__ 1 + +extern int probe_sst_fwhub(struct flashchip *flash); +extern int erase_sst_fwhub(struct flashchip *flash); +extern int write_sst_fwhub(struct flashchip *flash, unsigned char *buf); + +extern __inline__ void toggle_ready_sst_fwhub(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; +	} +} + +extern __inline__ void data_polling_sst_fwhub(volatile char *dst, char data) +{ +	unsigned int i = 0; +	char tmp; + +	data &= 0x80; + +	while (i++ < 0xFFFFFF) { +		tmp = *dst & 0x80; +		if (tmp == data) { +			break; +		} +	} +} + +extern __inline__ void protect_sst_fwhub(volatile char *bios) +{ +	*(volatile char *) (bios + 0x5555) = 0xAA; +	*(volatile char *) (bios + 0x2AAA) = 0x55; +	*(volatile char *) (bios + 0x5555) = 0xA0; + +	usleep(200); +} + +#endif				/* !__SST_FWHUB_H__ */ | 
