gen_probe.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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