2 * This file is part of the coreboot project.
4 * Copyright (C) 2000 AG Electronics Ltd.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <console/console.h>
32 static const char *identify_amd (struct flash_device *flash_device);
33 static int erase_flash_amd800 (void *data, unsigned offset, unsigned length);
34 static int program_flash_amd800 (void *data, unsigned offset, const void *source,
36 static uint8_t read_byte_amd800(void *data, unsigned offset);
38 static flash_fn fn_amd800 = {
47 const char *identify_amd (struct flash_device *flash_device)
49 struct data_amd800 *d800 = flash_device->data;
53 volatile unsigned char *flash =
55 (volatile unsigned char *) d800->base;
59 *(flash + 0xaaa * d800->spacing) = 0xaa;
60 *(flash + 0x555 * d800->spacing) = 0x55;
61 *(flash + 0xaaa * d800->spacing) = 0x90;
62 type = *(flash + 2 * d800->spacing);
65 if ((id == 1 || id == 0x20) && type == 0x5b)
68 d800->tag = "Am29LV800BB";
69 flash_device->base = d800->base;
70 flash_device->size = 1024*1024;
71 flash_device->erase_size = 64*1024;
72 flash_device->store_size = 1;
76 printk_info("Unknown flash ID: 0x%02x 0x%02x\n", id, type);
82 int erase_flash_amd800 (void *data, unsigned offset, unsigned length)
84 struct data_amd800 *d800 = data;
85 volatile unsigned char *flash = (volatile unsigned char *) d800->base;
86 volatile unsigned char *flash_aaa = flash + 0xaaa * d800->spacing;
87 volatile unsigned char *flash_555 = flash + 0x555 * d800->spacing;
91 printk_info("Erase from 0x%08x to 0x%08x\n", offset, offset + length);
92 *flash_aaa = 0xAA; // Chip Erase
102 if (id & 0xA0) // DQ7 or DQ5 set: done or error
104 printk_info("%4d\b\b\b\b", cs);
107 *flash_aaa = 0xF0; // In case of error
109 printk_info("\b\b\b\b \b\b\b\b");
112 printk_info("Could not erase flash, timeout.\n");
115 else if ((id & 0x80) == 0)
117 printk_info("Could not erase flash, status=%02x.\n", id);
120 printk_info("Flash erased\n");
124 int init_flash_amd800 (char *tag, unsigned base, unsigned spacing)
126 struct data_amd800 *data = malloc (sizeof (struct data_amd800));
131 data->spacing = spacing;
133 if (register_flash_device (&fn_amd800, tag, data) < 0)
144 int program_flash_amd800 (void *data, unsigned offset, const void *source,
147 struct data_amd800 *d800 = data;
148 volatile unsigned char *flash = (volatile unsigned char *) d800->base;
149 volatile unsigned char *flash_aaa = flash + 0xaaa * d800->spacing;
150 volatile unsigned char *flash_555 = flash + 0x555 * d800->spacing;
157 printk_info("Program from 0x%08x to 0x%08x\n", offset, offset + length);
158 printk_info("Data at %p\n", source);
160 *flash_aaa = 0xAA; // Unlock Bypass
164 s = (unsigned char *) source;
165 d = flash + offset * d800->spacing;
168 while (cs > 0 && !errs)
170 *flash = 0xA0; // Unlock Bypass Program
171 *d = *s; // Program data
176 if ((id & 0x80) == (*s & 0x80)) // DQ7 right? => program done
179 { // DQ5 set? => maybe errors
181 if ((id & 0x80) != (*s & 0x80))
189 // PRINT("Set %08lx = %02x\n", d, *d);
196 *flash = 0x90; // Unlock Bypass Program Reset
202 printk_info("FAIL: Status=%02x Address=%p.\n", id, d - d800->spacing);
205 printk_info("OK.\n");
208 // Step 4: Verify the flash.
210 printk_info(" Verifying flash : ...");
212 s = (unsigned char *) source;
213 d = flash + offset * d800->spacing;
214 for (cs = 0; cs < length; cs++)
219 printk_info("ERROR: Addr: %08p, PCI: %02x Lcl: %02x.\n",
228 printk_info("OK.\n");
231 printk_info(" FAIL: %d errors.\n", errs);
238 uint8_t read_byte_amd800 (void *data, unsigned offset)
240 struct data_amd800 *d800 = data;
241 volatile unsigned char *flash = (volatile unsigned char *) d800->base;
242 return *(flash + offset * d800->spacing);