Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / drivers / mtd / chips / cfi_probe.c
1 /* 
2    Common Flash Interface probe code.
3    (C) 2000 Red Hat. GPL'd.
4    $Id: cfi_probe.c,v 1.83 2004/11/16 18:19:02 nico Exp $
5 */
6
7 #include <linux/config.h>
8 #include <linux/module.h>
9 #include <linux/types.h>
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <asm/io.h>
13 #include <asm/byteorder.h>
14 #include <linux/errno.h>
15 #include <linux/slab.h>
16 #include <linux/interrupt.h>
17
18 #include <linux/mtd/xip.h>
19 #include <linux/mtd/map.h>
20 #include <linux/mtd/cfi.h>
21 #include <linux/mtd/gen_probe.h>
22
23 //#define DEBUG_CFI 
24
25 #ifdef DEBUG_CFI
26 static void print_cfi_ident(struct cfi_ident *);
27 #endif
28
29 static int cfi_probe_chip(struct map_info *map, __u32 base,
30                           unsigned long *chip_map, struct cfi_private *cfi);
31 static int cfi_chip_setup(struct map_info *map, struct cfi_private *cfi);
32
33 struct mtd_info *cfi_probe(struct map_info *map);
34
35 #ifdef CONFIG_MTD_XIP
36
37 /* only needed for short periods, so this is rather simple */
38 #define xip_disable()   local_irq_disable()
39
40 #define xip_allowed(base, map) \
41 do { \
42         (void) map_read(map, base); \
43         asm volatile (".rep 8; nop; .endr"); \
44         local_irq_enable(); \
45 } while (0)
46
47 #define xip_enable(base, map, cfi) \
48 do { \
49         cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); \
50         cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); \
51         xip_allowed(base, map); \
52 } while (0)
53
54 #define xip_disable_qry(base, map, cfi) \
55 do { \
56         xip_disable(); \
57         cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); \
58         cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); \
59         cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); \
60 } while (0)
61
62 #else
63
64 #define xip_disable()                   do { } while (0)
65 #define xip_allowed(base, map)          do { } while (0)
66 #define xip_enable(base, map, cfi)      do { } while (0)
67 #define xip_disable_qry(base, map, cfi) do { } while (0)
68
69 #endif
70
71 /* check for QRY.
72    in: interleave,type,mode
73    ret: table index, <0 for error
74  */
75 static int __xipram qry_present(struct map_info *map, __u32 base,
76                                 struct cfi_private *cfi)
77 {
78         int osf = cfi->interleave * cfi->device_type;   // scale factor
79         map_word val[3];
80         map_word qry[3];
81
82         qry[0] = cfi_build_cmd('Q', map, cfi);
83         qry[1] = cfi_build_cmd('R', map, cfi);
84         qry[2] = cfi_build_cmd('Y', map, cfi);
85
86         val[0] = map_read(map, base + osf*0x10);
87         val[1] = map_read(map, base + osf*0x11);
88         val[2] = map_read(map, base + osf*0x12);
89
90         if (!map_word_equal(map, qry[0], val[0]))
91                 return 0;
92
93         if (!map_word_equal(map, qry[1], val[1]))
94                 return 0;
95
96         if (!map_word_equal(map, qry[2], val[2]))
97                 return 0;
98
99         return 1;       // "QRY" found
100 }
101
102 static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
103                                    unsigned long *chip_map, struct cfi_private *cfi)
104 {
105         int i;
106         
107         if ((base + 0) >= map->size) {
108                 printk(KERN_NOTICE
109                         "Probe at base[0x00](0x%08lx) past the end of the map(0x%08lx)\n",
110                         (unsigned long)base, map->size -1);
111                 return 0;
112         }
113         if ((base + 0xff) >= map->size) {
114                 printk(KERN_NOTICE
115                         "Probe at base[0x55](0x%08lx) past the end of the map(0x%08lx)\n",
116                         (unsigned long)base + 0x55, map->size -1);
117                 return 0;
118         }
119
120         xip_disable();
121         cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
122         cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
123         cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
124
125         if (!qry_present(map,base,cfi)) {
126                 xip_enable(base, map, cfi);
127                 return 0;
128         }
129
130         if (!cfi->numchips) {
131                 /* This is the first time we're called. Set up the CFI 
132                    stuff accordingly and return */
133                 return cfi_chip_setup(map, cfi);
134         }
135
136         /* Check each previous chip to see if it's an alias */
137         for (i=0; i < (base >> cfi->chipshift); i++) {
138                 unsigned long start;
139                 if(!test_bit(i, chip_map)) {
140                         /* Skip location; no valid chip at this address */
141                         continue; 
142                 }
143                 start = i << cfi->chipshift;
144                 /* This chip should be in read mode if it's one
145                    we've already touched. */
146                 if (qry_present(map, start, cfi)) {
147                         /* Eep. This chip also had the QRY marker. 
148                          * Is it an alias for the new one? */
149                         cfi_send_gen_cmd(0xF0, 0, start, map, cfi, cfi->device_type, NULL);
150                         cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
151
152                         /* If the QRY marker goes away, it's an alias */
153                         if (!qry_present(map, start, cfi)) {
154                                 xip_allowed(base, map);
155                                 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
156                                        map->name, base, start);
157                                 return 0;
158                         }
159                         /* Yes, it's actually got QRY for data. Most 
160                          * unfortunate. Stick the new chip in read mode
161                          * too and if it's the same, assume it's an alias. */
162                         /* FIXME: Use other modes to do a proper check */
163                         cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
164                         cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
165                         
166                         if (qry_present(map, base, cfi)) {
167                                 xip_allowed(base, map);
168                                 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
169                                        map->name, base, start);
170                                 return 0;
171                         }
172                 }
173         }
174         
175         /* OK, if we got to here, then none of the previous chips appear to
176            be aliases for the current one. */
177         set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
178         cfi->numchips++;
179         
180         /* Put it back into Read Mode */
181         cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
182         cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
183         xip_allowed(base, map);
184
185         printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
186                map->name, cfi->interleave, cfi->device_type*8, base,
187                map->bankwidth*8);
188         
189         return 1;
190 }
191
192 static int __xipram cfi_chip_setup(struct map_info *map, 
193                                    struct cfi_private *cfi)
194 {
195         int ofs_factor = cfi->interleave*cfi->device_type;
196         __u32 base = 0;
197         int num_erase_regions = cfi_read_query(map, base + (0x10 + 28)*ofs_factor);
198         int i;
199
200         xip_enable(base, map, cfi);
201 #ifdef DEBUG_CFI
202         printk("Number of erase regions: %d\n", num_erase_regions);
203 #endif
204         if (!num_erase_regions)
205                 return 0;
206
207         cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
208         if (!cfi->cfiq) {
209                 printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
210                 return 0;
211         }
212         
213         memset(cfi->cfiq,0,sizeof(struct cfi_ident));   
214         
215         cfi->cfi_mode = CFI_MODE_CFI;
216         
217         /* Read the CFI info structure */
218         xip_disable_qry(base, map, cfi);
219         for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++)
220                 ((unsigned char *)cfi->cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor);
221
222         /* Note we put the device back into Read Mode BEFORE going into Auto
223          * Select Mode, as some devices support nesting of modes, others
224          * don't. This way should always work.
225          * On cmdset 0001 the writes of 0xaa and 0x55 are not needed, and
226          * so should be treated as nops or illegal (and so put the device
227          * back into Read Mode, which is a nop in this case).
228          */
229         cfi_send_gen_cmd(0xf0,     0, base, map, cfi, cfi->device_type, NULL);
230         cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL);
231         cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL);
232         cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL);
233         cfi->mfr = cfi_read_query(map, base);
234         cfi->id = cfi_read_query(map, base + ofs_factor);    
235
236         /* Put it back into Read Mode */
237         cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
238         /* ... even if it's an Intel chip */
239         cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
240         xip_allowed(base, map);
241
242         /* Do any necessary byteswapping */
243         cfi->cfiq->P_ID = le16_to_cpu(cfi->cfiq->P_ID);
244
245         cfi->cfiq->P_ADR = le16_to_cpu(cfi->cfiq->P_ADR);
246         cfi->cfiq->A_ID = le16_to_cpu(cfi->cfiq->A_ID);
247         cfi->cfiq->A_ADR = le16_to_cpu(cfi->cfiq->A_ADR);
248         cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc);
249         cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize);
250
251 #ifdef DEBUG_CFI
252         /* Dump the information therein */
253         print_cfi_ident(cfi->cfiq);
254 #endif
255
256         for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
257                 cfi->cfiq->EraseRegionInfo[i] = le32_to_cpu(cfi->cfiq->EraseRegionInfo[i]);
258                 
259 #ifdef DEBUG_CFI                
260                 printk("  Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n",
261                        i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff, 
262                        (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1);
263 #endif
264         }
265
266         printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
267                map->name, cfi->interleave, cfi->device_type*8, base,
268                map->bankwidth*8);
269
270         return 1;
271 }
272
273 #ifdef DEBUG_CFI
274 static char *vendorname(__u16 vendor) 
275 {
276         switch (vendor) {
277         case P_ID_NONE:
278                 return "None";
279                 
280         case P_ID_INTEL_EXT:
281                 return "Intel/Sharp Extended";
282                 
283         case P_ID_AMD_STD:
284                 return "AMD/Fujitsu Standard";
285                 
286         case P_ID_INTEL_STD:
287                 return "Intel/Sharp Standard";
288                 
289         case P_ID_AMD_EXT:
290                 return "AMD/Fujitsu Extended";
291
292         case P_ID_WINBOND:
293                 return "Winbond Standard";
294                 
295         case P_ID_ST_ADV:
296                 return "ST Advanced";
297
298         case P_ID_MITSUBISHI_STD:
299                 return "Mitsubishi Standard";
300                 
301         case P_ID_MITSUBISHI_EXT:
302                 return "Mitsubishi Extended";
303
304         case P_ID_SST_PAGE:
305                 return "SST Page Write";
306
307         case P_ID_INTEL_PERFORMANCE:
308                 return "Intel Performance Code";
309                 
310         case P_ID_INTEL_DATA:
311                 return "Intel Data";
312                 
313         case P_ID_RESERVED:
314                 return "Not Allowed / Reserved for Future Use";
315                 
316         default:
317                 return "Unknown";
318         }
319 }
320
321
322 static void print_cfi_ident(struct cfi_ident *cfip)
323 {
324 #if 0
325         if (cfip->qry[0] != 'Q' || cfip->qry[1] != 'R' || cfip->qry[2] != 'Y') {
326                 printk("Invalid CFI ident structure.\n");
327                 return;
328         }       
329 #endif          
330         printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip->P_ID, vendorname(cfip->P_ID));
331         if (cfip->P_ADR)
332                 printk("Primary Algorithm Table at %4.4X\n", cfip->P_ADR);
333         else
334                 printk("No Primary Algorithm Table\n");
335         
336         printk("Alternative Vendor Command Set: %4.4X (%s)\n", cfip->A_ID, vendorname(cfip->A_ID));
337         if (cfip->A_ADR)
338                 printk("Alternate Algorithm Table at %4.4X\n", cfip->A_ADR);
339         else
340                 printk("No Alternate Algorithm Table\n");
341                 
342                 
343         printk("Vcc Minimum: %2d.%d V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf);
344         printk("Vcc Maximum: %2d.%d V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf);
345         if (cfip->VppMin) {
346                 printk("Vpp Minimum: %2d.%d V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf);
347                 printk("Vpp Maximum: %2d.%d V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf);
348         }
349         else
350                 printk("No Vpp line\n");
351         
352         printk("Typical byte/word write timeout: %d µs\n", 1<<cfip->WordWriteTimeoutTyp);
353         printk("Maximum byte/word write timeout: %d µs\n", (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
354         
355         if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) {
356                 printk("Typical full buffer write timeout: %d µs\n", 1<<cfip->BufWriteTimeoutTyp);
357                 printk("Maximum full buffer write timeout: %d µs\n", (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
358         }
359         else
360                 printk("Full buffer write not supported\n");
361         
362         printk("Typical block erase timeout: %d ms\n", 1<<cfip->BlockEraseTimeoutTyp);
363         printk("Maximum block erase timeout: %d ms\n", (1<<cfip->BlockEraseTimeoutMax) * (1<<cfip->BlockEraseTimeoutTyp));
364         if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) {
365                 printk("Typical chip erase timeout: %d ms\n", 1<<cfip->ChipEraseTimeoutTyp); 
366                 printk("Maximum chip erase timeout: %d ms\n", (1<<cfip->ChipEraseTimeoutMax) * (1<<cfip->ChipEraseTimeoutTyp));
367         }
368         else
369                 printk("Chip erase not supported\n");
370         
371         printk("Device size: 0x%X bytes (%d MiB)\n", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20));
372         printk("Flash Device Interface description: 0x%4.4X\n", cfip->InterfaceDesc);
373         switch(cfip->InterfaceDesc) {
374         case 0:
375                 printk("  - x8-only asynchronous interface\n");
376                 break;
377                 
378         case 1:
379                 printk("  - x16-only asynchronous interface\n");
380                 break;
381                 
382         case 2:
383                 printk("  - supports x8 and x16 via BYTE# with asynchronous interface\n");
384                 break;
385                 
386         case 3:
387                 printk("  - x32-only asynchronous interface\n");
388                 break;
389                 
390         case 4:
391                 printk("  - supports x16 and x32 via Word# with asynchronous interface\n");
392                 break;
393                 
394         case 65535:
395                 printk("  - Not Allowed / Reserved\n");
396                 break;
397                 
398         default:
399                 printk("  - Unknown\n");
400                 break;
401         }
402         
403         printk("Max. bytes in buffer write: 0x%x\n", 1<< cfip->MaxBufWriteSize);
404         printk("Number of Erase Block Regions: %d\n", cfip->NumEraseRegions);
405         
406 }
407 #endif /* DEBUG_CFI */
408
409 static struct chip_probe cfi_chip_probe = {
410         .name           = "CFI",
411         .probe_chip     = cfi_probe_chip
412 };
413
414 struct mtd_info *cfi_probe(struct map_info *map)
415 {
416         /*
417          * Just use the generic probe stuff to call our CFI-specific
418          * chip_probe routine in all the possible permutations, etc.
419          */
420         return mtd_do_chip_probe(map, &cfi_chip_probe);
421 }
422
423 static struct mtd_chip_driver cfi_chipdrv = {
424         .probe          = cfi_probe,
425         .name           = "cfi_probe",
426         .module         = THIS_MODULE
427 };
428
429 int __init cfi_probe_init(void)
430 {
431         register_mtd_chip_driver(&cfi_chipdrv);
432         return 0;
433 }
434
435 static void __exit cfi_probe_exit(void)
436 {
437         unregister_mtd_chip_driver(&cfi_chipdrv);
438 }
439
440 module_init(cfi_probe_init);
441 module_exit(cfi_probe_exit);
442
443 MODULE_LICENSE("GPL");
444 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
445 MODULE_DESCRIPTION("Probe code for CFI-compliant flash chips");