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