initial commit with v2.6.9
[linux-2.6.9-moxart.git] / drivers / mtd / devices / doc1000.c
blobff8375fb6d7fbc83d32895b57ed3771d6e887284
1 /*======================================================================
3 $Id: doc1000.c,v 1.15 2001/10/02 15:05:13 dwmw2 Exp $
5 ======================================================================*/
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 <stdarg.h>
24 #include <linux/delay.h>
25 #include <linux/init.h>
27 #include <linux/mtd/mtd.h>
28 #include <linux/mtd/iflash.h>
30 /* Parameters that can be set with 'insmod' */
32 static u_long base = 0xe0000;
33 static int erase_timeout = 10*HZ; /* in ticks */
34 static int retry_limit = 4; /* write retries */
35 static u_long max_tries = 4096; /* status polling */
37 MODULE_PARM(base,"l");
38 MODULE_PARM(erase_timeout, "i");
39 MODULE_PARM(retry_limit, "i");
40 MODULE_PARM(max_tries, "i");
42 #define WINDOW_SIZE 0x2000
43 #define WINDOW_MASK (WINDOW_SIZE - 1)
44 #define PAGEREG_LO (WINDOW_SIZE)
45 #define PAGEREG_HI (WINDOW_SIZE + 2)
47 static struct mtd_info *mymtd;
48 static struct timer_list flashcard_timer;
50 #define MAX_CELLS 32
51 #define MAX_FLASH_DEVICES 8
53 /* A flash region is composed of one or more "cells", where we allow
54 simultaneous erases if they are in different cells */
58 struct mypriv {
59 u_char *baseaddr;
60 u_short curpage;
61 u_char locked;
62 u_short numdevices;
63 u_char interleave;
64 struct erase_info *cur_erases;
65 wait_queue_head_t wq;
66 u_char devstat[MAX_FLASH_DEVICES];
67 u_long devshift;
71 static void flashcard_periodic(u_long data);
72 static int flashcard_erase (struct mtd_info *mtd, struct erase_info *instr);
73 static int flashcard_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
74 static int flashcard_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
75 static void flashcard_sync (struct mtd_info *mtd);
77 static inline void resume_erase(volatile u_char *addr);
78 static inline int suspend_erase(volatile u_char *addr);
79 static inline int byte_write (volatile u_char *addr, u_char byte);
80 static inline int word_write (volatile u_char *addr, __u16 word);
81 static inline int check_write(volatile u_char *addr);
82 static inline void block_erase (volatile u_char *addr);
83 static inline int check_erase(volatile u_char *addr);
85 #ifdef CONFIG_SMP
86 #warning This is definitely not SMP safe. Lock the paging mechanism.
87 #endif
89 static u_char *pagein(struct mtd_info *mtd, u_long addr)
91 struct mypriv *priv=mtd->priv;
92 u_short page = addr >> 13;
94 priv->baseaddr[PAGEREG_LO] = page & 0xff;
95 priv->baseaddr[PAGEREG_HI] = page >> 8;
96 priv->curpage = page;
98 return &priv->baseaddr[addr & WINDOW_MASK];
102 void flashcard_sync (struct mtd_info *mtd)
104 struct mypriv *priv=mtd->priv;
106 flashcard_periodic((u_long) mtd);
107 printk("sync...");
108 if (priv->cur_erases)
109 interruptible_sleep_on(&priv->wq);
110 printk("Done.\n");
113 int flashcard_erase (struct mtd_info *mtd, struct erase_info *instr)
115 u_char *pageaddr;
116 struct mypriv *priv=mtd->priv;
117 struct erase_info **tmp=&priv->cur_erases;
119 if (instr->len != mtd->erasesize)
120 return -EINVAL;
121 if (instr->addr + instr->len > mtd->size)
122 return -EINVAL;
124 pageaddr=pagein(mtd,instr->addr);
125 instr->mtd = mtd;
126 instr->dev = instr->addr >> priv->devshift;
127 instr->cell = (instr->addr - (instr->dev << priv->devshift)) / mtd->erasesize;
128 instr->next = NULL;
129 instr->state = MTD_ERASE_PENDING;
131 while (*tmp)
133 tmp = &((*tmp) -> next);
136 *tmp = instr;
137 flashcard_periodic((u_long)mtd);
138 return 0;
142 int flashcard_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
144 u_char *pageaddr=pagein(mtd,from);
145 struct mypriv *priv=mtd->priv;
146 u_char device = from >> priv->devshift;
147 u_char cell = (int) (from - (device << priv->devshift)) / mtd->erasesize;
148 int ret = 0, timeron = 0;
150 if ((from & WINDOW_MASK) + len <= WINDOW_SIZE)
151 *retlen = len;
152 else
153 *retlen = WINDOW_SIZE - (from & WINDOW_MASK);
155 if (priv->devstat[device])
158 /* There is an erase in progress or pending for this device. Stop it */
159 timeron = del_timer(&flashcard_timer);
161 if (priv->cur_erases && priv->cur_erases->cell == cell)
164 /* The erase is on the current cell. Just return all 0xff */
165 add_timer(&flashcard_timer);
168 printk("Cell %d currently erasing. Setting to all 0xff\n",cell);
169 memset(buf, 0xff, *retlen);
170 return 0;
172 if (priv->devstat[device] == MTD_ERASING)
174 ret = suspend_erase(pageaddr);
175 priv->devstat[device] = MTD_ERASE_SUSPEND;
177 if (ret)
179 printk("flashcard: failed to suspend erase\n");
180 add_timer (&flashcard_timer);
181 return ret;
187 writew(IF_READ_ARRAY, (u_long)pageaddr & ~1);
189 ret = 0;
190 memcpy (buf, pageaddr, *retlen);
192 writew(IF_READ_CSR, (u_long)pageaddr & ~1);
195 if (priv->devstat[device] & MTD_ERASE_SUSPEND)
197 resume_erase(pageaddr);
198 priv->devstat[device]=MTD_ERASING;
202 if (timeron) add_timer (&flashcard_timer);
204 return ret;
208 int flashcard_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
210 struct mypriv *priv = (struct mypriv *)mtd->priv;
211 u_char *endaddr, *startaddr;
212 register u_char *pageaddr;
213 u_char device = to >> priv->devshift;
214 /* jiffies_t oldj=jiffies;*/
215 int ret;
217 while (priv->devstat[device])
219 flashcard_sync(mtd);
222 if ((to & WINDOW_MASK) + len <= WINDOW_SIZE)
223 *retlen = len;
224 else
225 *retlen = WINDOW_SIZE - (to & WINDOW_MASK);
227 pageaddr = pagein(mtd, to);
228 startaddr = (u_char *)((u_long) pageaddr & ~1);
229 endaddr = pageaddr+(*retlen);
233 /* Set up to read */
234 writew(IF_READ_CSR, startaddr);
236 /* Make sure it's aligned by reading the first byte if necessary */
237 if (to & 1)
239 /* Unaligned access */
241 u_char cbuf;
243 cbuf = *buf;
245 if (!((u_long)pageaddr & 0xf))
246 schedule();
248 ret = byte_write(pageaddr, cbuf);
249 if (ret) return ret;
251 pageaddr++; buf++;
255 for ( ; pageaddr + 1 < endaddr; buf += 2, pageaddr += 2)
257 /* if ((u_long)pageaddr & 0xf) schedule();*/
259 ret = word_write(pageaddr, *(__u16 *)buf);
260 if (ret)
261 return ret;
264 if (pageaddr != endaddr)
266 /* One more byte to write at the end. */
267 u_char cbuf;
269 cbuf = *buf;
271 ret = byte_write(pageaddr, cbuf);
273 if (ret) return ret;
276 return check_write(startaddr);
277 /* printk("Time taken in flashcard_write: %lx jiffies\n",jiffies - oldj);*/
283 /*====================================================================*/
285 static inline int byte_write (volatile u_char *addr, u_char byte)
287 register u_char status;
288 register u_short i = 0;
290 do {
291 status = readb(addr);
292 if (status & CSR_WR_READY)
294 writeb(IF_WRITE & 0xff, addr);
295 writeb(byte, addr);
296 return 0;
298 i++;
299 } while(i < max_tries);
302 printk(KERN_NOTICE "flashcard: byte_write timed out, status 0x%x\n",status);
303 return -EIO;
306 static inline int word_write (volatile u_char *addr, __u16 word)
308 register u_short status;
309 register u_short i = 0;
311 do {
312 status = readw(addr);
313 if ((status & CSR_WR_READY) == CSR_WR_READY)
315 writew(IF_WRITE, addr);
316 writew(word, addr);
317 return 0;
319 i++;
320 } while(i < max_tries);
322 printk(KERN_NOTICE "flashcard: word_write timed out at %p, status 0x%x\n", addr, status);
323 return -EIO;
326 static inline void block_erase (volatile u_char *addr)
328 writew(IF_BLOCK_ERASE, addr);
329 writew(IF_CONFIRM, addr);
333 static inline int check_erase(volatile u_char *addr)
335 __u16 status;
337 /* writew(IF_READ_CSR, addr);*/
338 status = readw(addr);
341 if ((status & CSR_WR_READY) != CSR_WR_READY)
342 return -EBUSY;
344 if (status & (CSR_ERA_ERR | CSR_VPP_LOW | CSR_WR_ERR))
346 printk(KERN_NOTICE "flashcard: erase failed, status 0x%x\n",
347 status);
348 return -EIO;
351 return 0;
354 static inline int suspend_erase(volatile u_char *addr)
356 __u16 status;
357 u_long i = 0;
359 writew(IF_ERASE_SUSPEND, addr);
360 writew(IF_READ_CSR, addr);
362 do {
363 status = readw(addr);
364 if ((status & CSR_WR_READY) == CSR_WR_READY)
365 return 0;
366 i++;
367 } while(i < max_tries);
369 printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status);
370 return -EIO;
374 static inline void resume_erase(volatile u_char *addr)
376 __u16 status;
378 writew(IF_READ_CSR, addr);
379 status = readw(addr);
381 /* Only give resume signal if the erase is really suspended */
382 if (status & CSR_ERA_SUSPEND)
383 writew(IF_CONFIRM, addr);
386 static inline void reset_block(volatile u_char *addr)
388 u_short i;
389 __u16 status;
391 writew(IF_CLEAR_CSR, addr);
393 for (i = 0; i < 100; i++) {
394 writew(IF_READ_CSR, addr);
395 status = readw(addr);
396 if (status != 0xffff) break;
397 udelay(1000);
400 writew(IF_READ_CSR, addr);
403 static inline int check_write(volatile u_char *addr)
405 u_short status, i = 0;
407 writew(IF_READ_CSR, addr);
409 do {
410 status = readw(addr);
411 if (status & (CSR_WR_ERR | CSR_VPP_LOW))
413 printk(KERN_NOTICE "flashcard: write failure at %p, status 0x%x\n", addr, status);
414 reset_block(addr);
415 return -EIO;
417 if ((status & CSR_WR_READY) == CSR_WR_READY)
418 return 0;
419 i++;
420 } while (i < max_tries);
422 printk(KERN_NOTICE "flashcard: write timed out at %p, status 0x%x\n", addr, status);
423 return -EIO;
427 /*====================================================================*/
431 static void flashcard_periodic(unsigned long data)
433 register struct mtd_info *mtd = (struct mtd_info *)data;
434 register struct mypriv *priv = mtd->priv;
435 struct erase_info *erase = priv->cur_erases;
436 u_char *pageaddr;
438 del_timer (&flashcard_timer);
440 if (!erase)
441 return;
443 pageaddr = pagein(mtd, erase->addr);
445 if (erase->state == MTD_ERASE_PENDING)
447 block_erase(pageaddr);
448 priv->devstat[erase->dev] = erase->state = MTD_ERASING;
449 erase->time = jiffies;
450 erase->retries = 0;
452 else if (erase->state == MTD_ERASING)
454 /* It's trying to erase. Check whether it's finished */
456 int ret = check_erase(pageaddr);
458 if (!ret)
460 /* It's finished OK */
461 priv->devstat[erase->dev] = 0;
462 priv->cur_erases = erase->next;
463 erase->state = MTD_ERASE_DONE;
464 if (erase->callback)
465 (*(erase->callback))(erase);
466 else
467 kfree(erase);
469 else if (ret == -EIO)
471 if (++erase->retries > retry_limit)
473 printk("Failed too many times. Giving up\n");
474 priv->cur_erases = erase->next;
475 priv->devstat[erase->dev] = 0;
476 erase->state = MTD_ERASE_FAILED;
477 if (erase->callback)
478 (*(erase->callback))(erase);
479 else
480 kfree(erase);
482 else
483 priv->devstat[erase->dev] = erase->state = MTD_ERASE_PENDING;
485 else if (erase->time + erase_timeout < jiffies)
487 printk("Flash erase timed out. The world is broken.\n");
489 /* Just ignore and hope it goes away. For a while, read ops will give the CSR
490 and writes won't work. */
492 priv->cur_erases = erase->next;
493 priv->devstat[erase->dev] = 0;
494 erase->state = MTD_ERASE_FAILED;
495 if (erase->callback)
496 (*(erase->callback))(erase);
497 else
498 kfree(erase);
502 if (priv->cur_erases)
504 flashcard_timer.expires = jiffies + HZ;
505 add_timer (&flashcard_timer);
507 else
508 wake_up_interruptible(&priv->wq);
512 int __init init_doc1000(void)
514 struct mypriv *priv;
516 if (!base)
518 printk(KERN_NOTICE "flashcard: No start address for memory device.\n");
519 return -EINVAL;
522 mymtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
524 if (!mymtd)
526 printk(KERN_NOTICE "physmem: Cannot allocate memory for new MTD device.\n");
527 return -ENOMEM;
530 memset(mymtd,0,sizeof(struct mtd_info));
532 mymtd->priv = (void *) kmalloc (sizeof(struct mypriv), GFP_KERNEL);
533 if (!mymtd->priv)
535 kfree(mymtd);
536 printk(KERN_NOTICE "physmem: Cannot allocate memory for new MTD device's private data.\n");
537 return -ENOMEM;
543 priv=mymtd->priv;
544 init_waitqueue_head(&priv->wq);
546 memset (priv,0,sizeof(struct mypriv));
548 priv->baseaddr = phys_to_virt(base);
549 priv->numdevices = 4;
551 mymtd->name = "M-Systems DiskOnChip 1000";
553 mymtd->size = 0x100000;
554 mymtd->flags = MTD_CLEAR_BITS | MTD_ERASEABLE;
555 mymtd->erase = flashcard_erase;
556 mymtd->point = NULL;
557 mymtd->unpoint = NULL;
558 mymtd->read = flashcard_read;
559 mymtd->write = flashcard_write;
561 mymtd->sync = flashcard_sync;
562 mymtd->erasesize = 0x10000;
563 // mymtd->interleave = 2;
564 priv->devshift = 24;
565 mymtd->type = MTD_NORFLASH;
567 if (add_mtd_device(mymtd))
569 printk(KERN_NOTICE "MTD device registration failed!\n");
570 kfree(mymtd->priv);
571 kfree(mymtd);
572 return -EAGAIN;
575 init_timer(&flashcard_timer);
576 flashcard_timer.function = flashcard_periodic;
577 flashcard_timer.data = (u_long)mymtd;
578 return 0;
581 static void __init cleanup_doc1000(void)
583 kfree (mymtd->priv);
584 del_mtd_device(mymtd);
585 kfree(mymtd);
588 module_init(init_doc1000);
589 module_exit(cleanup_doc1000);
591 MODULE_LICENSE("GPL");
592 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
593 MODULE_DESCRIPTION("MTD driver for DiskOnChip 1000");