• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * MTD driver for the 28F160F3 Flash Memory (non-CFI) on LART.
4  *
5  * Author: Abraham vd Merwe <abraham@2d3d.co.za>
6  *
7  * Copyright (c) 2001, 2d3D, Inc.
8  *
9  * This code is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  * References:
14  *
15  *    [1] 3 Volt Fast Boot Block Flash Memory" Intel Datasheet
16  *           - Order Number: 290644-005
17  *           - January 2000
18  *
19  *    [2] MTD internal API documentation
20  *           - http://www.linux-mtd.infradead.org/tech/
21  *
22  * Limitations:
23  *
24  *    Even though this driver is written for 3 Volt Fast Boot
25  *    Block Flash Memory, it is rather specific to LART. With
26  *    Minor modifications, notably the without data/address line
27  *    mangling and different bus settings, etc. it should be
28  *    trivial to adapt to other platforms.
29  *
30  *    If somebody would sponsor me a different board, I'll
31  *    adapt the driver (:
32  */
33 
34 /* debugging */
35 //#define LART_DEBUG
36 
37 /* partition support */
38 #define HAVE_PARTITIONS
39 
40 #include <linux/kernel.h>
41 #include <linux/module.h>
42 #include <linux/types.h>
43 #include <linux/init.h>
44 #include <linux/errno.h>
45 #include <linux/string.h>
46 #include <linux/mtd/mtd.h>
47 #ifdef HAVE_PARTITIONS
48 #include <linux/mtd/partitions.h>
49 #endif
50 
51 #ifndef CONFIG_SA1100_LART
52 #error This is for LART architecture only
53 #endif
54 
55 static char module_name[] = "lart";
56 
57 /*
58  * These values is specific to 28Fxxxx3 flash memory.
59  * See section 2.3.1 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
60  */
61 #define FLASH_BLOCKSIZE_PARAM		(4096 * BUSWIDTH)
62 #define FLASH_NUMBLOCKS_16m_PARAM	8
63 #define FLASH_NUMBLOCKS_8m_PARAM	8
64 
65 /*
66  * These values is specific to 28Fxxxx3 flash memory.
67  * See section 2.3.2 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
68  */
69 #define FLASH_BLOCKSIZE_MAIN		(32768 * BUSWIDTH)
70 #define FLASH_NUMBLOCKS_16m_MAIN	31
71 #define FLASH_NUMBLOCKS_8m_MAIN		15
72 
73 /*
74  * These values are specific to LART
75  */
76 
77 /* general */
78 #define BUSWIDTH			4				/* don't change this - a lot of the code _will_ break if you change this */
79 #define FLASH_OFFSET		0xe8000000		/* see linux/arch/arm/mach-sa1100/lart.c */
80 
81 /* blob */
82 #define NUM_BLOB_BLOCKS		FLASH_NUMBLOCKS_16m_PARAM
83 #define BLOB_START			0x00000000
84 #define BLOB_LEN			(NUM_BLOB_BLOCKS * FLASH_BLOCKSIZE_PARAM)
85 
86 /* kernel */
87 #define NUM_KERNEL_BLOCKS	7
88 #define KERNEL_START		(BLOB_START + BLOB_LEN)
89 #define KERNEL_LEN			(NUM_KERNEL_BLOCKS * FLASH_BLOCKSIZE_MAIN)
90 
91 /* initial ramdisk */
92 #define NUM_INITRD_BLOCKS	24
93 #define INITRD_START		(KERNEL_START + KERNEL_LEN)
94 #define INITRD_LEN			(NUM_INITRD_BLOCKS * FLASH_BLOCKSIZE_MAIN)
95 
96 /*
97  * See section 4.0 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
98  */
99 #define READ_ARRAY			0x00FF00FF		/* Read Array/Reset */
100 #define READ_ID_CODES		0x00900090		/* Read Identifier Codes */
101 #define ERASE_SETUP			0x00200020		/* Block Erase */
102 #define ERASE_CONFIRM		0x00D000D0		/* Block Erase and Program Resume */
103 #define PGM_SETUP			0x00400040		/* Program */
104 #define STATUS_READ			0x00700070		/* Read Status Register */
105 #define STATUS_CLEAR		0x00500050		/* Clear Status Register */
106 #define STATUS_BUSY			0x00800080		/* Write State Machine Status (WSMS) */
107 #define STATUS_ERASE_ERR	0x00200020		/* Erase Status (ES) */
108 #define STATUS_PGM_ERR		0x00100010		/* Program Status (PS) */
109 
110 /*
111  * See section 4.2 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
112  */
113 #define FLASH_MANUFACTURER			0x00890089
114 #define FLASH_DEVICE_8mbit_TOP		0x88f188f1
115 #define FLASH_DEVICE_8mbit_BOTTOM	0x88f288f2
116 #define FLASH_DEVICE_16mbit_TOP		0x88f388f3
117 #define FLASH_DEVICE_16mbit_BOTTOM	0x88f488f4
118 
119 /***************************************************************************************************/
120 
121 /*
122  * The data line mapping on LART is as follows:
123  *
124  *   	 U2  CPU |   U3  CPU
125  *   	 -------------------
126  *   	  0  20  |   0   12
127  *   	  1  22  |   1   14
128  *   	  2  19  |   2   11
129  *   	  3  17  |   3   9
130  *   	  4  24  |   4   0
131  *   	  5  26  |   5   2
132  *   	  6  31  |   6   7
133  *   	  7  29  |   7   5
134  *   	  8  21  |   8   13
135  *   	  9  23  |   9   15
136  *   	  10 18  |   10  10
137  *   	  11 16  |   11  8
138  *   	  12 25  |   12  1
139  *   	  13 27  |   13  3
140  *   	  14 30  |   14  6
141  *   	  15 28  |   15  4
142  */
143 
144 /* Mangle data (x) */
145 #define DATA_TO_FLASH(x)				\
146 	(									\
147 		(((x) & 0x08009000) >> 11)	+	\
148 		(((x) & 0x00002000) >> 10)	+	\
149 		(((x) & 0x04004000) >> 8)	+	\
150 		(((x) & 0x00000010) >> 4)	+	\
151 		(((x) & 0x91000820) >> 3)	+	\
152 		(((x) & 0x22080080) >> 2)	+	\
153 		((x) & 0x40000400)			+	\
154 		(((x) & 0x00040040) << 1)	+	\
155 		(((x) & 0x00110000) << 4)	+	\
156 		(((x) & 0x00220100) << 5)	+	\
157 		(((x) & 0x00800208) << 6)	+	\
158 		(((x) & 0x00400004) << 9)	+	\
159 		(((x) & 0x00000001) << 12)	+	\
160 		(((x) & 0x00000002) << 13)		\
161 	)
162 
163 /* Unmangle data (x) */
164 #define FLASH_TO_DATA(x)				\
165 	(									\
166 		(((x) & 0x00010012) << 11)	+	\
167 		(((x) & 0x00000008) << 10)	+	\
168 		(((x) & 0x00040040) << 8)	+	\
169 		(((x) & 0x00000001) << 4)	+	\
170 		(((x) & 0x12200104) << 3)	+	\
171 		(((x) & 0x08820020) << 2)	+	\
172 		((x) & 0x40000400)			+	\
173 		(((x) & 0x00080080) >> 1)	+	\
174 		(((x) & 0x01100000) >> 4)	+	\
175 		(((x) & 0x04402000) >> 5)	+	\
176 		(((x) & 0x20008200) >> 6)	+	\
177 		(((x) & 0x80000800) >> 9)	+	\
178 		(((x) & 0x00001000) >> 12)	+	\
179 		(((x) & 0x00004000) >> 13)		\
180 	)
181 
182 /*
183  * The address line mapping on LART is as follows:
184  *
185  *   	 U3  CPU |   U2  CPU
186  *   	 -------------------
187  *   	  0  2   |   0   2
188  *   	  1  3   |   1   3
189  *   	  2  9   |   2   9
190  *   	  3  13  |   3   8
191  *   	  4  8   |   4   7
192  *   	  5  12  |   5   6
193  *   	  6  11  |   6   5
194  *   	  7  10  |   7   4
195  *   	  8  4   |   8   10
196  *   	  9  5   |   9   11
197  *   	 10  6   |   10  12
198  *   	 11  7   |   11  13
199  *
200  *   	 BOOT BLOCK BOUNDARY
201  *
202  *   	 12  15  |   12  15
203  *   	 13  14  |   13  14
204  *   	 14  16  |   14  16
205  *
206  *   	 MAIN BLOCK BOUNDARY
207  *
208  *   	 15  17  |   15  18
209  *   	 16  18  |   16  17
210  *   	 17  20  |   17  20
211  *   	 18  19  |   18  19
212  *   	 19  21  |   19  21
213  *
214  * As we can see from above, the addresses aren't mangled across
215  * block boundaries, so we don't need to worry about address
216  * translations except for sending/reading commands during
217  * initialization
218  */
219 
220 /* Mangle address (x) on chip U2 */
221 #define ADDR_TO_FLASH_U2(x)				\
222 	(									\
223 		(((x) & 0x00000f00) >> 4)	+	\
224 		(((x) & 0x00042000) << 1)	+	\
225 		(((x) & 0x0009c003) << 2)	+	\
226 		(((x) & 0x00021080) << 3)	+	\
227 		(((x) & 0x00000010) << 4)	+	\
228 		(((x) & 0x00000040) << 5)	+	\
229 		(((x) & 0x00000024) << 7)	+	\
230 		(((x) & 0x00000008) << 10)		\
231 	)
232 
233 /* Unmangle address (x) on chip U2 */
234 #define FLASH_U2_TO_ADDR(x)				\
235 	(									\
236 		(((x) << 4) & 0x00000f00)	+	\
237 		(((x) >> 1) & 0x00042000)	+	\
238 		(((x) >> 2) & 0x0009c003)	+	\
239 		(((x) >> 3) & 0x00021080)	+	\
240 		(((x) >> 4) & 0x00000010)	+	\
241 		(((x) >> 5) & 0x00000040)	+	\
242 		(((x) >> 7) & 0x00000024)	+	\
243 		(((x) >> 10) & 0x00000008)		\
244 	)
245 
246 /* Mangle address (x) on chip U3 */
247 #define ADDR_TO_FLASH_U3(x)				\
248 	(									\
249 		(((x) & 0x00000080) >> 3)	+	\
250 		(((x) & 0x00000040) >> 1)	+	\
251 		(((x) & 0x00052020) << 1)	+	\
252 		(((x) & 0x00084f03) << 2)	+	\
253 		(((x) & 0x00029010) << 3)	+	\
254 		(((x) & 0x00000008) << 5)	+	\
255 		(((x) & 0x00000004) << 7)		\
256 	)
257 
258 /* Unmangle address (x) on chip U3 */
259 #define FLASH_U3_TO_ADDR(x)				\
260 	(									\
261 		(((x) << 3) & 0x00000080)	+	\
262 		(((x) << 1) & 0x00000040)	+	\
263 		(((x) >> 1) & 0x00052020)	+	\
264 		(((x) >> 2) & 0x00084f03)	+	\
265 		(((x) >> 3) & 0x00029010)	+	\
266 		(((x) >> 5) & 0x00000008)	+	\
267 		(((x) >> 7) & 0x00000004)		\
268 	)
269 
270 /***************************************************************************************************/
271 
read8(__u32 offset)272 static __u8 read8 (__u32 offset)
273 {
274    volatile __u8 *data = (__u8 *) (FLASH_OFFSET + offset);
275 #ifdef LART_DEBUG
276    printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.2x\n", __func__, offset, *data);
277 #endif
278    return (*data);
279 }
280 
read32(__u32 offset)281 static __u32 read32 (__u32 offset)
282 {
283    volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
284 #ifdef LART_DEBUG
285    printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.8x\n", __func__, offset, *data);
286 #endif
287    return (*data);
288 }
289 
write32(__u32 x,__u32 offset)290 static void write32 (__u32 x,__u32 offset)
291 {
292    volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
293    *data = x;
294 #ifdef LART_DEBUG
295    printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, *data);
296 #endif
297 }
298 
299 /***************************************************************************************************/
300 
301 /*
302  * Probe for 16mbit flash memory on a LART board without doing
303  * too much damage. Since we need to write 1 dword to memory,
304  * we're f**cked if this happens to be DRAM since we can't
305  * restore the memory (otherwise we might exit Read Array mode).
306  *
307  * Returns 1 if we found 16mbit flash memory on LART, 0 otherwise.
308  */
flash_probe(void)309 static int flash_probe (void)
310 {
311    __u32 manufacturer,devtype;
312 
313    /* setup "Read Identifier Codes" mode */
314    write32 (DATA_TO_FLASH (READ_ID_CODES),0x00000000);
315 
316    /* probe U2. U2/U3 returns the same data since the first 3
317 	* address lines is mangled in the same way */
318    manufacturer = FLASH_TO_DATA (read32 (ADDR_TO_FLASH_U2 (0x00000000)));
319    devtype = FLASH_TO_DATA (read32 (ADDR_TO_FLASH_U2 (0x00000001)));
320 
321    /* put the flash back into command mode */
322    write32 (DATA_TO_FLASH (READ_ARRAY),0x00000000);
323 
324    return (manufacturer == FLASH_MANUFACTURER && (devtype == FLASH_DEVICE_16mbit_TOP || devtype == FLASH_DEVICE_16mbit_BOTTOM));
325 }
326 
327 /*
328  * Erase one block of flash memory at offset ``offset'' which is any
329  * address within the block which should be erased.
330  *
331  * Returns 1 if successful, 0 otherwise.
332  */
erase_block(__u32 offset)333 static inline int erase_block (__u32 offset)
334 {
335    __u32 status;
336 
337 #ifdef LART_DEBUG
338    printk (KERN_DEBUG "%s(): 0x%.8x\n", __func__, offset);
339 #endif
340 
341    /* erase and confirm */
342    write32 (DATA_TO_FLASH (ERASE_SETUP),offset);
343    write32 (DATA_TO_FLASH (ERASE_CONFIRM),offset);
344 
345    /* wait for block erase to finish */
346    do
347 	 {
348 		write32 (DATA_TO_FLASH (STATUS_READ),offset);
349 		status = FLASH_TO_DATA (read32 (offset));
350 	 }
351    while ((~status & STATUS_BUSY) != 0);
352 
353    /* put the flash back into command mode */
354    write32 (DATA_TO_FLASH (READ_ARRAY),offset);
355 
356    /* was the erase successfull? */
357    if ((status & STATUS_ERASE_ERR))
358 	 {
359 		printk (KERN_WARNING "%s: erase error at address 0x%.8x.\n",module_name,offset);
360 		return (0);
361 	 }
362 
363    return (1);
364 }
365 
flash_erase(struct mtd_info * mtd,struct erase_info * instr)366 static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
367 {
368    __u32 addr,len;
369    int i,first;
370 
371 #ifdef LART_DEBUG
372    printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n", __func__, instr->addr, instr->len);
373 #endif
374 
375    /* sanity checks */
376    if (instr->addr + instr->len > mtd->size) return (-EINVAL);
377 
378    /*
379 	* check that both start and end of the requested erase are
380 	* aligned with the erasesize at the appropriate addresses.
381 	*
382 	* skip all erase regions which are ended before the start of
383 	* the requested erase. Actually, to save on the calculations,
384 	* we skip to the first erase region which starts after the
385 	* start of the requested erase, and then go back one.
386 	*/
387    for (i = 0; i < mtd->numeraseregions && instr->addr >= mtd->eraseregions[i].offset; i++) ;
388    i--;
389 
390    /*
391 	* ok, now i is pointing at the erase region in which this
392 	* erase request starts. Check the start of the requested
393 	* erase range is aligned with the erase size which is in
394 	* effect here.
395 	*/
396    if (instr->addr & (mtd->eraseregions[i].erasesize - 1)) return (-EINVAL);
397 
398    /* Remember the erase region we start on */
399    first = i;
400 
401    /*
402 	* next, check that the end of the requested erase is aligned
403 	* with the erase region at that address.
404 	*
405 	* as before, drop back one to point at the region in which
406 	* the address actually falls
407 	*/
408    for (; i < mtd->numeraseregions && instr->addr + instr->len >= mtd->eraseregions[i].offset; i++) ;
409    i--;
410 
411    /* is the end aligned on a block boundary? */
412    if ((instr->addr + instr->len) & (mtd->eraseregions[i].erasesize - 1)) return (-EINVAL);
413 
414    addr = instr->addr;
415    len = instr->len;
416 
417    i = first;
418 
419    /* now erase those blocks */
420    while (len)
421 	 {
422 		if (!erase_block (addr))
423 		  {
424 			 instr->state = MTD_ERASE_FAILED;
425 			 return (-EIO);
426 		  }
427 
428 		addr += mtd->eraseregions[i].erasesize;
429 		len -= mtd->eraseregions[i].erasesize;
430 
431 		if (addr == mtd->eraseregions[i].offset + (mtd->eraseregions[i].erasesize * mtd->eraseregions[i].numblocks)) i++;
432 	 }
433 
434    instr->state = MTD_ERASE_DONE;
435    mtd_erase_callback(instr);
436 
437    return (0);
438 }
439 
flash_read(struct mtd_info * mtd,loff_t from,size_t len,size_t * retlen,u_char * buf)440 static int flash_read (struct mtd_info *mtd,loff_t from,size_t len,size_t *retlen,u_char *buf)
441 {
442 #ifdef LART_DEBUG
443    printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n", __func__, (__u32)from, len);
444 #endif
445 
446    /* sanity checks */
447    if (!len) return (0);
448    if (from + len > mtd->size) return (-EINVAL);
449 
450    /* we always read len bytes */
451    *retlen = len;
452 
453    /* first, we read bytes until we reach a dword boundary */
454    if (from & (BUSWIDTH - 1))
455 	 {
456 		int gap = BUSWIDTH - (from & (BUSWIDTH - 1));
457 
458 		while (len && gap--) *buf++ = read8 (from++), len--;
459 	 }
460 
461    /* now we read dwords until we reach a non-dword boundary */
462    while (len >= BUSWIDTH)
463 	 {
464 		*((__u32 *) buf) = read32 (from);
465 
466 		buf += BUSWIDTH;
467 		from += BUSWIDTH;
468 		len -= BUSWIDTH;
469 	 }
470 
471    /* top up the last unaligned bytes */
472    if (len & (BUSWIDTH - 1))
473 	 while (len--) *buf++ = read8 (from++);
474 
475    return (0);
476 }
477 
478 /*
479  * Write one dword ``x'' to flash memory at offset ``offset''. ``offset''
480  * must be 32 bits, i.e. it must be on a dword boundary.
481  *
482  * Returns 1 if successful, 0 otherwise.
483  */
write_dword(__u32 offset,__u32 x)484 static inline int write_dword (__u32 offset,__u32 x)
485 {
486    __u32 status;
487 
488 #ifdef LART_DEBUG
489    printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, x);
490 #endif
491 
492    /* setup writing */
493    write32 (DATA_TO_FLASH (PGM_SETUP),offset);
494 
495    /* write the data */
496    write32 (x,offset);
497 
498    /* wait for the write to finish */
499    do
500 	 {
501 		write32 (DATA_TO_FLASH (STATUS_READ),offset);
502 		status = FLASH_TO_DATA (read32 (offset));
503 	 }
504    while ((~status & STATUS_BUSY) != 0);
505 
506    /* put the flash back into command mode */
507    write32 (DATA_TO_FLASH (READ_ARRAY),offset);
508 
509    /* was the write successfull? */
510    if ((status & STATUS_PGM_ERR) || read32 (offset) != x)
511 	 {
512 		printk (KERN_WARNING "%s: write error at address 0x%.8x.\n",module_name,offset);
513 		return (0);
514 	 }
515 
516    return (1);
517 }
518 
flash_write(struct mtd_info * mtd,loff_t to,size_t len,size_t * retlen,const u_char * buf)519 static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
520 {
521    __u8 tmp[4];
522    int i,n;
523 
524 #ifdef LART_DEBUG
525    printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n", __func__, (__u32)to, len);
526 #endif
527 
528    *retlen = 0;
529 
530    /* sanity checks */
531    if (!len) return (0);
532    if (to + len > mtd->size) return (-EINVAL);
533 
534    /* first, we write a 0xFF.... padded byte until we reach a dword boundary */
535    if (to & (BUSWIDTH - 1))
536 	 {
537 		__u32 aligned = to & ~(BUSWIDTH - 1);
538 		int gap = to - aligned;
539 
540 		i = n = 0;
541 
542 		while (gap--) tmp[i++] = 0xFF;
543 		while (len && i < BUSWIDTH) tmp[i++] = buf[n++], len--;
544 		while (i < BUSWIDTH) tmp[i++] = 0xFF;
545 
546 		if (!write_dword (aligned,*((__u32 *) tmp))) return (-EIO);
547 
548 		to += n;
549 		buf += n;
550 		*retlen += n;
551 	 }
552 
553    /* now we write dwords until we reach a non-dword boundary */
554    while (len >= BUSWIDTH)
555 	 {
556 		if (!write_dword (to,*((__u32 *) buf))) return (-EIO);
557 
558 		to += BUSWIDTH;
559 		buf += BUSWIDTH;
560 		*retlen += BUSWIDTH;
561 		len -= BUSWIDTH;
562 	 }
563 
564    /* top up the last unaligned bytes, padded with 0xFF.... */
565    if (len & (BUSWIDTH - 1))
566 	 {
567 		i = n = 0;
568 
569 		while (len--) tmp[i++] = buf[n++];
570 		while (i < BUSWIDTH) tmp[i++] = 0xFF;
571 
572 		if (!write_dword (to,*((__u32 *) tmp))) return (-EIO);
573 
574 		*retlen += n;
575 	 }
576 
577    return (0);
578 }
579 
580 /***************************************************************************************************/
581 
582 static struct mtd_info mtd;
583 
584 static struct mtd_erase_region_info erase_regions[] = {
585 	/* parameter blocks */
586 	{
587 		.offset		= 0x00000000,
588 		.erasesize	= FLASH_BLOCKSIZE_PARAM,
589 		.numblocks	= FLASH_NUMBLOCKS_16m_PARAM,
590 	},
591 	/* main blocks */
592 	{
593 		.offset	 = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM,
594 		.erasesize	= FLASH_BLOCKSIZE_MAIN,
595 		.numblocks	= FLASH_NUMBLOCKS_16m_MAIN,
596 	}
597 };
598 
599 #ifdef HAVE_PARTITIONS
600 static struct mtd_partition lart_partitions[] = {
601 	/* blob */
602 	{
603 		.name	= "blob",
604 		.offset	= BLOB_START,
605 		.size	= BLOB_LEN,
606 	},
607 	/* kernel */
608 	{
609 		.name	= "kernel",
610 		.offset	= KERNEL_START,		/* MTDPART_OFS_APPEND */
611 		.size	= KERNEL_LEN,
612 	},
613 	/* initial ramdisk / file system */
614 	{
615 		.name	= "file system",
616 		.offset	= INITRD_START,		/* MTDPART_OFS_APPEND */
617 		.size	= INITRD_LEN,		/* MTDPART_SIZ_FULL */
618 	}
619 };
620 #endif
621 
lart_flash_init(void)622 static int __init lart_flash_init (void)
623 {
624    int result;
625    memset (&mtd,0,sizeof (mtd));
626    printk ("MTD driver for LART. Written by Abraham vd Merwe <abraham@2d3d.co.za>\n");
627    printk ("%s: Probing for 28F160x3 flash on LART...\n",module_name);
628    if (!flash_probe ())
629 	 {
630 		printk (KERN_WARNING "%s: Found no LART compatible flash device\n",module_name);
631 		return (-ENXIO);
632 	 }
633    printk ("%s: This looks like a LART board to me.\n",module_name);
634    mtd.name = module_name;
635    mtd.type = MTD_NORFLASH;
636    mtd.writesize = 1;
637    mtd.flags = MTD_CAP_NORFLASH;
638    mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN;
639    mtd.erasesize = FLASH_BLOCKSIZE_MAIN;
640    mtd.numeraseregions = ARRAY_SIZE(erase_regions);
641    mtd.eraseregions = erase_regions;
642    mtd.erase = flash_erase;
643    mtd.read = flash_read;
644    mtd.write = flash_write;
645    mtd.owner = THIS_MODULE;
646 
647 #ifdef LART_DEBUG
648    printk (KERN_DEBUG
649 		   "mtd.name = %s\n"
650 		   "mtd.size = 0x%.8x (%uM)\n"
651 		   "mtd.erasesize = 0x%.8x (%uK)\n"
652 		   "mtd.numeraseregions = %d\n",
653 		   mtd.name,
654 		   mtd.size,mtd.size / (1024*1024),
655 		   mtd.erasesize,mtd.erasesize / 1024,
656 		   mtd.numeraseregions);
657 
658    if (mtd.numeraseregions)
659 	 for (result = 0; result < mtd.numeraseregions; result++)
660 	   printk (KERN_DEBUG
661 			   "\n\n"
662 			   "mtd.eraseregions[%d].offset = 0x%.8x\n"
663 			   "mtd.eraseregions[%d].erasesize = 0x%.8x (%uK)\n"
664 			   "mtd.eraseregions[%d].numblocks = %d\n",
665 			   result,mtd.eraseregions[result].offset,
666 			   result,mtd.eraseregions[result].erasesize,mtd.eraseregions[result].erasesize / 1024,
667 			   result,mtd.eraseregions[result].numblocks);
668 
669 #ifdef HAVE_PARTITIONS
670    printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions));
671 
672    for (result = 0; result < ARRAY_SIZE(lart_partitions); result++)
673 	 printk (KERN_DEBUG
674 			 "\n\n"
675 			 "lart_partitions[%d].name = %s\n"
676 			 "lart_partitions[%d].offset = 0x%.8x\n"
677 			 "lart_partitions[%d].size = 0x%.8x (%uK)\n",
678 			 result,lart_partitions[result].name,
679 			 result,lart_partitions[result].offset,
680 			 result,lart_partitions[result].size,lart_partitions[result].size / 1024);
681 #endif
682 #endif
683 
684 #ifndef HAVE_PARTITIONS
685    result = add_mtd_device (&mtd);
686 #else
687    result = add_mtd_partitions (&mtd,lart_partitions, ARRAY_SIZE(lart_partitions));
688 #endif
689 
690    return (result);
691 }
692 
lart_flash_exit(void)693 static void __exit lart_flash_exit (void)
694 {
695 #ifndef HAVE_PARTITIONS
696    del_mtd_device (&mtd);
697 #else
698    del_mtd_partitions (&mtd);
699 #endif
700 }
701 
702 module_init (lart_flash_init);
703 module_exit (lart_flash_exit);
704 
705 MODULE_LICENSE("GPL");
706 MODULE_AUTHOR("Abraham vd Merwe <abraham@2d3d.co.za>");
707 MODULE_DESCRIPTION("MTD driver for Intel 28F160F3 on LART board");
708