Blame view

drivers/mtd/chips/cfi_probe.c 13 KB
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
     Common Flash Interface probe code.
     (C) 2000 Red Hat. GPL'd.
2b9175c17   Adrian Bunk   [MTD] Make functi...
4
     $Id: cfi_probe.c,v 1.86 2005/11/29 14:48:31 gleixner Exp $
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
  */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <asm/io.h>
  #include <asm/byteorder.h>
  #include <linux/errno.h>
  #include <linux/slab.h>
  #include <linux/interrupt.h>
  
  #include <linux/mtd/xip.h>
  #include <linux/mtd/map.h>
  #include <linux/mtd/cfi.h>
  #include <linux/mtd/gen_probe.h>
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
20
  //#define DEBUG_CFI
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  
  #ifdef DEBUG_CFI
  static void print_cfi_ident(struct cfi_ident *);
  #endif
  
  static int cfi_probe_chip(struct map_info *map, __u32 base,
  			  unsigned long *chip_map, struct cfi_private *cfi);
  static int cfi_chip_setup(struct map_info *map, struct cfi_private *cfi);
  
  struct mtd_info *cfi_probe(struct map_info *map);
  
  #ifdef CONFIG_MTD_XIP
  
  /* only needed for short periods, so this is rather simple */
  #define xip_disable()	local_irq_disable()
  
  #define xip_allowed(base, map) \
  do { \
  	(void) map_read(map, base); \
ca5c23c3b   Paulius Zaleckas   [MTD] XIP: Use ge...
40
  	xip_iprefetch(); \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  	local_irq_enable(); \
  } while (0)
  
  #define xip_enable(base, map, cfi) \
  do { \
  	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); \
  	cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); \
  	xip_allowed(base, map); \
  } while (0)
  
  #define xip_disable_qry(base, map, cfi) \
  do { \
  	xip_disable(); \
  	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); \
  	cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); \
  	cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); \
  } while (0)
  
  #else
  
  #define xip_disable()			do { } while (0)
  #define xip_allowed(base, map)		do { } while (0)
  #define xip_enable(base, map, cfi)	do { } while (0)
  #define xip_disable_qry(base, map, cfi) do { } while (0)
  
  #endif
  
  /* check for QRY.
     in: interleave,type,mode
     ret: table index, <0 for error
   */
  static int __xipram qry_present(struct map_info *map, __u32 base,
  				struct cfi_private *cfi)
  {
  	int osf = cfi->interleave * cfi->device_type;	// scale factor
  	map_word val[3];
  	map_word qry[3];
  
  	qry[0] = cfi_build_cmd('Q', map, cfi);
  	qry[1] = cfi_build_cmd('R', map, cfi);
  	qry[2] = cfi_build_cmd('Y', map, cfi);
  
  	val[0] = map_read(map, base + osf*0x10);
  	val[1] = map_read(map, base + osf*0x11);
  	val[2] = map_read(map, base + osf*0x12);
  
  	if (!map_word_equal(map, qry[0], val[0]))
  		return 0;
  
  	if (!map_word_equal(map, qry[1], val[1]))
  		return 0;
  
  	if (!map_word_equal(map, qry[2], val[2]))
  		return 0;
  
  	return 1; 	// "QRY" found
  }
  
  static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
  				   unsigned long *chip_map, struct cfi_private *cfi)
  {
  	int i;
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
103

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  	if ((base + 0) >= map->size) {
  		printk(KERN_NOTICE
  			"Probe at base[0x00](0x%08lx) past the end of the map(0x%08lx)
  ",
  			(unsigned long)base, map->size -1);
  		return 0;
  	}
  	if ((base + 0xff) >= map->size) {
  		printk(KERN_NOTICE
  			"Probe at base[0x55](0x%08lx) past the end of the map(0x%08lx)
  ",
  			(unsigned long)base + 0x55, map->size -1);
  		return 0;
  	}
  
  	xip_disable();
  	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
  	cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
  	cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
  
  	if (!qry_present(map,base,cfi)) {
  		xip_enable(base, map, cfi);
  		return 0;
  	}
  
  	if (!cfi->numchips) {
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
130
  		/* This is the first time we're called. Set up the CFI
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
134
135
136
137
138
139
  		   stuff accordingly and return */
  		return cfi_chip_setup(map, cfi);
  	}
  
  	/* Check each previous chip to see if it's an alias */
   	for (i=0; i < (base >> cfi->chipshift); i++) {
   		unsigned long start;
   		if(!test_bit(i, chip_map)) {
  			/* Skip location; no valid chip at this address */
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
140
   			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
144
145
   		}
   		start = i << cfi->chipshift;
  		/* This chip should be in read mode if it's one
  		   we've already touched. */
  		if (qry_present(map, start, cfi)) {
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
146
  			/* Eep. This chip also had the QRY marker.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
150
151
152
153
154
155
156
157
158
  			 * Is it an alias for the new one? */
  			cfi_send_gen_cmd(0xF0, 0, start, map, cfi, cfi->device_type, NULL);
  			cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
  
  			/* If the QRY marker goes away, it's an alias */
  			if (!qry_present(map, start, cfi)) {
  				xip_allowed(base, map);
  				printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx
  ",
  				       map->name, base, start);
  				return 0;
  			}
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
159
  			/* Yes, it's actually got QRY for data. Most
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
163
164
  			 * unfortunate. Stick the new chip in read mode
  			 * too and if it's the same, assume it's an alias. */
  			/* FIXME: Use other modes to do a proper check */
  			cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
  			cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
165

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
168
169
170
171
172
173
174
  			if (qry_present(map, base, cfi)) {
  				xip_allowed(base, map);
  				printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx
  ",
  				       map->name, base, start);
  				return 0;
  			}
  		}
  	}
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
175

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
179
  	/* OK, if we got to here, then none of the previous chips appear to
  	   be aliases for the current one. */
  	set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
  	cfi->numchips++;
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
180

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
183
184
185
186
187
188
189
  	/* Put it back into Read Mode */
  	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
  	cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
  	xip_allowed(base, map);
  
  	printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank
  ",
  	       map->name, cfi->interleave, cfi->device_type*8, base,
  	       map->bankwidth*8);
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
190

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
  	return 1;
  }
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
193
  static int __xipram cfi_chip_setup(struct map_info *map,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  				   struct cfi_private *cfi)
  {
  	int ofs_factor = cfi->interleave*cfi->device_type;
  	__u32 base = 0;
  	int num_erase_regions = cfi_read_query(map, base + (0x10 + 28)*ofs_factor);
  	int i;
  
  	xip_enable(base, map, cfi);
  #ifdef DEBUG_CFI
  	printk("Number of erase regions: %d
  ", num_erase_regions);
  #endif
  	if (!num_erase_regions)
  		return 0;
  
  	cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
  	if (!cfi->cfiq) {
  		printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure
  ", map->name);
  		return 0;
  	}
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
215
216
  
  	memset(cfi->cfiq,0,sizeof(struct cfi_ident));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
  	cfi->cfi_mode = CFI_MODE_CFI;
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
218

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  	/* Read the CFI info structure */
  	xip_disable_qry(base, map, cfi);
  	for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++)
  		((unsigned char *)cfi->cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor);
  
  	/* Note we put the device back into Read Mode BEFORE going into Auto
  	 * Select Mode, as some devices support nesting of modes, others
  	 * don't. This way should always work.
  	 * On cmdset 0001 the writes of 0xaa and 0x55 are not needed, and
  	 * so should be treated as nops or illegal (and so put the device
  	 * back into Read Mode, which is a nop in this case).
  	 */
  	cfi_send_gen_cmd(0xf0,     0, base, map, cfi, cfi->device_type, NULL);
  	cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL);
  	cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL);
  	cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL);
