1
2
3
4
5
6#include <linux/module.h>
7#include <linux/types.h>
8#include <linux/kernel.h>
9#include <linux/init.h>
10#include <asm/io.h>
11#include <asm/byteorder.h>
12#include <linux/errno.h>
13#include <linux/slab.h>
14#include <linux/interrupt.h>
15
16#include <linux/mtd/xip.h>
17#include <linux/mtd/map.h>
18#include <linux/mtd/cfi.h>
19#include <linux/mtd/gen_probe.h>
20
21
22
23#ifdef DEBUG_CFI
24static void print_cfi_ident(struct cfi_ident *);
25#endif
26
27static int cfi_probe_chip(struct map_info *map, __u32 base,
28 unsigned long *chip_map, struct cfi_private *cfi);
29static int cfi_chip_setup(struct map_info *map, struct cfi_private *cfi);
30
31struct mtd_info *cfi_probe(struct map_info *map);
32
33#ifdef CONFIG_MTD_XIP
34
35
36#define xip_disable() local_irq_disable()
37
38#define xip_allowed(base, map) \
39do { \
40 (void) map_read(map, base); \
41 xip_iprefetch(); \
42 local_irq_enable(); \
43} while (0)
44
45#define xip_enable(base, map, cfi) \
46do { \
47 cfi_qry_mode_off(base, map, cfi); \
48 xip_allowed(base, map); \
49} while (0)
50
51#define xip_disable_qry(base, map, cfi) \
52do { \
53 xip_disable(); \
54 cfi_qry_mode_on(base, map, cfi); \
55} while (0)
56
57#else
58
59#define xip_disable() do { } while (0)
60#define xip_allowed(base, map) do { } while (0)
61#define xip_enable(base, map, cfi) do { } while (0)
62#define xip_disable_qry(base, map, cfi) do { } while (0)
63
64#endif
65
66
67
68
69
70
71static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
72 unsigned long *chip_map, struct cfi_private *cfi)
73{
74 int i;
75
76 if ((base + 0) >= map->size) {
77 printk(KERN_NOTICE
78 "Probe at base[0x00](0x%08lx) past the end of the map(0x%08lx)\n",
79 (unsigned long)base, map->size -1);
80 return 0;
81 }
82 if ((base + 0xff) >= map->size) {
83 printk(KERN_NOTICE
84 "Probe at base[0x55](0x%08lx) past the end of the map(0x%08lx)\n",
85 (unsigned long)base + 0x55, map->size -1);
86 return 0;
87 }
88
89 xip_disable();
90 if (!cfi_qry_mode_on(base, map, cfi)) {
91 xip_enable(base, map, cfi);
92 return 0;
93 }
94
95 if (!cfi->numchips) {
96
97
98 return cfi_chip_setup(map, cfi);
99 }
100
101
102 for (i=0; i < (base >> cfi->chipshift); i++) {
103 unsigned long start;
104 if(!test_bit(i, chip_map)) {
105
106 continue;
107 }
108 start = i << cfi->chipshift;
109
110
111 if (cfi_qry_present(map, start, cfi)) {
112
113
114 cfi_qry_mode_off(start, map, cfi);
115
116
117 if (!cfi_qry_present(map, start, cfi)) {
118 xip_allowed(base, map);
119 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
120 map->name, base, start);
121 return 0;
122 }
123
124
125
126
127 cfi_qry_mode_off(base, map, cfi);
128
129 if (cfi_qry_present(map, base, cfi)) {
130 xip_allowed(base, map);
131 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
132 map->name, base, start);
133 return 0;
134 }
135 }
136 }
137
138
139
140 set_bit((base >> cfi->chipshift), chip_map);
141 cfi->numchips++;
142
143
144 cfi_qry_mode_off(base, map, cfi);
145 xip_allowed(base, map);
146
147 printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
148 map->name, cfi->interleave, cfi->device_type*8, base,
149 map->bankwidth*8);
150
151 return 1;
152}
153
154static int __xipram cfi_chip_setup(struct map_info *map,
155 struct cfi_private *cfi)
156{
157 int ofs_factor = cfi->interleave*cfi->device_type;
158 __u32 base = 0;
159 int num_erase_regions = cfi_read_query(map, base + (0x10 + 28)*ofs_factor);
160 int i;
161 int extendedId1 = 0;
162 int extendedId2 = 0;
163 int extendedId3 = 0;
164 int addr_unlock1 = 0x555, addr_unlock2 = 0x2AA;
165
166 xip_enable(base, map, cfi);
167#ifdef DEBUG_CFI
168 printk("Number of erase regions: %d\n", num_erase_regions);
169#endif
170 if (!num_erase_regions)
171 return 0;
172
173 cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
174 if (!cfi->cfiq)
175 return 0;
176
177 memset(cfi->cfiq,0,sizeof(struct cfi_ident));
178
179 cfi->cfi_mode = CFI_MODE_CFI;
180
181 cfi->sector_erase_cmd = CMD(0x30);
182
183
184 xip_disable_qry(base, map, cfi);
185 for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++)
186 ((unsigned char *)cfi->cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor);
187
188
189
190
191
192
193
194
195 cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL);
196 cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL);
197 cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL);
198 cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL);
199 cfi->mfr = cfi_read_query16(map, base);
200 cfi->id = cfi_read_query16(map, base + ofs_factor);
201
202
203 if ((cfi->mfr == CFI_MFR_INTEL || cfi->mfr == CFI_MFR_ST)
204 && ((cfi->id & 0xff) == 0x7e)
205 && (le16_to_cpu(cfi->cfiq->P_ID) == 0x0002)) {
206 extendedId1 = cfi_read_query16(map, base + 0x1 * ofs_factor);
207 extendedId2 = cfi_read_query16(map, base + 0xe * ofs_factor);
208 extendedId3 = cfi_read_query16(map, base + 0xf * ofs_factor);
209 }
210
211
212 if (cfi->mfr == CFI_MFR_AMD && (cfi->id & 0xff) == 0x7e)
213 cfi->id = cfi_read_query(map, base + 0xe * ofs_factor) << 8 |
214 cfi_read_query(map, base + 0xf * ofs_factor);
215
216
217 cfi_qry_mode_off(base, map, cfi);
218 xip_allowed(base, map);
219
220
221 cfi->cfiq->P_ID = le16_to_cpu(cfi->cfiq->P_ID);
222
223 cfi->cfiq->P_ADR = le16_to_cpu(cfi->cfiq->P_ADR);
224 cfi->cfiq->A_ID = le16_to_cpu(cfi->cfiq->A_ID);
225 cfi->cfiq->A_ADR = le16_to_cpu(cfi->cfiq->A_ADR);
226 cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc);
227 cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize);
228
229
230 if ((cfi->cfiq->MaxBufWriteSize > 0x8) && (cfi->mfr == CFI_MFR_INTEL ||
231 cfi->mfr == CFI_MFR_ST) && (extendedId1 == 0x7E) &&
232 (extendedId2 == 0x22 || extendedId2 == 0x23 || extendedId2 == 0x28) &&
233 (extendedId3 == 0x01)) {
234 cfi->cfiq->MaxBufWriteSize = 0x8;
235 pr_warning("Adjusted buffer size on Numonyx flash M29EW family");
236 pr_warning("in 8 bit mode\n");
237 }
238
239#ifdef DEBUG_CFI
240
241 print_cfi_ident(cfi->cfiq);
242#endif
243
244 for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
245 cfi->cfiq->EraseRegionInfo[i] = le32_to_cpu(cfi->cfiq->EraseRegionInfo[i]);
246
247#ifdef DEBUG_CFI
248 printk(" Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n",
249 i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff,
250 (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1);
251#endif
252 }
253
254 if (cfi->cfiq->P_ID == P_ID_SST_OLD) {
255 addr_unlock1 = 0x5555;
256 addr_unlock2 = 0x2AAA;
257 }
258
259
260
261
262
263
264
265
266
267 cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL);
268 cfi_send_gen_cmd(0xaa, addr_unlock1, base, map, cfi, cfi->device_type, NULL);
269 cfi_send_gen_cmd(0x55, addr_unlock2, base, map, cfi, cfi->device_type, NULL);
270 cfi_send_gen_cmd(0x90, addr_unlock1, base, map, cfi, cfi->device_type, NULL);
271 cfi->mfr = cfi_read_query16(map, base);
272 cfi->id = cfi_read_query16(map, base + ofs_factor);
273
274
275 if (cfi->mfr == CFI_MFR_AMD && (cfi->id & 0xff) == 0x7e)
276 cfi->id = cfi_read_query(map, base + 0xe * ofs_factor) << 8 |
277 cfi_read_query(map, base + 0xf * ofs_factor);
278
279
280 cfi_qry_mode_off(base, map, cfi);
281 xip_allowed(base, map);
282
283 printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank. Manufacturer ID %#08x Chip ID %#08x\n",
284 map->name, cfi->interleave, cfi->device_type*8, base,
285 map->bankwidth*8, cfi->mfr, cfi->id);
286
287 return 1;
288}
289
290#ifdef DEBUG_CFI
291static char *vendorname(__u16 vendor)
292{
293 switch (vendor) {
294 case P_ID_NONE:
295 return "None";
296
297 case P_ID_INTEL_EXT:
298 return "Intel/Sharp Extended";
299
300 case P_ID_AMD_STD:
301 return "AMD/Fujitsu Standard";
302
303 case P_ID_INTEL_STD:
304 return "Intel/Sharp Standard";
305
306 case P_ID_AMD_EXT:
307 return "AMD/Fujitsu Extended";
308
309 case P_ID_WINBOND:
310 return "Winbond Standard";
311
312 case P_ID_ST_ADV:
313 return "ST Advanced";
314
315 case P_ID_MITSUBISHI_STD:
316 return "Mitsubishi Standard";
317
318 case P_ID_MITSUBISHI_EXT:
319 return "Mitsubishi Extended";
320
321 case P_ID_SST_PAGE:
322 return "SST Page Write";
323
324 case P_ID_SST_OLD:
325 return "SST 39VF160x/39VF320x";
326
327 case P_ID_INTEL_PERFORMANCE:
328 return "Intel Performance Code";
329
330 case P_ID_INTEL_DATA:
331 return "Intel Data";
332
333 case P_ID_RESERVED:
334 return "Not Allowed / Reserved for Future Use";
335
336 default:
337 return "Unknown";
338 }
339}
340
341
342static void print_cfi_ident(struct cfi_ident *cfip)
343{
344#if 0
345 if (cfip->qry[0] != 'Q' || cfip->qry[1] != 'R' || cfip->qry[2] != 'Y') {
346 printk("Invalid CFI ident structure.\n");
347 return;
348 }
349#endif
350 printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip->P_ID, vendorname(cfip->P_ID));
351 if (cfip->P_ADR)
352 printk("Primary Algorithm Table at %4.4X\n", cfip->P_ADR);
353 else
354 printk("No Primary Algorithm Table\n");
355
356 printk("Alternative Vendor Command Set: %4.4X (%s)\n", cfip->A_ID, vendorname(cfip->A_ID));
357 if (cfip->A_ADR)
358 printk("Alternate Algorithm Table at %4.4X\n", cfip->A_ADR);
359 else
360 printk("No Alternate Algorithm Table\n");
361
362
363 printk("Vcc Minimum: %2d.%d V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf);
364 printk("Vcc Maximum: %2d.%d V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf);
365 if (cfip->VppMin) {
366 printk("Vpp Minimum: %2d.%d V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf);
367 printk("Vpp Maximum: %2d.%d V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf);
368 }
369 else
370 printk("No Vpp line\n");
371
372 printk("Typical byte/word write timeout: %d µs\n", 1<<cfip->WordWriteTimeoutTyp);
373 printk("Maximum byte/word write timeout: %d µs\n", (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
374
375 if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) {
376 printk("Typical full buffer write timeout: %d µs\n", 1<<cfip->BufWriteTimeoutTyp);
377 printk("Maximum full buffer write timeout: %d µs\n", (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
378 }
379 else
380 printk("Full buffer write not supported\n");
381
382 printk("Typical block erase timeout: %d ms\n", 1<<cfip->BlockEraseTimeoutTyp);
383 printk("Maximum block erase timeout: %d ms\n", (1<<cfip->BlockEraseTimeoutMax) * (1<<cfip->BlockEraseTimeoutTyp));
384 if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) {
385 printk("Typical chip erase timeout: %d ms\n", 1<<cfip->ChipEraseTimeoutTyp);
386 printk("Maximum chip erase timeout: %d ms\n", (1<<cfip->ChipEraseTimeoutMax) * (1<<cfip->ChipEraseTimeoutTyp));
387 }
388 else
389 printk("Chip erase not supported\n");
390
391 printk("Device size: 0x%X bytes (%d MiB)\n", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20));
392 printk("Flash Device Interface description: 0x%4.4X\n", cfip->InterfaceDesc);
393 switch(cfip->InterfaceDesc) {
394 case CFI_INTERFACE_X8_ASYNC:
395 printk(" - x8-only asynchronous interface\n");
396 break;
397
398 case CFI_INTERFACE_X16_ASYNC:
399 printk(" - x16-only asynchronous interface\n");
400 break;
401
402 case CFI_INTERFACE_X8_BY_X16_ASYNC:
403 printk(" - supports x8 and x16 via BYTE# with asynchronous interface\n");
404 break;
405
406 case CFI_INTERFACE_X32_ASYNC:
407 printk(" - x32-only asynchronous interface\n");
408 break;
409
410 case CFI_INTERFACE_X16_BY_X32_ASYNC:
411 printk(" - supports x16 and x32 via Word# with asynchronous interface\n");
412 break;
413
414 case CFI_INTERFACE_NOT_ALLOWED:
415 printk(" - Not Allowed / Reserved\n");
416 break;
417
418 default:
419 printk(" - Unknown\n");
420 break;
421 }
422
423 printk("Max. bytes in buffer write: 0x%x\n", 1<< cfip->MaxBufWriteSize);
424 printk("Number of Erase Block Regions: %d\n", cfip->NumEraseRegions);
425
426}
427#endif
428
429static struct chip_probe cfi_chip_probe = {
430 .name = "CFI",
431 .probe_chip = cfi_probe_chip
432};
433
434struct mtd_info *cfi_probe(struct map_info *map)
435{
436
437
438
439
440 return mtd_do_chip_probe(map, &cfi_chip_probe);
441}
442
443static struct mtd_chip_driver cfi_chipdrv = {
444 .probe = cfi_probe,
445 .name = "cfi_probe",
446 .module = THIS_MODULE
447};
448
449static int __init cfi_probe_init(void)
450{
451 register_mtd_chip_driver(&cfi_chipdrv);
452 return 0;
453}
454
455static void __exit cfi_probe_exit(void)
456{
457 unregister_mtd_chip_driver(&cfi_chipdrv);
458}
459
460module_init(cfi_probe_init);
461module_exit(cfi_probe_exit);
462
463MODULE_LICENSE("GPL");
464MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
465MODULE_DESCRIPTION("Probe code for CFI-compliant flash chips");
466