1 /* 2 * Routines common to all CFI-type probes. 3 * (C) 2001-2003 Red Hat, Inc. 4 * GPL'd 5 * $Id: gen_probe.c,v 1.24 2005/11/07 11:14:23 gleixner Exp $ 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/slab.h> 10 #include <linux/module.h> 11 #include <linux/mtd/mtd.h> 12 #include <linux/mtd/map.h> 13 #include <linux/mtd/cfi.h> 14 #include <linux/mtd/gen_probe.h> 15 16 static struct mtd_info *check_cmd_set(struct map_info *, int); 17 static struct cfi_private *genprobe_ident_chips(struct map_info *map, 18 struct chip_probe *cp); 19 static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp, 20 struct cfi_private *cfi); 21 22 struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp) 23 { 24 struct mtd_info *mtd = NULL; 25 struct cfi_private *cfi; 26 27 /* First probe the map to see if we have CFI stuff there. */ 28 cfi = genprobe_ident_chips(map, cp); 29 30 if (!cfi) 31 return NULL; 32 33 map->fldrv_priv = cfi; 34 /* OK we liked it. Now find a driver for the command set it talks */ 35 36 mtd = check_cmd_set(map, 1); /* First the primary cmdset */ 37 if (!mtd) 38 mtd = check_cmd_set(map, 0); /* Then the secondary */ 39 40 if (mtd) 41 return mtd; 42 43 printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n"); 44 45 kfree(cfi->cfiq); 46 kfree(cfi); 47 map->fldrv_priv = NULL; 48 return NULL; 49 } 50 EXPORT_SYMBOL(mtd_do_chip_probe); 51 52 53 static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp) 54 { 55 struct cfi_private cfi; 56 struct cfi_private *retcfi; 57 unsigned long *chip_map; 58 int i, j, mapsize; 59 int max_chips; 60 61 memset(&cfi, 0, sizeof(cfi)); 62 63 /* Call the probetype-specific code with all permutations of 64 interleave and device type, etc. */ 65 if (!genprobe_new_chip(map, cp, &cfi)) { 66 /* The probe didn't like it */ 67 printk(KERN_DEBUG "%s: Found no %s device at location zero\n", 68 cp->name, map->name); 69 return NULL; 70 } 71 72 #if 0 /* Let the CFI probe routine do this sanity check. The Intel and AMD 73 probe routines won't ever return a broken CFI structure anyway, 74 because they make them up themselves. 75 */ 76 if (cfi.cfiq->NumEraseRegions == 0) { 77 printk(KERN_WARNING "Number of erase regions is zero\n"); 78 kfree(cfi.cfiq); 79 return NULL; 80 } 81 #endif 82 cfi.chipshift = cfi.cfiq->DevSize; 83 84 if (cfi_interleave_is_1(&cfi)) { 85 ; 86 } else if (cfi_interleave_is_2(&cfi)) { 87 cfi.chipshift++; 88 } else if (cfi_interleave_is_4((&cfi))) { 89 cfi.chipshift += 2; 90 } else if (cfi_interleave_is_8(&cfi)) { 91 cfi.chipshift += 3; 92 } else { 93 BUG(); 94 } 95 96 cfi.numchips = 1; 97 98 /* 99 * Allocate memory for bitmap of valid chips. 100 * Align bitmap storage size to full byte. 101 */ 102 max_chips = map->size >> cfi.chipshift; 103 mapsize = (max_chips / 8) + ((max_chips % 8) ? 1 : 0); 104 chip_map = kmalloc(mapsize, GFP_KERNEL); 105 if (!chip_map) { 106 printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name); 107 kfree(cfi.cfiq); 108 return NULL; 109 } 110 memset (chip_map, 0, mapsize); 111 112 set_bit(0, chip_map); /* Mark first chip valid */ 113 114 /* 115 * Now probe for other chips, checking sensibly for aliases while 116 * we're at it. The new_chip probe above should have let the first 117 * chip in read mode. 118 */ 119 120 for (i = 1; i < max_chips; i++) { 121 cp->probe_chip(map, i << cfi.chipshift, chip_map, &cfi); 122 } 123 124 /* 125 * Now allocate the space for the structures we need to return to 126 * our caller, and copy the appropriate data into them. 127 */ 128 129 retcfi = kmalloc(sizeof(struct cfi_private) + cfi.numchips * sizeof(struct flchip), GFP_KERNEL); 130 131 if (!retcfi) { 132 printk(KERN_WARNING "%s: kmalloc failed for CFI private structure\n", map->name); 133 kfree(cfi.cfiq); 134 kfree(chip_map); 135 return NULL; 136 } 137 138 memcpy(retcfi, &cfi, sizeof(cfi)); 139 memset(&retcfi->chips[0], 0, sizeof(struct flchip) * cfi.numchips); 140 141 for (i = 0, j = 0; (j < cfi.numchips) && (i < max_chips); i++) { 142 if(test_bit(i, chip_map)) { 143 struct flchip *pchip = &retcfi->chips[j++]; 144 145 pchip->start = (i << cfi.chipshift); 146 pchip->state = FL_READY; 147 init_waitqueue_head(&pchip->wq); 148 spin_lock_init(&pchip->_spinlock); 149 pchip->mutex = &pchip->_spinlock; 150 } 151 } 152 153 kfree(chip_map); 154 return retcfi; 155 } 156 157 158 static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp, 159 struct cfi_private *cfi) 160 { 161 int min_chips = (map_bankwidth(map)/4?:1); /* At most 4-bytes wide. */ 162 int max_chips = map_bankwidth(map); /* And minimum 1 */ 163 int nr_chips, type; 164 165 for (nr_chips = max_chips; nr_chips >= min_chips; nr_chips >>= 1) { 166 167 if (!cfi_interleave_supported(nr_chips)) 168 continue; 169 170 cfi->interleave = nr_chips; 171 172 /* Minimum device size. Don't look for one 8-bit device 173 in a 16-bit bus, etc. */ 174 type = map_bankwidth(map) / nr_chips; 175 176 for (; type <= CFI_DEVICETYPE_X32; type<<=1) { 177 cfi->device_type = type; 178 179 if (cp->probe_chip(map, 0, NULL, cfi)) 180 return 1; 181 } 182 } 183 return 0; 184 } 185 186 typedef struct mtd_info *cfi_cmdset_fn_t(struct map_info *, int); 187 188 extern cfi_cmdset_fn_t cfi_cmdset_0001; 189 extern cfi_cmdset_fn_t cfi_cmdset_0002; 190 extern cfi_cmdset_fn_t cfi_cmdset_0020; 191 192 static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map, 193 int primary) 194 { 195 struct cfi_private *cfi = map->fldrv_priv; 196 __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID; 197 #if defined(CONFIG_MODULES) && defined(HAVE_INTER_MODULE) 198 char probename[32]; 199 cfi_cmdset_fn_t *probe_function; 200 201 sprintf(probename, "cfi_cmdset_%4.4X", type); 202 203 probe_function = inter_module_get_request(probename, probename); 204 205 if (probe_function) { 206 struct mtd_info *mtd; 207 208 mtd = (*probe_function)(map, primary); 209 /* If it was happy, it'll have increased its own use count */ 210 inter_module_put(probename); 211 return mtd; 212 } 213 #endif 214 printk(KERN_NOTICE "Support for command set %04X not present\n", 215 type); 216 217 return NULL; 218 } 219 220 static struct mtd_info *check_cmd_set(struct map_info *map, int primary) 221 { 222 struct cfi_private *cfi = map->fldrv_priv; 223 __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID; 224 225 if (type == P_ID_NONE || type == P_ID_RESERVED) 226 return NULL; 227 228 switch(type){ 229 /* Urgh. Ifdefs. The version with weak symbols was 230 * _much_ nicer. Shame it didn't seem to work on 231 * anything but x86, really. 232 * But we can't rely in inter_module_get() because 233 * that'd mean we depend on link order. 234 */ 235 #ifdef CONFIG_MTD_CFI_INTELEXT 236 case 0x0001: 237 case 0x0003: 238 case 0x0200: 239 return cfi_cmdset_0001(map, primary); 240 #endif 241 #ifdef CONFIG_MTD_CFI_AMDSTD 242 case 0x0002: 243 return cfi_cmdset_0002(map, primary); 244 #endif 245 #ifdef CONFIG_MTD_CFI_STAA 246 case 0x0020: 247 return cfi_cmdset_0020(map, primary); 248 #endif 249 } 250 251 return cfi_cmdset_unknown(map, primary); 252 } 253 254 MODULE_LICENSE("GPL"); 255 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 256 MODULE_DESCRIPTION("Helper routines for flash chip probe code"); 257