987d24018   Todd Poynor   [MTD] CFI: Use 16...
235
236
  	cfi->mfr = cfi_read_query16(map, base);
  	cfi->id = cfi_read_query16(map, base + ofs_factor);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237

fecb8865d   Trent Piepho   [MTD] [NOR] Read ...
238
239
240
241
  	/* Get AMD/Spansion extended JEDEC ID */
  	if (cfi->mfr == CFI_MFR_AMD && (cfi->id & 0xff) == 0x7e)
  		cfi->id = cfi_read_query(map, base + 0xe * ofs_factor) << 8 |
  			  cfi_read_query(map, base + 0xf * ofs_factor);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
  	/* Put it back into Read Mode */
  	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
  	/* ... even if it's an Intel chip */
  	cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
  	xip_allowed(base, map);
  
  	/* Do any necessary byteswapping */
  	cfi->cfiq->P_ID = le16_to_cpu(cfi->cfiq->P_ID);
  
  	cfi->cfiq->P_ADR = le16_to_cpu(cfi->cfiq->P_ADR);
  	cfi->cfiq->A_ID = le16_to_cpu(cfi->cfiq->A_ID);
  	cfi->cfiq->A_ADR = le16_to_cpu(cfi->cfiq->A_ADR);
  	cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc);
  	cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize);
  
  #ifdef DEBUG_CFI
  	/* Dump the information therein */
  	print_cfi_ident(cfi->cfiq);
  #endif
  
  	for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
  		cfi->cfiq->EraseRegionInfo[i] = le32_to_cpu(cfi->cfiq->EraseRegionInfo[i]);
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
264
265
  
  #ifdef DEBUG_CFI
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
  		printk("  Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks
  ",
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
268
  		       i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
271
272
273
274
275
276
277
278
279
280
281
  		       (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1);
  #endif
  	}
  
  	printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank
  ",
  	       map->name, cfi->interleave, cfi->device_type*8, base,
  	       map->bankwidth*8);
  
  	return 1;
  }
  
  #ifdef DEBUG_CFI
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
282
  static char *vendorname(__u16 vendor)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
