1 /* Copyright 2000 AG Electronics Ltd. */
2 /* This code is distributed without warranty under the GPL v2 (see COPYING) */
4 #include <console/console.h>
16 static const char *identify_amd (struct flash_device *flash_device);
17 static int erase_flash_amd800 (void *data, unsigned offset, unsigned length);
18 static int program_flash_amd800 (void *data, unsigned offset, const void *source,
20 static uint8_t read_byte_amd800(void *data, unsigned offset);
22 static flash_fn fn_amd800 = {
31 const char *identify_amd (struct flash_device *flash_device)
33 struct data_amd800 *d800 = flash_device->data;
37 volatile unsigned char *flash =
39 (volatile unsigned char *) d800->base;
43 *(flash + 0xaaa * d800->spacing) = 0xaa;
44 *(flash + 0x555 * d800->spacing) = 0x55;
45 *(flash + 0xaaa * d800->spacing) = 0x90;
46 type = *(flash + 2 * d800->spacing);
49 if ((id == 1 || id == 0x20) && type == 0x5b)
52 d800->tag = "Am29LV800BB";
53 flash_device->base = d800->base;
54 flash_device->size = 1024*1024;
55 flash_device->erase_size = 64*1024;
56 flash_device->store_size = 1;
60 printk_info("Unknown flash ID: 0x%02x 0x%02x\n", id, type);
66 int erase_flash_amd800 (void *data, unsigned offset, unsigned length)
68 struct data_amd800 *d800 = data;
69 volatile unsigned char *flash = (volatile unsigned char *) d800->base;
70 volatile unsigned char *flash_aaa = flash + 0xaaa * d800->spacing;
71 volatile unsigned char *flash_555 = flash + 0x555 * d800->spacing;
75 printk_info("Erase from 0x%08x to 0x%08x\n", offset, offset + length);
76 *flash_aaa = 0xAA; // Chip Erase
86 if (id & 0xA0) // DQ7 or DQ5 set: done or error
88 printk_info("%4d\b\b\b\b", cs);
91 *flash_aaa = 0xF0; // In case of error
93 printk_info("\b\b\b\b \b\b\b\b");
96 printk_info("Could not erase flash, timeout.\n");
99 else if ((id & 0x80) == 0)
101 printk_info("Could not erase flash, status=%02x.\n", id);
104 printk_info("Flash erased\n");
108 int init_flash_amd800 (char *tag, unsigned base, unsigned spacing)
110 struct data_amd800 *data = malloc (sizeof (struct data_amd800));
115 data->spacing = spacing;
117 if (register_flash_device (&fn_amd800, tag, data) < 0)
128 int program_flash_amd800 (void *data, unsigned offset, const void *source,
131 struct data_amd800 *d800 = data;
132 volatile unsigned char *flash = (volatile unsigned char *) d800->base;
133 volatile unsigned char *flash_aaa = flash + 0xaaa * d800->spacing;
134 volatile unsigned char *flash_555 = flash + 0x555 * d800->spacing;
141 printk_info("Program from 0x%08x to 0x%08x\n", offset, offset + length);
142 printk_info("Data at %p\n", source);
144 *flash_aaa = 0xAA; // Unlock Bypass
148 s = (unsigned char *) source;
149 d = flash + offset * d800->spacing;
152 while (cs > 0 && !errs)
154 *flash = 0xA0; // Unlock Bypass Program
155 *d = *s; // Program data
160 if ((id & 0x80) == (*s & 0x80)) // DQ7 right? => program done
163 { // DQ5 set? => maybe errors
165 if ((id & 0x80) != (*s & 0x80))
173 // PRINT("Set %08lx = %02x\n", d, *d);
180 *flash = 0x90; // Unlock Bypass Program Reset
186 printk_info("FAIL: Status=%02x Address=%p.\n", id, d - d800->spacing);
189 printk_info("OK.\n");
192 // Step 4: Verify the flash.
194 printk_info(" Verifying flash : ...");
196 s = (unsigned char *) source;
197 d = flash + offset * d800->spacing;
198 for (cs = 0; cs < length; cs++)
203 printk_info("ERROR: Addr: %08p, PCI: %02x Lcl: %02x.\n",
212 printk_info("OK.\n");
215 printk_info(" FAIL: %d errors.\n", errs);
222 uint8_t read_byte_amd800 (void *data, unsigned offset)
224 struct data_amd800 *d800 = data;
225 volatile unsigned char *flash = (volatile unsigned char *) d800->base;
226 return *(flash + offset * d800->spacing);