1/*
2   Common Flash Interface probe code.
3   (C) 2000 Red Hat. GPL'd.
4   $Id: cfi_probe.c,v 1.1.1.1 2008/10/15 03:26:35 james26_jang 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 <asm/io.h>
12#include <asm/byteorder.h>
13#include <linux/errno.h>
14#include <linux/slab.h>
15#include <linux/interrupt.h>
16
17#include <linux/mtd/map.h>
18#include <linux/mtd/cfi.h>
19#include <linux/mtd/gen_probe.h>
20
21//#define DEBUG_CFI
22
23#ifdef DEBUG_CFI
24static void print_cfi_ident(struct cfi_ident *);
25#endif
26
27int cfi_jedec_setup(struct cfi_private *p_cfi, int index);
28int cfi_jedec_lookup(int index, int mfr_id, int dev_id);
29
30static int cfi_probe_chip(struct map_info *map, __u32 base,
31			  struct flchip *chips, struct cfi_private *cfi);
32static int cfi_chip_setup(struct map_info *map, struct cfi_private *cfi);
33
34struct mtd_info *cfi_probe(struct map_info *map);
35
36/* check for QRY, or search for jedec id.
37   in: interleave,type,mode
38   ret: table index, <0 for error
39 */
40static inline int qry_present(struct map_info *map, __u32 base,
41				struct cfi_private *cfi)
42{
43	int osf = cfi->interleave * cfi->device_type;	// scale factor
44
45	if (cfi_read(map,base+osf*0x10)==cfi_build_cmd('Q',map,cfi) &&
46	    cfi_read(map,base+osf*0x11)==cfi_build_cmd('R',map,cfi) &&
47	    cfi_read(map,base+osf*0x12)==cfi_build_cmd('Y',map,cfi))
48		return 1;	// ok !
49
50	return 0; 	// nothing found
51}
52
53static int cfi_probe_chip(struct map_info *map, __u32 base,
54			  struct flchip *chips, struct cfi_private *cfi)
55{
56	int i;
57
58	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
59	cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
60
61	if (!qry_present(map,base,cfi)) {
62		/* rather broken SST cfi probe (requires SST unlock) */
63		cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
64		cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
65		cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
66		cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
67		if (!qry_present(map,base,cfi))
68			return 0;
69	}
70
71	if (!cfi->numchips) {
72		/* This is the first time we're called. Set up the CFI
73		   stuff accordingly and return */
74		return cfi_chip_setup(map, cfi);
75	}
76
77	/* Check each previous chip to see if it's an alias */
78	for (i=0; i<cfi->numchips; i++) {
79		/* This chip should be in read mode if it's one
80		   we've already touched. */
81		if (qry_present(map,chips[i].start,cfi)) {
82			/* Eep. This chip also had the QRY marker.
83			 * Is it an alias for the new one? */
84			cfi_send_gen_cmd(0xF0, 0, chips[i].start, map, cfi, cfi->device_type, NULL);
85
86			/* If the QRY marker goes away, it's an alias */
87			if (!qry_present(map, chips[i].start, cfi)) {
88				printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
89				       map->name, base, chips[i].start);
90				return 0;
91			}
92			/* Yes, it's actually got QRY for data. Most
93			 * unfortunate. Stick the new chip in read mode
94			 * too and if it's the same, assume it's an alias. */
95			cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
96
97			if (qry_present(map, base, cfi)) {
98				printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
99				       map->name, base, chips[i].start);
100				return 0;
101			}
102		}
103	}
104
105	/* OK, if we got to here, then none of the previous chips appear to
106	   be aliases for the current one. */
107	if (cfi->numchips == MAX_CFI_CHIPS) {
108		printk(KERN_WARNING"%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d.\n", map->name, MAX_CFI_CHIPS);
109		/* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */
110		return -1;
111	}
112	chips[cfi->numchips].start = base;
113	chips[cfi->numchips].state = FL_READY;
114	cfi->numchips++;
115
116	/* Put it back into Read Mode */
117	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
118
119	printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit mode\n",
120	       map->name, cfi->interleave, cfi->device_type*8, base,
121	       map->buswidth*8);
122
123	return 1;
124}
125
126static int cfi_chip_setup(struct map_info *map,
127		   struct cfi_private *cfi)
128{
129	int ofs_factor = cfi->interleave*cfi->device_type;
130	__u32 base = 0;
131	int num_erase_regions = cfi_read_query(map, base + (0x10 + 28)*ofs_factor);
132	int i;
133
134#ifdef DEBUG_CFI
135	printk("Number of erase regions: %d\n", num_erase_regions);
136#endif
137	if (!num_erase_regions)
138		return 0;
139
140	cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
141	if (!cfi->cfiq) {
142		printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
143		return 0;
144	}
145
146	memset(cfi->cfiq,0,sizeof(struct cfi_ident));
147
148	cfi->cfi_mode = 1;
149	cfi->fast_prog=1;		/* CFI supports fast programming */
150
151	/* Read the CFI info structure */
152	for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) {
153		((unsigned char *)cfi->cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor);
154	}
155
156	/* Do any necessary byteswapping */
157	cfi->cfiq->P_ID = le16_to_cpu(cfi->cfiq->P_ID);
158
159	cfi->cfiq->P_ADR = le16_to_cpu(cfi->cfiq->P_ADR);
160	cfi->cfiq->A_ID = le16_to_cpu(cfi->cfiq->A_ID);
161	cfi->cfiq->A_ADR = le16_to_cpu(cfi->cfiq->A_ADR);
162	cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc);
163	cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize);
164
165#ifdef DEBUG_CFI
166	/* Dump the information therein */
167	print_cfi_ident(cfi->cfiq);
168#endif
169
170	for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
171		cfi->cfiq->EraseRegionInfo[i] = le32_to_cpu(cfi->cfiq->EraseRegionInfo[i]);
172
173#ifdef DEBUG_CFI
174		printk("  Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n",
175		       i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff,
176		       (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1);
177#endif
178	}
179	/* Put it back into Read Mode */
180	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
181
182	return 1;
183}
184
185#ifdef DEBUG_CFI
186static char *vendorname(__u16 vendor)
187{
188	switch (vendor) {
189	case P_ID_NONE:
190		return "None";
191
192	case P_ID_INTEL_EXT:
193		return "Intel/Sharp Extended";
194
195	case P_ID_AMD_STD:
196		return "AMD/Fujitsu Standard";
197
198	case P_ID_INTEL_STD:
199		return "Intel/Sharp Standard";
200
201	case P_ID_AMD_EXT:
202		return "AMD/Fujitsu Extended";
203
204	case P_ID_MITSUBISHI_STD:
205		return "Mitsubishi Standard";
206
207	case P_ID_MITSUBISHI_EXT:
208		return "Mitsubishi Extended";
209
210	case P_ID_RESERVED:
211		return "Not Allowed / Reserved for Future Use";
212
213	default:
214		return "Unknown";
215	}
216}
217
218
219static void print_cfi_ident(struct cfi_ident *cfip)
220{
221	printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip->P_ID, vendorname(cfip->P_ID));
222	if (cfip->P_ADR)
223		printk("Primary Algorithm Table at %4.4X\n", cfip->P_ADR);
224	else
225		printk("No Primary Algorithm Table\n");
226
227	printk("Alternative Vendor Command Set: %4.4X (%s)\n", cfip->A_ID, vendorname(cfip->A_ID));
228	if (cfip->A_ADR)
229		printk("Alternate Algorithm Table at %4.4X\n", cfip->A_ADR);
230	else
231		printk("No Alternate Algorithm Table\n");
232
233
234	printk("Vcc Minimum: %x.%x V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf);
235	printk("Vcc Maximum: %x.%x V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf);
236	if (cfip->VppMin) {
237		printk("Vpp Minimum: %x.%x V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf);
238		printk("Vpp Maximum: %x.%x V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf);
239	}
240	else
241		printk("No Vpp line\n");
242
243	printk("Typical byte/word write timeout: %d �s\n", 1<<cfip->WordWriteTimeoutTyp);
244	printk("Maximum byte/word write timeout: %d �s\n", (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
245
246	if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) {
247		printk("Typical full buffer write timeout: %d �s\n", 1<<cfip->BufWriteTimeoutTyp);
248		printk("Maximum full buffer write timeout: %d �s\n", (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
249	}
250	else
251		printk("Full buffer write not supported\n");
252
253	printk("Typical block erase timeout: %d �s\n", 1<<cfip->BlockEraseTimeoutTyp);
254	printk("Maximum block erase timeout: %d �s\n", (1<<cfip->BlockEraseTimeoutMax) * (1<<cfip->BlockEraseTimeoutTyp));
255	if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) {
256		printk("Typical chip erase timeout: %d �s\n", 1<<cfip->ChipEraseTimeoutTyp);
257		printk("Maximum chip erase timeout: %d �s\n", (1<<cfip->ChipEraseTimeoutMax) * (1<<cfip->ChipEraseTimeoutTyp));
258	}
259	else
260		printk("Chip erase not supported\n");
261
262	printk("Device size: 0x%X bytes (%d MiB)\n", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20));
263	printk("Flash Device Interface description: 0x%4.4X\n", cfip->InterfaceDesc);
264	switch(cfip->InterfaceDesc) {
265	case 0:
266		printk("  - x8-only asynchronous interface\n");
267		break;
268
269	case 1:
270		printk("  - x16-only asynchronous interface\n");
271		break;
272
273	case 2:
274		printk("  - supports x8 and x16 via BYTE# with asynchronous interface\n");
275		break;
276
277	case 3:
278		printk("  - x32-only asynchronous interface\n");
279		break;
280
281	case 65535:
282		printk("  - Not Allowed / Reserved\n");
283		break;
284
285	default:
286		printk("  - Unknown\n");
287		break;
288	}
289
290	printk("Max. bytes in buffer write: 0x%x\n", 1<< cfip->MaxBufWriteSize);
291	printk("Number of Erase Block Regions: %d\n", cfip->NumEraseRegions);
292
293}
294#endif /* DEBUG_CFI */
295
296static struct chip_probe cfi_chip_probe = {
297	name: "CFI",
298	probe_chip: cfi_probe_chip
299};
300
301struct mtd_info *cfi_probe(struct map_info *map)
302{
303	/*
304	 * Just use the generic probe stuff to call our CFI-specific
305	 * chip_probe routine in all the possible permutations, etc.
306	 */
307	return mtd_do_chip_probe(map, &cfi_chip_probe);
308}
309
310static struct mtd_chip_driver cfi_chipdrv = {
311	probe: cfi_probe,
312	name: "cfi_probe",
313	module: THIS_MODULE
314};
315
316int __init cfi_probe_init(void)
317{
318	register_mtd_chip_driver(&cfi_chipdrv);
319	return 0;
320}
321
322static void __exit cfi_probe_exit(void)
323{
324	unregister_mtd_chip_driver(&cfi_chipdrv);
325}
326
327module_init(cfi_probe_init);
328module_exit(cfi_probe_exit);
329
330MODULE_LICENSE("GPL");
331MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
332MODULE_DESCRIPTION("Probe code for CFI-compliant flash chips");
333