11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Routines common to all CFI-type probes. 31da177e4SLinus Torvalds * (C) 2001-2003 Red Hat, Inc. 41da177e4SLinus Torvalds * GPL'd 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds #include <linux/kernel.h> 81da177e4SLinus Torvalds #include <linux/slab.h> 91da177e4SLinus Torvalds #include <linux/module.h> 101da177e4SLinus Torvalds #include <linux/mtd/mtd.h> 111da177e4SLinus Torvalds #include <linux/mtd/map.h> 121da177e4SLinus Torvalds #include <linux/mtd/cfi.h> 131da177e4SLinus Torvalds #include <linux/mtd/gen_probe.h> 141da177e4SLinus Torvalds 151da177e4SLinus Torvalds static struct mtd_info *check_cmd_set(struct map_info *, int); 161da177e4SLinus Torvalds static struct cfi_private *genprobe_ident_chips(struct map_info *map, 171da177e4SLinus Torvalds struct chip_probe *cp); 181da177e4SLinus Torvalds static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp, 191da177e4SLinus Torvalds struct cfi_private *cfi); 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp) 221da177e4SLinus Torvalds { 23*f454b43aSSergei Shtylyov struct mtd_info *mtd; 241da177e4SLinus Torvalds struct cfi_private *cfi; 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds /* First probe the map to see if we have CFI stuff there. */ 271da177e4SLinus Torvalds cfi = genprobe_ident_chips(map, cp); 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds if (!cfi) 301da177e4SLinus Torvalds return NULL; 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds map->fldrv_priv = cfi; 331da177e4SLinus Torvalds /* OK we liked it. Now find a driver for the command set it talks */ 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds mtd = check_cmd_set(map, 1); /* First the primary cmdset */ 361da177e4SLinus Torvalds if (!mtd) 371da177e4SLinus Torvalds mtd = check_cmd_set(map, 0); /* Then the secondary */ 381da177e4SLinus Torvalds 390f5ae3d2SDavid Woodhouse if (mtd) { 400f5ae3d2SDavid Woodhouse if (mtd->size > map->size) { 41f6a673b3SDavid Woodhouse printk(KERN_WARNING "Reducing visibility of %ldKiB chip to %ldKiB\n", 420f5ae3d2SDavid Woodhouse (unsigned long)mtd->size >> 10, 430f5ae3d2SDavid Woodhouse (unsigned long)map->size >> 10); 440f5ae3d2SDavid Woodhouse mtd->size = map->size; 450f5ae3d2SDavid Woodhouse } 461da177e4SLinus Torvalds return mtd; 470f5ae3d2SDavid Woodhouse } 481da177e4SLinus Torvalds 491da177e4SLinus Torvalds printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n"); 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds kfree(cfi->cfiq); 521da177e4SLinus Torvalds kfree(cfi); 531da177e4SLinus Torvalds map->fldrv_priv = NULL; 541da177e4SLinus Torvalds return NULL; 551da177e4SLinus Torvalds } 561da177e4SLinus Torvalds EXPORT_SYMBOL(mtd_do_chip_probe); 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp) 601da177e4SLinus Torvalds { 611da177e4SLinus Torvalds struct cfi_private cfi; 621da177e4SLinus Torvalds struct cfi_private *retcfi; 631da177e4SLinus Torvalds unsigned long *chip_map; 641da177e4SLinus Torvalds int i, j, mapsize; 651da177e4SLinus Torvalds int max_chips; 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds memset(&cfi, 0, sizeof(cfi)); 681da177e4SLinus Torvalds 691da177e4SLinus Torvalds /* Call the probetype-specific code with all permutations of 701da177e4SLinus Torvalds interleave and device type, etc. */ 711da177e4SLinus Torvalds if (!genprobe_new_chip(map, cp, &cfi)) { 721da177e4SLinus Torvalds /* The probe didn't like it */ 733a3688b6SJean Delvare pr_debug("%s: Found no %s device at location zero\n", 741da177e4SLinus Torvalds cp->name, map->name); 751da177e4SLinus Torvalds return NULL; 761da177e4SLinus Torvalds } 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds #if 0 /* Let the CFI probe routine do this sanity check. The Intel and AMD 791da177e4SLinus Torvalds probe routines won't ever return a broken CFI structure anyway, 801da177e4SLinus Torvalds because they make them up themselves. 811da177e4SLinus Torvalds */ 821da177e4SLinus Torvalds if (cfi.cfiq->NumEraseRegions == 0) { 831da177e4SLinus Torvalds printk(KERN_WARNING "Number of erase regions is zero\n"); 841da177e4SLinus Torvalds kfree(cfi.cfiq); 851da177e4SLinus Torvalds return NULL; 861da177e4SLinus Torvalds } 871da177e4SLinus Torvalds #endif 881da177e4SLinus Torvalds cfi.chipshift = cfi.cfiq->DevSize; 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds if (cfi_interleave_is_1(&cfi)) { 911da177e4SLinus Torvalds ; 921da177e4SLinus Torvalds } else if (cfi_interleave_is_2(&cfi)) { 931da177e4SLinus Torvalds cfi.chipshift++; 941da177e4SLinus Torvalds } else if (cfi_interleave_is_4((&cfi))) { 951da177e4SLinus Torvalds cfi.chipshift += 2; 961da177e4SLinus Torvalds } else if (cfi_interleave_is_8(&cfi)) { 971da177e4SLinus Torvalds cfi.chipshift += 3; 981da177e4SLinus Torvalds } else { 991da177e4SLinus Torvalds BUG(); 1001da177e4SLinus Torvalds } 1011da177e4SLinus Torvalds 1021da177e4SLinus Torvalds cfi.numchips = 1; 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds /* 1051da177e4SLinus Torvalds * Allocate memory for bitmap of valid chips. 1061da177e4SLinus Torvalds * Align bitmap storage size to full byte. 1071da177e4SLinus Torvalds */ 1081da177e4SLinus Torvalds max_chips = map->size >> cfi.chipshift; 1090f5ae3d2SDavid Woodhouse if (!max_chips) { 1100f5ae3d2SDavid Woodhouse printk(KERN_WARNING "NOR chip too large to fit in mapping. Attempting to cope...\n"); 1110f5ae3d2SDavid Woodhouse max_chips = 1; 1120f5ae3d2SDavid Woodhouse } 1130f5ae3d2SDavid Woodhouse 114c8872b06SJulia Lawall mapsize = sizeof(long) * DIV_ROUND_UP(max_chips, BITS_PER_LONG); 11595b93a0cSBurman Yan chip_map = kzalloc(mapsize, GFP_KERNEL); 1161da177e4SLinus Torvalds if (!chip_map) { 1171da177e4SLinus Torvalds kfree(cfi.cfiq); 1181da177e4SLinus Torvalds return NULL; 1191da177e4SLinus Torvalds } 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds set_bit(0, chip_map); /* Mark first chip valid */ 1221da177e4SLinus Torvalds 1231da177e4SLinus Torvalds /* 1241da177e4SLinus Torvalds * Now probe for other chips, checking sensibly for aliases while 1251da177e4SLinus Torvalds * we're at it. The new_chip probe above should have let the first 1261da177e4SLinus Torvalds * chip in read mode. 1271da177e4SLinus Torvalds */ 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds for (i = 1; i < max_chips; i++) { 1301da177e4SLinus Torvalds cp->probe_chip(map, i << cfi.chipshift, chip_map, &cfi); 1311da177e4SLinus Torvalds } 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds /* 1341da177e4SLinus Torvalds * Now allocate the space for the structures we need to return to 1351da177e4SLinus Torvalds * our caller, and copy the appropriate data into them. 1361da177e4SLinus Torvalds */ 1371da177e4SLinus Torvalds 1389cb76a6aSGustavo A. R. Silva retcfi = kmalloc(struct_size(retcfi, chips, cfi.numchips), GFP_KERNEL); 1391da177e4SLinus Torvalds 1401da177e4SLinus Torvalds if (!retcfi) { 1411da177e4SLinus Torvalds kfree(cfi.cfiq); 1421da177e4SLinus Torvalds kfree(chip_map); 1431da177e4SLinus Torvalds return NULL; 1441da177e4SLinus Torvalds } 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds memcpy(retcfi, &cfi, sizeof(cfi)); 1471da177e4SLinus Torvalds memset(&retcfi->chips[0], 0, sizeof(struct flchip) * cfi.numchips); 1481da177e4SLinus Torvalds 1491da177e4SLinus Torvalds for (i = 0, j = 0; (j < cfi.numchips) && (i < max_chips); i++) { 1501da177e4SLinus Torvalds if(test_bit(i, chip_map)) { 1511da177e4SLinus Torvalds struct flchip *pchip = &retcfi->chips[j++]; 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds pchip->start = (i << cfi.chipshift); 1541da177e4SLinus Torvalds pchip->state = FL_READY; 1551da177e4SLinus Torvalds init_waitqueue_head(&pchip->wq); 156c4e77376SStefani Seibold mutex_init(&pchip->mutex); 1571da177e4SLinus Torvalds } 1581da177e4SLinus Torvalds } 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds kfree(chip_map); 1611da177e4SLinus Torvalds return retcfi; 1621da177e4SLinus Torvalds } 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds 1651da177e4SLinus Torvalds static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp, 1661da177e4SLinus Torvalds struct cfi_private *cfi) 1671da177e4SLinus Torvalds { 1681da177e4SLinus Torvalds int min_chips = (map_bankwidth(map)/4?:1); /* At most 4-bytes wide. */ 1691da177e4SLinus Torvalds int max_chips = map_bankwidth(map); /* And minimum 1 */ 1701da177e4SLinus Torvalds int nr_chips, type; 1711da177e4SLinus Torvalds 1726170b434SRussell King for (nr_chips = max_chips; nr_chips >= min_chips; nr_chips >>= 1) { 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds if (!cfi_interleave_supported(nr_chips)) 1751da177e4SLinus Torvalds continue; 1761da177e4SLinus Torvalds 1771da177e4SLinus Torvalds cfi->interleave = nr_chips; 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds /* Minimum device size. Don't look for one 8-bit device 1801da177e4SLinus Torvalds in a 16-bit bus, etc. */ 1811da177e4SLinus Torvalds type = map_bankwidth(map) / nr_chips; 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds for (; type <= CFI_DEVICETYPE_X32; type<<=1) { 1841da177e4SLinus Torvalds cfi->device_type = type; 1851da177e4SLinus Torvalds 1861da177e4SLinus Torvalds if (cp->probe_chip(map, 0, NULL, cfi)) 1871da177e4SLinus Torvalds return 1; 1881da177e4SLinus Torvalds } 1891da177e4SLinus Torvalds } 1901da177e4SLinus Torvalds return 0; 1911da177e4SLinus Torvalds } 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds typedef struct mtd_info *cfi_cmdset_fn_t(struct map_info *, int); 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds extern cfi_cmdset_fn_t cfi_cmdset_0001; 1961da177e4SLinus Torvalds extern cfi_cmdset_fn_t cfi_cmdset_0002; 1971da177e4SLinus Torvalds extern cfi_cmdset_fn_t cfi_cmdset_0020; 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map, 2001da177e4SLinus Torvalds int primary) 2011da177e4SLinus Torvalds { 2021da177e4SLinus Torvalds struct cfi_private *cfi = map->fldrv_priv; 2031da177e4SLinus Torvalds __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID; 204a15bdeefSDavid Woodhouse #ifdef CONFIG_MODULES 2051da177e4SLinus Torvalds cfi_cmdset_fn_t *probe_function; 20648360246SGeert Uytterhoeven char *probename; 2071da177e4SLinus Torvalds 20848360246SGeert Uytterhoeven probename = kasprintf(GFP_KERNEL, "cfi_cmdset_%4.4X", type); 20948360246SGeert Uytterhoeven if (!probename) 21048360246SGeert Uytterhoeven return NULL; 2111da177e4SLinus Torvalds 2125fc3dbc4SDavid Woodhouse probe_function = __symbol_get(probename); 213a15bdeefSDavid Woodhouse if (!probe_function) { 214f9827ddeSKees Cook request_module("cfi_cmdset_%4.4X", type); 2155fc3dbc4SDavid Woodhouse probe_function = __symbol_get(probename); 216a15bdeefSDavid Woodhouse } 21748360246SGeert Uytterhoeven kfree(probename); 2181da177e4SLinus Torvalds 2191da177e4SLinus Torvalds if (probe_function) { 2201da177e4SLinus Torvalds struct mtd_info *mtd; 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds mtd = (*probe_function)(map, primary); 2231da177e4SLinus Torvalds /* If it was happy, it'll have increased its own use count */ 224a15bdeefSDavid Woodhouse symbol_put_addr(probe_function); 2251da177e4SLinus Torvalds return mtd; 2261da177e4SLinus Torvalds } 2271da177e4SLinus Torvalds #endif 228a15bdeefSDavid Woodhouse printk(KERN_NOTICE "Support for command set %04X not present\n", type); 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds return NULL; 2311da177e4SLinus Torvalds } 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds static struct mtd_info *check_cmd_set(struct map_info *map, int primary) 2341da177e4SLinus Torvalds { 2351da177e4SLinus Torvalds struct cfi_private *cfi = map->fldrv_priv; 2361da177e4SLinus Torvalds __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID; 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds if (type == P_ID_NONE || type == P_ID_RESERVED) 2391da177e4SLinus Torvalds return NULL; 2401da177e4SLinus Torvalds 2411da177e4SLinus Torvalds switch(type){ 242a15bdeefSDavid Woodhouse /* We need these for the !CONFIG_MODULES case, 243a15bdeefSDavid Woodhouse because symbol_get() doesn't work there */ 2441da177e4SLinus Torvalds #ifdef CONFIG_MTD_CFI_INTELEXT 24558598861SGuillaume LECERF case P_ID_INTEL_EXT: 24658598861SGuillaume LECERF case P_ID_INTEL_STD: 24758598861SGuillaume LECERF case P_ID_INTEL_PERFORMANCE: 2481da177e4SLinus Torvalds return cfi_cmdset_0001(map, primary); 2491da177e4SLinus Torvalds #endif 2501da177e4SLinus Torvalds #ifdef CONFIG_MTD_CFI_AMDSTD 25158598861SGuillaume LECERF case P_ID_AMD_STD: 25283dcd3bbSGuillaume LECERF case P_ID_SST_OLD: 25380461128SGuillaume LECERF case P_ID_WINBOND: 2541da177e4SLinus Torvalds return cfi_cmdset_0002(map, primary); 2551da177e4SLinus Torvalds #endif 2561da177e4SLinus Torvalds #ifdef CONFIG_MTD_CFI_STAA 25758598861SGuillaume LECERF case P_ID_ST_ADV: 2581da177e4SLinus Torvalds return cfi_cmdset_0020(map, primary); 2591da177e4SLinus Torvalds #endif 260a15bdeefSDavid Woodhouse default: 2611da177e4SLinus Torvalds return cfi_cmdset_unknown(map, primary); 2621da177e4SLinus Torvalds } 263a15bdeefSDavid Woodhouse } 2641da177e4SLinus Torvalds 2651da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 2661da177e4SLinus Torvalds MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 2671da177e4SLinus Torvalds MODULE_DESCRIPTION("Helper routines for flash chip probe code"); 268