Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
doc2001plus.c
Go to the documentation of this file.
1 /*
2  * Linux driver for Disk-On-Chip Millennium Plus
3  *
4  * (c) 2002-2003 Greg Ungerer <[email protected]>
5  * (c) 2002-2003 SnapGear Inc
6  * (c) 1999 Machine Vision Holdings, Inc.
7  * (c) 1999, 2000 David Woodhouse <[email protected]>
8  *
9  * Released under GPL
10  */
11 
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <asm/errno.h>
15 #include <asm/io.h>
16 #include <asm/uaccess.h>
17 #include <linux/delay.h>
18 #include <linux/slab.h>
19 #include <linux/init.h>
20 #include <linux/types.h>
21 #include <linux/bitops.h>
22 
23 #include <linux/mtd/mtd.h>
24 #include <linux/mtd/nand.h>
25 #include <linux/mtd/doc2000.h>
26 
27 /* #define ECC_DEBUG */
28 
29 /* I have no idea why some DoC chips can not use memcop_form|to_io().
30  * This may be due to the different revisions of the ASIC controller built-in or
31  * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment
32  * this:*/
33 #undef USE_MEMCPY
34 
35 static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
36  size_t *retlen, u_char *buf);
37 static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
38  size_t *retlen, const u_char *buf);
39 static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
40  struct mtd_oob_ops *ops);
41 static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
42  struct mtd_oob_ops *ops);
43 static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
44 
45 static struct mtd_info *docmilpluslist = NULL;
46 
47 
48 /* Perform the required delay cycles by writing to the NOP register */
49 static void DoC_Delay(void __iomem * docptr, int cycles)
50 {
51  int i;
52 
53  for (i = 0; (i < cycles); i++)
54  WriteDOC(0, docptr, Mplus_NOP);
55 }
56 
57 #define CDSN_CTRL_FR_B_MASK (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1)
58 
59 /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
60 static int _DoC_WaitReady(void __iomem * docptr)
61 {
62  unsigned int c = 0xffff;
63 
64  pr_debug("_DoC_WaitReady called for out-of-line wait\n");
65 
66  /* Out-of-line routine to wait for chip response */
67  while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c)
68  ;
69 
70  if (c == 0)
71  pr_debug("_DoC_WaitReady timed out.\n");
72 
73  return (c == 0);
74 }
75 
76 static inline int DoC_WaitReady(void __iomem * docptr)
77 {
78  /* This is inline, to optimise the common case, where it's ready instantly */
79  int ret = 0;
80 
81  /* read form NOP register should be issued prior to the read from CDSNControl
82  see Software Requirement 11.4 item 2. */
83  DoC_Delay(docptr, 4);
84 
85  if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK)
86  /* Call the out-of-line routine to wait */
87  ret = _DoC_WaitReady(docptr);
88 
89  return ret;
90 }
91 
92 /* For some reason the Millennium Plus seems to occasionally put itself
93  * into reset mode. For me this happens randomly, with no pattern that I
94  * can detect. M-systems suggest always check this on any block level
95  * operation and setting to normal mode if in reset mode.
96  */
97 static inline void DoC_CheckASIC(void __iomem * docptr)
98 {
99  /* Make sure the DoC is in normal mode */
100  if ((ReadDOC(docptr, Mplus_DOCControl) & DOC_MODE_NORMAL) == 0) {
101  WriteDOC((DOC_MODE_NORMAL | DOC_MODE_MDWREN), docptr, Mplus_DOCControl);
102  WriteDOC(~(DOC_MODE_NORMAL | DOC_MODE_MDWREN), docptr, Mplus_CtrlConfirm);
103  }
104 }
105 
106 /* DoC_Command: Send a flash command to the flash chip through the Flash
107  * command register. Need 2 Write Pipeline Terminates to complete send.
108  */
109 static void DoC_Command(void __iomem * docptr, unsigned char command,
110  unsigned char xtraflags)
111 {
112  WriteDOC(command, docptr, Mplus_FlashCmd);
113  WriteDOC(command, docptr, Mplus_WritePipeTerm);
114  WriteDOC(command, docptr, Mplus_WritePipeTerm);
115 }
116 
117 /* DoC_Address: Set the current address for the flash chip through the Flash
118  * Address register. Need 2 Write Pipeline Terminates to complete send.
119  */
120 static inline void DoC_Address(struct DiskOnChip *doc, int numbytes,
121  unsigned long ofs, unsigned char xtraflags1,
122  unsigned char xtraflags2)
123 {
124  void __iomem * docptr = doc->virtadr;
125 
126  /* Allow for possible Mill Plus internal flash interleaving */
127  ofs >>= doc->interleave;
128 
129  switch (numbytes) {
130  case 1:
131  /* Send single byte, bits 0-7. */
132  WriteDOC(ofs & 0xff, docptr, Mplus_FlashAddress);
133  break;
134  case 2:
135  /* Send bits 9-16 followed by 17-23 */
136  WriteDOC((ofs >> 9) & 0xff, docptr, Mplus_FlashAddress);
137  WriteDOC((ofs >> 17) & 0xff, docptr, Mplus_FlashAddress);
138  break;
139  case 3:
140  /* Send 0-7, 9-16, then 17-23 */
141  WriteDOC(ofs & 0xff, docptr, Mplus_FlashAddress);
142  WriteDOC((ofs >> 9) & 0xff, docptr, Mplus_FlashAddress);
143  WriteDOC((ofs >> 17) & 0xff, docptr, Mplus_FlashAddress);
144  break;
145  default:
146  return;
147  }
148 
149  WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
150  WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
151 }
152 
153 /* DoC_SelectChip: Select a given flash chip within the current floor */
154 static int DoC_SelectChip(void __iomem * docptr, int chip)
155 {
156  /* No choice for flash chip on Millennium Plus */
157  return 0;
158 }
159 
160 /* DoC_SelectFloor: Select a given floor (bank of flash chips) */
161 static int DoC_SelectFloor(void __iomem * docptr, int floor)
162 {
163  WriteDOC((floor & 0x3), docptr, Mplus_DeviceSelect);
164  return 0;
165 }
166 
167 /*
168  * Translate the given offset into the appropriate command and offset.
169  * This does the mapping using the 16bit interleave layout defined by
170  * M-Systems, and looks like this for a sector pair:
171  * +-----------+-------+-------+-------+--------------+---------+-----------+
172  * | 0 --- 511 |512-517|518-519|520-521| 522 --- 1033 |1034-1039|1040 - 1055|
173  * +-----------+-------+-------+-------+--------------+---------+-----------+
174  * | Data 0 | ECC 0 |Flags0 |Flags1 | Data 1 |ECC 1 | OOB 1 + 2 |
175  * +-----------+-------+-------+-------+--------------+---------+-----------+
176  */
177 /* FIXME: This lives in INFTL not here. Other users of flash devices
178  may not want it */
179 static unsigned int DoC_GetDataOffset(struct mtd_info *mtd, loff_t *from)
180 {
181  struct DiskOnChip *this = mtd->priv;
182 
183  if (this->interleave) {
184  unsigned int ofs = *from & 0x3ff;
185  unsigned int cmd;
186 
187  if (ofs < 512) {
188  cmd = NAND_CMD_READ0;
189  ofs &= 0x1ff;
190  } else if (ofs < 1014) {
191  cmd = NAND_CMD_READ1;
192  ofs = (ofs & 0x1ff) + 10;
193  } else {
194  cmd = NAND_CMD_READOOB;
195  ofs = ofs - 1014;
196  }
197 
198  *from = (*from & ~0x3ff) | ofs;
199  return cmd;
200  } else {
201  /* No interleave */
202  if ((*from) & 0x100)
203  return NAND_CMD_READ1;
204  return NAND_CMD_READ0;
205  }
206 }
207 
208 static unsigned int DoC_GetECCOffset(struct mtd_info *mtd, loff_t *from)
209 {
210  unsigned int ofs, cmd;
211 
212  if (*from & 0x200) {
213  cmd = NAND_CMD_READOOB;
214  ofs = 10 + (*from & 0xf);
215  } else {
216  cmd = NAND_CMD_READ1;
217  ofs = (*from & 0xf);
218  }
219 
220  *from = (*from & ~0x3ff) | ofs;
221  return cmd;
222 }
223 
224 static unsigned int DoC_GetFlagsOffset(struct mtd_info *mtd, loff_t *from)
225 {
226  unsigned int ofs, cmd;
227 
228  cmd = NAND_CMD_READ1;
229  ofs = (*from & 0x200) ? 8 : 6;
230  *from = (*from & ~0x3ff) | ofs;
231  return cmd;
232 }
233 
234 static unsigned int DoC_GetHdrOffset(struct mtd_info *mtd, loff_t *from)
235 {
236  unsigned int ofs, cmd;
237 
238  cmd = NAND_CMD_READOOB;
239  ofs = (*from & 0x200) ? 24 : 16;
240  *from = (*from & ~0x3ff) | ofs;
241  return cmd;
242 }
243 
244 static inline void MemReadDOC(void __iomem * docptr, unsigned char *buf, int len)
245 {
246 #ifndef USE_MEMCPY
247  int i;
248  for (i = 0; i < len; i++)
249  buf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
250 #else
251  memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len);
252 #endif
253 }
254 
255 static inline void MemWriteDOC(void __iomem * docptr, unsigned char *buf, int len)
256 {
257 #ifndef USE_MEMCPY
258  int i;
259  for (i = 0; i < len; i++)
260  WriteDOC(buf[i], docptr, Mil_CDSN_IO + i);
261 #else
262  memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len);
263 #endif
264 }
265 
266 /* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
267 static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
268 {
269  int mfr, id, i, j;
270  volatile char dummy;
271  void __iomem * docptr = doc->virtadr;
272 
273  /* Page in the required floor/chip */
274  DoC_SelectFloor(docptr, floor);
275  DoC_SelectChip(docptr, chip);
276 
277  /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
278  WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect);
279 
280  /* Reset the chip, see Software Requirement 11.4 item 1. */
281  DoC_Command(docptr, NAND_CMD_RESET, 0);
282  DoC_WaitReady(docptr);
283 
284  /* Read the NAND chip ID: 1. Send ReadID command */
285  DoC_Command(docptr, NAND_CMD_READID, 0);
286 
287  /* Read the NAND chip ID: 2. Send address byte zero */
288  DoC_Address(doc, 1, 0x00, 0, 0x00);
289 
290  WriteDOC(0, docptr, Mplus_FlashControl);
291  DoC_WaitReady(docptr);
292 
293  /* Read the manufacturer and device id codes of the flash device through
294  CDSN IO register see Software Requirement 11.4 item 5.*/
295  dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
296  dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
297 
298  mfr = ReadDOC(docptr, Mil_CDSN_IO);
299  if (doc->interleave)
300  dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */
301 
302  id = ReadDOC(docptr, Mil_CDSN_IO);
303  if (doc->interleave)
304  dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */
305 
306  dummy = ReadDOC(docptr, Mplus_LastDataRead);
307  dummy = ReadDOC(docptr, Mplus_LastDataRead);
308 
309  /* Disable flash internally */
310  WriteDOC(0, docptr, Mplus_FlashSelect);
311 
312  /* No response - return failure */
313  if (mfr == 0xff || mfr == 0)
314  return 0;
315 
316  for (i = 0; nand_flash_ids[i].name != NULL; i++) {
317  if (id == nand_flash_ids[i].id) {
318  /* Try to identify manufacturer */
319  for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
320  if (nand_manuf_ids[j].id == mfr)
321  break;
322  }
323  printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, "
324  "Chip ID: %2.2X (%s:%s)\n", mfr, id,
325  nand_manuf_ids[j].name, nand_flash_ids[i].name);
326  doc->mfr = mfr;
327  doc->id = id;
328  doc->chipshift = ffs((nand_flash_ids[i].chipsize << 20)) - 1;
329  doc->erasesize = nand_flash_ids[i].erasesize << doc->interleave;
330  break;
331  }
332  }
333 
334  if (nand_flash_ids[i].name == NULL)
335  return 0;
336  return 1;
337 }
338 
339 /* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
340 static void DoC_ScanChips(struct DiskOnChip *this)
341 {
342  int floor, chip;
344  int ret;
345 
346  this->numchips = 0;
347  this->mfr = 0;
348  this->id = 0;
349 
350  /* Work out the intended interleave setting */
351  this->interleave = 0;
352  if (this->ChipID == DOC_ChipID_DocMilPlus32)
353  this->interleave = 1;
354 
355  /* Check the ASIC agrees */
356  if ( (this->interleave << 2) !=
357  (ReadDOC(this->virtadr, Mplus_Configuration) & 4)) {
358  u_char conf = ReadDOC(this->virtadr, Mplus_Configuration);
359  printk(KERN_NOTICE "Setting DiskOnChip Millennium Plus interleave to %s\n",
360  this->interleave?"on (16-bit)":"off (8-bit)");
361  conf ^= 4;
362  WriteDOC(conf, this->virtadr, Mplus_Configuration);
363  }
364 
365  /* For each floor, find the number of valid chips it contains */
366  for (floor = 0,ret = 1; floor < MAX_FLOORS_MPLUS; floor++) {
367  numchips[floor] = 0;
368  for (chip = 0; chip < MAX_CHIPS_MPLUS && ret != 0; chip++) {
369  ret = DoC_IdentChip(this, floor, chip);
370  if (ret) {
371  numchips[floor]++;
372  this->numchips++;
373  }
374  }
375  }
376  /* If there are none at all that we recognise, bail */
377  if (!this->numchips) {
378  printk("No flash chips recognised.\n");
379  return;
380  }
381 
382  /* Allocate an array to hold the information for each chip */
383  this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL);
384  if (!this->chips){
385  printk("MTD: No memory for allocating chip info structures\n");
386  return;
387  }
388 
389  /* Fill out the chip array with {floor, chipno} for each
390  * detected chip in the device. */
391  for (floor = 0, ret = 0; floor < MAX_FLOORS_MPLUS; floor++) {
392  for (chip = 0 ; chip < numchips[floor] ; chip++) {
393  this->chips[ret].floor = floor;
394  this->chips[ret].chip = chip;
395  this->chips[ret].curadr = 0;
396  this->chips[ret].curmode = 0x50;
397  ret++;
398  }
399  }
400 
401  /* Calculate and print the total size of the device */
402  this->totlen = this->numchips * (1 << this->chipshift);
403  printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld MiB\n",
404  this->numchips ,this->totlen >> 20);
405 }
406 
407 static int DoCMilPlus_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
408 {
409  int tmp1, tmp2, retval;
410 
411  if (doc1->physadr == doc2->physadr)
412  return 1;
413 
414  /* Use the alias resolution register which was set aside for this
415  * purpose. If it's value is the same on both chips, they might
416  * be the same chip, and we write to one and check for a change in
417  * the other. It's unclear if this register is usuable in the
418  * DoC 2000 (it's in the Millennium docs), but it seems to work. */
419  tmp1 = ReadDOC(doc1->virtadr, Mplus_AliasResolution);
420  tmp2 = ReadDOC(doc2->virtadr, Mplus_AliasResolution);
421  if (tmp1 != tmp2)
422  return 0;
423 
424  WriteDOC((tmp1+1) % 0xff, doc1->virtadr, Mplus_AliasResolution);
425  tmp2 = ReadDOC(doc2->virtadr, Mplus_AliasResolution);
426  if (tmp2 == (tmp1+1) % 0xff)
427  retval = 1;
428  else
429  retval = 0;
430 
431  /* Restore register contents. May not be necessary, but do it just to
432  * be safe. */
433  WriteDOC(tmp1, doc1->virtadr, Mplus_AliasResolution);
434 
435  return retval;
436 }
437 
438 /* This routine is found from the docprobe code by symbol_get(),
439  * which will bump the use count of this module. */
440 void DoCMilPlus_init(struct mtd_info *mtd)
441 {
442  struct DiskOnChip *this = mtd->priv;
443  struct DiskOnChip *old = NULL;
444 
445  /* We must avoid being called twice for the same device. */
446  if (docmilpluslist)
447  old = docmilpluslist->priv;
448 
449  while (old) {
450  if (DoCMilPlus_is_alias(this, old)) {
451  printk(KERN_NOTICE "Ignoring DiskOnChip Millennium "
452  "Plus at 0x%lX - already configured\n",
453  this->physadr);
454  iounmap(this->virtadr);
455  kfree(mtd);
456  return;
457  }
458  if (old->nextdoc)
459  old = old->nextdoc->priv;
460  else
461  old = NULL;
462  }
463 
464  mtd->name = "DiskOnChip Millennium Plus";
465  printk(KERN_NOTICE "DiskOnChip Millennium Plus found at "
466  "address 0x%lX\n", this->physadr);
467 
468  mtd->type = MTD_NANDFLASH;
469  mtd->flags = MTD_CAP_NANDFLASH;
470  mtd->writebufsize = mtd->writesize = 512;
471  mtd->oobsize = 16;
472  mtd->ecc_strength = 2;
473  mtd->owner = THIS_MODULE;
474  mtd->_erase = doc_erase;
475  mtd->_read = doc_read;
476  mtd->_write = doc_write;
477  mtd->_read_oob = doc_read_oob;
478  mtd->_write_oob = doc_write_oob;
479  this->curfloor = -1;
480  this->curchip = -1;
481 
482  /* Ident all the chips present. */
483  DoC_ScanChips(this);
484 
485  if (!this->totlen) {
486  kfree(mtd);
487  iounmap(this->virtadr);
488  } else {
489  this->nextdoc = docmilpluslist;
490  docmilpluslist = mtd;
491  mtd->size = this->totlen;
492  mtd->erasesize = this->erasesize;
493  mtd_device_register(mtd, NULL, 0);
494  return;
495  }
496 }
498 
499 #if 0
500 static int doc_dumpblk(struct mtd_info *mtd, loff_t from)
501 {
502  int i;
503  loff_t fofs;
504  struct DiskOnChip *this = mtd->priv;
505  void __iomem * docptr = this->virtadr;
506  struct Nand *mychip = &this->chips[from >> (this->chipshift)];
507  unsigned char *bp, buf[1056];
508  char c[32];
509 
510  from &= ~0x3ff;
511 
512  /* Don't allow read past end of device */
513  if (from >= this->totlen)
514  return -EINVAL;
515 
516  DoC_CheckASIC(docptr);
517 
518  /* Find the chip which is to be used and select it */
519  if (this->curfloor != mychip->floor) {
520  DoC_SelectFloor(docptr, mychip->floor);
521  DoC_SelectChip(docptr, mychip->chip);
522  } else if (this->curchip != mychip->chip) {
523  DoC_SelectChip(docptr, mychip->chip);
524  }
525  this->curfloor = mychip->floor;
526  this->curchip = mychip->chip;
527 
528  /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
529  WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect);
530 
531  /* Reset the chip, see Software Requirement 11.4 item 1. */
532  DoC_Command(docptr, NAND_CMD_RESET, 0);
533  DoC_WaitReady(docptr);
534 
535  fofs = from;
536  DoC_Command(docptr, DoC_GetDataOffset(mtd, &fofs), 0);
537  DoC_Address(this, 3, fofs, 0, 0x00);
538  WriteDOC(0, docptr, Mplus_FlashControl);
539  DoC_WaitReady(docptr);
540 
541  /* disable the ECC engine */
542  WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
543 
544  ReadDOC(docptr, Mplus_ReadPipeInit);
545  ReadDOC(docptr, Mplus_ReadPipeInit);
546 
547  /* Read the data via the internal pipeline through CDSN IO
548  register, see Pipelined Read Operations 11.3 */
549  MemReadDOC(docptr, buf, 1054);
550  buf[1054] = ReadDOC(docptr, Mplus_LastDataRead);
551  buf[1055] = ReadDOC(docptr, Mplus_LastDataRead);
552 
553  memset(&c[0], 0, sizeof(c));
554  printk("DUMP OFFSET=%x:\n", (int)from);
555 
556  for (i = 0, bp = &buf[0]; (i < 1056); i++) {
557  if ((i % 16) == 0)
558  printk("%08x: ", i);
559  printk(" %02x", *bp);
560  c[(i & 0xf)] = ((*bp >= 0x20) && (*bp <= 0x7f)) ? *bp : '.';
561  bp++;
562  if (((i + 1) % 16) == 0)
563  printk(" %s\n", c);
564  }
565  printk("\n");
566 
567  /* Disable flash internally */
568  WriteDOC(0, docptr, Mplus_FlashSelect);
569 
570  return 0;
571 }
572 #endif
573 
574 static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
575  size_t *retlen, u_char *buf)
576 {
577  int ret, i;
578  volatile char dummy;
579  loff_t fofs;
580  unsigned char syndrome[6], eccbuf[6];
581  struct DiskOnChip *this = mtd->priv;
582  void __iomem * docptr = this->virtadr;
583  struct Nand *mychip = &this->chips[from >> (this->chipshift)];
584 
585  /* Don't allow a single read to cross a 512-byte block boundary */
586  if (from + len > ((from | 0x1ff) + 1))
587  len = ((from | 0x1ff) + 1) - from;
588 
589  DoC_CheckASIC(docptr);
590 
591  /* Find the chip which is to be used and select it */
592  if (this->curfloor != mychip->floor) {
593  DoC_SelectFloor(docptr, mychip->floor);
594  DoC_SelectChip(docptr, mychip->chip);
595  } else if (this->curchip != mychip->chip) {
596  DoC_SelectChip(docptr, mychip->chip);
597  }
598  this->curfloor = mychip->floor;
599  this->curchip = mychip->chip;
600 
601  /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
602  WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect);
603 
604  /* Reset the chip, see Software Requirement 11.4 item 1. */
605  DoC_Command(docptr, NAND_CMD_RESET, 0);
606  DoC_WaitReady(docptr);
607 
608  fofs = from;
609  DoC_Command(docptr, DoC_GetDataOffset(mtd, &fofs), 0);
610  DoC_Address(this, 3, fofs, 0, 0x00);
611  WriteDOC(0, docptr, Mplus_FlashControl);
612  DoC_WaitReady(docptr);
613 
614  /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
615  WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
616  WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
617 
618  /* Let the caller know we completed it */
619  *retlen = len;
620  ret = 0;
621 
622  ReadDOC(docptr, Mplus_ReadPipeInit);
623  ReadDOC(docptr, Mplus_ReadPipeInit);
624 
625  /* Read the data via the internal pipeline through CDSN IO
626  register, see Pipelined Read Operations 11.3 */
627  MemReadDOC(docptr, buf, len);
628 
629  /* Read the ECC data following raw data */
630  MemReadDOC(docptr, eccbuf, 4);
631  eccbuf[4] = ReadDOC(docptr, Mplus_LastDataRead);
632  eccbuf[5] = ReadDOC(docptr, Mplus_LastDataRead);
633 
634  /* Flush the pipeline */
635  dummy = ReadDOC(docptr, Mplus_ECCConf);
636  dummy = ReadDOC(docptr, Mplus_ECCConf);
637 
638  /* Check the ECC Status */
639  if (ReadDOC(docptr, Mplus_ECCConf) & 0x80) {
640  int nb_errors;
641  /* There was an ECC error */
642 #ifdef ECC_DEBUG
643  printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
644 #endif
645  /* Read the ECC syndrome through the DiskOnChip ECC logic.
646  These syndrome will be all ZERO when there is no error */
647  for (i = 0; i < 6; i++)
648  syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
649 
650  nb_errors = doc_decode_ecc(buf, syndrome);
651 #ifdef ECC_DEBUG
652  printk("ECC Errors corrected: %x\n", nb_errors);
653 #endif
654  if (nb_errors < 0) {
655  /* We return error, but have actually done the
656  read. Not that this can be told to user-space, via
657  sys_read(), but at least MTD-aware stuff can know
658  about it by checking *retlen */
659 #ifdef ECC_DEBUG
660  printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n",
661  __FILE__, __LINE__, (int)from);
662  printk(" syndrome= %*phC\n", 6, syndrome);
663  printk(" eccbuf= %*phC\n", 6, eccbuf);
664 #endif
665  ret = -EIO;
666  }
667  }
668 
669 #ifdef PSYCHO_DEBUG
670  printk("ECC DATA at %lx: %*ph\n", (long)from, 6, eccbuf);
671 #endif
672  /* disable the ECC engine */
673  WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf);
674 
675  /* Disable flash internally */
676  WriteDOC(0, docptr, Mplus_FlashSelect);
677 
678  return ret;
679 }
680 
681 static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
682  size_t *retlen, const u_char *buf)
683 {
684  int i, before, ret = 0;
685  loff_t fto;
686  volatile char dummy;
687  char eccbuf[6];
688  struct DiskOnChip *this = mtd->priv;
689  void __iomem * docptr = this->virtadr;
690  struct Nand *mychip = &this->chips[to >> (this->chipshift)];
691 
692  /* Don't allow writes which aren't exactly one block (512 bytes) */
693  if ((to & 0x1ff) || (len != 0x200))
694  return -EINVAL;
695 
696  /* Determine position of OOB flags, before or after data */
697  before = (this->interleave && (to & 0x200));
698 
699  DoC_CheckASIC(docptr);
700 
701  /* Find the chip which is to be used and select it */
702  if (this->curfloor != mychip->floor) {
703  DoC_SelectFloor(docptr, mychip->floor);
704  DoC_SelectChip(docptr, mychip->chip);
705  } else if (this->curchip != mychip->chip) {
706  DoC_SelectChip(docptr, mychip->chip);
707  }
708  this->curfloor = mychip->floor;
709  this->curchip = mychip->chip;
710 
711  /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
712  WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect);
713 
714  /* Reset the chip, see Software Requirement 11.4 item 1. */
715  DoC_Command(docptr, NAND_CMD_RESET, 0);
716  DoC_WaitReady(docptr);
717 
718  /* Set device to appropriate plane of flash */
719  fto = to;
720  WriteDOC(DoC_GetDataOffset(mtd, &fto), docptr, Mplus_FlashCmd);
721 
722  /* On interleaved devices the flags for 2nd half 512 are before data */
723  if (before)
724  fto -= 2;
725 
726  /* issue the Serial Data In command to initial the Page Program process */
727  DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
728  DoC_Address(this, 3, fto, 0x00, 0x00);
729 
730  /* Disable the ECC engine */
731  WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
732 
733  if (before) {
734  /* Write the block status BLOCK_USED (0x5555) */
735  WriteDOC(0x55, docptr, Mil_CDSN_IO);
736  WriteDOC(0x55, docptr, Mil_CDSN_IO);
737  }
738 
739  /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
740  WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);
741 
742  MemWriteDOC(docptr, (unsigned char *) buf, len);
743 
744  /* Write ECC data to flash, the ECC info is generated by
745  the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */
746  DoC_Delay(docptr, 3);
747 
748  /* Read the ECC data through the DiskOnChip ECC logic */
749  for (i = 0; i < 6; i++)
750  eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
751 
752  /* disable the ECC engine */
753  WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
754 
755  /* Write the ECC data to flash */
756  MemWriteDOC(docptr, eccbuf, 6);
757 
758  if (!before) {
759  /* Write the block status BLOCK_USED (0x5555) */
760  WriteDOC(0x55, docptr, Mil_CDSN_IO+6);
761  WriteDOC(0x55, docptr, Mil_CDSN_IO+7);
762  }
763 
764 #ifdef PSYCHO_DEBUG
765  printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
766  (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
767  eccbuf[4], eccbuf[5]);
768 #endif
769 
770  WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
771  WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
772 
773  /* Commit the Page Program command and wait for ready
774  see Software Requirement 11.4 item 1.*/
775  DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
776  DoC_WaitReady(docptr);
777 
778  /* Read the status of the flash device through CDSN IO register
779  see Software Requirement 11.4 item 5.*/
780  DoC_Command(docptr, NAND_CMD_STATUS, 0);
781  dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
782  dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
783  DoC_Delay(docptr, 2);
784  if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) {
785  printk("MTD: Error 0x%x programming at 0x%x\n", dummy, (int)to);
786  /* Error in programming
787  FIXME: implement Bad Block Replacement (in nftl.c ??) */
788  ret = -EIO;
789  }
790  dummy = ReadDOC(docptr, Mplus_LastDataRead);
791 
792  /* Disable flash internally */
793  WriteDOC(0, docptr, Mplus_FlashSelect);
794 
795  /* Let the caller know we completed it */
796  *retlen = len;
797 
798  return ret;
799 }
800 
801 static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
802  struct mtd_oob_ops *ops)
803 {
804  loff_t fofs, base;
805  struct DiskOnChip *this = mtd->priv;
806  void __iomem * docptr = this->virtadr;
807  struct Nand *mychip = &this->chips[ofs >> this->chipshift];
808  size_t i, size, got, want;
809  uint8_t *buf = ops->oobbuf;
810  size_t len = ops->len;
811 
812  BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
813 
814  ofs += ops->ooboffs;
815 
816  DoC_CheckASIC(docptr);
817 
818  /* Find the chip which is to be used and select it */
819  if (this->curfloor != mychip->floor) {
820  DoC_SelectFloor(docptr, mychip->floor);
821  DoC_SelectChip(docptr, mychip->chip);
822  } else if (this->curchip != mychip->chip) {
823  DoC_SelectChip(docptr, mychip->chip);
824  }
825  this->curfloor = mychip->floor;
826  this->curchip = mychip->chip;
827 
828  /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
829  WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect);
830 
831  /* disable the ECC engine */
832  WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
833  DoC_WaitReady(docptr);
834 
835  /* Maximum of 16 bytes in the OOB region, so limit read to that */
836  if (len > 16)
837  len = 16;
838  got = 0;
839  want = len;
840 
841  for (i = 0; ((i < 3) && (want > 0)); i++) {
842  /* Figure out which region we are accessing... */
843  fofs = ofs;
844  base = ofs & 0xf;
845  if (!this->interleave) {
846  DoC_Command(docptr, NAND_CMD_READOOB, 0);
847  size = 16 - base;
848  } else if (base < 6) {
849  DoC_Command(docptr, DoC_GetECCOffset(mtd, &fofs), 0);
850  size = 6 - base;
851  } else if (base < 8) {
852  DoC_Command(docptr, DoC_GetFlagsOffset(mtd, &fofs), 0);
853  size = 8 - base;
854  } else {
855  DoC_Command(docptr, DoC_GetHdrOffset(mtd, &fofs), 0);
856  size = 16 - base;
857  }
858  if (size > want)
859  size = want;
860 
861  /* Issue read command */
862  DoC_Address(this, 3, fofs, 0, 0x00);
863  WriteDOC(0, docptr, Mplus_FlashControl);
864  DoC_WaitReady(docptr);
865 
866  ReadDOC(docptr, Mplus_ReadPipeInit);
867  ReadDOC(docptr, Mplus_ReadPipeInit);
868  MemReadDOC(docptr, &buf[got], size - 2);
869  buf[got + size - 2] = ReadDOC(docptr, Mplus_LastDataRead);
870  buf[got + size - 1] = ReadDOC(docptr, Mplus_LastDataRead);
871 
872  ofs += size;
873  got += size;
874  want -= size;
875  }
876 
877  /* Disable flash internally */
878  WriteDOC(0, docptr, Mplus_FlashSelect);
879 
880  ops->retlen = len;
881  return 0;
882 }
883 
884 static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
885  struct mtd_oob_ops *ops)
886 {
887  volatile char dummy;
888  loff_t fofs, base;
889  struct DiskOnChip *this = mtd->priv;
890  void __iomem * docptr = this->virtadr;
891  struct Nand *mychip = &this->chips[ofs >> this->chipshift];
892  size_t i, size, got, want;
893  int ret = 0;
894  uint8_t *buf = ops->oobbuf;
895  size_t len = ops->len;
896 
897  BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
898 
899  ofs += ops->ooboffs;
900 
901  DoC_CheckASIC(docptr);
902 
903  /* Find the chip which is to be used and select it */
904  if (this->curfloor != mychip->floor) {
905  DoC_SelectFloor(docptr, mychip->floor);
906  DoC_SelectChip(docptr, mychip->chip);
907  } else if (this->curchip != mychip->chip) {
908  DoC_SelectChip(docptr, mychip->chip);
909  }
910  this->curfloor = mychip->floor;
911  this->curchip = mychip->chip;
912 
913  /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
914  WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect);
915 
916 
917  /* Maximum of 16 bytes in the OOB region, so limit write to that */
918  if (len > 16)
919  len = 16;
920  got = 0;
921  want = len;
922 
923  for (i = 0; ((i < 3) && (want > 0)); i++) {
924  /* Reset the chip, see Software Requirement 11.4 item 1. */
925  DoC_Command(docptr, NAND_CMD_RESET, 0);
926  DoC_WaitReady(docptr);
927 
928  /* Figure out which region we are accessing... */
929  fofs = ofs;
930  base = ofs & 0x0f;
931  if (!this->interleave) {
932  WriteDOC(NAND_CMD_READOOB, docptr, Mplus_FlashCmd);
933  size = 16 - base;
934  } else if (base < 6) {
935  WriteDOC(DoC_GetECCOffset(mtd, &fofs), docptr, Mplus_FlashCmd);
936  size = 6 - base;
937  } else if (base < 8) {
938  WriteDOC(DoC_GetFlagsOffset(mtd, &fofs), docptr, Mplus_FlashCmd);
939  size = 8 - base;
940  } else {
941  WriteDOC(DoC_GetHdrOffset(mtd, &fofs), docptr, Mplus_FlashCmd);
942  size = 16 - base;
943  }
944  if (size > want)
945  size = want;
946 
947  /* Issue the Serial Data In command to initial the Page Program process */
948  DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
949  DoC_Address(this, 3, fofs, 0, 0x00);
950 
951  /* Disable the ECC engine */
952  WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
953 
954  /* Write the data via the internal pipeline through CDSN IO
955  register, see Pipelined Write Operations 11.2 */
956  MemWriteDOC(docptr, (unsigned char *) &buf[got], size);
957  WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
958  WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
959 
960  /* Commit the Page Program command and wait for ready
961  see Software Requirement 11.4 item 1.*/
962  DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
963  DoC_WaitReady(docptr);
964 
965  /* Read the status of the flash device through CDSN IO register
966  see Software Requirement 11.4 item 5.*/
967  DoC_Command(docptr, NAND_CMD_STATUS, 0x00);
968  dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
969  dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
970  DoC_Delay(docptr, 2);
971  if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) {
972  printk("MTD: Error 0x%x programming oob at 0x%x\n",
973  dummy, (int)ofs);
974  /* FIXME: implement Bad Block Replacement */
975  ops->retlen = 0;
976  ret = -EIO;
977  }
978  dummy = ReadDOC(docptr, Mplus_LastDataRead);
979 
980  ofs += size;
981  got += size;
982  want -= size;
983  }
984 
985  /* Disable flash internally */
986  WriteDOC(0, docptr, Mplus_FlashSelect);
987 
988  ops->retlen = len;
989  return ret;
990 }
991 
992 int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
993 {
994  volatile char dummy;
995  struct DiskOnChip *this = mtd->priv;
996  __u32 ofs = instr->addr;
997  __u32 len = instr->len;
998  void __iomem * docptr = this->virtadr;
999  struct Nand *mychip = &this->chips[ofs >> this->chipshift];
1000 
1001  DoC_CheckASIC(docptr);
1002 
1003  if (len != mtd->erasesize)
1004  printk(KERN_WARNING "MTD: Erase not right size (%x != %x)n",
1005  len, mtd->erasesize);
1006 
1007  /* Find the chip which is to be used and select it */
1008  if (this->curfloor != mychip->floor) {
1009  DoC_SelectFloor(docptr, mychip->floor);
1010  DoC_SelectChip(docptr, mychip->chip);
1011  } else if (this->curchip != mychip->chip) {
1012  DoC_SelectChip(docptr, mychip->chip);
1013  }
1014  this->curfloor = mychip->floor;
1015  this->curchip = mychip->chip;
1016 
1017  instr->state = MTD_ERASE_PENDING;
1018 
1019  /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
1020  WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect);
1021 
1022  DoC_Command(docptr, NAND_CMD_RESET, 0x00);
1023  DoC_WaitReady(docptr);
1024 
1025  DoC_Command(docptr, NAND_CMD_ERASE1, 0);
1026  DoC_Address(this, 2, ofs, 0, 0x00);
1027  DoC_Command(docptr, NAND_CMD_ERASE2, 0);
1028  DoC_WaitReady(docptr);
1029  instr->state = MTD_ERASING;
1030 
1031  /* Read the status of the flash device through CDSN IO register
1032  see Software Requirement 11.4 item 5. */
1033  DoC_Command(docptr, NAND_CMD_STATUS, 0);
1034  dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
1035  dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
1036  if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) {
1037  printk("MTD: Error 0x%x erasing at 0x%x\n", dummy, ofs);
1038  /* FIXME: implement Bad Block Replacement (in nftl.c ??) */
1039  instr->state = MTD_ERASE_FAILED;
1040  } else {
1041  instr->state = MTD_ERASE_DONE;
1042  }
1043  dummy = ReadDOC(docptr, Mplus_LastDataRead);
1044 
1045  /* Disable flash internally */
1046  WriteDOC(0, docptr, Mplus_FlashSelect);
1047 
1048  mtd_erase_callback(instr);
1049 
1050  return 0;
1051 }
1052 
1053 /****************************************************************************
1054  *
1055  * Module stuff
1056  *
1057  ****************************************************************************/
1058 
1059 static void __exit cleanup_doc2001plus(void)
1060 {
1061  struct mtd_info *mtd;
1062  struct DiskOnChip *this;
1063 
1064  while ((mtd=docmilpluslist)) {
1065  this = mtd->priv;
1066  docmilpluslist = this->nextdoc;
1067 
1068  mtd_device_unregister(mtd);
1069 
1070  iounmap(this->virtadr);
1071  kfree(this->chips);
1072  kfree(mtd);
1073  }
1074 }
1075 
1076 module_exit(cleanup_doc2001plus);
1077 
1078 MODULE_LICENSE("GPL");
1079 MODULE_AUTHOR("Greg Ungerer <[email protected]> et al.");
1080 MODULE_DESCRIPTION("Driver for DiskOnChip Millennium Plus");