284
285
286
  {
  	switch (vendor) {
  	case P_ID_NONE:
  		return "None";
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
287

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
  	case P_ID_INTEL_EXT:
  		return "Intel/Sharp Extended";
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
290

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
  	case P_ID_AMD_STD:
  		return "AMD/Fujitsu Standard";
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
293

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
295
  	case P_ID_INTEL_STD:
  		return "Intel/Sharp Standard";
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
296

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
298
299
300
301
  	case P_ID_AMD_EXT:
  		return "AMD/Fujitsu Extended";
  
  	case P_ID_WINBOND:
  		return "Winbond Standard";
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
302

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
304
305
306
307
  	case P_ID_ST_ADV:
  		return "ST Advanced";
  
  	case P_ID_MITSUBISHI_STD:
  		return "Mitsubishi Standard";
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
308

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
311
312
313
314
315
316
  	case P_ID_MITSUBISHI_EXT:
  		return "Mitsubishi Extended";
  
  	case P_ID_SST_PAGE:
  		return "SST Page Write";
  
  	case P_ID_INTEL_PERFORMANCE:
  		return "Intel Performance Code";
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
317

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
  	case P_ID_INTEL_DATA:
  		return "Intel Data";
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
320

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
322
  	case P_ID_RESERVED:
  		return "Not Allowed / Reserved for Future Use";
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
323

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
326
327
328
329
330
331
332
333
334
335
336
  	default:
  		return "Unknown";
  	}
  }
  
  
  static void print_cfi_ident(struct cfi_ident *cfip)
  {
  #if 0
  	if (cfip->qry[0] != 'Q' || cfip->qry[1] != 'R' || cfip->qry[2] != 'Y') {
  		printk("Invalid CFI ident structure.
  ");
  		return;
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
337
338
  	}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
341
342
343
344
345
346
  	printk("Primary Vendor Command Set: %4.4X (%s)
  ", cfip->P_ID, vendorname(cfip->P_ID));
  	if (cfip->P_ADR)
  		printk("Primary Algorithm Table at %4.4X
  ", cfip->P_ADR);
  	else
  		printk("No Primary Algorithm Table
  ");
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
347

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
350
351
352
353
354
355
  	printk("Alternative Vendor Command Set: %4.4X (%s)
  ", cfip->A_ID, vendorname(cfip->A_ID));
  	if (cfip->A_ADR)
  		printk("Alternate Algorithm Table at %4.4X
  ", cfip->A_ADR);
  	else
  		printk("No Alternate Algorithm Table
  ");
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
356

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
358
359
360
361
362
363
364
365
366
367
368
369
  	printk("Vcc Minimum: %2d.%d V
  ", cfip->VccMin >> 4, cfip->VccMin & 0xf);
  	printk("Vcc Maximum: %2d.%d V
  ", cfip->VccMax >> 4, cfip->VccMax & 0xf);
  	if (cfip->VppMin) {
  		printk("Vpp Minimum: %2d.%d V
  ", cfip->VppMin >> 4, cfip->VppMin & 0xf);
  		printk("Vpp Maximum: %2d.%d V
  ", cfip->VppMax >> 4, cfip->VppMax & 0xf);
  	}
  	else
  		printk("No Vpp line
  ");
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
370

151e76590   David Woodhouse   [MTD] Fix legacy ...
371
372
373
374
  	printk("Typical byte/word write timeout: %d µs
  ", 1<<cfip->WordWriteTimeoutTyp);
  	printk("Maximum byte/word write timeout: %d µs
  ", (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
375

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
  	if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) {
151e76590   David Woodhouse   [MTD] Fix legacy ...
377
378
379
380
  		printk("Typical full buffer write timeout: %d µs
  ", 1<<cfip->BufWriteTimeoutTyp);
  		printk("Maximum full buffer write timeout: %d µs
  ", (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
382
383
384
  	}
  	else
  		printk("Full buffer write not supported
  ");
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
385

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
388
389
390
  	printk("Typical block erase timeout: %d ms
  ", 1<<cfip->BlockEraseTimeoutTyp);
  	printk("Maximum block erase timeout: %d ms
  ", (1<<cfip->BlockEraseTimeoutMax) * (1<<cfip->BlockEraseTimeoutTyp));
  	if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) {
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
391
392
  		printk("Typical chip erase timeout: %d ms
  ", 1<<cfip->ChipEraseTimeoutTyp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
395
396
397
398
  		printk("Maximum chip erase timeout: %d ms
  ", (1<<cfip->ChipEraseTimeoutMax) * (1<<cfip->ChipEraseTimeoutTyp));
  	}
  	else
  		printk("Chip erase not supported
  ");
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
399

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
401
402
403
404
  	printk("Device size: 0x%X bytes (%d MiB)
  ", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20));
  	printk("Flash Device Interface description: 0x%4.4X
  ", cfip->InterfaceDesc);
  	switch(cfip->InterfaceDesc) {
de7921f01   Bartlomiej Sieka   [MTD] [NOR] Fix i...
405
  	case CFI_INTERFACE_X8_ASYNC:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
408
  		printk("  - x8-only asynchronous interface
  ");
  		break;
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
409

de7921f01   Bartlomiej Sieka   [MTD] [NOR] Fix i...
410
  	case CFI_INTERFACE_X16_ASYNC:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
413
  		printk("  - x16-only asynchronous interface
  ");
  		break;
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
414

de7921f01   Bartlomiej Sieka   [MTD] [NOR] Fix i...
415
  	case CFI_INTERFACE_X8_BY_X16_ASYNC:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
417
418
  		printk("  - supports x8 and x16 via BYTE# with asynchronous interface
  ");
  		break;
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
419

de7921f01   Bartlomiej Sieka   [MTD] [NOR] Fix i...
420
  	case CFI_INTERFACE_X32_ASYNC:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
422
423
  		printk("  - x32-only asynchronous interface
  ");
  		break;
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
424

de7921f01   Bartlomiej Sieka   [MTD] [NOR] Fix i...
425
  	case CFI_INTERFACE_X16_BY_X32_ASYNC:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
428
  		printk("  - supports x16 and x32 via Word# with asynchronous interface
  ");
  		break;
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
429

de7921f01   Bartlomiej Sieka   [MTD] [NOR] Fix i...
430
  	case CFI_INTERFACE_NOT_ALLOWED:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
432
433
  		printk("  - Not Allowed / Reserved
  ");
  		break;
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
434

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
437
438
439
  	default:
  		printk("  - Unknown
  ");
  		break;
  	}
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
440

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
443
444
  	printk("Max. bytes in buffer write: 0x%x
  ", 1<< cfip->MaxBufWriteSize);
  	printk("Number of Erase Block Regions: %d
  ", cfip->NumEraseRegions);
1f948b43f   Thomas Gleixner   [MTD] chips: Clea...
445

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
  }
  #endif /* DEBUG_CFI */
  
  static struct chip_probe cfi_chip_probe = {
  	.name		= "CFI",
  	.probe_chip	= cfi_probe_chip
  };
  
  struct mtd_info *cfi_probe(struct map_info *map)
  {
  	/*
  	 * Just use the generic probe stuff to call our CFI-specific
  	 * chip_probe routine in all the possible permutations, etc.
  	 */
  	return mtd_do_chip_probe(map, &cfi_chip_probe);
  }
  
  static struct mtd_chip_driver cfi_chipdrv = {
  	.probe		= cfi_probe,
  	.name		= "cfi_probe",
  	.module		= THIS_MODULE
  };
2b9175c17   Adrian Bunk   [MTD] Make functi...
468
  static int __init cfi_probe_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
  {
  	register_mtd_chip_driver(&cfi_chipdrv);
  	return 0;
  }
  
  static void __exit cfi_probe_exit(void)
  {
  	unregister_mtd_chip_driver(&cfi_chipdrv);
  }
  
  module_init(cfi_probe_init);
  module_exit(cfi_probe_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
  MODULE_DESCRIPTION("Probe code for CFI-compliant flash chips");