Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.7-rc5 1080 lines 31 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 * 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 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 76static 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 */ 97static 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 */ 109static 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 */ 120static 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 */ 154static 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) */ 161static 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 */ 179static 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 208static 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 224static 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 234static 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 244static 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 255static 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} */ 267static 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 */ 340static void DoC_ScanChips(struct DiskOnChip *this) 341{ 342 int floor, chip; 343 int numchips[MAX_FLOORS_MPLUS]; 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 407static 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. */ 440void 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} 497EXPORT_SYMBOL_GPL(DoCMilPlus_init); 498 499#if 0 500static 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 574static 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 681static 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 801static 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 884static 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 992int 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 1059static 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 1076module_exit(cleanup_doc2001plus); 1077 1078MODULE_LICENSE("GPL"); 1079MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com> et al."); 1080MODULE_DESCRIPTION("Driver for DiskOnChip Millennium Plus");