mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-26 22:52:34 +02:00
Trying to make this general purpose user-land flash burner
Corresponding to coreboot v1 svn r489.
This commit is contained in:
commit
5e5f75e559
11
Makefile
Normal file
11
Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
OBJS = jedec.o sst28sf040.o am29f040b.o mx29f002.c
|
||||
CC = gcc -O2
|
||||
|
||||
all: ${OBJS}
|
||||
${CC} -o flash_rom flash_rom.c ${OBJS}
|
||||
${CC} -o flash_on flash_on.c
|
||||
${CC} -o acpi_reset acpi_reset.c
|
||||
${CC} -o acpi_shutdown acpi_shutdown.c
|
||||
|
||||
clean:
|
||||
rm -f flash_rom flash_on acpi_reset acpi_shutdown *.o *~
|
15
README
Normal file
15
README
Normal file
@ -0,0 +1,15 @@
|
||||
I am making this a general-purpose userland flash burner -- RGM
|
||||
|
||||
Earlier notes from Ollie:
|
||||
|
||||
Here is some utilities for using/programming flash ROM on SiS 630/950 M/Bs
|
||||
|
||||
1. flash_on, turnning on the flash writer enable for 630/950 M/Bs,
|
||||
you have to run this before load DoC drivers.
|
||||
|
||||
2. flash_rom, use your 630/950 M/Bs as a flash programmer for some
|
||||
flash parts. This utility is made as modular as possible. If
|
||||
you find your flash part is not supported, you can add a driver
|
||||
your own. Or sending me the data sheet.
|
||||
|
||||
Ollie
|
120
am29f040b.c
Normal file
120
am29f040b.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* am29f040.c: driver for programming AMD am29f040b models
|
||||
*
|
||||
*
|
||||
* 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:
|
||||
* AMD Am29F040B data sheet
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "flash.h"
|
||||
#include "jedec.h"
|
||||
|
||||
static __inline__ erase_sector_29f040b (char * bios, unsigned long address)
|
||||
{
|
||||
*(bios + 0x555) = 0xAA;
|
||||
*(bios + 0x2AA) = 0x55;
|
||||
*(bios + 0x555) = 0x80;
|
||||
*(bios + 0x555) = 0xAA;
|
||||
*(bios + 0x2AA) = 0x55;
|
||||
*(bios + address) = 0x30;
|
||||
|
||||
sleep(2);
|
||||
|
||||
/* wait for Toggle bit ready */
|
||||
toggle_ready_jedec(bios + address);
|
||||
}
|
||||
|
||||
static __inline__ write_sector_29f040b(char * bios, unsigned char * src,
|
||||
unsigned char * dst, unsigned int page_size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < page_size; i++) {
|
||||
printf("0x%08x", (unsigned long) dst - (unsigned long) bios);
|
||||
|
||||
*(bios + 0x555) = 0xAA;
|
||||
*(bios + 0x2AA) = 0x55;
|
||||
*(bios + 0x555) = 0xA0;
|
||||
*dst++ = *src++;
|
||||
|
||||
/* wait for Toggle bit ready */
|
||||
toggle_ready_jedec(bios);
|
||||
|
||||
printf("\b\b\b\b\b\b\b\b\b\b");
|
||||
}
|
||||
}
|
||||
|
||||
int probe_29f040b (struct flashchip * flash)
|
||||
{
|
||||
char * bios = flash->virt_addr;
|
||||
unsigned char id1, id2;
|
||||
|
||||
*(bios + 0x555) = 0xAA;
|
||||
*(bios + 0x2AA) = 0x55;
|
||||
*(bios + 0x555) = 0x90;
|
||||
|
||||
id1 = *(unsigned char *) bios;
|
||||
id2 = *(unsigned char *) (bios + 0x01);
|
||||
|
||||
*bios = 0xF0;
|
||||
|
||||
usleep(10);
|
||||
|
||||
if (id1 == flash->manufacture_id && id2 == flash->model_id)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int erase_29f040b (struct flashchip * flash)
|
||||
{
|
||||
char * bios = flash->virt_addr;
|
||||
|
||||
*(bios + 0x555) = 0xAA;
|
||||
*(bios + 0x2AA) = 0x55;
|
||||
*(bios + 0x555) = 0x80;
|
||||
*(bios + 0x555) = 0xAA;
|
||||
*(bios + 0x2AA) = 0x55;
|
||||
*(bios + 0x555) = 0x10;
|
||||
|
||||
usleep(10);
|
||||
toggle_ready_jedec(bios);
|
||||
}
|
||||
|
||||
int write_29f040b (struct flashchip * flash, char * buf)
|
||||
{
|
||||
int i;
|
||||
int total_size = flash->total_size * 1024, page_size = flash->page_size;
|
||||
char * bios = flash->virt_addr;
|
||||
|
||||
printf ("Programming Page: ");
|
||||
for (i = 0; i < total_size/page_size; i++) {
|
||||
/* erase the page before programming */
|
||||
erase_sector_29f040b(bios, i * page_size);
|
||||
|
||||
/* write to the sector */
|
||||
printf ("%04d at address: ", i);
|
||||
write_sector_29f040b(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");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
44
flash.h
Normal file
44
flash.h
Normal file
@ -0,0 +1,44 @@
|
||||
#include <sys/io.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct flashchip {
|
||||
char * name;
|
||||
int manufacture_id;
|
||||
int model_id;
|
||||
|
||||
char * virt_addr;
|
||||
int total_size;
|
||||
int page_size;
|
||||
|
||||
int (*probe) (struct flashchip * flash);
|
||||
int (*erase) (struct flashchip * flash);
|
||||
int (*write) (struct flashchip * flash, char * buf);
|
||||
};
|
||||
|
||||
#define AMD_ID 0x01
|
||||
#define AM_29F040B 0xA4
|
||||
|
||||
#define ATMEL_ID 0x1F /* Winbond Manufacture ID code */
|
||||
#define AT_29C040A 0xA4 /* Winbond w29c020c device code*/
|
||||
|
||||
#define MX_ID 0xC2
|
||||
#define MX_29F002 0xB0
|
||||
|
||||
#define SST_ID 0xBF /* SST Manufacturer ID[B code */
|
||||
#define SST_29EE020A 0x10 /* SST 29EE020 device code */
|
||||
#define SST_28SF040 0x04 /* SST 29EE040 device code */
|
||||
|
||||
#define WINBOND_ID 0xDA /* Winbond Manufacture ID code */
|
||||
#define W_29C020C 0x45 /* Winbond w29c020c device code*/
|
||||
|
||||
extern int probe_28sf040 (struct flashchip * flash);
|
||||
extern int erase_28sf040 (struct flashchip * flash);
|
||||
extern int write_28sf040 (struct flashchip * flash, char * buf);
|
||||
|
||||
extern int probe_29f040b (struct flashchip * flash);
|
||||
extern int erase_29f040b (struct flashchip * flash);
|
||||
extern int write_29f040b (struct flashchip * flash, char * buf);
|
||||
|
||||
extern int probe_29f002 (struct flashchip * flash);
|
||||
extern int erase_29f002 (struct flashchip * flash);
|
||||
extern int write_29f002 (struct flashchip * flash, char * buf);
|
74
flash_on.c
Normal file
74
flash_on.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* flash_rom.c: Turnning on Flash Write Enable for SiS 630/950 M/Bs,
|
||||
* use this program before loading DoC drivers.
|
||||
*
|
||||
*
|
||||
* 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:
|
||||
* 1. SiS 630 Specification
|
||||
* 2. SiS 950 Specification
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/io.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
main()
|
||||
{
|
||||
char b;
|
||||
|
||||
/* get io privilege access PCI configuration space */
|
||||
if (iopl(3) != 0) {
|
||||
perror("Can not set io priviliage");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Enable 0xFFF8000~0xFFFF0000 decoding on SiS 540/630 */
|
||||
outl(0x80000840, 0x0cf8);
|
||||
b = inb(0x0cfc) | 0x0b;
|
||||
outb(b, 0xcfc);
|
||||
/* Flash write enable on SiS 540/630 */
|
||||
outl(0x80000845, 0x0cf8);
|
||||
b = inb(0x0cfd) | 0x40;
|
||||
outb(b, 0xcfd);
|
||||
|
||||
/* The same thing on SiS 950 SuperIO side */
|
||||
outb(0x87, 0x2e);
|
||||
outb(0x01, 0x2e);
|
||||
outb(0x55, 0x2e);
|
||||
outb(0x55, 0x2e);
|
||||
|
||||
if (inb(0x2f) != 0x87) {
|
||||
printf("Can not access SiS 950\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
outb(0x24, 0x2e);
|
||||
b = inb(0x2f) | 0xfc;
|
||||
outb(0x24, 0x2e);
|
||||
outb(b, 0x2f);
|
||||
|
||||
outb(0x02, 0x2e);
|
||||
outb(0x02, 0x2f);
|
||||
}
|
196
flash_rom.c
Normal file
196
flash_rom.c
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* flash_rom.c: Flash programming utility for SiS 630/950 M/Bs
|
||||
*
|
||||
*
|
||||
* 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:
|
||||
* 1. SiS 630 Specification
|
||||
* 2. SiS 950 Specification
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/io.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "flash.h"
|
||||
#include "jedec.h"
|
||||
|
||||
struct flashchip flashchips[] = {
|
||||
{"Am29F040B", AMD_ID, AM_29F040B, NULL, 512, 64*1024,
|
||||
probe_29f040b, erase_29f040b, write_29f040b},
|
||||
{"At29C040A", ATMEL_ID, AT_29C040A, NULL, 512, 256,
|
||||
probe_jedec, erase_jedec, write_jedec},
|
||||
{"Mx29f002", MX_ID, MX_29F002, NULL, 256, 64*1024,
|
||||
probe_29f002, erase_29f002, write_29f002},
|
||||
{"SST29EE020A", SST_ID, SST_29EE020A, NULL, 256, 128,
|
||||
probe_jedec, erase_jedec, write_jedec},
|
||||
{"SST28SF040A", SST_ID, SST_28SF040, NULL, 512, 256,
|
||||
probe_28sf040, erase_28sf040, write_28sf040},
|
||||
{"W29C020C", WINBOND_ID, W_29C020C, NULL, 256, 128,
|
||||
probe_jedec, erase_jedec, write_jedec},
|
||||
{NULL,}
|
||||
};
|
||||
|
||||
int enable_flash_sis630 (void)
|
||||
{
|
||||
char b;
|
||||
|
||||
/* get io privilege access PCI configuration space */
|
||||
if (iopl(3) != 0) {
|
||||
perror("Can not set io priviliage");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Enable 0xFFF8000~0xFFFF0000 decoding on SiS 540/630 */
|
||||
outl(0x80000840, 0x0cf8);
|
||||
b = inb(0x0cfc) | 0x0b;
|
||||
outb(b, 0xcfc);
|
||||
/* Flash write enable on SiS 540/630 */
|
||||
outl(0x80000845, 0x0cf8);
|
||||
b = inb(0x0cfd) | 0x40;
|
||||
outb(b, 0xcfd);
|
||||
|
||||
/* The same thing on SiS 950 SuperIO side */
|
||||
outb(0x87, 0x2e);
|
||||
outb(0x01, 0x2e);
|
||||
outb(0x55, 0x2e);
|
||||
outb(0x55, 0x2e);
|
||||
|
||||
if (inb(0x2f) != 0x87) {
|
||||
outb(0x87, 0x4e);
|
||||
outb(0x01, 0x4e);
|
||||
outb(0x55, 0x4e);
|
||||
outb(0xaa, 0x4e);
|
||||
if (inb(0x4f) != 0x87) {
|
||||
printf("Can not access SiS 950\n");
|
||||
return -1;
|
||||
}
|
||||
outb(0x24, 0x4e);
|
||||
b = inb(0x4f) | 0xfc;
|
||||
outb(0x24, 0x4e);
|
||||
outb(b, 0x4f);
|
||||
outb(0x02, 0x4e);
|
||||
outb(0x02, 0x4f);
|
||||
}
|
||||
|
||||
outb(0x24, 0x2e);
|
||||
printf("2f is %#x\n", inb(0x2f));
|
||||
b = inb(0x2f) | 0xfc;
|
||||
outb(0x24, 0x2e);
|
||||
outb(b, 0x2f);
|
||||
|
||||
outb(0x02, 0x2e);
|
||||
outb(0x02, 0x2f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct flashchip * probe_flash(struct flashchip * flash)
|
||||
{
|
||||
int fd_mem;
|
||||
char * bios;
|
||||
unsigned long size;
|
||||
|
||||
if ((fd_mem = open("/dev/mem", O_RDWR)) < 0) {
|
||||
perror("Can not open /dev/mem");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (flash->name != NULL) {
|
||||
size = flash->total_size * 1024;
|
||||
bios = mmap (0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
|
||||
fd_mem, (off_t) (0 - size));
|
||||
if (bios == MAP_FAILED) {
|
||||
perror("Error MMAP /dev/mem");
|
||||
exit(1);
|
||||
}
|
||||
flash->virt_addr = bios;
|
||||
|
||||
if (flash->probe(flash) == 1) {
|
||||
printf ("%s found at physical address: 0x%lx\n",
|
||||
flash->name, (0 - size), bios);
|
||||
return flash;
|
||||
}
|
||||
munmap (bios, size);
|
||||
flash++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int verify_flash (struct flashchip * flash, char * buf)
|
||||
{
|
||||
int i = 0;
|
||||
int total_size = flash->total_size *1024;
|
||||
char * bios = flash->virt_addr;
|
||||
|
||||
printf("Verifying address: ");
|
||||
while (i++ < total_size) {
|
||||
printf("0x%08x", i);
|
||||
if (*(bios+i) != *(buf+i)) {
|
||||
return 0;
|
||||
}
|
||||
printf("\b\b\b\b\b\b\b\b\b\b");
|
||||
}
|
||||
printf("\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
main (int argc, char * argv[])
|
||||
{
|
||||
char * buf;
|
||||
unsigned long size;
|
||||
FILE * image;
|
||||
struct flashchip * flash;
|
||||
|
||||
if (argc > 2){
|
||||
printf("usage: %s [romimage]\n", argv[0]);
|
||||
printf(" If no romimage is specified, then all that happens\n");
|
||||
printf(" is that flash writes are enabled (useful for DoC)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
enable_flash_sis630 ();
|
||||
|
||||
if ((flash = probe_flash (flashchips)) == NULL) {
|
||||
printf("EEPROM not found\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argc < 2){
|
||||
printf("OK, only ENABLING flash write, but NOT FLASHING\n");
|
||||
exit(0);
|
||||
}
|
||||
size = flash->total_size * 1024;
|
||||
|
||||
if ((image = fopen (argv[1], "r")) == NULL) {
|
||||
perror("Error opening image file");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
buf = (char *) calloc (size, sizeof(char));
|
||||
fread (buf, sizeof(char), size, image);
|
||||
|
||||
flash->write (flash, buf);
|
||||
verify_flash (flash, buf);
|
||||
}
|
88
jedec.c
Normal file
88
jedec.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* jedec.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$
|
||||
*/
|
||||
|
||||
#include "flash.h"
|
||||
#include "jedec.h"
|
||||
|
||||
int probe_jedec (struct flashchip * flash)
|
||||
{
|
||||
char * bios = flash->virt_addr;
|
||||
unsigned char id1, id2;
|
||||
|
||||
*(char *) (bios + 0x5555) = 0xAA;
|
||||
*(char *) (bios + 0x2AAA) = 0x55;
|
||||
*(char *) (bios + 0x5555) = 0x90;
|
||||
|
||||
usleep(10);
|
||||
|
||||
id1 = *(unsigned char *) bios;
|
||||
id2 = *(unsigned char *) (bios + 0x01);
|
||||
|
||||
*(char *) (bios + 0x5555) = 0xAA;
|
||||
*(char *) (bios + 0x2AAA) = 0x55;
|
||||
*(char *) (bios + 0x5555) = 0xF0;
|
||||
|
||||
usleep(10);
|
||||
|
||||
if (id1 == flash->manufacture_id && id2 == flash->model_id)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int erase_jedec (struct flashchip * flash)
|
||||
{
|
||||
char * bios = flash->virt_addr;
|
||||
|
||||
*(char *) (bios + 0x5555) = 0xAA;
|
||||
*(char *) (bios + 0x2AAA) = 0x55;
|
||||
*(char *) (bios + 0x5555) = 0x80;
|
||||
|
||||
*(char *) (bios + 0x5555) = 0xAA;
|
||||
*(char *) (bios + 0x2AAA) = 0x55;
|
||||
*(char *) (bios + 0x5555) = 0x10;
|
||||
|
||||
usleep(10);
|
||||
toggle_ready_jedec(bios);
|
||||
}
|
||||
|
||||
int write_jedec (struct flashchip * flash, char * buf)
|
||||
{
|
||||
int i;
|
||||
int total_size = flash->total_size *1024, page_size = flash->page_size;
|
||||
char * bios = flash->virt_addr;
|
||||
|
||||
erase_jedec (flash);
|
||||
printf ("Programming Page: ");
|
||||
for (i = 0; i < total_size/page_size; i++) {
|
||||
printf ("%04d at address: 0x%08x", i, i * page_size);
|
||||
write_page_jedec(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_jedec (bios);
|
||||
}
|
61
jedec.h
Normal file
61
jedec.h
Normal file
@ -0,0 +1,61 @@
|
||||
extern int probe_jedec (struct flashchip * flash);
|
||||
extern int erase_jedec (struct flashchip * flash);
|
||||
extern int write_jedec (struct flashchip * flash, char * buf);
|
||||
|
||||
extern __inline__ void toggle_ready_jedec (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_jedec (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_jedec (char * bios)
|
||||
{
|
||||
*(char *) (bios + 0x5555) = 0xAA;
|
||||
*(char *) (bios + 0x2AAA) = 0x55;
|
||||
*(char *) (bios + 0x5555) = 0xA0;
|
||||
|
||||
usleep(200);
|
||||
}
|
||||
|
||||
extern __inline__ void write_page_jedec (char * bios, char * src, char * dst,
|
||||
int page_size)
|
||||
{
|
||||
int i;
|
||||
|
||||
*(char *) (bios + 0x5555) = 0xAA;
|
||||
*(char *) (bios + 0x2AAA) = 0x55;
|
||||
*(char *) (bios + 0x5555) = 0xA0;
|
||||
|
||||
for (i = 0; i < page_size; i++) {
|
||||
/* transfer data from source to destination */
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
usleep(100);
|
||||
toggle_ready_jedec(dst-1);
|
||||
}
|
112
mx29f002.c
Normal file
112
mx29f002.c
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* mx29f002.c: driver for MXIC MX29F002 flash models
|
||||
*
|
||||
*
|
||||
* 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:
|
||||
* MX29F002/002N data sheet
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "flash.h"
|
||||
#include "jedec.h"
|
||||
|
||||
int probe_29f002 (struct flashchip * flash)
|
||||
{
|
||||
char * bios = flash->virt_addr;
|
||||
unsigned char id1, id2, id3;
|
||||
|
||||
*(bios + 0x5555) = 0xAA;
|
||||
*(bios + 0x2AAA) = 0x55;
|
||||
*(bios + 0x5555) = 0x90;
|
||||
|
||||
id1 = *(unsigned char *) bios;
|
||||
id2 = *(unsigned char *) (bios + 0x01);
|
||||
|
||||
*bios = 0xF0;
|
||||
|
||||
usleep(10);
|
||||
|
||||
if (id1 == flash->manufacture_id && id2 == flash->model_id)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int erase_29f002 (struct flashchip * flash)
|
||||
{
|
||||
char * bios = flash->virt_addr;
|
||||
|
||||
again:
|
||||
*(bios + 0x555) = 0xF0;
|
||||
*(bios + 0x555) = 0xAA;
|
||||
*(bios + 0x2AA) = 0x55;
|
||||
*(bios + 0x555) = 0x80;
|
||||
*(bios + 0x555) = 0xAA;
|
||||
*(bios + 0x2AA) = 0x55;
|
||||
*(bios + 0x555) = 0x10;
|
||||
|
||||
usleep(100);
|
||||
toggle_ready_jedec(bios);
|
||||
|
||||
// while ((*bios & 0x40) != 0x40)
|
||||
//;
|
||||
|
||||
#if 0
|
||||
toggle_ready_jedec(bios);
|
||||
*(bios + 0x0ffff) = 0x30;
|
||||
*(bios + 0x1ffff) = 0x30;
|
||||
*(bios + 0x2ffff) = 0x30;
|
||||
*(bios + 0x37fff) = 0x30;
|
||||
*(bios + 0x39fff) = 0x30;
|
||||
*(bios + 0x3bfff) = 0x30;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int write_29f002 (struct flashchip * flash, char * buf)
|
||||
{
|
||||
int i;
|
||||
int total_size = flash->total_size * 1024, page_size = flash->page_size;
|
||||
char * bios = flash->virt_addr;
|
||||
char * dst = bios, * src = buf;
|
||||
|
||||
*bios = 0xF0;
|
||||
usleep(10);
|
||||
erase_29f002(flash);
|
||||
//*bios = 0xF0;
|
||||
#if 1
|
||||
printf ("Programming Page: ");
|
||||
for (i = 0; i < total_size; i++) {
|
||||
/* write to the sector */
|
||||
printf ("address: 0x%08lx", i);
|
||||
*(bios + 0x5555) = 0xAA;
|
||||
*(bios + 0x2AAA) = 0x55;
|
||||
*(bios + 0x5555) = 0xA0;
|
||||
*dst++ = 0x33;
|
||||
|
||||
/* wait for Toggle bit ready */
|
||||
toggle_ready_jedec(dst);
|
||||
|
||||
printf ("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
||||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
}
|
136
spd_dump.c
Normal file
136
spd_dump.c
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* acpi_reset.c: Reboot your LinuxBIOS system with ACPI software watchdo
|
||||
*
|
||||
*
|
||||
* 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:
|
||||
* 1. SiS 630 Specification
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/io.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
unsigned short acpi_base;
|
||||
|
||||
void
|
||||
waitsmbus()
|
||||
{
|
||||
unsigned short port = acpi_base;
|
||||
unsigned char val;
|
||||
|
||||
//printf("waitsmb ..\n");
|
||||
|
||||
for (val = inb(port); (val & 8) == 0; val = inb(port))
|
||||
;
|
||||
//printf("past first test\n");
|
||||
}
|
||||
|
||||
void
|
||||
setsmbus(unsigned char index, unsigned char value)
|
||||
{
|
||||
unsigned short port = acpi_base + index;
|
||||
|
||||
//printf("setsmbus: index 0x%02x, value 0x%02x\n",
|
||||
// index, value);
|
||||
|
||||
outb(value, port);
|
||||
}
|
||||
|
||||
unsigned char
|
||||
getsmbus(unsigned char index)
|
||||
{
|
||||
unsigned short port = acpi_base + index;
|
||||
unsigned char value;
|
||||
|
||||
value = inb(port);
|
||||
|
||||
//printf("getsmbus: index 0x%02x, value 0x%02x\n",
|
||||
// index, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
read_spd(unsigned char slot, unsigned char index)
|
||||
{
|
||||
unsigned char value;
|
||||
|
||||
setsmbus(0x03, 0x20);
|
||||
|
||||
setsmbus(0x04, 0xA1 + (slot << 1));
|
||||
|
||||
setsmbus(0x05, index);
|
||||
|
||||
setsmbus(0x03, 0x12);
|
||||
|
||||
waitsmbus();
|
||||
|
||||
value = getsmbus(0x08);
|
||||
|
||||
setsmbus(0x00, 0xFF);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
unsigned char b;
|
||||
unsigned short w;
|
||||
|
||||
|
||||
/* get io privilege access PCI configuration space */
|
||||
if (iopl(3) != 0) {
|
||||
perror("Can not set io priviliage");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Enable ACPI by set B7 on Reg 0x40, LPC */
|
||||
outl(0x80000840, 0x0cf8);
|
||||
b = inb(0x0cfc) | 0x80;
|
||||
outb(b, 0xcfc);
|
||||
|
||||
/* get the ACPI base address for register 0x74,0x75 of LPC */
|
||||
outl(0x80000874, 0x0cf8);
|
||||
w = inw(0x0cfc);
|
||||
acpi_base = w + 0x80;
|
||||
|
||||
printf("Number of bytes used by module manufacturer 0x%02x\n",
|
||||
read_spd(0x00, 0x00));
|
||||
|
||||
printf("Memory Type 0x%02x\n",
|
||||
read_spd(0x00, 0x02));
|
||||
|
||||
printf("Number of Row Address bits 0x%02x\n",
|
||||
read_spd(0x00, 0x03));
|
||||
|
||||
printf("Number of Column Address bits 0x%02x\n",
|
||||
read_spd(0x00, 0x04));
|
||||
|
||||
printf("Number of Sides 0x%02x\n",
|
||||
read_spd(0x00, 0x05));
|
||||
|
||||
printf("Number of Banks 0x%02x\n",
|
||||
read_spd(0x00, 0x11));
|
||||
}
|
159
sst28sf040.c
Normal file
159
sst28sf040.c
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* sst28sf040.c: driver for SST28SF040C flash models.
|
||||
*
|
||||
*
|
||||
* 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:
|
||||
* 4 MEgabit (512K x 8) SuperFlash EEPROM, SST28SF040 data sheet
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "flash.h"
|
||||
#include "jedec.h"
|
||||
|
||||
#define AUTO_PG_ERASE1 0x20
|
||||
#define AUTO_PG_ERASE2 0xD0
|
||||
#define AUTO_PGRM 0x10
|
||||
#define CHIP_ERASE 0x30
|
||||
#define RESET 0xFF
|
||||
#define READ_ID 0x90
|
||||
|
||||
static __inline__ void protect_28sf040 (char * bios)
|
||||
{
|
||||
/* ask compiler not to optimize this */
|
||||
volatile unsigned char tmp;
|
||||
|
||||
tmp = *(unsigned char *) (bios + 0x1823);
|
||||
tmp = *(unsigned char *) (bios + 0x1820);
|
||||
tmp = *(unsigned char *) (bios + 0x1822);
|
||||
tmp = *(unsigned char *) (bios + 0x0418);
|
||||
tmp = *(unsigned char *) (bios + 0x041B);
|
||||
tmp = *(unsigned char *) (bios + 0x0419);
|
||||
tmp = *(unsigned char *) (bios + 0x040A);
|
||||
}
|
||||
|
||||
static __inline__ void unprotect_28sf040 (char * bios)
|
||||
{
|
||||
/* ask compiler not to optimize this */
|
||||
volatile unsigned char tmp;
|
||||
|
||||
tmp = *(unsigned char *) (bios + 0x1823);
|
||||
tmp = *(unsigned char *) (bios + 0x1820);
|
||||
tmp = *(unsigned char *) (bios + 0x1822);
|
||||
tmp = *(unsigned char *) (bios + 0x0418);
|
||||
tmp = *(unsigned char *) (bios + 0x041B);
|
||||
tmp = *(unsigned char *) (bios + 0x0419);
|
||||
tmp = *(unsigned char *) (bios + 0x041A);
|
||||
}
|
||||
|
||||
static __inline__ erase_sector_28sf040 (char * bios, unsigned long address)
|
||||
{
|
||||
*bios = AUTO_PG_ERASE1;
|
||||
*(bios + address) = AUTO_PG_ERASE2;
|
||||
|
||||
/* wait for Toggle bit ready */
|
||||
toggle_ready_jedec(bios);
|
||||
}
|
||||
|
||||
static __inline__ write_sector_28sf040(char * bios, unsigned char * src,
|
||||
unsigned char * dst, unsigned int page_size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < page_size; i++) {
|
||||
/* transfer data from source to destination */
|
||||
if (*src == 0xFF) {
|
||||
dst++, src++;
|
||||
/* If the data is 0xFF, don't program it */
|
||||
continue;
|
||||
}
|
||||
/*issue AUTO PROGRAM command */
|
||||
*dst = AUTO_PGRM;
|
||||
*dst++ = *src++;
|
||||
|
||||
/* wait for Toggle bit ready */
|
||||
toggle_ready_jedec(bios);
|
||||
}
|
||||
}
|
||||
|
||||
int probe_28sf040 (struct flashchip * flash)
|
||||
{
|
||||
char * bios = flash->virt_addr;
|
||||
unsigned char id1, id2, tmp;
|
||||
|
||||
/* save the value at the beginning of the Flash */
|
||||
tmp = *bios;
|
||||
|
||||
*bios = RESET;
|
||||
usleep(10);
|
||||
|
||||
*bios = READ_ID;
|
||||
usleep(10);
|
||||
id1 = *(unsigned char *) bios;
|
||||
usleep(10);
|
||||
id2 = *(unsigned char *) (bios + 0x01);
|
||||
|
||||
*bios = RESET;
|
||||
usleep(10);
|
||||
|
||||
if (id1 == flash->manufacture_id && id2 == flash->model_id)
|
||||
return 1;
|
||||
|
||||
/* if there is no SST28SF040, restore the original value */
|
||||
*bios = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int erase_28sf040 (struct flashchip * flash)
|
||||
{
|
||||
char * bios = flash->virt_addr;
|
||||
|
||||
unprotect_28sf040 (bios);
|
||||
*bios = CHIP_ERASE;
|
||||
*bios = CHIP_ERASE;
|
||||
protect_28sf040 (bios);
|
||||
|
||||
usleep(10);
|
||||
toggle_ready_jedec(bios);
|
||||
}
|
||||
|
||||
int write_28sf040 (struct flashchip * flash, char * buf)
|
||||
{
|
||||
int i;
|
||||
int total_size = flash->total_size * 1024, page_size = flash->page_size;
|
||||
char * bios = flash->virt_addr;
|
||||
|
||||
unprotect_28sf040 (bios);
|
||||
|
||||
printf ("Programming Page: ");
|
||||
for (i = 0; i < total_size/page_size; i++) {
|
||||
/* erase the page before programming */
|
||||
erase_sector_28sf040(bios, i * page_size);
|
||||
|
||||
/* write to the sector */
|
||||
printf ("%04d at address: 0x%08x", i, i * page_size);
|
||||
write_sector_28sf040(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_28sf040 (bios);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user