2 Common Flash Interface probe code.
3 (C) 2000 Red Hat. GPL'd.
4 $Id: cfi_probe.c,v 1.12 2000/07/03 13:29:16 dwmw2 Exp $
8 #include <linux/module.h>
9 #include <linux/types.h>
10 #include <linux/kernel.h>
12 #include <asm/byteorder.h>
13 #include <linux/errno.h>
14 #include <linux/malloc.h>
16 #include <linux/mtd/map.h>
17 #include <linux/mtd/cfi.h>
20 struct mtd_info
*cfi_probe(struct map_info
*);
21 EXPORT_SYMBOL(cfi_probe
);
23 static void print_cfi_ident(struct cfi_ident
*);
24 static void check_cmd_set(struct map_info
*, int, unsigned long);
25 static struct cfi_private
*cfi_cfi_probe(struct map_info
*);
27 struct mtd_info
*cfi_probe(struct map_info
*map
)
29 struct mtd_info
*mtd
= NULL
;
30 struct cfi_private
*cfi
;
31 /* First probe the map to see if we have CFI stuff there. */
32 cfi
= cfi_cfi_probe(map
);
37 map
->fldrv_priv
= cfi
;
39 /* OK we liked it. Now find a driver for the command set it talks */
41 check_cmd_set(map
, 1, cfi
->chips
[0].start
); /* First the primary cmdset */
42 check_cmd_set(map
, 0, cfi
->chips
[0].start
); /* Then the secondary */
44 /* check_cmd_set() will have used get_module_symbol to increase
45 the use count of the module which provides the command set
46 driver. If we're quitting, we have to decrease it again.
49 if(cfi
->cmdset_setup
) {
50 mtd
= cfi
->cmdset_setup(map
);
54 put_module_symbol((unsigned long)cfi
->cmdset_setup
);
56 printk("No supported Vendor Command Set found\n");
59 map
->fldrv_priv
= NULL
;
64 static int cfi_probe_new_chip(struct map_info
*map
, unsigned long base
,
65 struct flchip
*chips
, struct cfi_private
*cfi
)
67 switch (map
->buswidth
) {
70 unsigned char tmp
= map
->read8(map
, base
+ 0x55);
72 /* If there's a device there, put it in Query Mode */
73 map
->write8(map
, 0x98, base
+0x55);
75 if (map
->read8(map
,base
+0x10) == 'Q' &&
76 map
->read8(map
,base
+0x11) == 'R' &&
77 map
->read8(map
,base
+0x12) == 'Y') {
78 printk("%s: Found a CFI device at 0x%lx in 8 bit mode\n", map
->name
, base
);
80 /* Check previous chips for aliases */
81 printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__
);
82 /* Put it back into Read Mode */
83 map
->write8(map
, 0x98, base
+0x55);
87 if (map
->read8(map
, base
+ 0x55) == 0x98) {
88 /* It looks like RAM. Put back the stuff we overwrote */
89 map
->write8(map
, tmp
, base
+0x55);
96 __u16 tmp
= map
->read16(map
, base
+ 0xaa);
98 /* If there's a device there, put it into Query Mode */
99 map
->write16(map
, 0x9898, base
+0xAA);
101 if (map
->read16(map
, base
+0x20) == cpu_to_le16(0x0051) &&
102 map
->read16(map
, base
+0x22) == cpu_to_le16(0x0052) &&
103 map
->read16(map
, base
+0x24) == cpu_to_le16(0x0059)) {
104 printk("%s: Found a CFI device at 0x%lx in 16 bit mode\n", map
->name
, base
);
106 /* Check previous chips for aliases */
109 for (i
=0; i
< cfi
->numchips
; i
++) {
110 /* This chip should be in read mode if it's one
111 we've already touched. */
112 if (map
->read16(map
, chips
[i
].start
+0x20) == cpu_to_le16(0x0051) &&
113 map
->read16(map
, chips
[i
].start
+0x22) == cpu_to_le16(0x0052) &&
114 map
->read16(map
, chips
[i
].start
+0x24) == cpu_to_le16(0x0059)){
115 /* Either the old chip has got 'Q''R''Y' in a most
116 unfortunate place, or it's an alias of the new
117 chip. Double-check that it's in read mode, and check. */
118 map
->write16(map
, 0xffff, chips
[i
].start
+0x20);
119 if (map
->read16(map
, chips
[i
].start
+0x20) == cpu_to_le16(0x0051) &&
120 map
->read16(map
, chips
[i
].start
+0x22) == cpu_to_le16(0x0052) &&
121 map
->read16(map
, chips
[i
].start
+0x24) == cpu_to_le16(0x0059)) {
122 /* Yes it's got QRY for data. Most unfortunate.
123 Stick the old one in read mode too. */
124 map
->write16(map
, 0xffff, base
);
125 if (map
->read16(map
, base
+0x20) == cpu_to_le16(0x0051) &&
126 map
->read16(map
, base
+0x22) == cpu_to_le16(0x0052) &&
127 map
->read16(map
, base
+0x24) == cpu_to_le16(0x0059)) {
128 /* OK, so has the new one. Assume it's an alias */
129 printk("T'was probably an alias for the chip at 0x%lx\n", chips
[i
].start
);
131 } /* else no, they're different, fall through. */
133 /* No the old one hasn't got QRY for data. Therefore,
134 it's an alias of the new one. */
135 map
->write16(map
, 0xffff, base
+0xaa);
136 /* Just to be paranoid. */
137 map
->write16(map
, 0xffff, chips
[i
].start
+0xaa);
138 printk("T'was an alias for the chip at 0x%lx\n", chips
[i
].start
);
142 /* No, the old one didn't look like it's in query mode. Next. */
145 /* OK, if we got to here, then none of the previous chips appear to
146 be aliases for the current one. */
147 if (cfi
->numchips
== MAX_CFI_CHIPS
) {
148 printk("%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d.\n", map
->name
, MAX_CFI_CHIPS
);
149 /* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */
152 printk("Not an alias. Adding\n");
153 chips
[cfi
->numchips
].start
= base
;
154 chips
[cfi
->numchips
].state
= FL_READY
;
155 chips
[cfi
->numchips
].mutex
= &chips
[cfi
->numchips
]._spinlock
;
158 /* Put it back into Read Mode */
159 map
->write16(map
, 0xffff, base
+0xaa);
164 else if (map
->read16(map
, base
+0x20) == 0x5151 &&
165 map
->read16(map
, base
+0x22) == 0x5252 &&
166 map
->read16(map
, base
+0x24) == 0x5959) {
167 printk("%s: Found a coupled pair of CFI devices at %lx in 8 bit mode\n",
170 /* Check previous chips for aliases */
171 printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__
);
173 /* Put it back into Read Mode */
174 map
->write16(map
, 0xffff, base
+0xaa);
179 if (map
->read16(map
, base
+0xaa) == 0x9898) {
180 /* It looks like RAM. Put back the stuff we overwrote */
181 map
->write16(map
, tmp
, base
+0xaa);
189 __u32 tmp
= map
->read32(map
, base
+0x154);
191 /* If there's a device there, put it into Query Mode */
192 map
->write32(map
, 0x98989898, base
+0x154);
194 if (map
->read32(map
, base
+0x40) == cpu_to_le32(0x00000051) &&
195 map
->read32(map
, base
+0x44) == cpu_to_le32(0x00000052) &&
196 map
->read32(map
, base
+0x48) == cpu_to_le32(0x00000059)) {
197 /* This isn't actually in the CFI spec - only x8 and x16 are. */
198 printk("%s: Found a CFI device at %lx in 32 bit mode\n", map
->name
, base
);
200 /* Check previous chips for aliases */
201 printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__
);
203 /* Put it back into read mode */
204 map
->write32(map
, 0xffffffff, base
+0x154);
208 else if (map
->read32(map
, base
+0x40) == cpu_to_le32(0x00510051) &&
209 map
->read32(map
, base
+0x44) == cpu_to_le32(0x00520052) &&
210 map
->read32(map
, base
+0x48) == cpu_to_le32(0x00590059)) {
211 printk("%s: Found a coupled pair of CFI devices at location %lx in 16 bit mode\n", map
->name
, base
);
213 /* Check previous chips for aliases */
214 printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__
);
216 /* Put it back into read mode */
217 map
->write32(map
, 0xffffffff, base
+0x154);
221 else if (map
->read32(map
, base
+0x40) == 0x51515151 &&
222 map
->read32(map
, base
+0x44) == 0x52525252 &&
223 map
->read32(map
, base
+0x48) == 0x59595959) {
224 printk("%s: Found four side-by-side CFI devices at location %lx in 8 bit mode\n", map
->name
, base
);
226 /* Check previous chips for aliases */
227 printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__
);
229 /* Put it back into read mode */
230 map
->write32(map
, 0xffffffff, base
+0x154);
234 if (map
->read32(map
, base
+0x154) == 0x98989898) {
235 /* It looks like RAM. Put back the stuff we overwrote */
236 map
->write32(map
, tmp
, base
+0x154);
242 printk(KERN_WARNING
"cfi_cfi_probe called with strange buswidth %d\n", map
->buswidth
);
247 static struct cfi_private
*cfi_cfi_probe(struct map_info
*map
)
249 unsigned long base
=0;
250 struct cfi_private cfi
;
251 struct cfi_private
*retcfi
;
252 struct flchip chip
[MAX_CFI_CHIPS
];
255 memset(&cfi
, 0, sizeof(cfi
));
257 /* The first invocation (with chips == NULL) leaves the device in Query Mode */
258 cfi
.interleave
= cfi_probe_new_chip(map
, 0, NULL
, NULL
);
260 if (!cfi
.interleave
) {
261 printk("%s: Found no CFI device at location zero\n", map
->name
);
262 /* Doesn't appear to be CFI-compliant at all */
266 /* Read the Basic Query Structure from the device */
268 for (i
=0; i
<sizeof(struct cfi_ident
); i
++) {
269 ((unsigned char *)&cfi
.cfiq
)[i
] = map
->read8(map
,base
+ ((0x10 + i
)*map
->buswidth
));
272 /* Do any necessary byteswapping */
273 cfi
.cfiq
.P_ID
= le16_to_cpu(cfi
.cfiq
.P_ID
);
274 cfi
.cfiq
.P_ADR
= le16_to_cpu(cfi
.cfiq
.P_ADR
);
275 cfi
.cfiq
.A_ID
= le16_to_cpu(cfi
.cfiq
.A_ID
);
276 cfi
.cfiq
.A_ADR
= le16_to_cpu(cfi
.cfiq
.A_ADR
);
277 cfi
.cfiq
.InterfaceDesc
= le16_to_cpu(cfi
.cfiq
.InterfaceDesc
);
278 cfi
.cfiq
.MaxBufWriteSize
= le16_to_cpu(cfi
.cfiq
.MaxBufWriteSize
);
281 /* Dump the information therein */
282 print_cfi_ident(&cfi
.cfiq
);
284 for (i
=0; i
<cfi
.cfiq
.NumEraseRegions
; i
++) {
285 __u16 EraseRegionInfoNum
= (map
->read8(map
,base
+ ((0x2d + (4*i
))*map
->buswidth
))) +
286 (((map
->read8(map
,(0x2e + (4*i
))*map
->buswidth
)) << 8));
287 __u16 EraseRegionInfoSize
= (map
->read8(map
, base
+ ((0x2f + (4*i
))*map
->buswidth
))) +
288 (map
->read8(map
, base
+ ((0x30 + (4*i
))*map
->buswidth
)) << 8);
290 printk(" Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n",
291 i
, EraseRegionInfoSize
* 256, EraseRegionInfoNum
+1);
297 /* Switch the chip back into Read Mode, to make the alias detection work */
298 switch(map
->buswidth
) {
300 map
->write8(map
, 0xff, 0x55);
303 map
->write16(map
, 0xffff, 0xaa);
306 map
->write32(map
, 0xffffffff, 0x154);
310 /* OK. We've worked out what it is and we're happy with it. Now see if there are others */
313 chip
[0].state
= FL_READY
;
314 chip
[0].mutex
= &chip
[0]._spinlock
;
316 cfi
.chipshift
= cfi
.cfiq
.DevSize
;
319 if (!cfi
.chipshift
) {
320 printk("cfi.chipsize is zero. This is bad. cfi.cfiq.DevSize is %d\n", cfi
.cfiq
.DevSize
);
324 for (base
= (1<<cfi
.chipshift
); base
< map
->size
; base
+= (1<<cfi
.chipshift
))
325 cfi_probe_new_chip(map
, base
, &chip
[0], &cfi
);
327 retcfi
= kmalloc(sizeof(struct cfi_private
) + cfi
.numchips
* sizeof(struct flchip
), GFP_KERNEL
);
332 memcpy(retcfi
, &cfi
, sizeof(cfi
));
333 memcpy(&retcfi
->chips
[0], chip
, sizeof(struct flchip
) * cfi
.numchips
);
334 for (i
=0; i
< retcfi
->numchips
; i
++) {
335 init_waitqueue_head(&retcfi
->chips
[i
].wq
);
336 spin_lock_init(&retcfi
->chips
[i
]._spinlock
);
341 static char *vendorname(__u16 vendor
)
348 return "Intel/Sharp Extended";
351 return "AMD/Fujitsu Standard";
354 return "Intel/Sharp Standard";
357 return "AMD/Fujitsu Extended";
359 case P_ID_MITSUBISHI_STD
:
360 return "Mitsubishi Standard";
362 case P_ID_MITSUBISHI_EXT
:
363 return "Mitsubishi Extended";
366 return "Not Allowed / Reserved for Future Use";
374 static void print_cfi_ident(struct cfi_ident
*cfip
)
376 if (cfip
->qry
[0] != 'Q' || cfip
->qry
[1] != 'R' || cfip
->qry
[2] != 'Y') {
377 printk("Invalid CFI ident structure.\n");
381 printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip
->P_ID
, vendorname(cfip
->P_ID
));
383 printk("Primary Algorithm Table at %4.4X\n", cfip
->P_ADR
);
385 printk("No Primary Algorithm Table\n");
387 printk("Alternative Vendor Command Set: %4.4X (%s)\n", cfip
->A_ID
, vendorname(cfip
->A_ID
));
389 printk("Alternate Algorithm Table at %4.4X\n", cfip
->A_ADR
);
391 printk("No Alternate Algorithm Table\n");
394 printk("Vcc Minimum: %x.%x V\n", cfip
->VccMin
>> 4, cfip
->VccMin
& 0xf);
395 printk("Vcc Maximum: %x.%x V\n", cfip
->VccMax
>> 4, cfip
->VccMax
& 0xf);
397 printk("Vpp Minimum: %x.%x V\n", cfip
->VppMin
>> 4, cfip
->VppMin
& 0xf);
398 printk("Vpp Maximum: %x.%x V\n", cfip
->VppMax
>> 4, cfip
->VppMax
& 0xf);
401 printk("No Vpp line\n");
403 printk("Typical byte/word write timeout: %d µs\n", 1<<cfip
->WordWriteTimeoutTyp
);
404 printk("Maximum byte/word write timeout: %d µs\n", (1<<cfip
->WordWriteTimeoutMax
) * (1<<cfip
->WordWriteTimeoutTyp
));
406 if (cfip
->BufWriteTimeoutTyp
|| cfip
->BufWriteTimeoutMax
) {
407 printk("Typical full buffer write timeout: %d µs\n", 1<<cfip
->BufWriteTimeoutTyp
);
408 printk("Maximum full buffer write timeout: %d µs\n", (1<<cfip
->BufWriteTimeoutMax
) * (1<<cfip
->BufWriteTimeoutTyp
));
411 printk("Full buffer write not supported\n");
413 printk("Typical block erase timeout: %d µs\n", 1<<cfip
->BlockEraseTimeoutTyp
);
414 printk("Maximum block erase timeout: %d µs\n", (1<<cfip
->BlockEraseTimeoutMax
) * (1<<cfip
->BlockEraseTimeoutTyp
));
415 if (cfip
->ChipEraseTimeoutTyp
|| cfip
->ChipEraseTimeoutMax
) {
416 printk("Typical chip erase timeout: %d µs\n", 1<<cfip
->ChipEraseTimeoutTyp
);
417 printk("Maximum chip erase timeout: %d µs\n", (1<<cfip
->ChipEraseTimeoutMax
) * (1<<cfip
->ChipEraseTimeoutTyp
));
420 printk("Chip erase not supported\n");
422 printk("Device size: 0x%X bytes (%d Mb)\n", 1 << cfip
->DevSize
, 1<< (cfip
->DevSize
- 20));
423 printk("Flash Device Interface description: 0x%4.4X\n", cfip
->InterfaceDesc
);
424 switch(cfip
->InterfaceDesc
) {
426 printk(" - x8-only asynchronous interface\n");
430 printk(" - x16-only asynchronous interface\n");
434 printk(" - supports x8 and x16 via BYTE# with asynchronous interface\n");
438 printk(" - x32-only asynchronous interface\n");
442 printk(" - Not Allowed / Reserved\n");
446 printk(" - Unknown\n");
450 printk("Max. bytes in buffer write: 0x%x\n", 1<< cfip
->MaxBufWriteSize
);
451 printk("Number of Erase Block Regions: %d\n", cfip
->NumEraseRegions
);
455 static void check_cmd_set(struct map_info
*map
, int primary
, unsigned long base
)
458 struct cfi_private
*cfi
= map
->fldrv_priv
;
459 __u16 type
= primary
?cfi
->cfiq
.P_ID
:cfi
->cfiq
.A_ID
;
461 void (*probe_function
)(struct map_info
*, int, unsigned long);
463 if (type
== P_ID_NONE
|| type
== P_ID_RESERVED
)
466 sprintf(probename
, "cfi_cmdset_%4.4X", type
);
468 probe_function
= (void *)get_module_symbol(NULL
, probename
);
469 if (!probe_function
) {
470 request_module(probename
);
472 probe_function
= (void *)get_module_symbol(NULL
, probename
);
475 if (probe_function
) {
476 (*probe_function
)(map
, primary
, base
);
477 put_module_symbol((unsigned long)probe_function
);
481 /* This was a command set we don't know about. Print only the basic info */
482 adr
= primary
?cfi
->cfiq
.P_ADR
:cfi
->cfiq
.A_ADR
;
485 printk(" No Extended Query Table\n");
487 else if (map
->read8(map
,base
+(adr
*map
->buswidth
)) != (primary
?'P':'A') ||
488 map
->read8(map
,base
+((adr
+1)*map
->buswidth
)) != (primary
?'R':'L') ||
489 map
->read8(map
,base
+((adr
+2)*map
->buswidth
)) != (primary
?'I':'T')) {
490 printk ("Invalid Extended Query Table at %4.4X: %2.2X %2.2X %2.2X\n",
492 map
->read8(map
,base
+(adr
*map
->buswidth
)),
493 map
->read8(map
,base
+((adr
+1)*map
->buswidth
)),
494 map
->read8(map
,base
+((adr
+2)*map
->buswidth
)));
497 printk(" Extended Query Table version %c.%c\n",
498 map
->read8(map
,base
+((adr
+3)*map
->buswidth
)),
499 map
->read8(map
,base
+((adr
+4)*map
->buswidth
)));