Moved from freebios
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@864 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
		
							
								
								
									
										230
									
								
								src/mainboard/motorola/sandpoint/flash/amd800.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								src/mainboard/motorola/sandpoint/flash/amd800.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,230 @@ | ||||
| /* $Id$ */ | ||||
| /* Copyright 2000  AG Electronics Ltd. */ | ||||
| /* This code is distributed without warranty under the GPL v2 (see COPYING) */ | ||||
|  | ||||
| #include <types.h> | ||||
| #include <printk.h> | ||||
| #include <stdlib.h> | ||||
| #include "../flash.h" | ||||
|  | ||||
| struct data_amd800 | ||||
| { | ||||
|     unsigned base; | ||||
|     unsigned spacing; | ||||
|     unsigned cs; | ||||
|     const char *tag; | ||||
| }; | ||||
|  | ||||
| static const char *identify_amd (struct flash_device *flash_device); | ||||
| static int erase_flash_amd800 (void *data, unsigned offset, unsigned length); | ||||
| static int program_flash_amd800 (void *data, unsigned offset, const void *source, | ||||
| 				 unsigned length); | ||||
| static u8 read_byte_amd800(void *data, unsigned offset); | ||||
|  | ||||
| static flash_fn fn_amd800 = { | ||||
|     identify_amd, | ||||
|     0, | ||||
|     0, | ||||
|     erase_flash_amd800, | ||||
|     program_flash_amd800, | ||||
|     read_byte_amd800 | ||||
| }; | ||||
|  | ||||
| const char *identify_amd (struct flash_device *flash_device) | ||||
| { | ||||
|     struct data_amd800 *d800 = flash_device->data; | ||||
|  | ||||
|     if (!d800->tag) | ||||
|     { | ||||
| 	volatile unsigned char *flash = | ||||
|  | ||||
| 	    (volatile unsigned char *) d800->base; | ||||
| 	unsigned char type, | ||||
| 	 id; | ||||
|  | ||||
| 	*(flash + 0xaaa * d800->spacing) = 0xaa; | ||||
| 	*(flash + 0x555 * d800->spacing) = 0x55; | ||||
| 	*(flash + 0xaaa * d800->spacing) = 0x90; | ||||
| 	type = *(flash + 2 * d800->spacing); | ||||
| 	id = *flash; | ||||
| 	*flash = 0xf0; | ||||
| 	if ((id == 1 || id == 0x20) && type == 0x5b) | ||||
| 	{ | ||||
| 	    d800->cs = 45; | ||||
| 	    d800->tag = "Am29LV800BB"; | ||||
|     	    flash_device->base = d800->base; | ||||
|     	    flash_device->size = 1024*1024; | ||||
| 	    flash_device->erase_size = 64*1024; | ||||
| 	    flash_device->store_size = 1; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 	    printk_info("Unknown flash ID: 0x%02x 0x%02x\n", id, type); | ||||
| 	} | ||||
|     } | ||||
|     return d800->tag; | ||||
| } | ||||
|  | ||||
| int erase_flash_amd800 (void *data, unsigned offset, unsigned length) | ||||
| { | ||||
|     struct data_amd800 *d800 = data; | ||||
|     volatile unsigned char *flash = (volatile unsigned char *) d800->base; | ||||
|     volatile unsigned char *flash_aaa = flash + 0xaaa * d800->spacing; | ||||
|     volatile unsigned char *flash_555 = flash + 0x555 * d800->spacing; | ||||
|     int id; | ||||
|     int cs = 9999; | ||||
|  | ||||
|     printk_info("Erase from 0x%08x to 0x%08x\n", offset, offset + length); | ||||
|     *flash_aaa = 0xAA;		// Chip Erase | ||||
|     *flash_555 = 0x55; | ||||
|     *flash_aaa = 0x80; | ||||
|     *flash_aaa = 0xAA; | ||||
|     *flash_555 = 0x55; | ||||
|     *flash_aaa = 0x10; | ||||
|  | ||||
|     for (; cs > 0; cs--) | ||||
|     { | ||||
| 	id = *(flash + 16); | ||||
| 	if (id & 0xA0)		// DQ7 or DQ5 set: done or error | ||||
| 	    break; | ||||
| 	printk_info("%4d\b\b\b\b", cs); | ||||
|     } | ||||
|  | ||||
|     *flash_aaa = 0xF0;		// In case of error | ||||
|  | ||||
|     printk_info("\b\b\b\b    \b\b\b\b"); | ||||
|     if (cs == 0) | ||||
|     { | ||||
| 	printk_info("Could not erase flash, timeout.\n"); | ||||
| 	return -1; | ||||
|     } | ||||
|     else if ((id & 0x80) == 0) | ||||
|     { | ||||
| 	printk_info("Could not erase flash, status=%02x.\n", id); | ||||
| 	return -1; | ||||
|     } | ||||
|     printk_info("Flash erased\n"); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int init_flash_amd800 (char *tag, unsigned base, unsigned spacing) | ||||
| { | ||||
|     struct data_amd800 *data = malloc (sizeof (struct data_amd800)); | ||||
|  | ||||
|     if (data) | ||||
|     { | ||||
| 	data->base = base; | ||||
| 	data->spacing = spacing; | ||||
| 	data->tag = 0; | ||||
| 	if (register_flash_device (&fn_amd800, tag, data) < 0) | ||||
| 	{ | ||||
| 	    free (data); | ||||
| 	    return -1; | ||||
| 	} | ||||
|     } | ||||
|     else | ||||
| 	return -1; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int program_flash_amd800 (void *data, unsigned offset, const void *source, | ||||
| 			  unsigned length) | ||||
| { | ||||
|     struct data_amd800 *d800 = data; | ||||
|     volatile unsigned char *flash = (volatile unsigned char *) d800->base; | ||||
|     volatile unsigned char *flash_aaa = flash + 0xaaa * d800->spacing; | ||||
|     volatile unsigned char *flash_555 = flash + 0x555 * d800->spacing; | ||||
|     int id = 0; | ||||
|     int cs; | ||||
|     int errs = 0; | ||||
|     volatile char *s; | ||||
|     volatile char *d; | ||||
|  | ||||
|     printk_info("Program from 0x%08x to 0x%08x\n", offset, offset + length); | ||||
|     printk_info("Data at %p\n", source); | ||||
|  | ||||
|     *flash_aaa = 0xAA;		// Unlock Bypass | ||||
|     *flash_555 = 0x55; | ||||
|     *flash_aaa = 0x20; | ||||
|  | ||||
|     s = (unsigned char *) source; | ||||
|     d = flash + offset * d800->spacing; | ||||
|     cs = length; | ||||
|  | ||||
|     while (cs > 0 && !errs) | ||||
|     { | ||||
| 	*flash = 0xA0;	// Unlock Bypass Program | ||||
| 	*d = *s;		// Program data | ||||
|  | ||||
| 	while (1) | ||||
| 	{ | ||||
| 	    id = *d; | ||||
| 	    if ((id & 0x80) == (*s & 0x80))	// DQ7 right? => program done | ||||
| 		break; | ||||
| 	    else if (id & 0x20) | ||||
| 	    {			// DQ5 set? => maybe errors | ||||
| 		id = *d; | ||||
| 		if ((id & 0x80) != (*s & 0x80)) | ||||
| 		{ | ||||
| 		    errs++; | ||||
| 		    break; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|  | ||||
| 	// PRINT("Set %08lx = %02x\n", d, *d); | ||||
|  | ||||
| 	s += 1; | ||||
| 	d += d800->spacing; | ||||
| 	cs--; | ||||
|     } | ||||
|  | ||||
|     *flash = 0x90;		// Unlock Bypass Program Reset | ||||
|     *flash = 0x00; | ||||
|     *flash = 0xF0; | ||||
|  | ||||
|     if (errs != 0) | ||||
|     { | ||||
| 	printk_info("FAIL: Status=%02x Address=%p.\n", id, d - d800->spacing); | ||||
| 	return -1; | ||||
|     } | ||||
|     printk_info("OK.\n"); | ||||
|  | ||||
|  | ||||
|     // Step 4: Verify the flash. | ||||
|  | ||||
|     printk_info("  Verifying flash : ..."); | ||||
|     errs = 0; | ||||
|     s = (unsigned char *) source; | ||||
|     d = flash + offset * d800->spacing; | ||||
|     for (cs = 0; cs < length; cs++) | ||||
|     { | ||||
| 	if (*s != *d) | ||||
| 	{ | ||||
| 	    if (errs == 0) | ||||
| 		printk_info("ERROR: Addr: %08p, PCI: %02x Lcl: %02x.\n", | ||||
| 		       s, *s, *d); | ||||
| 	    errs++; | ||||
| 	} | ||||
| 	s += 1; | ||||
| 	d += d800->spacing; | ||||
|     } | ||||
|  | ||||
|     if (errs == 0) | ||||
| 	printk_info("OK.\n"); | ||||
|     else | ||||
|     { | ||||
| 	printk_info("  FAIL: %d errors.\n", errs); | ||||
| 	return -1; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| u8 read_byte_amd800 (void *data, unsigned offset) | ||||
| { | ||||
|     struct data_amd800 *d800 = data; | ||||
|     volatile unsigned char *flash = (volatile unsigned char *) d800->base; | ||||
|     return *(flash + offset * d800->spacing); | ||||
| } | ||||
|  | ||||
							
								
								
									
										48
									
								
								src/mainboard/motorola/sandpoint/flash/flash.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/mainboard/motorola/sandpoint/flash/flash.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| /* $Id$ */ | ||||
| /* Copyright 2000  AG Electronics Ltd. */ | ||||
| /* This code is distributed without warranty under the GPL v2 (see COPYING) */ | ||||
|  | ||||
| #include <types.h> | ||||
| #include <string.h> | ||||
| #include <printk.h> | ||||
| #include <stdlib.h> | ||||
| #include "../flash.h" | ||||
|  | ||||
| static flash_device *first_flash = 0; | ||||
|  | ||||
| int register_flash_device (const flash_fn * fn, char *tag, void *data) | ||||
| { | ||||
|     flash_device *device = malloc (sizeof (flash_device)); | ||||
|  | ||||
|     if (device) | ||||
|     { | ||||
| 	const char *result; | ||||
| 	device->fn = fn; | ||||
| 	device->tag = tag; | ||||
| 	device->data = data; | ||||
| 	if ((result = fn->identify(device)) != 0) | ||||
| 	{ | ||||
| 	    printk_info("Registered flash %s\n", result); | ||||
| 	    device->next = first_flash; | ||||
| 	    first_flash = device; | ||||
| 	} | ||||
| 	return result ? 0 : -1; | ||||
|     } | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| flash_device *find_flash_device(const char *name) | ||||
| { | ||||
|     int len = strlen(name); | ||||
|  | ||||
|     if (first_flash) | ||||
|     { | ||||
| 	flash_device *flash; | ||||
|  | ||||
| 	for (flash = first_flash; flash; flash = flash->next) | ||||
| 	    if (strlen(flash->tag) == len && memcmp(name, flash->tag, len) == 0) | ||||
| 		return flash; | ||||
|     } | ||||
|     printk_info ("No flash %s registered\n", name); | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										54
									
								
								src/mainboard/motorola/sandpoint/nvram/bsp_nvram.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/mainboard/motorola/sandpoint/nvram/bsp_nvram.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| /* | ||||
|  * (C) Copyright 2001 | ||||
|  * Humboldt Solutions Ltd, adrian@humboldt.co.uk. | ||||
|  * | ||||
|  * 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., 59 Temple Place, Suite 330, Boston, | ||||
|  * MA 02111-1307 USA | ||||
|  */ | ||||
|  | ||||
| #include <arch/io.h> | ||||
| #include "../nvram.h" | ||||
|  | ||||
| static unsigned bsp_size(struct nvram_device *data) | ||||
| { | ||||
|     return 8 * 1024;    | ||||
| } | ||||
|  | ||||
| static int bsp_read_block(struct nvram_device *dev, unsigned offset, | ||||
| 	    unsigned char *data, unsigned length) | ||||
| { | ||||
|     unsigned i; | ||||
|      | ||||
|     for(i = 0; i < length; i++) | ||||
|     { | ||||
| 	outb(((offset + i) >> 8) & 0xff, 0x74); | ||||
| 	outb((offset + i) & 0xff, 0x75); | ||||
| 	data[i] = inb(0x76); | ||||
|     } | ||||
|     return length; | ||||
| } | ||||
|     | ||||
| static int bsp_write_byte(struct nvram_device *data, unsigned offset, unsigned char byte) | ||||
| { | ||||
|     outb((offset >> 8) & 0xff, 0x74); | ||||
|     outb(offset & 0xff, 0x75); | ||||
|     outb(byte, 0x76); | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| nvram_device bsp_nvram = { | ||||
|     bsp_size, bsp_read_block, bsp_write_byte, NULL, NULL    | ||||
| }; | ||||
|      | ||||
							
								
								
									
										103
									
								
								src/mainboard/motorola/sandpoint/nvram/nvram.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/mainboard/motorola/sandpoint/nvram/nvram.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | ||||
| /* $Id$ */ | ||||
| /* Copyright 2000  AG Electronics Ltd. */ | ||||
| /* This code is distributed without warranty under the GPL v2 (see COPYING) */ | ||||
|  | ||||
| #include <types.h> | ||||
| #include <printk.h> | ||||
| #include <stdlib.h> | ||||
| #include "../nvram.h" | ||||
|  | ||||
| /* NVRAM layout | ||||
|  *  | ||||
|  * Environment variable record runs: | ||||
|  * [length]NAME=value[length]NAME=value[0]\0 | ||||
|  * A deleted variable is: | ||||
|  * [length]\0AME=value | ||||
|  *  | ||||
|  * When memory is full, we compact. | ||||
|  *  | ||||
|  */ | ||||
| static nvram_device *nvram_dev = 0; | ||||
| static unsigned char *nvram_buffer = 0; | ||||
| static unsigned nvram_size = 0; | ||||
| static u8 nvram_csum = 0; | ||||
| #define NVRAM_INVALID (! nvram_dev) | ||||
|  | ||||
| static void update_device(unsigned i, unsigned char data) | ||||
| { | ||||
|     if (i < nvram_size) | ||||
|     { | ||||
| 	nvram_csum -= nvram_buffer[i]; | ||||
| 	nvram_buffer[i] = data; | ||||
| 	nvram_dev->write_byte(nvram_dev, i, data); | ||||
| 	nvram_csum += data; | ||||
|     } | ||||
|     else | ||||
| 	printk_info("Offset %d out of range in nvram\n", i); | ||||
| } | ||||
|  | ||||
| static void update_csum(void) | ||||
| { | ||||
|     nvram_dev->write_byte(nvram_dev, nvram_size, nvram_csum); | ||||
|     if (nvram_dev->commit) | ||||
| 	nvram_dev->commit(nvram_dev); | ||||
| } | ||||
|  | ||||
| static void update_string_device(unsigned i, const unsigned char *data, | ||||
| 	    	    	    unsigned len) | ||||
| { | ||||
|     if (i + len < nvram_size) | ||||
|     { | ||||
| 	unsigned j; | ||||
| 	for(j = 0; j < len; j++) | ||||
| 	{ | ||||
| 	    nvram_csum -= nvram_buffer[i]; | ||||
|     	    nvram_buffer[i] = *data; | ||||
|     	    nvram_dev->write_byte(nvram_dev, i, *data); | ||||
|     	    nvram_csum += *data; | ||||
| 	    data++; | ||||
| 	    i++; | ||||
| 	}    | ||||
|     } | ||||
|     else | ||||
| 	printk_info("Offset %d out of range in nvram\n", i + len); | ||||
| } | ||||
|  | ||||
| int nvram_init (struct nvram_device *dev) | ||||
| { | ||||
|     nvram_dev = dev; | ||||
|      | ||||
|     if (! nvram_size) | ||||
| 	nvram_size = dev->size(dev) - 1; | ||||
|     printk_info("NVRAM size is %d\n", nvram_size); | ||||
|     if (!nvram_buffer) | ||||
|     { | ||||
| 	unsigned i; | ||||
| 	 | ||||
| 	nvram_buffer = malloc (nvram_size); | ||||
| 	if (!nvram_buffer) | ||||
| 	    return -1; | ||||
|  | ||||
| 	nvram_csum = 0; | ||||
| 	dev->read_block(dev, 0, nvram_buffer, nvram_size+1); | ||||
| 	for(i = 0; i < nvram_size; i++) | ||||
| 	    nvram_csum += nvram_buffer[i]; | ||||
|  | ||||
| 	if (nvram_csum != nvram_buffer[nvram_size]) | ||||
| 	{ | ||||
| 	    printk_info("NVRAM checksum invalid - erasing\n"); | ||||
| 	    //update_device(0, 0); | ||||
| 	    //update_csum(); | ||||
| 	} | ||||
|     } | ||||
|     printk_info("Initialised nvram\n"); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| void nvram_clear(void) | ||||
| { | ||||
|     printk_info("Erasing NVRAM\n"); | ||||
|     update_device(0, 0); | ||||
|     update_csum();     | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user