aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/chips
diff options
context:
space:
mode:
authorGuillaume LECERF <glecerf@gmail.com>2010-04-24 11:58:17 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2010-05-13 20:33:27 -0400
commit564b84978df2bf83d334940f1a1190702579f79f (patch)
tree10f7ce02b4c0bb876c3e2c24afdb6eb0ac7707a4 /drivers/mtd/chips
parent58598861227877bb481b9035d2a07283577a2274 (diff)
mtd: cfi_cmdset_0002: do not fail on no extended query table as they are both optional
After looking at AMD's CFI specification [1], both of the extended query tables are optional. Thus, it looks like relying that at least one of those tables exist is a bug in cfi_cmdset_0002. This patch inverts the logic and checks for unlock function pointers before exiting on error. This approach leaves place to add a call to a fixup function to try to handle chips compatible with the early AMD specification from 1995 [2]. [1] http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_r20.pdf [2] http://noel.feld.cvut.cz/hw/amd/20158a.pdf Signed-off-by: Guillaume LECERF <glecerf@gmail.com> Reviewed-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/chips')
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c89
1 files changed, 45 insertions, 44 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index c16b8cecc3a8..ce38d3d049ef 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -357,65 +357,66 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
357 357
358 if (cfi->cfi_mode==CFI_MODE_CFI){ 358 if (cfi->cfi_mode==CFI_MODE_CFI){
359 unsigned char bootloc; 359 unsigned char bootloc;
360 /*
361 * It's a real CFI chip, not one for which the probe
362 * routine faked a CFI structure. So we read the feature
363 * table from it.
364 */
365 __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; 360 __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
366 struct cfi_pri_amdstd *extp; 361 struct cfi_pri_amdstd *extp;
367 362
368 extp = (struct cfi_pri_amdstd*)cfi_read_pri(map, adr, sizeof(*extp), "Amd/Fujitsu"); 363 extp = (struct cfi_pri_amdstd*)cfi_read_pri(map, adr, sizeof(*extp), "Amd/Fujitsu");
369 if (!extp) { 364 if (extp) {
370 kfree(mtd); 365 /*
371 return NULL; 366 * It's a real CFI chip, not one for which the probe
372 } 367 * routine faked a CFI structure.
373 368 */
374 cfi_fixup_major_minor(cfi, extp); 369 cfi_fixup_major_minor(cfi, extp);
375 370
376 if (extp->MajorVersion != '1' || 371 if (extp->MajorVersion != '1' ||
377 (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { 372 (extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
378 printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " 373 printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
379 "version %c.%c.\n", extp->MajorVersion, 374 "version %c.%c.\n", extp->MajorVersion,
380 extp->MinorVersion); 375 extp->MinorVersion);
381 kfree(extp); 376 kfree(extp);
382 kfree(mtd); 377 kfree(mtd);
383 return NULL; 378 return NULL;
384 } 379 }
385 380
386 /* Install our own private info structure */ 381 /* Install our own private info structure */
387 cfi->cmdset_priv = extp; 382 cfi->cmdset_priv = extp;
388 383
389 /* Apply cfi device specific fixups */ 384 /* Apply cfi device specific fixups */
390 cfi_fixup(mtd, cfi_fixup_table); 385 cfi_fixup(mtd, cfi_fixup_table);
391 386
392#ifdef DEBUG_CFI_FEATURES 387#ifdef DEBUG_CFI_FEATURES
393 /* Tell the user about it in lots of lovely detail */ 388 /* Tell the user about it in lots of lovely detail */
394 cfi_tell_features(extp); 389 cfi_tell_features(extp);
395#endif 390#endif
396 391
397 bootloc = extp->TopBottom; 392 bootloc = extp->TopBottom;
398 if ((bootloc != 2) && (bootloc != 3)) { 393 if ((bootloc != 2) && (bootloc != 3)) {
399 printk(KERN_WARNING "%s: CFI does not contain boot " 394 printk(KERN_WARNING "%s: CFI does not contain boot "
400 "bank location. Assuming top.\n", map->name); 395 "bank location. Assuming top.\n", map->name);
401 bootloc = 2; 396 bootloc = 2;
402 } 397 }
403 398
404 if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) { 399 if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) {
405 printk(KERN_WARNING "%s: Swapping erase regions for broken CFI table.\n", map->name); 400 printk(KERN_WARNING "%s: Swapping erase regions for broken CFI table.\n", map->name);
406 401
407 for (i=0; i<cfi->cfiq->NumEraseRegions / 2; i++) { 402 for (i=0; i<cfi->cfiq->NumEraseRegions / 2; i++) {
408 int j = (cfi->cfiq->NumEraseRegions-1)-i; 403 int j = (cfi->cfiq->NumEraseRegions-1)-i;
409 __u32 swap; 404 __u32 swap;
410 405
411 swap = cfi->cfiq->EraseRegionInfo[i]; 406 swap = cfi->cfiq->EraseRegionInfo[i];
412 cfi->cfiq->EraseRegionInfo[i] = cfi->cfiq->EraseRegionInfo[j]; 407 cfi->cfiq->EraseRegionInfo[i] = cfi->cfiq->EraseRegionInfo[j];
413 cfi->cfiq->EraseRegionInfo[j] = swap; 408 cfi->cfiq->EraseRegionInfo[j] = swap;
409 }
414 } 410 }
411 /* Set the default CFI lock/unlock addresses */
412 cfi->addr_unlock1 = 0x555;
413 cfi->addr_unlock2 = 0x2aa;
414 }
415
416 if (!cfi->addr_unlock1 || !cfi->addr_unlock2) {
417 kfree(mtd);
418 return NULL;
415 } 419 }
416 /* Set the default CFI lock/unlock addresses */
417 cfi->addr_unlock1 = 0x555;
418 cfi->addr_unlock2 = 0x2aa;
419 420
420 } /* CFI mode */ 421 } /* CFI mode */
421 else if (cfi->cfi_mode == CFI_MODE_JEDEC) { 422 else if (cfi->cfi_mode == CFI_MODE_JEDEC) {