File: /usr/src/linux/drivers/mtd/devices/doc1000.c

1     /*======================================================================
2     
3       $Id: doc1000.c,v 1.11 2000/11/24 13:43:16 dwmw2 Exp $
4     
5     ======================================================================*/
6     
7     
8     #include <linux/config.h>
9     #include <linux/module.h>
10     #include <asm/uaccess.h>
11     #include <linux/types.h>
12     #include <linux/kernel.h>
13     #include <linux/sched.h>
14     #include <linux/ptrace.h>
15     #include <linux/slab.h>
16     #include <linux/string.h>
17     #include <linux/timer.h>
18     #include <linux/major.h>
19     #include <linux/fs.h>
20     #include <linux/ioctl.h>
21     #include <asm/io.h>
22     #include <asm/system.h>
23     #include <asm/segment.h>
24     #include <stdarg.h>
25     #include <linux/delay.h>
26     #include <linux/init.h>
27     
28     #include <linux/mtd/mtd.h>
29     #include <linux/mtd/iflash.h>
30     
31     /* Parameters that can be set with 'insmod' */
32     
33     static u_long base              = 0xe0000;
34     static int erase_timeout	= 10*HZ;	/* in ticks */
35     static int retry_limit		= 4;		/* write retries */
36     static u_long max_tries       	= 4096;		/* status polling */
37     
38     MODULE_PARM(base,"l");
39     MODULE_PARM(erase_timeout, "i");
40     MODULE_PARM(retry_limit, "i");
41     MODULE_PARM(max_tries, "i");
42     
43     #define WINDOW_SIZE 0x2000
44     #define WINDOW_MASK (WINDOW_SIZE - 1)
45     #define PAGEREG_LO (WINDOW_SIZE)
46     #define PAGEREG_HI (WINDOW_SIZE + 2)
47     
48     static struct mtd_info *mymtd;
49     static struct timer_list flashcard_timer;
50     
51     #define MAX_CELLS		32
52     #define MAX_FLASH_DEVICES       8
53     
54     /* A flash region is composed of one or more "cells", where we allow
55        simultaneous erases if they are in different cells */
56     
57     
58     
59     struct mypriv {
60     	u_char *baseaddr;
61     	u_short curpage;
62     	u_char locked;
63     	u_short numdevices;
64     	u_char interleave;
65     	struct erase_info *cur_erases;
66     	wait_queue_head_t wq;
67     	u_char devstat[MAX_FLASH_DEVICES];
68     	u_long devshift;
69     };
70     
71     
72     static void flashcard_periodic(u_long data);
73     static int flashcard_erase (struct mtd_info *mtd, struct erase_info *instr);
74     static int flashcard_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
75     static int flashcard_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
76     static void flashcard_sync (struct mtd_info *mtd);
77     
78     static inline void resume_erase(volatile u_char *addr);
79     static inline int suspend_erase(volatile u_char *addr);
80     static inline int byte_write (volatile u_char *addr, u_char byte);
81     static inline int word_write (volatile u_char *addr, __u16 word);
82     static inline int check_write(volatile u_char *addr);
83     static inline void block_erase (volatile u_char *addr);
84     static inline int check_erase(volatile u_char *addr);
85     
86     #ifdef CONFIG_SMP
87     #warning This is definitely not SMP safe. Lock the paging mechanism.
88     #endif
89     
90     static u_char *pagein(struct mtd_info *mtd, u_long addr)
91     {
92       struct mypriv *priv=mtd->priv;
93       u_short page = addr >> 13;
94     
95       priv->baseaddr[PAGEREG_LO] = page & 0xff;
96       priv->baseaddr[PAGEREG_HI] = page >> 8;
97       priv->curpage = page;
98       
99       return &priv->baseaddr[addr & WINDOW_MASK];
100     }
101     
102     
103     void flashcard_sync (struct mtd_info *mtd)
104     {
105     	struct mypriv *priv=mtd->priv;
106     
107     	flashcard_periodic((u_long) mtd);
108     	printk("sync...");
109     	if (priv->cur_erases)
110     		interruptible_sleep_on(&priv->wq);
111     	printk("Done.\n");
112     }
113     
114     int flashcard_erase (struct mtd_info *mtd, struct erase_info *instr)
115     {
116     	u_char *pageaddr;
117     	struct mypriv *priv=mtd->priv;
118     	struct erase_info **tmp=&priv->cur_erases;
119     	
120     	if (instr->len != mtd->erasesize)
121     		return -EINVAL;
122     	if (instr->addr + instr->len > mtd->size)
123     		return -EINVAL;
124     
125     	pageaddr=pagein(mtd,instr->addr);
126     	instr->mtd = mtd;
127     	instr->dev = instr->addr >> priv->devshift;
128     	instr->cell = (instr->addr - (instr->dev << priv->devshift)) / mtd->erasesize;
129     	instr->next = NULL;
130     	instr->state = MTD_ERASE_PENDING;
131     	
132     	while (*tmp)
133     	{
134     		tmp = &((*tmp) -> next);
135     	}
136     	
137     	*tmp = instr;
138     	flashcard_periodic((u_long)mtd);
139     	return 0;
140     }
141     
142     
143     int flashcard_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
144     {
145      	u_char *pageaddr=pagein(mtd,from);
146     	struct mypriv *priv=mtd->priv;
147     	u_char device = from >> priv->devshift;
148     	u_char cell = (int) (from - (device << priv->devshift)) / mtd->erasesize;
149     	int ret = 0, timeron = 0;
150     
151     	if ((from & WINDOW_MASK) + len <= WINDOW_SIZE)
152     		*retlen = len;
153     	else
154     		*retlen = WINDOW_SIZE - (from & WINDOW_MASK);
155     
156     	if (priv->devstat[device])
157     	{
158     		
159     		/* There is an erase in progress or pending for this device. Stop it */
160     		timeron = del_timer(&flashcard_timer);
161     		
162     		if (priv->cur_erases && priv->cur_erases->cell == cell) 
163     			
164     		{
165     			/* The erase is on the current cell. Just return all 0xff */ 
166     			add_timer(&flashcard_timer);
167     			
168     			
169     			printk("Cell %d currently erasing. Setting to all 0xff\n",cell);
170     			memset(buf, 0xff, *retlen);
171     			return 0;
172     		}
173     		if (priv->devstat[device] == MTD_ERASING)
174     		{
175     			ret = suspend_erase(pageaddr);
176     			priv->devstat[device] = MTD_ERASE_SUSPEND;
177     		       
178     			if (ret) 
179     			{
180     				printk("flashcard: failed to suspend erase\n");
181     				add_timer (&flashcard_timer);
182     				return ret;
183     			}
184     		}
185     
186     	}
187     
188     	writew(IF_READ_ARRAY, (u_long)pageaddr & ~1);
189     	
190     	ret = 0;
191     	memcpy (buf, pageaddr, *retlen);
192     	
193     	writew(IF_READ_CSR, (u_long)pageaddr & ~1);
194     	
195     	
196     	if (priv->devstat[device] & MTD_ERASE_SUSPEND)
197     	{
198     		resume_erase(pageaddr);
199     		priv->devstat[device]=MTD_ERASING;
200     	}
201     
202     
203     	if (timeron) add_timer (&flashcard_timer);
204     		
205     	return ret;
206     }
207     
208     
209     int flashcard_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
210     {
211     	struct mypriv *priv = (struct mypriv *)mtd->priv;
212      	u_char *endaddr, *startaddr;
213     	register u_char *pageaddr;
214     	u_char device = to >> priv->devshift;
215     /*	jiffies_t oldj=jiffies;*/
216     	int ret;
217     
218     	while (priv->devstat[device])
219     	{
220     		flashcard_sync(mtd);
221     	}
222     
223     	if ((to & WINDOW_MASK) + len <= WINDOW_SIZE)
224     		*retlen = len;
225     	else
226     		*retlen = WINDOW_SIZE - (to & WINDOW_MASK);
227     	
228     	pageaddr = pagein(mtd, to);
229     	startaddr = (u_char *)((u_long) pageaddr & ~1);
230     	endaddr = pageaddr+(*retlen);
231     
232     
233     
234     	/* Set up to read */
235     	writew(IF_READ_CSR, startaddr);
236     	
237     	/* Make sure it's aligned by reading the first byte if necessary */
238     	if (to & 1)
239     	{
240     		/* Unaligned access */
241     
242     		u_char cbuf;
243     
244     		cbuf = *buf;
245     
246     		if (!((u_long)pageaddr & 0xf))
247     			schedule();
248     			
249     		ret = byte_write(pageaddr, cbuf);
250     		if (ret) return ret;
251     
252     		pageaddr++; buf++;
253     	}
254     
255     
256     	for ( ; pageaddr + 1 < endaddr; buf += 2, pageaddr += 2)
257     		{
258     			/* if ((u_long)pageaddr & 0xf) schedule();*/
259     			
260     			ret = word_write(pageaddr, *(__u16 *)buf);
261     			if (ret) 
262     				return ret;
263     		}
264     	
265     	if (pageaddr != endaddr)
266     	{
267     		/* One more byte to write at the end. */
268     		u_char cbuf;
269     
270     		cbuf = *buf;
271     
272     		ret = byte_write(pageaddr, cbuf);
273     
274     		if (ret) return ret;
275     	}
276     
277     	return check_write(startaddr);
278     /*	printk("Time taken in flashcard_write: %lx jiffies\n",jiffies - oldj);*/
279     }
280     
281     
282     
283     
284     /*====================================================================*/
285     
286     static inline int byte_write (volatile u_char *addr, u_char byte)
287     {
288     	register u_char status;
289      	register u_short i = 0;
290       	
291      	do {
292     		status = readb(addr);
293     		if (status & CSR_WR_READY)
294     		{
295     			writeb(IF_WRITE & 0xff, addr);
296     			writeb(byte, addr);
297     			return 0;
298     		}
299     		i++;
300     	} while(i < max_tries);
301     
302     		
303     	printk(KERN_NOTICE "flashcard: byte_write timed out, status 0x%x\n",status);
304     	return -EIO;
305     }
306     
307     static inline int word_write (volatile u_char *addr, __u16 word)
308     {
309     	register u_short status;
310     	register u_short i = 0;
311     	
312     	do {
313     		status = readw(addr);
314     		if ((status & CSR_WR_READY) == CSR_WR_READY)
315     		{
316     			writew(IF_WRITE, addr);
317     			writew(word, addr);
318     			return 0;
319     		}
320     		i++;
321     	} while(i < max_tries);
322     		
323     	printk(KERN_NOTICE "flashcard: word_write timed out at %p, status 0x%x\n", addr, status);
324     	return -EIO;
325     }
326     
327     static inline void block_erase (volatile u_char *addr)
328     {
329     	writew(IF_BLOCK_ERASE, addr);
330     	writew(IF_CONFIRM, addr);
331     }
332     
333     
334     static inline int check_erase(volatile u_char *addr)
335     {
336     	__u16 status;
337     	
338     /*	writew(IF_READ_CSR, addr);*/
339     	status = readw(addr);
340     	
341     
342     	if ((status & CSR_WR_READY) != CSR_WR_READY)
343     		return -EBUSY;
344     	
345     	if (status & (CSR_ERA_ERR | CSR_VPP_LOW | CSR_WR_ERR)) 
346     	{
347     		printk(KERN_NOTICE "flashcard: erase failed, status 0x%x\n",
348     		       status);
349     		return -EIO;
350     	}
351     	
352     	return 0;
353     }
354     
355     static inline int suspend_erase(volatile u_char *addr)
356     {
357     	__u16 status;
358     	u_long i = 0;
359     	
360     	writew(IF_ERASE_SUSPEND, addr);
361     	writew(IF_READ_CSR, addr);
362     	
363     	do {
364     		status = readw(addr);
365     		if ((status & CSR_WR_READY) == CSR_WR_READY)
366     			return 0;
367     		i++;
368     	} while(i < max_tries);
369     
370     	printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status);
371     	return -EIO;
372     
373     }
374     
375     static inline void resume_erase(volatile u_char *addr)
376     {
377     	__u16 status;
378     	
379     	writew(IF_READ_CSR, addr);
380     	status = readw(addr);
381     	
382     	/* Only give resume signal if the erase is really suspended */
383     	if (status & CSR_ERA_SUSPEND)
384     		writew(IF_CONFIRM, addr);
385     }
386     
387     static inline void reset_block(volatile u_char *addr)
388     {
389     	u_short i;
390     	__u16 status;
391     
392     	writew(IF_CLEAR_CSR, addr);
393     
394     	for (i = 0; i < 100; i++) {
395     		writew(IF_READ_CSR, addr);
396     		status = readw(addr);
397     		if (status != 0xffff) break;
398     		udelay(1000);
399     	}
400     
401     	writew(IF_READ_CSR, addr);
402     }
403     
404     static inline int check_write(volatile u_char *addr)
405     {
406     	u_short status, i = 0;
407     	
408     	writew(IF_READ_CSR, addr);
409     	
410     	do {
411     		status = readw(addr);
412     		if (status & (CSR_WR_ERR | CSR_VPP_LOW))
413     		{
414     			printk(KERN_NOTICE "flashcard: write failure at %p, status 0x%x\n", addr, status);
415     			reset_block(addr);
416     			return -EIO;
417     		}
418     		if ((status & CSR_WR_READY) == CSR_WR_READY)
419     			return 0;
420     		i++;
421     	} while (i < max_tries);
422     
423     	printk(KERN_NOTICE "flashcard: write timed out at %p, status 0x%x\n", addr, status);
424     	return -EIO;
425     }
426     
427     
428     /*====================================================================*/
429     
430     
431     
432     static void flashcard_periodic(unsigned long data)
433     {
434     	register struct mtd_info *mtd = (struct mtd_info *)data;
435     	register struct mypriv *priv = mtd->priv;
436     	struct erase_info *erase = priv->cur_erases;
437     	u_char *pageaddr;
438     
439     	del_timer (&flashcard_timer);
440     
441     	if (!erase)
442     		return;
443     
444     	pageaddr = pagein(mtd, erase->addr);
445     	
446     	if (erase->state == MTD_ERASE_PENDING)
447     	{
448     		block_erase(pageaddr);
449     		priv->devstat[erase->dev] = erase->state = MTD_ERASING;
450     		erase->time = jiffies;
451     		erase->retries = 0;
452     	}
453     	else if (erase->state == MTD_ERASING)
454     	{
455     		/* It's trying to erase. Check whether it's finished */
456     
457     		int ret = check_erase(pageaddr);
458     
459     		if (!ret)
460     		{
461     			/* It's finished OK */
462     			priv->devstat[erase->dev] = 0;
463     			priv->cur_erases = erase->next;
464     			erase->state = MTD_ERASE_DONE;
465     			if (erase->callback)
466     				(*(erase->callback))(erase);
467     			else
468     				kfree(erase);
469     		}
470     		else if (ret == -EIO)
471     		{
472     			if (++erase->retries > retry_limit)
473     			{
474     				printk("Failed too many times. Giving up\n");
475     				priv->cur_erases = erase->next;
476     				priv->devstat[erase->dev] = 0;
477     				erase->state = MTD_ERASE_FAILED;
478     				if (erase->callback)
479     					(*(erase->callback))(erase);
480     				else
481     					kfree(erase);
482     			}
483     			else
484     				priv->devstat[erase->dev] = erase->state = MTD_ERASE_PENDING;
485     		}
486     		else if (erase->time + erase_timeout < jiffies)
487     		{
488     			printk("Flash erase timed out. The world is broken.\n");
489     
490     			/* Just ignore and hope it goes away. For a while, read ops will give the CSR
491     			   and writes won't work. */
492     
493     			priv->cur_erases = erase->next;
494     			priv->devstat[erase->dev] = 0;
495     			erase->state = MTD_ERASE_FAILED;
496     			if (erase->callback)
497     					(*(erase->callback))(erase);
498     				else
499     					kfree(erase);
500     		}
501     	}
502     
503     	if (priv->cur_erases)
504     	{
505     		flashcard_timer.expires = jiffies + HZ;
506     		add_timer (&flashcard_timer);
507     	}
508     	else 
509     		wake_up_interruptible(&priv->wq);
510     
511     }
512     
513     #if defined (MODULE) && LINUX_VERSION_CODE < 0x20211
514     #define init_doc1000 init_module
515     #define cleanup_doc1000 cleanup_module
516     #endif
517     
518     int __init init_doc1000(void)
519     {
520     	struct mypriv *priv;
521     
522     	if (!base)
523     	{
524     		printk(KERN_NOTICE "flashcard: No start address for memory device.\n");
525     		return -EINVAL;
526     	}
527     
528     	mymtd  = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
529     
530     	if (!mymtd)
531     	{
532     		printk(KERN_NOTICE "physmem: Cannot allocate memory for new MTD device.\n");
533     		return -ENOMEM;
534     	}
535     
536     	memset(mymtd,0,sizeof(struct mtd_info));
537     
538     	mymtd->priv = (void *) kmalloc (sizeof(struct mypriv), GFP_KERNEL);
539     	if (!mymtd->priv)
540     	  {
541     	    kfree(mymtd);
542     	    printk(KERN_NOTICE "physmem: Cannot allocate memory for new MTD device's private data.\n");
543     	    return -ENOMEM;
544     	  }
545     	
546     
547     
548     
549     	priv=mymtd->priv;
550     	init_waitqueue_head(&priv->wq);
551     
552     	memset (priv,0,sizeof(struct mypriv));
553     
554     	priv->baseaddr = phys_to_virt(base);
555     	priv->numdevices = 4;
556     	
557     	mymtd->name = "M-Systems DiskOnChip 1000";
558     
559     	mymtd->size = 0x100000;
560     	mymtd->flags = MTD_CLEAR_BITS | MTD_ERASEABLE;
561             mymtd->erase = flashcard_erase;
562     	mymtd->point = NULL;
563     	mymtd->unpoint = NULL;
564     	mymtd->read = flashcard_read;
565     	mymtd->write = flashcard_write;
566     
567     	mymtd->sync = flashcard_sync;
568     	mymtd->erasesize = 0x10000;
569     	//	mymtd->interleave = 2;
570     	priv->devshift =  24;
571     	mymtd->type = MTD_NORFLASH;
572     	
573     	if (add_mtd_device(mymtd))
574     	{
575     		printk(KERN_NOTICE "MTD device registration failed!\n");
576     		kfree(mymtd->priv);
577     		kfree(mymtd);
578     		return -EAGAIN;
579     	}
580     	
581     	init_timer(&flashcard_timer);
582     	flashcard_timer.function = flashcard_periodic;
583     	flashcard_timer.data = (u_long)mymtd;
584     	return 0;
585     }
586     
587     static void __init cleanup_doc1000(void)
588     {
589     	kfree (mymtd->priv);
590     	del_mtd_device(mymtd);
591     	kfree(mymtd);
592     }
593     
594     #if LINUX_VERSION_CODE >= 0x20211
595     module_init(init_doc1000);
596     module_exit(cleanup_doc1000);
597     #endif
598