ia64/linux-2.6.18-xen.hg

annotate drivers/mtd/chips/jedec.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
rev   line source
ian@0 1
ian@0 2 /* JEDEC Flash Interface.
ian@0 3 * This is an older type of interface for self programming flash. It is
ian@0 4 * commonly use in older AMD chips and is obsolete compared with CFI.
ian@0 5 * It is called JEDEC because the JEDEC association distributes the ID codes
ian@0 6 * for the chips.
ian@0 7 *
ian@0 8 * See the AMD flash databook for information on how to operate the interface.
ian@0 9 *
ian@0 10 * This code does not support anything wider than 8 bit flash chips, I am
ian@0 11 * not going to guess how to send commands to them, plus I expect they will
ian@0 12 * all speak CFI..
ian@0 13 *
ian@0 14 * $Id: jedec.c,v 1.22 2005/01/05 18:05:11 dwmw2 Exp $
ian@0 15 */
ian@0 16
ian@0 17 #include <linux/init.h>
ian@0 18 #include <linux/module.h>
ian@0 19 #include <linux/kernel.h>
ian@0 20 #include <linux/slab.h>
ian@0 21 #include <linux/mtd/jedec.h>
ian@0 22 #include <linux/mtd/map.h>
ian@0 23 #include <linux/mtd/mtd.h>
ian@0 24 #include <linux/mtd/compatmac.h>
ian@0 25
ian@0 26 static struct mtd_info *jedec_probe(struct map_info *);
ian@0 27 static int jedec_probe8(struct map_info *map,unsigned long base,
ian@0 28 struct jedec_private *priv);
ian@0 29 static int jedec_probe16(struct map_info *map,unsigned long base,
ian@0 30 struct jedec_private *priv);
ian@0 31 static int jedec_probe32(struct map_info *map,unsigned long base,
ian@0 32 struct jedec_private *priv);
ian@0 33 static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start,
ian@0 34 unsigned long len);
ian@0 35 static int flash_erase(struct mtd_info *mtd, struct erase_info *instr);
ian@0 36 static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
ian@0 37 size_t *retlen, const u_char *buf);
ian@0 38
ian@0 39 static unsigned long my_bank_size;
ian@0 40
ian@0 41 /* Listing of parts and sizes. We need this table to learn the sector
ian@0 42 size of the chip and the total length */
ian@0 43 static const struct JEDECTable JEDEC_table[] = {
ian@0 44 {
ian@0 45 .jedec = 0x013D,
ian@0 46 .name = "AMD Am29F017D",
ian@0 47 .size = 2*1024*1024,
ian@0 48 .sectorsize = 64*1024,
ian@0 49 .capabilities = MTD_CAP_NORFLASH
ian@0 50 },
ian@0 51 {
ian@0 52 .jedec = 0x01AD,
ian@0 53 .name = "AMD Am29F016",
ian@0 54 .size = 2*1024*1024,
ian@0 55 .sectorsize = 64*1024,
ian@0 56 .capabilities = MTD_CAP_NORFLASH
ian@0 57 },
ian@0 58 {
ian@0 59 .jedec = 0x01D5,
ian@0 60 .name = "AMD Am29F080",
ian@0 61 .size = 1*1024*1024,
ian@0 62 .sectorsize = 64*1024,
ian@0 63 .capabilities = MTD_CAP_NORFLASH
ian@0 64 },
ian@0 65 {
ian@0 66 .jedec = 0x01A4,
ian@0 67 .name = "AMD Am29F040",
ian@0 68 .size = 512*1024,
ian@0 69 .sectorsize = 64*1024,
ian@0 70 .capabilities = MTD_CAP_NORFLASH
ian@0 71 },
ian@0 72 {
ian@0 73 .jedec = 0x20E3,
ian@0 74 .name = "AMD Am29W040B",
ian@0 75 .size = 512*1024,
ian@0 76 .sectorsize = 64*1024,
ian@0 77 .capabilities = MTD_CAP_NORFLASH
ian@0 78 },
ian@0 79 {
ian@0 80 .jedec = 0xC2AD,
ian@0 81 .name = "Macronix MX29F016",
ian@0 82 .size = 2*1024*1024,
ian@0 83 .sectorsize = 64*1024,
ian@0 84 .capabilities = MTD_CAP_NORFLASH
ian@0 85 },
ian@0 86 { .jedec = 0x0 }
ian@0 87 };
ian@0 88
ian@0 89 static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id);
ian@0 90 static void jedec_sync(struct mtd_info *mtd) {};
ian@0 91 static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len,
ian@0 92 size_t *retlen, u_char *buf);
ian@0 93 static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len,
ian@0 94 size_t *retlen, u_char *buf);
ian@0 95
ian@0 96 static struct mtd_info *jedec_probe(struct map_info *map);
ian@0 97
ian@0 98
ian@0 99
ian@0 100 static struct mtd_chip_driver jedec_chipdrv = {
ian@0 101 .probe = jedec_probe,
ian@0 102 .name = "jedec",
ian@0 103 .module = THIS_MODULE
ian@0 104 };
ian@0 105
ian@0 106 /* Probe entry point */
ian@0 107
ian@0 108 static struct mtd_info *jedec_probe(struct map_info *map)
ian@0 109 {
ian@0 110 struct mtd_info *MTD;
ian@0 111 struct jedec_private *priv;
ian@0 112 unsigned long Base;
ian@0 113 unsigned long SectorSize;
ian@0 114 unsigned count;
ian@0 115 unsigned I,Uniq;
ian@0 116 char Part[200];
ian@0 117 memset(&priv,0,sizeof(priv));
ian@0 118
ian@0 119 MTD = kmalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL);
ian@0 120 if (!MTD)
ian@0 121 return NULL;
ian@0 122
ian@0 123 memset(MTD, 0, sizeof(struct mtd_info) + sizeof(struct jedec_private));
ian@0 124 priv = (struct jedec_private *)&MTD[1];
ian@0 125
ian@0 126 my_bank_size = map->size;
ian@0 127
ian@0 128 if (map->size/my_bank_size > MAX_JEDEC_CHIPS)
ian@0 129 {
ian@0 130 printk("mtd: Increase MAX_JEDEC_CHIPS, too many banks.\n");
ian@0 131 kfree(MTD);
ian@0 132 return NULL;
ian@0 133 }
ian@0 134
ian@0 135 for (Base = 0; Base < map->size; Base += my_bank_size)
ian@0 136 {
ian@0 137 // Perhaps zero could designate all tests?
ian@0 138 if (map->buswidth == 0)
ian@0 139 map->buswidth = 1;
ian@0 140
ian@0 141 if (map->buswidth == 1){
ian@0 142 if (jedec_probe8(map,Base,priv) == 0) {
ian@0 143 printk("did recognize jedec chip\n");
ian@0 144 kfree(MTD);
ian@0 145 return NULL;
ian@0 146 }
ian@0 147 }
ian@0 148 if (map->buswidth == 2)
ian@0 149 jedec_probe16(map,Base,priv);
ian@0 150 if (map->buswidth == 4)
ian@0 151 jedec_probe32(map,Base,priv);
ian@0 152 }
ian@0 153
ian@0 154 // Get the biggest sector size
ian@0 155 SectorSize = 0;
ian@0 156 for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
ian@0 157 {
ian@0 158 // printk("priv->chips[%d].jedec is %x\n",I,priv->chips[I].jedec);
ian@0 159 // printk("priv->chips[%d].sectorsize is %lx\n",I,priv->chips[I].sectorsize);
ian@0 160 if (priv->chips[I].sectorsize > SectorSize)
ian@0 161 SectorSize = priv->chips[I].sectorsize;
ian@0 162 }
ian@0 163
ian@0 164 // Quickly ensure that the other sector sizes are factors of the largest
ian@0 165 for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
ian@0 166 {
ian@0 167 if ((SectorSize/priv->chips[I].sectorsize)*priv->chips[I].sectorsize != SectorSize)
ian@0 168 {
ian@0 169 printk("mtd: Failed. Device has incompatible mixed sector sizes\n");
ian@0 170 kfree(MTD);
ian@0 171 return NULL;
ian@0 172 }
ian@0 173 }
ian@0 174
ian@0 175 /* Generate a part name that includes the number of different chips and
ian@0 176 other configuration information */
ian@0 177 count = 1;
ian@0 178 strlcpy(Part,map->name,sizeof(Part)-10);
ian@0 179 strcat(Part," ");
ian@0 180 Uniq = 0;
ian@0 181 for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
ian@0 182 {
ian@0 183 const struct JEDECTable *JEDEC;
ian@0 184
ian@0 185 if (priv->chips[I+1].jedec == priv->chips[I].jedec)
ian@0 186 {
ian@0 187 count++;
ian@0 188 continue;
ian@0 189 }
ian@0 190
ian@0 191 // Locate the chip in the jedec table
ian@0 192 JEDEC = jedec_idtoinf(priv->chips[I].jedec >> 8,priv->chips[I].jedec);
ian@0 193 if (JEDEC == 0)
ian@0 194 {
ian@0 195 printk("mtd: Internal Error, JEDEC not set\n");
ian@0 196 kfree(MTD);
ian@0 197 return NULL;
ian@0 198 }
ian@0 199
ian@0 200 if (Uniq != 0)
ian@0 201 strcat(Part,",");
ian@0 202 Uniq++;
ian@0 203
ian@0 204 if (count != 1)
ian@0 205 sprintf(Part+strlen(Part),"%x*[%s]",count,JEDEC->name);
ian@0 206 else
ian@0 207 sprintf(Part+strlen(Part),"%s",JEDEC->name);
ian@0 208 if (strlen(Part) > sizeof(Part)*2/3)
ian@0 209 break;
ian@0 210 count = 1;
ian@0 211 }
ian@0 212
ian@0 213 /* Determine if the chips are organized in a linear fashion, or if there
ian@0 214 are empty banks. Note, the last bank does not count here, only the
ian@0 215 first banks are important. Holes on non-bank boundaries can not exist
ian@0 216 due to the way the detection algorithm works. */
ian@0 217 if (priv->size < my_bank_size)
ian@0 218 my_bank_size = priv->size;
ian@0 219 priv->is_banked = 0;
ian@0 220 //printk("priv->size is %x, my_bank_size is %x\n",priv->size,my_bank_size);
ian@0 221 //printk("priv->bank_fill[0] is %x\n",priv->bank_fill[0]);
ian@0 222 if (!priv->size) {
ian@0 223 printk("priv->size is zero\n");
ian@0 224 kfree(MTD);
ian@0 225 return NULL;
ian@0 226 }
ian@0 227 if (priv->size/my_bank_size) {
ian@0 228 if (priv->size/my_bank_size == 1) {
ian@0 229 priv->size = my_bank_size;
ian@0 230 }
ian@0 231 else {
ian@0 232 for (I = 0; I != priv->size/my_bank_size - 1; I++)
ian@0 233 {
ian@0 234 if (priv->bank_fill[I] != my_bank_size)
ian@0 235 priv->is_banked = 1;
ian@0 236
ian@0 237 /* This even could be eliminated, but new de-optimized read/write
ian@0 238 functions have to be written */
ian@0 239 printk("priv->bank_fill[%d] is %lx, priv->bank_fill[0] is %lx\n",I,priv->bank_fill[I],priv->bank_fill[0]);
ian@0 240 if (priv->bank_fill[I] != priv->bank_fill[0])
ian@0 241 {
ian@0 242 printk("mtd: Failed. Cannot handle unsymmetric banking\n");
ian@0 243 kfree(MTD);
ian@0 244 return NULL;
ian@0 245 }
ian@0 246 }
ian@0 247 }
ian@0 248 }
ian@0 249 if (priv->is_banked == 1)
ian@0 250 strcat(Part,", banked");
ian@0 251
ian@0 252 // printk("Part: '%s'\n",Part);
ian@0 253
ian@0 254 memset(MTD,0,sizeof(*MTD));
ian@0 255 // strlcpy(MTD->name,Part,sizeof(MTD->name));
ian@0 256 MTD->name = map->name;
ian@0 257 MTD->type = MTD_NORFLASH;
ian@0 258 MTD->flags = MTD_CAP_NORFLASH;
ian@0 259 MTD->writesize = 1;
ian@0 260 MTD->erasesize = SectorSize*(map->buswidth);
ian@0 261 // printk("MTD->erasesize is %x\n",(unsigned int)MTD->erasesize);
ian@0 262 MTD->size = priv->size;
ian@0 263 // printk("MTD->size is %x\n",(unsigned int)MTD->size);
ian@0 264 //MTD->module = THIS_MODULE; // ? Maybe this should be the low level module?
ian@0 265 MTD->erase = flash_erase;
ian@0 266 if (priv->is_banked == 1)
ian@0 267 MTD->read = jedec_read_banked;
ian@0 268 else
ian@0 269 MTD->read = jedec_read;
ian@0 270 MTD->write = flash_write;
ian@0 271 MTD->sync = jedec_sync;
ian@0 272 MTD->priv = map;
ian@0 273 map->fldrv_priv = priv;
ian@0 274 map->fldrv = &jedec_chipdrv;
ian@0 275 __module_get(THIS_MODULE);
ian@0 276 return MTD;
ian@0 277 }
ian@0 278
ian@0 279 /* Helper for the JEDEC function, JEDEC numbers all have odd parity */
ian@0 280 static int checkparity(u_char C)
ian@0 281 {
ian@0 282 u_char parity = 0;
ian@0 283 while (C != 0)
ian@0 284 {
ian@0 285 parity ^= C & 1;
ian@0 286 C >>= 1;
ian@0 287 }
ian@0 288
ian@0 289 return parity == 1;
ian@0 290 }
ian@0 291
ian@0 292
ian@0 293 /* Take an array of JEDEC numbers that represent interleved flash chips
ian@0 294 and process them. Check to make sure they are good JEDEC numbers, look
ian@0 295 them up and then add them to the chip list */
ian@0 296 static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count,
ian@0 297 unsigned long base,struct jedec_private *priv)
ian@0 298 {
ian@0 299 unsigned I,J;
ian@0 300 unsigned long Size;
ian@0 301 unsigned long SectorSize;
ian@0 302 const struct JEDECTable *JEDEC;
ian@0 303
ian@0 304 // Test #2 JEDEC numbers exhibit odd parity
ian@0 305 for (I = 0; I != Count; I++)
ian@0 306 {
ian@0 307 if (checkparity(Mfg[I]) == 0 || checkparity(Id[I]) == 0)
ian@0 308 return 0;
ian@0 309 }
ian@0 310
ian@0 311 // Finally, just make sure all the chip sizes are the same
ian@0 312 JEDEC = jedec_idtoinf(Mfg[0],Id[0]);
ian@0 313
ian@0 314 if (JEDEC == 0)
ian@0 315 {
ian@0 316 printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]);
ian@0 317 return 0;
ian@0 318 }
ian@0 319
ian@0 320 Size = JEDEC->size;
ian@0 321 SectorSize = JEDEC->sectorsize;
ian@0 322 for (I = 0; I != Count; I++)
ian@0 323 {
ian@0 324 JEDEC = jedec_idtoinf(Mfg[0],Id[0]);
ian@0 325 if (JEDEC == 0)
ian@0 326 {
ian@0 327 printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]);
ian@0 328 return 0;
ian@0 329 }
ian@0 330
ian@0 331 if (Size != JEDEC->size || SectorSize != JEDEC->sectorsize)
ian@0 332 {
ian@0 333 printk("mtd: Failed. Interleved flash does not have matching characteristics\n");
ian@0 334 return 0;
ian@0 335 }
ian@0 336 }
ian@0 337
ian@0 338 // Load the Chips
ian@0 339 for (I = 0; I != MAX_JEDEC_CHIPS; I++)
ian@0 340 {
ian@0 341 if (priv->chips[I].jedec == 0)
ian@0 342 break;
ian@0 343 }
ian@0 344
ian@0 345 if (I + Count > MAX_JEDEC_CHIPS)
ian@0 346 {
ian@0 347 printk("mtd: Device has too many chips. Increase MAX_JEDEC_CHIPS\n");
ian@0 348 return 0;
ian@0 349 }
ian@0 350
ian@0 351 // Add them to the table
ian@0 352 for (J = 0; J != Count; J++)
ian@0 353 {
ian@0 354 unsigned long Bank;
ian@0 355
ian@0 356 JEDEC = jedec_idtoinf(Mfg[J],Id[J]);
ian@0 357 priv->chips[I].jedec = (Mfg[J] << 8) | Id[J];
ian@0 358 priv->chips[I].size = JEDEC->size;
ian@0 359 priv->chips[I].sectorsize = JEDEC->sectorsize;
ian@0 360 priv->chips[I].base = base + J;
ian@0 361 priv->chips[I].datashift = J*8;
ian@0 362 priv->chips[I].capabilities = JEDEC->capabilities;
ian@0 363 priv->chips[I].offset = priv->size + J;
ian@0 364
ian@0 365 // log2 n :|
ian@0 366 priv->chips[I].addrshift = 0;
ian@0 367 for (Bank = Count; Bank != 1; Bank >>= 1, priv->chips[I].addrshift++);
ian@0 368
ian@0 369 // Determine how filled this bank is.
ian@0 370 Bank = base & (~(my_bank_size-1));
ian@0 371 if (priv->bank_fill[Bank/my_bank_size] < base +
ian@0 372 (JEDEC->size << priv->chips[I].addrshift) - Bank)
ian@0 373 priv->bank_fill[Bank/my_bank_size] = base + (JEDEC->size << priv->chips[I].addrshift) - Bank;
ian@0 374 I++;
ian@0 375 }
ian@0 376
ian@0 377 priv->size += priv->chips[I-1].size*Count;
ian@0 378
ian@0 379 return priv->chips[I-1].size;
ian@0 380 }
ian@0 381
ian@0 382 /* Lookup the chip information from the JEDEC ID table. */
ian@0 383 static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id)
ian@0 384 {
ian@0 385 __u16 Id = (mfr << 8) | id;
ian@0 386 unsigned long I = 0;
ian@0 387 for (I = 0; JEDEC_table[I].jedec != 0; I++)
ian@0 388 if (JEDEC_table[I].jedec == Id)
ian@0 389 return JEDEC_table + I;
ian@0 390 return NULL;
ian@0 391 }
ian@0 392
ian@0 393 // Look for flash using an 8 bit bus interface
ian@0 394 static int jedec_probe8(struct map_info *map,unsigned long base,
ian@0 395 struct jedec_private *priv)
ian@0 396 {
ian@0 397 #define flread(x) map_read8(map,base+x)
ian@0 398 #define flwrite(v,x) map_write8(map,v,base+x)
ian@0 399
ian@0 400 const unsigned long AutoSel1 = 0xAA;
ian@0 401 const unsigned long AutoSel2 = 0x55;
ian@0 402 const unsigned long AutoSel3 = 0x90;
ian@0 403 const unsigned long Reset = 0xF0;
ian@0 404 __u32 OldVal;
ian@0 405 __u8 Mfg[1];
ian@0 406 __u8 Id[1];
ian@0 407 unsigned I;
ian@0 408 unsigned long Size;
ian@0 409
ian@0 410 // Wait for any write/erase operation to settle
ian@0 411 OldVal = flread(base);
ian@0 412 for (I = 0; OldVal != flread(base) && I < 10000; I++)
ian@0 413 OldVal = flread(base);
ian@0 414
ian@0 415 // Reset the chip
ian@0 416 flwrite(Reset,0x555);
ian@0 417
ian@0 418 // Send the sequence
ian@0 419 flwrite(AutoSel1,0x555);
ian@0 420 flwrite(AutoSel2,0x2AA);
ian@0 421 flwrite(AutoSel3,0x555);
ian@0 422
ian@0 423 // Get the JEDEC numbers
ian@0 424 Mfg[0] = flread(0);
ian@0 425 Id[0] = flread(1);
ian@0 426 // printk("Mfg is %x, Id is %x\n",Mfg[0],Id[0]);
ian@0 427
ian@0 428 Size = handle_jedecs(map,Mfg,Id,1,base,priv);
ian@0 429 // printk("handle_jedecs Size is %x\n",(unsigned int)Size);
ian@0 430 if (Size == 0)
ian@0 431 {
ian@0 432 flwrite(Reset,0x555);
ian@0 433 return 0;
ian@0 434 }
ian@0 435
ian@0 436
ian@0 437 // Reset.
ian@0 438 flwrite(Reset,0x555);
ian@0 439
ian@0 440 return 1;
ian@0 441
ian@0 442 #undef flread
ian@0 443 #undef flwrite
ian@0 444 }
ian@0 445
ian@0 446 // Look for flash using a 16 bit bus interface (ie 2 8-bit chips)
ian@0 447 static int jedec_probe16(struct map_info *map,unsigned long base,
ian@0 448 struct jedec_private *priv)
ian@0 449 {
ian@0 450 return 0;
ian@0 451 }
ian@0 452
ian@0 453 // Look for flash using a 32 bit bus interface (ie 4 8-bit chips)
ian@0 454 static int jedec_probe32(struct map_info *map,unsigned long base,
ian@0 455 struct jedec_private *priv)
ian@0 456 {
ian@0 457 #define flread(x) map_read32(map,base+((x)<<2))
ian@0 458 #define flwrite(v,x) map_write32(map,v,base+((x)<<2))
ian@0 459
ian@0 460 const unsigned long AutoSel1 = 0xAAAAAAAA;
ian@0 461 const unsigned long AutoSel2 = 0x55555555;
ian@0 462 const unsigned long AutoSel3 = 0x90909090;
ian@0 463 const unsigned long Reset = 0xF0F0F0F0;
ian@0 464 __u32 OldVal;
ian@0 465 __u8 Mfg[4];
ian@0 466 __u8 Id[4];
ian@0 467 unsigned I;
ian@0 468 unsigned long Size;
ian@0 469
ian@0 470 // Wait for any write/erase operation to settle
ian@0 471 OldVal = flread(base);
ian@0 472 for (I = 0; OldVal != flread(base) && I < 10000; I++)
ian@0 473 OldVal = flread(base);
ian@0 474
ian@0 475 // Reset the chip
ian@0 476 flwrite(Reset,0x555);
ian@0 477
ian@0 478 // Send the sequence
ian@0 479 flwrite(AutoSel1,0x555);
ian@0 480 flwrite(AutoSel2,0x2AA);
ian@0 481 flwrite(AutoSel3,0x555);
ian@0 482
ian@0 483 // Test #1, JEDEC numbers are readable from 0x??00/0x??01
ian@0 484 if (flread(0) != flread(0x100) ||
ian@0 485 flread(1) != flread(0x101))
ian@0 486 {
ian@0 487 flwrite(Reset,0x555);
ian@0 488 return 0;
ian@0 489 }
ian@0 490
ian@0 491 // Split up the JEDEC numbers
ian@0 492 OldVal = flread(0);
ian@0 493 for (I = 0; I != 4; I++)
ian@0 494 Mfg[I] = (OldVal >> (I*8));
ian@0 495 OldVal = flread(1);
ian@0 496 for (I = 0; I != 4; I++)
ian@0 497 Id[I] = (OldVal >> (I*8));
ian@0 498
ian@0 499 Size = handle_jedecs(map,Mfg,Id,4,base,priv);
ian@0 500 if (Size == 0)
ian@0 501 {
ian@0 502 flwrite(Reset,0x555);
ian@0 503 return 0;
ian@0 504 }
ian@0 505
ian@0 506 /* Check if there is address wrap around within a single bank, if this
ian@0 507 returns JEDEC numbers then we assume that it is wrap around. Notice
ian@0 508 we call this routine with the JEDEC return still enabled, if two or
ian@0 509 more flashes have a truncated address space the probe test will still
ian@0 510 work */
ian@0 511 if (base + (Size<<2)+0x555 < map->size &&
ian@0 512 base + (Size<<2)+0x555 < (base & (~(my_bank_size-1))) + my_bank_size)
ian@0 513 {
ian@0 514 if (flread(base+Size) != flread(base+Size + 0x100) ||
ian@0 515 flread(base+Size + 1) != flread(base+Size + 0x101))
ian@0 516 {
ian@0 517 jedec_probe32(map,base+Size,priv);
ian@0 518 }
ian@0 519 }
ian@0 520
ian@0 521 // Reset.
ian@0 522 flwrite(0xF0F0F0F0,0x555);
ian@0 523
ian@0 524 return 1;
ian@0 525
ian@0 526 #undef flread
ian@0 527 #undef flwrite
ian@0 528 }
ian@0 529
ian@0 530 /* Linear read. */
ian@0 531 static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len,
ian@0 532 size_t *retlen, u_char *buf)
ian@0 533 {
ian@0 534 struct map_info *map = mtd->priv;
ian@0 535
ian@0 536 map_copy_from(map, buf, from, len);
ian@0 537 *retlen = len;
ian@0 538 return 0;
ian@0 539 }
ian@0 540
ian@0 541 /* Banked read. Take special care to jump past the holes in the bank
ian@0 542 mapping. This version assumes symetry in the holes.. */
ian@0 543 static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len,
ian@0 544 size_t *retlen, u_char *buf)
ian@0 545 {
ian@0 546 struct map_info *map = mtd->priv;
ian@0 547 struct jedec_private *priv = map->fldrv_priv;
ian@0 548
ian@0 549 *retlen = 0;
ian@0 550 while (len > 0)
ian@0 551 {
ian@0 552 // Determine what bank and offset into that bank the first byte is
ian@0 553 unsigned long bank = from & (~(priv->bank_fill[0]-1));
ian@0 554 unsigned long offset = from & (priv->bank_fill[0]-1);
ian@0 555 unsigned long get = len;
ian@0 556 if (priv->bank_fill[0] - offset < len)
ian@0 557 get = priv->bank_fill[0] - offset;
ian@0 558
ian@0 559 bank /= priv->bank_fill[0];
ian@0 560 map_copy_from(map,buf + *retlen,bank*my_bank_size + offset,get);
ian@0 561
ian@0 562 len -= get;
ian@0 563 *retlen += get;
ian@0 564 from += get;
ian@0 565 }
ian@0 566 return 0;
ian@0 567 }
ian@0 568
ian@0 569 /* Pass the flags value that the flash return before it re-entered read
ian@0 570 mode. */
ian@0 571 static void jedec_flash_failed(unsigned char code)
ian@0 572 {
ian@0 573 /* Bit 5 being high indicates that there was an internal device
ian@0 574 failure, erasure time limits exceeded or something */
ian@0 575 if ((code & (1 << 5)) != 0)
ian@0 576 {
ian@0 577 printk("mtd: Internal Flash failure\n");
ian@0 578 return;
ian@0 579 }
ian@0 580 printk("mtd: Programming didn't take\n");
ian@0 581 }
ian@0 582
ian@0 583 /* This uses the erasure function described in the AMD Flash Handbook,
ian@0 584 it will work for flashes with a fixed sector size only. Flashes with
ian@0 585 a selection of sector sizes (ie the AMD Am29F800B) will need a different
ian@0 586 routine. This routine tries to parallize erasing multiple chips/sectors
ian@0 587 where possible */
ian@0 588 static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
ian@0 589 {
ian@0 590 // Does IO to the currently selected chip
ian@0 591 #define flread(x) map_read8(map,chip->base+((x)<<chip->addrshift))
ian@0 592 #define flwrite(v,x) map_write8(map,v,chip->base+((x)<<chip->addrshift))
ian@0 593
ian@0 594 unsigned long Time = 0;
ian@0 595 unsigned long NoTime = 0;
ian@0 596 unsigned long start = instr->addr, len = instr->len;
ian@0 597 unsigned int I;
ian@0 598 struct map_info *map = mtd->priv;
ian@0 599 struct jedec_private *priv = map->fldrv_priv;
ian@0 600
ian@0 601 // Verify the arguments..
ian@0 602 if (start + len > mtd->size ||
ian@0 603 (start % mtd->erasesize) != 0 ||
ian@0 604 (len % mtd->erasesize) != 0 ||
ian@0 605 (len/mtd->erasesize) == 0)
ian@0 606 return -EINVAL;
ian@0 607
ian@0 608 jedec_flash_chip_scan(priv,start,len);
ian@0 609
ian@0 610 // Start the erase sequence on each chip
ian@0 611 for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
ian@0 612 {
ian@0 613 unsigned long off;
ian@0 614 struct jedec_flash_chip *chip = priv->chips + I;
ian@0 615
ian@0 616 if (chip->length == 0)
ian@0 617 continue;
ian@0 618
ian@0 619 if (chip->start + chip->length > chip->size)
ian@0 620 {
ian@0 621 printk("DIE\n");
ian@0 622 return -EIO;
ian@0 623 }
ian@0 624
ian@0 625 flwrite(0xF0,chip->start + 0x555);
ian@0 626 flwrite(0xAA,chip->start + 0x555);
ian@0 627 flwrite(0x55,chip->start + 0x2AA);
ian@0 628 flwrite(0x80,chip->start + 0x555);
ian@0 629 flwrite(0xAA,chip->start + 0x555);
ian@0 630 flwrite(0x55,chip->start + 0x2AA);
ian@0 631
ian@0 632 /* Once we start selecting the erase sectors the delay between each
ian@0 633 command must not exceed 50us or it will immediately start erasing
ian@0 634 and ignore the other sectors */
ian@0 635 for (off = 0; off < len; off += chip->sectorsize)
ian@0 636 {
ian@0 637 // Check to make sure we didn't timeout
ian@0 638 flwrite(0x30,chip->start + off);
ian@0 639 if (off == 0)
ian@0 640 continue;
ian@0 641 if ((flread(chip->start + off) & (1 << 3)) != 0)
ian@0 642 {
ian@0 643 printk("mtd: Ack! We timed out the erase timer!\n");
ian@0 644 return -EIO;
ian@0 645 }
ian@0 646 }
ian@0 647 }
ian@0 648
ian@0 649 /* We could split this into a timer routine and return early, performing
ian@0 650 background erasure.. Maybe later if the need warrents */
ian@0 651
ian@0 652 /* Poll the flash for erasure completion, specs say this can take as long
ian@0 653 as 480 seconds to do all the sectors (for a 2 meg flash).
ian@0 654 Erasure time is dependent on chip age, temp and wear.. */
ian@0 655
ian@0 656 /* This being a generic routine assumes a 32 bit bus. It does read32s
ian@0 657 and bundles interleved chips into the same grouping. This will work
ian@0 658 for all bus widths */
ian@0 659 Time = 0;
ian@0 660 NoTime = 0;
ian@0 661 for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
ian@0 662 {
ian@0 663 struct jedec_flash_chip *chip = priv->chips + I;
ian@0 664 unsigned long off = 0;
ian@0 665 unsigned todo[4] = {0,0,0,0};
ian@0 666 unsigned todo_left = 0;
ian@0 667 unsigned J;
ian@0 668
ian@0 669 if (chip->length == 0)
ian@0 670 continue;
ian@0 671
ian@0 672 /* Find all chips in this data line, realistically this is all
ian@0 673 or nothing up to the interleve count */
ian@0 674 for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++)
ian@0 675 {
ian@0 676 if ((priv->chips[J].base & (~((1<<chip->addrshift)-1))) ==
ian@0 677 (chip->base & (~((1<<chip->addrshift)-1))))
ian@0 678 {
ian@0 679 todo_left++;
ian@0 680 todo[priv->chips[J].base & ((1<<chip->addrshift)-1)] = 1;
ian@0 681 }
ian@0 682 }
ian@0 683
ian@0 684 /* printk("todo: %x %x %x %x\n",(short)todo[0],(short)todo[1],
ian@0 685 (short)todo[2],(short)todo[3]);
ian@0 686 */
ian@0 687 while (1)
ian@0 688 {
ian@0 689 __u32 Last[4];
ian@0 690 unsigned long Count = 0;
ian@0 691
ian@0 692 /* During erase bit 7 is held low and bit 6 toggles, we watch this,
ian@0 693 should it stop toggling or go high then the erase is completed,
ian@0 694 or this is not really flash ;> */
ian@0 695 switch (map->buswidth) {
ian@0 696 case 1:
ian@0 697 Last[0] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off);
ian@0 698 Last[1] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off);
ian@0 699 Last[2] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off);
ian@0 700 break;
ian@0 701 case 2:
ian@0 702 Last[0] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off);
ian@0 703 Last[1] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off);
ian@0 704 Last[2] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off);
ian@0 705 break;
ian@0 706 case 3:
ian@0 707 Last[0] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off);
ian@0 708 Last[1] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off);
ian@0 709 Last[2] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off);
ian@0 710 break;
ian@0 711 }
ian@0 712 Count = 3;
ian@0 713 while (todo_left != 0)
ian@0 714 {
ian@0 715 for (J = 0; J != 4; J++)
ian@0 716 {
ian@0 717 __u8 Byte1 = (Last[(Count-1)%4] >> (J*8)) & 0xFF;
ian@0 718 __u8 Byte2 = (Last[(Count-2)%4] >> (J*8)) & 0xFF;
ian@0 719 __u8 Byte3 = (Last[(Count-3)%4] >> (J*8)) & 0xFF;
ian@0 720 if (todo[J] == 0)
ian@0 721 continue;
ian@0 722
ian@0 723 if ((Byte1 & (1 << 7)) == 0 && Byte1 != Byte2)
ian@0 724 {
ian@0 725 // printk("Check %x %x %x\n",(short)J,(short)Byte1,(short)Byte2);
ian@0 726 continue;
ian@0 727 }
ian@0 728
ian@0 729 if (Byte1 == Byte2)
ian@0 730 {
ian@0 731 jedec_flash_failed(Byte3);
ian@0 732 return -EIO;
ian@0 733 }
ian@0 734
ian@0 735 todo[J] = 0;
ian@0 736 todo_left--;
ian@0 737 }
ian@0 738
ian@0 739 /* if (NoTime == 0)
ian@0 740 Time += HZ/10 - schedule_timeout(HZ/10);*/
ian@0 741 NoTime = 0;
ian@0 742
ian@0 743 switch (map->buswidth) {
ian@0 744 case 1:
ian@0 745 Last[Count % 4] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off);
ian@0 746 break;
ian@0 747 case 2:
ian@0 748 Last[Count % 4] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off);
ian@0 749 break;
ian@0 750 case 4:
ian@0 751 Last[Count % 4] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off);
ian@0 752 break;
ian@0 753 }
ian@0 754 Count++;
ian@0 755
ian@0 756 /* // Count time, max of 15s per sector (according to AMD)
ian@0 757 if (Time > 15*len/mtd->erasesize*HZ)
ian@0 758 {
ian@0 759 printk("mtd: Flash Erase Timed out\n");
ian@0 760 return -EIO;
ian@0 761 } */
ian@0 762 }
ian@0 763
ian@0 764 // Skip to the next chip if we used chip erase
ian@0 765 if (chip->length == chip->size)
ian@0 766 off = chip->size;
ian@0 767 else
ian@0 768 off += chip->sectorsize;
ian@0 769
ian@0 770 if (off >= chip->length)
ian@0 771 break;
ian@0 772 NoTime = 1;
ian@0 773 }
ian@0 774
ian@0 775 for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++)
ian@0 776 {
ian@0 777 if ((priv->chips[J].base & (~((1<<chip->addrshift)-1))) ==
ian@0 778 (chip->base & (~((1<<chip->addrshift)-1))))
ian@0 779 priv->chips[J].length = 0;
ian@0 780 }
ian@0 781 }
ian@0 782
ian@0 783 //printk("done\n");
ian@0 784 instr->state = MTD_ERASE_DONE;
ian@0 785 mtd_erase_callback(instr);
ian@0 786 return 0;
ian@0 787
ian@0 788 #undef flread
ian@0 789 #undef flwrite
ian@0 790 }
ian@0 791
ian@0 792 /* This is the simple flash writing function. It writes to every byte, in
ian@0 793 sequence. It takes care of how to properly address the flash if
ian@0 794 the flash is interleved. It can only be used if all the chips in the
ian@0 795 array are identical!*/
ian@0 796 static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
ian@0 797 size_t *retlen, const u_char *buf)
ian@0 798 {
ian@0 799 /* Does IO to the currently selected chip. It takes the bank addressing
ian@0 800 base (which is divisible by the chip size) adds the necessary lower bits
ian@0 801 of addrshift (interleave index) and then adds the control register index. */
ian@0 802 #define flread(x) map_read8(map,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
ian@0 803 #define flwrite(v,x) map_write8(map,v,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
ian@0 804
ian@0 805 struct map_info *map = mtd->priv;
ian@0 806 struct jedec_private *priv = map->fldrv_priv;
ian@0 807 unsigned long base;
ian@0 808 unsigned long off;
ian@0 809 size_t save_len = len;
ian@0 810
ian@0 811 if (start + len > mtd->size)
ian@0 812 return -EIO;
ian@0 813
ian@0 814 //printk("Here");
ian@0 815
ian@0 816 //printk("flash_write: start is %x, len is %x\n",start,(unsigned long)len);
ian@0 817 while (len != 0)
ian@0 818 {
ian@0 819 struct jedec_flash_chip *chip = priv->chips;
ian@0 820 unsigned long bank;
ian@0 821 unsigned long boffset;
ian@0 822
ian@0 823 // Compute the base of the flash.
ian@0 824 off = ((unsigned long)start) % (chip->size << chip->addrshift);
ian@0 825 base = start - off;
ian@0 826
ian@0 827 // Perform banked addressing translation.
ian@0 828 bank = base & (~(priv->bank_fill[0]-1));
ian@0 829 boffset = base & (priv->bank_fill[0]-1);
ian@0 830 bank = (bank/priv->bank_fill[0])*my_bank_size;
ian@0 831 base = bank + boffset;
ian@0 832
ian@0 833 // printk("Flasing %X %X %X\n",base,chip->size,len);
ian@0 834 // printk("off is %x, compare with %x\n",off,chip->size << chip->addrshift);
ian@0 835
ian@0 836 // Loop over this page
ian@0 837 for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++)
ian@0 838 {
ian@0 839 unsigned char oldbyte = map_read8(map,base+off);
ian@0 840 unsigned char Last[4];
ian@0 841 unsigned long Count = 0;
ian@0 842
ian@0 843 if (oldbyte == *buf) {
ian@0 844 // printk("oldbyte and *buf is %x,len is %x\n",oldbyte,len);
ian@0 845 continue;
ian@0 846 }
ian@0 847 if (((~oldbyte) & *buf) != 0)
ian@0 848 printk("mtd: warn: Trying to set a 0 to a 1\n");
ian@0 849
ian@0 850 // Write
ian@0 851 flwrite(0xAA,0x555);
ian@0 852 flwrite(0x55,0x2AA);
ian@0 853 flwrite(0xA0,0x555);
ian@0 854 map_write8(map,*buf,base + off);
ian@0 855 Last[0] = map_read8(map,base + off);
ian@0 856 Last[1] = map_read8(map,base + off);
ian@0 857 Last[2] = map_read8(map,base + off);
ian@0 858
ian@0 859 /* Wait for the flash to finish the operation. We store the last 4
ian@0 860 status bytes that have been retrieved so we can determine why
ian@0 861 it failed. The toggle bits keep toggling when there is a
ian@0 862 failure */
ian@0 863 for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] &&
ian@0 864 Count < 10000; Count++)
ian@0 865 Last[Count % 4] = map_read8(map,base + off);
ian@0 866 if (Last[(Count - 1) % 4] != *buf)
ian@0 867 {
ian@0 868 jedec_flash_failed(Last[(Count - 3) % 4]);
ian@0 869 return -EIO;
ian@0 870 }
ian@0 871 }
ian@0 872 }
ian@0 873 *retlen = save_len;
ian@0 874 return 0;
ian@0 875 }
ian@0 876
ian@0 877 /* This is used to enhance the speed of the erase routine,
ian@0 878 when things are being done to multiple chips it is possible to
ian@0 879 parallize the operations, particularly full memory erases of multi
ian@0 880 chip memories benifit */
ian@0 881 static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start,
ian@0 882 unsigned long len)
ian@0 883 {
ian@0 884 unsigned int I;
ian@0 885
ian@0 886 // Zero the records
ian@0 887 for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
ian@0 888 priv->chips[I].start = priv->chips[I].length = 0;
ian@0 889
ian@0 890 // Intersect the region with each chip
ian@0 891 for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
ian@0 892 {
ian@0 893 struct jedec_flash_chip *chip = priv->chips + I;
ian@0 894 unsigned long ByteStart;
ian@0 895 unsigned long ChipEndByte = chip->offset + (chip->size << chip->addrshift);
ian@0 896
ian@0 897 // End is before this chip or the start is after it
ian@0 898 if (start+len < chip->offset ||
ian@0 899 ChipEndByte - (1 << chip->addrshift) < start)
ian@0 900 continue;
ian@0 901
ian@0 902 if (start < chip->offset)
ian@0 903 {
ian@0 904 ByteStart = chip->offset;
ian@0 905 chip->start = 0;
ian@0 906 }
ian@0 907 else
ian@0 908 {
ian@0 909 chip->start = (start - chip->offset + (1 << chip->addrshift)-1) >> chip->addrshift;
ian@0 910 ByteStart = start;
ian@0 911 }
ian@0 912
ian@0 913 if (start + len >= ChipEndByte)
ian@0 914 chip->length = (ChipEndByte - ByteStart) >> chip->addrshift;
ian@0 915 else
ian@0 916 chip->length = (start + len - ByteStart + (1 << chip->addrshift)-1) >> chip->addrshift;
ian@0 917 }
ian@0 918 }
ian@0 919
ian@0 920 int __init jedec_init(void)
ian@0 921 {
ian@0 922 register_mtd_chip_driver(&jedec_chipdrv);
ian@0 923 return 0;
ian@0 924 }
ian@0 925
ian@0 926 static void __exit jedec_exit(void)
ian@0 927 {
ian@0 928 unregister_mtd_chip_driver(&jedec_chipdrv);
ian@0 929 }
ian@0 930
ian@0 931 module_init(jedec_init);
ian@0 932 module_exit(jedec_exit);
ian@0 933
ian@0 934 MODULE_LICENSE("GPL");
ian@0 935 MODULE_AUTHOR("Jason Gunthorpe <jgg@deltatee.com> et al.");
ian@0 936 MODULE_DESCRIPTION("Old MTD chip driver for JEDEC-compliant flash chips");