2 * Routines common to all CFI-type probes.
3 * (C) 2001-2003 Red Hat, Inc.
5 * $Id: gen_probe.c,v 1.24 2005/11/07 11:14:23 gleixner Exp $
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>
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
);
22 struct mtd_info
*mtd_do_chip_probe(struct map_info
*map
, struct chip_probe
*cp
)
24 struct mtd_info
*mtd
= NULL
;
25 struct cfi_private
*cfi
;
27 /* First probe the map to see if we have CFI stuff there. */
28 cfi
= genprobe_ident_chips(map
, cp
);
33 map
->fldrv_priv
= cfi
;
34 /* OK we liked it. Now find a driver for the command set it talks */
36 mtd
= check_cmd_set(map
, 1); /* First the primary cmdset */
38 mtd
= check_cmd_set(map
, 0); /* Then the secondary */
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
;
50 printk(KERN_WARNING
"gen_probe: No supported Vendor Command Set found\n");
54 map
->fldrv_priv
= NULL
;
57 EXPORT_SYMBOL(mtd_do_chip_probe
);
60 static struct cfi_private
*genprobe_ident_chips(struct map_info
*map
, struct chip_probe
*cp
)
62 struct cfi_private cfi
;
63 struct cfi_private
*retcfi
;
64 unsigned long *chip_map
;
68 memset(&cfi
, 0, sizeof(cfi
));
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",
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.
83 if (cfi
.cfiq
->NumEraseRegions
== 0) {
84 printk(KERN_WARNING
"Number of erase regions is zero\n");
89 cfi
.chipshift
= cfi
.cfiq
->DevSize
;
91 if (cfi_interleave_is_1(&cfi
)) {
93 } else if (cfi_interleave_is_2(&cfi
)) {
95 } else if (cfi_interleave_is_4((&cfi
))) {
97 } else if (cfi_interleave_is_8(&cfi
)) {
106 * Allocate memory for bitmap of valid chips.
107 * Align bitmap storage size to full byte.
109 max_chips
= map
->size
>> cfi
.chipshift
;
111 printk(KERN_WARNING
"NOR chip too large to fit in mapping. Attempting to cope...\n");
115 mapsize
= (max_chips
+ BITS_PER_LONG
-1) / BITS_PER_LONG
;
116 chip_map
= kzalloc(mapsize
, GFP_KERNEL
);
118 printk(KERN_WARNING
"%s: kmalloc failed for CFI chip map\n", map
->name
);
123 set_bit(0, chip_map
); /* Mark first chip valid */
126 * Now probe for other chips, checking sensibly for aliases while
127 * we're at it. The new_chip probe above should have let the first
131 for (i
= 1; i
< max_chips
; i
++) {
132 cp
->probe_chip(map
, i
<< cfi
.chipshift
, chip_map
, &cfi
);
136 * Now allocate the space for the structures we need to return to
137 * our caller, and copy the appropriate data into them.
140 retcfi
= kmalloc(sizeof(struct cfi_private
) + cfi
.numchips
* sizeof(struct flchip
), GFP_KERNEL
);
143 printk(KERN_WARNING
"%s: kmalloc failed for CFI private structure\n", map
->name
);
149 memcpy(retcfi
, &cfi
, sizeof(cfi
));
150 memset(&retcfi
->chips
[0], 0, sizeof(struct flchip
) * cfi
.numchips
);
152 for (i
= 0, j
= 0; (j
< cfi
.numchips
) && (i
< max_chips
); i
++) {
153 if(test_bit(i
, chip_map
)) {
154 struct flchip
*pchip
= &retcfi
->chips
[j
++];
156 pchip
->start
= (i
<< cfi
.chipshift
);
157 pchip
->state
= FL_READY
;
158 init_waitqueue_head(&pchip
->wq
);
159 spin_lock_init(&pchip
->_spinlock
);
160 pchip
->mutex
= &pchip
->_spinlock
;
169 static int genprobe_new_chip(struct map_info
*map
, struct chip_probe
*cp
,
170 struct cfi_private
*cfi
)
172 int min_chips
= (map_bankwidth(map
)/4?:1); /* At most 4-bytes wide. */
173 int max_chips
= map_bankwidth(map
); /* And minimum 1 */
176 for (nr_chips
= max_chips
; nr_chips
>= min_chips
; nr_chips
>>= 1) {
178 if (!cfi_interleave_supported(nr_chips
))
181 cfi
->interleave
= nr_chips
;
183 /* Minimum device size. Don't look for one 8-bit device
184 in a 16-bit bus, etc. */
185 type
= map_bankwidth(map
) / nr_chips
;
187 for (; type
<= CFI_DEVICETYPE_X32
; type
<<=1) {
188 cfi
->device_type
= type
;
190 if (cp
->probe_chip(map
, 0, NULL
, cfi
))
197 typedef struct mtd_info
*cfi_cmdset_fn_t(struct map_info
*, int);
199 extern cfi_cmdset_fn_t cfi_cmdset_0001
;
200 extern cfi_cmdset_fn_t cfi_cmdset_0002
;
201 extern cfi_cmdset_fn_t cfi_cmdset_0020
;
203 static inline struct mtd_info
*cfi_cmdset_unknown(struct map_info
*map
,
206 struct cfi_private
*cfi
= map
->fldrv_priv
;
207 __u16 type
= primary
?cfi
->cfiq
->P_ID
:cfi
->cfiq
->A_ID
;
208 #ifdef CONFIG_MODULES
209 char probename
[16+sizeof(MODULE_SYMBOL_PREFIX
)];
210 cfi_cmdset_fn_t
*probe_function
;
212 sprintf(probename
, MODULE_SYMBOL_PREFIX
"cfi_cmdset_%4.4X", type
);
214 probe_function
= __symbol_get(probename
);
215 if (!probe_function
) {
216 request_module(probename
+ sizeof(MODULE_SYMBOL_PREFIX
) - 1);
217 probe_function
= __symbol_get(probename
);
220 if (probe_function
) {
221 struct mtd_info
*mtd
;
223 mtd
= (*probe_function
)(map
, primary
);
224 /* If it was happy, it'll have increased its own use count */
225 symbol_put_addr(probe_function
);
229 printk(KERN_NOTICE
"Support for command set %04X not present\n", type
);
234 static struct mtd_info
*check_cmd_set(struct map_info
*map
, int primary
)
236 struct cfi_private
*cfi
= map
->fldrv_priv
;
237 __u16 type
= primary
?cfi
->cfiq
->P_ID
:cfi
->cfiq
->A_ID
;
239 if (type
== P_ID_NONE
|| type
== P_ID_RESERVED
)
243 /* We need these for the !CONFIG_MODULES case,
244 because symbol_get() doesn't work there */
245 #ifdef CONFIG_MTD_CFI_INTELEXT
249 return cfi_cmdset_0001(map
, primary
);
251 #ifdef CONFIG_MTD_CFI_AMDSTD
253 return cfi_cmdset_0002(map
, primary
);
255 #ifdef CONFIG_MTD_CFI_STAA
257 return cfi_cmdset_0020(map
, primary
);
260 return cfi_cmdset_unknown(map
, primary
);
264 MODULE_LICENSE("GPL");
265 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
266 MODULE_DESCRIPTION("Helper routines for flash chip probe code");