xref: /openbmc/linux/drivers/mtd/chips/cfi_util.c (revision d532c28b8c151cdb5b50280801c748ac4d93d563)
1  /*
2   * Common Flash Interface support:
3   *   Generic utility functions not dependent on command set
4   *
5   * Copyright (C) 2002 Red Hat
6   * Copyright (C) 2003 STMicroelectronics Limited
7   *
8   * This code is covered by the GPL.
9   */
10  
11  #include <linux/module.h>
12  #include <linux/types.h>
13  #include <linux/kernel.h>
14  #include <asm/io.h>
15  #include <asm/byteorder.h>
16  
17  #include <linux/errno.h>
18  #include <linux/slab.h>
19  #include <linux/delay.h>
20  #include <linux/interrupt.h>
21  #include <linux/mtd/xip.h>
22  #include <linux/mtd/mtd.h>
23  #include <linux/mtd/map.h>
24  #include <linux/mtd/cfi.h>
25  
26  void cfi_udelay(int us)
27  {
28  	if (us >= 1000) {
29  		msleep(DIV_ROUND_UP(us, 1000));
30  	} else {
31  		udelay(us);
32  		cond_resched();
33  	}
34  }
35  EXPORT_SYMBOL(cfi_udelay);
36  
37  /*
38   * Returns the command address according to the given geometry.
39   */
40  uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs,
41  				struct map_info *map, struct cfi_private *cfi)
42  {
43  	unsigned bankwidth = map_bankwidth(map);
44  	unsigned interleave = cfi_interleave(cfi);
45  	unsigned type = cfi->device_type;
46  	uint32_t addr;
47  
48  	addr = (cmd_ofs * type) * interleave;
49  
50  	/* Modify the unlock address if we are in compatibility mode.
51  	 * For 16bit devices on 8 bit busses
52  	 * and 32bit devices on 16 bit busses
53  	 * set the low bit of the alternating bit sequence of the address.
54  	 */
55  	if (((type * interleave) > bankwidth) && ((cmd_ofs & 0xff) == 0xaa))
56  		addr |= (type >> 1)*interleave;
57  
58  	return  addr;
59  }
60  EXPORT_SYMBOL(cfi_build_cmd_addr);
61  
62  /*
63   * Transforms the CFI command for the given geometry (bus width & interleave).
64   * It looks too long to be inline, but in the common case it should almost all
65   * get optimised away.
66   */
67  map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi)
68  {
69  	map_word val = { {0} };
70  	int wordwidth, words_per_bus, chip_mode, chips_per_word;
71  	unsigned long onecmd;
72  	int i;
73  
74  	/* We do it this way to give the compiler a fighting chance
75  	   of optimising away all the crap for 'bankwidth' larger than
76  	   an unsigned long, in the common case where that support is
77  	   disabled */
78  	if (map_bankwidth_is_large(map)) {
79  		wordwidth = sizeof(unsigned long);
80  		words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1
81  	} else {
82  		wordwidth = map_bankwidth(map);
83  		words_per_bus = 1;
84  	}
85  
86  	chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
87  	chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
88  
89  	/* First, determine what the bit-pattern should be for a single
90  	   device, according to chip mode and endianness... */
91  	switch (chip_mode) {
92  	default: BUG();
93  	case 1:
94  		onecmd = cmd;
95  		break;
96  	case 2:
97  		onecmd = cpu_to_cfi16(map, cmd);
98  		break;
99  	case 4:
100  		onecmd = cpu_to_cfi32(map, cmd);
101  		break;
102  	}
103  
104  	/* Now replicate it across the size of an unsigned long, or
105  	   just to the bus width as appropriate */
106  	switch (chips_per_word) {
107  	default: BUG();
108  #if BITS_PER_LONG >= 64
109  	case 8:
110  		onecmd |= (onecmd << (chip_mode * 32));
111  #endif
112  		/* fall through */
113  	case 4:
114  		onecmd |= (onecmd << (chip_mode * 16));
115  		/* fall through */
116  	case 2:
117  		onecmd |= (onecmd << (chip_mode * 8));
118  		/* fall through */
119  	case 1:
120  		;
121  	}
122  
123  	/* And finally, for the multi-word case, replicate it
124  	   in all words in the structure */
125  	for (i=0; i < words_per_bus; i++) {
126  		val.x[i] = onecmd;
127  	}
128  
129  	return val;
130  }
131  EXPORT_SYMBOL(cfi_build_cmd);
132  
133  unsigned long cfi_merge_status(map_word val, struct map_info *map,
134  					   struct cfi_private *cfi)
135  {
136  	int wordwidth, words_per_bus, chip_mode, chips_per_word;
137  	unsigned long onestat, res = 0;
138  	int i;
139  
140  	/* We do it this way to give the compiler a fighting chance
141  	   of optimising away all the crap for 'bankwidth' larger than
142  	   an unsigned long, in the common case where that support is
143  	   disabled */
144  	if (map_bankwidth_is_large(map)) {
145  		wordwidth = sizeof(unsigned long);
146  		words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1
147  	} else {
148  		wordwidth = map_bankwidth(map);
149  		words_per_bus = 1;
150  	}
151  
152  	chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
153  	chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
154  
155  	onestat = val.x[0];
156  	/* Or all status words together */
157  	for (i=1; i < words_per_bus; i++) {
158  		onestat |= val.x[i];
159  	}
160  
161  	res = onestat;
162  	switch(chips_per_word) {
163  	default: BUG();
164  #if BITS_PER_LONG >= 64
165  	case 8:
166  		res |= (onestat >> (chip_mode * 32));
167  #endif
168  		/* fall through */
169  	case 4:
170  		res |= (onestat >> (chip_mode * 16));
171  		/* fall through */
172  	case 2:
173  		res |= (onestat >> (chip_mode * 8));
174  		/* fall through */
175  	case 1:
176  		;
177  	}
178  
179  	/* Last, determine what the bit-pattern should be for a single
180  	   device, according to chip mode and endianness... */
181  	switch (chip_mode) {
182  	case 1:
183  		break;
184  	case 2:
185  		res = cfi16_to_cpu(map, res);
186  		break;
187  	case 4:
188  		res = cfi32_to_cpu(map, res);
189  		break;
190  	default: BUG();
191  	}
192  	return res;
193  }
194  EXPORT_SYMBOL(cfi_merge_status);
195  
196  /*
197   * Sends a CFI command to a bank of flash for the given geometry.
198   *
199   * Returns the offset in flash where the command was written.
200   * If prev_val is non-null, it will be set to the value at the command address,
201   * before the command was written.
202   */
203  uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t base,
204  				struct map_info *map, struct cfi_private *cfi,
205  				int type, map_word *prev_val)
206  {
207  	map_word val;
208  	uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, map, cfi);
209  	val = cfi_build_cmd(cmd, map, cfi);
210  
211  	if (prev_val)
212  		*prev_val = map_read(map, addr);
213  
214  	map_write(map, val, addr);
215  
216  	return addr - base;
217  }
218  EXPORT_SYMBOL(cfi_send_gen_cmd);
219  
220  int __xipram cfi_qry_present(struct map_info *map, __u32 base,
221  			     struct cfi_private *cfi)
222  {
223  	int osf = cfi->interleave * cfi->device_type;	/* scale factor */
224  	map_word val[3];
225  	map_word qry[3];
226  
227  	qry[0] = cfi_build_cmd('Q', map, cfi);
228  	qry[1] = cfi_build_cmd('R', map, cfi);
229  	qry[2] = cfi_build_cmd('Y', map, cfi);
230  
231  	val[0] = map_read(map, base + osf*0x10);
232  	val[1] = map_read(map, base + osf*0x11);
233  	val[2] = map_read(map, base + osf*0x12);
234  
235  	if (!map_word_equal(map, qry[0], val[0]))
236  		return 0;
237  
238  	if (!map_word_equal(map, qry[1], val[1]))
239  		return 0;
240  
241  	if (!map_word_equal(map, qry[2], val[2]))
242  		return 0;
243  
244  	return 1; 	/* "QRY" found */
245  }
246  EXPORT_SYMBOL_GPL(cfi_qry_present);
247  
248  int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
249  			     struct cfi_private *cfi)
250  {
251  	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
252  	cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
253  	if (cfi_qry_present(map, base, cfi))
254  		return 1;
255  	/* QRY not found probably we deal with some odd CFI chips */
256  	/* Some revisions of some old Intel chips? */
257  	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
258  	cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
259  	cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
260  	if (cfi_qry_present(map, base, cfi))
261  		return 1;
262  	/* ST M29DW chips */
263  	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
264  	cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
265  	if (cfi_qry_present(map, base, cfi))
266  		return 1;
267  	/* some old SST chips, e.g. 39VF160x/39VF320x */
268  	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
269  	cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
270  	cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
271  	cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
272  	if (cfi_qry_present(map, base, cfi))
273  		return 1;
274  	/* SST 39VF640xB */
275  	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
276  	cfi_send_gen_cmd(0xAA, 0x555, base, map, cfi, cfi->device_type, NULL);
277  	cfi_send_gen_cmd(0x55, 0x2AA, base, map, cfi, cfi->device_type, NULL);
278  	cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
279  	if (cfi_qry_present(map, base, cfi))
280  		return 1;
281  	/* QRY not found */
282  	return 0;
283  }
284  EXPORT_SYMBOL_GPL(cfi_qry_mode_on);
285  
286  void __xipram cfi_qry_mode_off(uint32_t base, struct map_info *map,
287  			       struct cfi_private *cfi)
288  {
289  	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
290  	cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
291  	/* M29W128G flashes require an additional reset command
292  	   when exit qry mode */
293  	if ((cfi->mfr == CFI_MFR_ST) && (cfi->id == 0x227E || cfi->id == 0x7E))
294  		cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
295  }
296  EXPORT_SYMBOL_GPL(cfi_qry_mode_off);
297  
298  struct cfi_extquery *
299  __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name)
300  {
301  	struct cfi_private *cfi = map->fldrv_priv;
302  	__u32 base = 0; // cfi->chips[0].start;
303  	int ofs_factor = cfi->interleave * cfi->device_type;
304  	int i;
305  	struct cfi_extquery *extp = NULL;
306  
307  	if (!adr)
308  		goto out;
309  
310  	printk(KERN_INFO "%s Extended Query Table at 0x%4.4X\n", name, adr);
311  
312  	extp = kmalloc(size, GFP_KERNEL);
313  	if (!extp)
314  		goto out;
315  
316  #ifdef CONFIG_MTD_XIP
317  	local_irq_disable();
318  #endif
319  
320  	/* Switch it into Query Mode */
321  	cfi_qry_mode_on(base, map, cfi);
322  	/* Read in the Extended Query Table */
323  	for (i=0; i<size; i++) {
324  		((unsigned char *)extp)[i] =
325  			cfi_read_query(map, base+((adr+i)*ofs_factor));
326  	}
327  
328  	/* Make sure it returns to read mode */
329  	cfi_qry_mode_off(base, map, cfi);
330  
331  #ifdef CONFIG_MTD_XIP
332  	(void) map_read(map, base);
333  	xip_iprefetch();
334  	local_irq_enable();
335  #endif
336  
337   out:	return extp;
338  }
339  
340  EXPORT_SYMBOL(cfi_read_pri);
341  
342  void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup *fixups)
343  {
344  	struct map_info *map = mtd->priv;
345  	struct cfi_private *cfi = map->fldrv_priv;
346  	struct cfi_fixup *f;
347  
348  	for (f=fixups; f->fixup; f++) {
349  		if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi->mfr)) &&
350  		    ((f->id  == CFI_ID_ANY)  || (f->id  == cfi->id))) {
351  			f->fixup(mtd);
352  		}
353  	}
354  }
355  
356  EXPORT_SYMBOL(cfi_fixup);
357  
358  int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
359  				     loff_t ofs, size_t len, void *thunk)
360  {
361  	struct map_info *map = mtd->priv;
362  	struct cfi_private *cfi = map->fldrv_priv;
363  	unsigned long adr;
364  	int chipnum, ret = 0;
365  	int i, first;
366  	struct mtd_erase_region_info *regions = mtd->eraseregions;
367  
368  	/* Check that both start and end of the requested erase are
369  	 * aligned with the erasesize at the appropriate addresses.
370  	 */
371  
372  	i = 0;
373  
374  	/* Skip all erase regions which are ended before the start of
375  	   the requested erase. Actually, to save on the calculations,
376  	   we skip to the first erase region which starts after the
377  	   start of the requested erase, and then go back one.
378  	*/
379  
380  	while (i < mtd->numeraseregions && ofs >= regions[i].offset)
381  	       i++;
382  	i--;
383  
384  	/* OK, now i is pointing at the erase region in which this
385  	   erase request starts. Check the start of the requested
386  	   erase range is aligned with the erase size which is in
387  	   effect here.
388  	*/
389  
390  	if (ofs & (regions[i].erasesize-1))
391  		return -EINVAL;
392  
393  	/* Remember the erase region we start on */
394  	first = i;
395  
396  	/* Next, check that the end of the requested erase is aligned
397  	 * with the erase region at that address.
398  	 */
399  
400  	while (i<mtd->numeraseregions && (ofs + len) >= regions[i].offset)
401  		i++;
402  
403  	/* As before, drop back one to point at the region in which
404  	   the address actually falls
405  	*/
406  	i--;
407  
408  	if ((ofs + len) & (regions[i].erasesize-1))
409  		return -EINVAL;
410  
411  	chipnum = ofs >> cfi->chipshift;
412  	adr = ofs - (chipnum << cfi->chipshift);
413  
414  	i=first;
415  
416  	while(len) {
417  		int size = regions[i].erasesize;
418  
419  		ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk);
420  
421  		if (ret)
422  			return ret;
423  
424  		adr += size;
425  		ofs += size;
426  		len -= size;
427  
428  		if (ofs == regions[i].offset + size * regions[i].numblocks)
429  			i++;
430  
431  		if (adr >> cfi->chipshift) {
432  			adr = 0;
433  			chipnum++;
434  
435  			if (chipnum >= cfi->numchips)
436  				break;
437  		}
438  	}
439  
440  	return 0;
441  }
442  
443  EXPORT_SYMBOL(cfi_varsize_frob);
444  
445  MODULE_LICENSE("GPL");
446