Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Routines common to all CFI-type probes.
0003  * (C) 2001-2003 Red Hat, Inc.
0004  * GPL'd
0005  */
0006 
0007 #include <linux/kernel.h>
0008 #include <linux/slab.h>
0009 #include <linux/module.h>
0010 #include <linux/mtd/mtd.h>
0011 #include <linux/mtd/map.h>
0012 #include <linux/mtd/cfi.h>
0013 #include <linux/mtd/gen_probe.h>
0014 
0015 static struct mtd_info *check_cmd_set(struct map_info *, int);
0016 static struct cfi_private *genprobe_ident_chips(struct map_info *map,
0017                         struct chip_probe *cp);
0018 static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
0019                  struct cfi_private *cfi);
0020 
0021 struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
0022 {
0023     struct mtd_info *mtd;
0024     struct cfi_private *cfi;
0025 
0026     /* First probe the map to see if we have CFI stuff there. */
0027     cfi = genprobe_ident_chips(map, cp);
0028 
0029     if (!cfi)
0030         return NULL;
0031 
0032     map->fldrv_priv = cfi;
0033     /* OK we liked it. Now find a driver for the command set it talks */
0034 
0035     mtd = check_cmd_set(map, 1); /* First the primary cmdset */
0036     if (!mtd)
0037         mtd = check_cmd_set(map, 0); /* Then the secondary */
0038 
0039     if (mtd) {
0040         if (mtd->size > map->size) {
0041             printk(KERN_WARNING "Reducing visibility of %ldKiB chip to %ldKiB\n",
0042                    (unsigned long)mtd->size >> 10,
0043                    (unsigned long)map->size >> 10);
0044             mtd->size = map->size;
0045         }
0046         return mtd;
0047     }
0048 
0049     printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n");
0050 
0051     kfree(cfi->cfiq);
0052     kfree(cfi);
0053     map->fldrv_priv = NULL;
0054     return NULL;
0055 }
0056 EXPORT_SYMBOL(mtd_do_chip_probe);
0057 
0058 
0059 static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp)
0060 {
0061     struct cfi_private cfi;
0062     struct cfi_private *retcfi;
0063     unsigned long *chip_map;
0064     int max_chips;
0065     int i, j;
0066 
0067     memset(&cfi, 0, sizeof(cfi));
0068 
0069     /* Call the probetype-specific code with all permutations of
0070        interleave and device type, etc. */
0071     if (!genprobe_new_chip(map, cp, &cfi)) {
0072         /* The probe didn't like it */
0073         pr_debug("%s: Found no %s device at location zero\n",
0074              cp->name, map->name);
0075         return NULL;
0076     }
0077 
0078 #if 0 /* Let the CFI probe routine do this sanity check. The Intel and AMD
0079      probe routines won't ever return a broken CFI structure anyway,
0080      because they make them up themselves.
0081       */
0082     if (cfi.cfiq->NumEraseRegions == 0) {
0083         printk(KERN_WARNING "Number of erase regions is zero\n");
0084         kfree(cfi.cfiq);
0085         return NULL;
0086     }
0087 #endif
0088     cfi.chipshift = cfi.cfiq->DevSize;
0089 
0090     if (cfi_interleave_is_1(&cfi)) {
0091         ;
0092     } else if (cfi_interleave_is_2(&cfi)) {
0093         cfi.chipshift++;
0094     } else if (cfi_interleave_is_4((&cfi))) {
0095         cfi.chipshift += 2;
0096     } else if (cfi_interleave_is_8(&cfi)) {
0097         cfi.chipshift += 3;
0098     } else {
0099         BUG();
0100     }
0101 
0102     cfi.numchips = 1;
0103 
0104     /*
0105      * Allocate memory for bitmap of valid chips.
0106      * Align bitmap storage size to full byte.
0107      */
0108     max_chips = map->size >> cfi.chipshift;
0109     if (!max_chips) {
0110         printk(KERN_WARNING "NOR chip too large to fit in mapping. Attempting to cope...\n");
0111         max_chips = 1;
0112     }
0113 
0114     chip_map = bitmap_zalloc(max_chips, GFP_KERNEL);
0115     if (!chip_map) {
0116         kfree(cfi.cfiq);
0117         return NULL;
0118     }
0119 
0120     set_bit(0, chip_map); /* Mark first chip valid */
0121 
0122     /*
0123      * Now probe for other chips, checking sensibly for aliases while
0124      * we're at it. The new_chip probe above should have let the first
0125      * chip in read mode.
0126      */
0127 
0128     for (i = 1; i < max_chips; i++) {
0129         cp->probe_chip(map, i << cfi.chipshift, chip_map, &cfi);
0130     }
0131 
0132     /*
0133      * Now allocate the space for the structures we need to return to
0134      * our caller, and copy the appropriate data into them.
0135      */
0136 
0137     retcfi = kmalloc(struct_size(retcfi, chips, cfi.numchips), GFP_KERNEL);
0138 
0139     if (!retcfi) {
0140         kfree(cfi.cfiq);
0141         bitmap_free(chip_map);
0142         return NULL;
0143     }
0144 
0145     memcpy(retcfi, &cfi, sizeof(cfi));
0146     memset(&retcfi->chips[0], 0, sizeof(struct flchip) * cfi.numchips);
0147 
0148     for (i = 0, j = 0; (j < cfi.numchips) && (i < max_chips); i++) {
0149         if(test_bit(i, chip_map)) {
0150             struct flchip *pchip = &retcfi->chips[j++];
0151 
0152             pchip->start = (i << cfi.chipshift);
0153             pchip->state = FL_READY;
0154             init_waitqueue_head(&pchip->wq);
0155             mutex_init(&pchip->mutex);
0156         }
0157     }
0158 
0159     bitmap_free(chip_map);
0160     return retcfi;
0161 }
0162 
0163 
0164 static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
0165                  struct cfi_private *cfi)
0166 {
0167     int min_chips = (map_bankwidth(map)/4?:1); /* At most 4-bytes wide. */
0168     int max_chips = map_bankwidth(map); /* And minimum 1 */
0169     int nr_chips, type;
0170 
0171     for (nr_chips = max_chips; nr_chips >= min_chips; nr_chips >>= 1) {
0172 
0173         if (!cfi_interleave_supported(nr_chips))
0174             continue;
0175 
0176         cfi->interleave = nr_chips;
0177 
0178         /* Minimum device size. Don't look for one 8-bit device
0179            in a 16-bit bus, etc. */
0180         type = map_bankwidth(map) / nr_chips;
0181 
0182         for (; type <= CFI_DEVICETYPE_X32; type<<=1) {
0183             cfi->device_type = type;
0184 
0185             if (cp->probe_chip(map, 0, NULL, cfi))
0186                 return 1;
0187         }
0188     }
0189     return 0;
0190 }
0191 
0192 typedef struct mtd_info *cfi_cmdset_fn_t(struct map_info *, int);
0193 
0194 extern cfi_cmdset_fn_t cfi_cmdset_0001;
0195 extern cfi_cmdset_fn_t cfi_cmdset_0002;
0196 extern cfi_cmdset_fn_t cfi_cmdset_0020;
0197 
0198 static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map,
0199                           int primary)
0200 {
0201     struct cfi_private *cfi = map->fldrv_priv;
0202     __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;
0203 #ifdef CONFIG_MODULES
0204     cfi_cmdset_fn_t *probe_function;
0205     char *probename;
0206 
0207     probename = kasprintf(GFP_KERNEL, "cfi_cmdset_%4.4X", type);
0208     if (!probename)
0209         return NULL;
0210 
0211     probe_function = __symbol_get(probename);
0212     if (!probe_function) {
0213         request_module("cfi_cmdset_%4.4X", type);
0214         probe_function = __symbol_get(probename);
0215     }
0216     kfree(probename);
0217 
0218     if (probe_function) {
0219         struct mtd_info *mtd;
0220 
0221         mtd = (*probe_function)(map, primary);
0222         /* If it was happy, it'll have increased its own use count */
0223         symbol_put_addr(probe_function);
0224         return mtd;
0225     }
0226 #endif
0227     printk(KERN_NOTICE "Support for command set %04X not present\n", type);
0228 
0229     return NULL;
0230 }
0231 
0232 static struct mtd_info *check_cmd_set(struct map_info *map, int primary)
0233 {
0234     struct cfi_private *cfi = map->fldrv_priv;
0235     __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;
0236 
0237     if (type == P_ID_NONE || type == P_ID_RESERVED)
0238         return NULL;
0239 
0240     switch(type){
0241         /* We need these for the !CONFIG_MODULES case,
0242            because symbol_get() doesn't work there */
0243 #ifdef CONFIG_MTD_CFI_INTELEXT
0244     case P_ID_INTEL_EXT:
0245     case P_ID_INTEL_STD:
0246     case P_ID_INTEL_PERFORMANCE:
0247         return cfi_cmdset_0001(map, primary);
0248 #endif
0249 #ifdef CONFIG_MTD_CFI_AMDSTD
0250     case P_ID_AMD_STD:
0251     case P_ID_SST_OLD:
0252     case P_ID_WINBOND:
0253         return cfi_cmdset_0002(map, primary);
0254 #endif
0255 #ifdef CONFIG_MTD_CFI_STAA
0256         case P_ID_ST_ADV:
0257         return cfi_cmdset_0020(map, primary);
0258 #endif
0259     default:
0260         return cfi_cmdset_unknown(map, primary);
0261     }
0262 }
0263 
0264 MODULE_LICENSE("GPL");
0265 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
0266 MODULE_DESCRIPTION("Helper routines for flash chip probe code");