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