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 if (mtd->size > map->size) { 42 printk(KERN_WARNING "Reducing visibility of %ldKiB chip to %ldKiB\n", 43 (unsigned long)mtd->size >> 10, 44 (unsigned long)map->size >> 10); 45 mtd->size = map->size; 46 } 47 return mtd; 48 } 49 50 printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n"); 51 52 kfree(cfi->cfiq); 53 kfree(cfi); 54 map->fldrv_priv = NULL; 55 return NULL; 56 } 57 EXPORT_SYMBOL(mtd_do_chip_probe); 58 59 60 static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp) 61 { 62 struct cfi_private cfi; 63 struct cfi_private *retcfi; 64 unsigned long *chip_map; 65 int i, j, mapsize; 66 int max_chips; 67 68 memset(&cfi, 0, sizeof(cfi)); 69 70 /* Call the probetype-specific code with all permutations of 71 interleave and device type, etc. */ 72 if (!genprobe_new_chip(map, cp, &cfi)) { 73 /* The probe didn't like it */ 74 printk(KERN_DEBUG "%s: Found no %s device at location zero\n", 75 cp->name, map->name); 76 return NULL; 77 } 78 79 #if 0 /* Let the CFI probe routine do this sanity check. The Intel and AMD 80 probe routines won't ever return a broken CFI structure anyway, 81 because they make them up themselves. 82 */ 83 if (cfi.cfiq->NumEraseRegions == 0) { 84 printk(KERN_WARNING "Number of erase regions is zero\n"); 85 kfree(cfi.cfiq); 86 return NULL; 87 } 88 #endif 89 cfi.chipshift = cfi.cfiq->DevSize; 90 91 if (cfi_interleave_is_1(&cfi)) { 92 ; 93 } else if (cfi_interleave_is_2(&cfi)) { 94 cfi.chipshift++; 95 } else if (cfi_interleave_is_4((&cfi))) { 96 cfi.chipshift += 2; 97 } else if (cfi_interleave_is_8(&cfi)) { 98 cfi.chipshift += 3; 99 } else { 100 BUG(); 101 } 102 103 cfi.numchips = 1; 104 105 /* 106 * Allocate memory for bitmap of valid chips. 107 * Align bitmap storage size to full byte. 108 */ 109 max_chips = map->size >> cfi.chipshift; 110 if (!max_chips) { 111 printk(KERN_WARNING "NOR chip too large to fit in mapping. Attempting to cope...\n"); 112 max_chips = 1; 113 } 114 115 mapsize = (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG; 116 chip_map = kmalloc(mapsize, GFP_KERNEL); 117 if (!chip_map) { 118 printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name); 119 kfree(cfi.cfiq); 120 return NULL; 121 } 122 memset (chip_map, 0, mapsize); 123 124 set_bit(0, chip_map); /* Mark first chip valid */ 125 126 /* 127 * Now probe for other chips, checking sensibly for aliases while 128 * we're at it. The new_chip probe above should have let the first 129 * chip in read mode. 130 */ 131 132 for (i = 1; i < max_chips; i++) { 133 cp->probe_chip(map, i << cfi.chipshift, chip_map, &cfi); 134 } 135 136 /* 137 * Now allocate the space for the structures we need to return to 138 * our caller, and copy the appropriate data into them. 139 */ 140 141 retcfi = kmalloc(sizeof(struct cfi_private) + cfi.numchips * sizeof(struct flchip), GFP_KERNEL); 142 143 if (!retcfi) { 144 printk(KERN_WARNING "%s: kmalloc failed for CFI private structure\n", map->name); 145 kfree(cfi.cfiq); 146 kfree(chip_map); 147 return NULL; 148 } 149 150 memcpy(retcfi, &cfi, sizeof(cfi)); 151 memset(&retcfi->chips[0], 0, sizeof(struct flchip) * cfi.numchips); 152 153 for (i = 0, j = 0; (j < cfi.numchips) && (i < max_chips); i++) { 154 if(test_bit(i, chip_map)) { 155 struct flchip *pchip = &retcfi->chips[j++]; 156 157 pchip->start = (i << cfi.chipshift); 158 pchip->state = FL_READY; 159 init_waitqueue_head(&pchip->wq); 160 spin_lock_init(&pchip->_spinlock); 161 pchip->mutex = &pchip->_spinlock; 162 } 163 } 164 165 kfree(chip_map); 166 return retcfi; 167 } 168 169 170 static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp, 171 struct cfi_private *cfi) 172 { 173 int min_chips = (map_bankwidth(map)/4?:1); /* At most 4-bytes wide. */ 174 int max_chips = map_bankwidth(map); /* And minimum 1 */ 175 int nr_chips, type; 176 177 for (nr_chips = max_chips; nr_chips >= min_chips; nr_chips >>= 1) { 178 179 if (!cfi_interleave_supported(nr_chips)) 180 continue; 181 182 cfi->interleave = nr_chips; 183 184 /* Minimum device size. Don't look for one 8-bit device 185 in a 16-bit bus, etc. */ 186 type = map_bankwidth(map) / nr_chips; 187 188 for (; type <= CFI_DEVICETYPE_X32; type<<=1) { 189 cfi->device_type = type; 190 191 if (cp->probe_chip(map, 0, NULL, cfi)) 192 return 1; 193 } 194 } 195 return 0; 196 } 197 198 typedef struct mtd_info *cfi_cmdset_fn_t(struct map_info *, int); 199 200 extern cfi_cmdset_fn_t cfi_cmdset_0001; 201 extern cfi_cmdset_fn_t cfi_cmdset_0002; 202 extern cfi_cmdset_fn_t cfi_cmdset_0020; 203 204 static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map, 205 int primary) 206 { 207 struct cfi_private *cfi = map->fldrv_priv; 208 __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID; 209 #ifdef CONFIG_MODULES 210 char probename[16+sizeof(MODULE_SYMBOL_PREFIX)]; 211 cfi_cmdset_fn_t *probe_function; 212 213 sprintf(probename, MODULE_SYMBOL_PREFIX "cfi_cmdset_%4.4X", type); 214 215 probe_function = __symbol_get(probename); 216 if (!probe_function) { 217 request_module(probename + sizeof(MODULE_SYMBOL_PREFIX) - 1); 218 probe_function = __symbol_get(probename); 219 } 220 221 if (probe_function) { 222 struct mtd_info *mtd; 223 224 mtd = (*probe_function)(map, primary); 225 /* If it was happy, it'll have increased its own use count */ 226 symbol_put_addr(probe_function); 227 return mtd; 228 } 229 #endif 230 printk(KERN_NOTICE "Support for command set %04X not present\n", type); 231 232 return NULL; 233 } 234 235 static struct mtd_info *check_cmd_set(struct map_info *map, int primary) 236 { 237 struct cfi_private *cfi = map->fldrv_priv; 238 __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID; 239 240 if (type == P_ID_NONE || type == P_ID_RESERVED) 241 return NULL; 242 243 switch(type){ 244 /* We need these for the !CONFIG_MODULES case, 245 because symbol_get() doesn't work there */ 246 #ifdef CONFIG_MTD_CFI_INTELEXT 247 case 0x0001: 248 case 0x0003: 249 case 0x0200: 250 return cfi_cmdset_0001(map, primary); 251 #endif 252 #ifdef CONFIG_MTD_CFI_AMDSTD 253 case 0x0002: 254 return cfi_cmdset_0002(map, primary); 255 #endif 256 #ifdef CONFIG_MTD_CFI_STAA 257 case 0x0020: 258 return cfi_cmdset_0020(map, primary); 259 #endif 260 default: 261 return cfi_cmdset_unknown(map, primary); 262 } 263 } 264 265 MODULE_LICENSE("GPL"); 266 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 267 MODULE_DESCRIPTION("Helper routines for flash chip probe code"); 268