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