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.4-rc7 1088 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 * 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= %02x:%02x:%02x:%02x:%02x:" 663 "%02x\n", 664 syndrome[0], syndrome[1], syndrome[2], 665 syndrome[3], syndrome[4], syndrome[5]); 666 printk(" eccbuf= %02x:%02x:%02x:%02x:%02x:" 667 "%02x\n", 668 eccbuf[0], eccbuf[1], eccbuf[2], 669 eccbuf[3], eccbuf[4], eccbuf[5]); 670#endif 671 ret = -EIO; 672 } 673 } 674 675#ifdef PSYCHO_DEBUG 676 printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", 677 (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], 678 eccbuf[4], eccbuf[5]); 679#endif 680 /* disable the ECC engine */ 681 WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf); 682 683 /* Disable flash internally */ 684 WriteDOC(0, docptr, Mplus_FlashSelect); 685 686 return ret; 687} 688 689static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, 690 size_t *retlen, const u_char *buf) 691{ 692 int i, before, ret = 0; 693 loff_t fto; 694 volatile char dummy; 695 char eccbuf[6]; 696 struct DiskOnChip *this = mtd->priv; 697 void __iomem * docptr = this->virtadr; 698 struct Nand *mychip = &this->chips[to >> (this->chipshift)]; 699 700 /* Don't allow writes which aren't exactly one block (512 bytes) */ 701 if ((to & 0x1ff) || (len != 0x200)) 702 return -EINVAL; 703 704 /* Determine position of OOB flags, before or after data */ 705 before = (this->interleave && (to & 0x200)); 706 707 DoC_CheckASIC(docptr); 708 709 /* Find the chip which is to be used and select it */ 710 if (this->curfloor != mychip->floor) { 711 DoC_SelectFloor(docptr, mychip->floor); 712 DoC_SelectChip(docptr, mychip->chip); 713 } else if (this->curchip != mychip->chip) { 714 DoC_SelectChip(docptr, mychip->chip); 715 } 716 this->curfloor = mychip->floor; 717 this->curchip = mychip->chip; 718 719 /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ 720 WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect); 721 722 /* Reset the chip, see Software Requirement 11.4 item 1. */ 723 DoC_Command(docptr, NAND_CMD_RESET, 0); 724 DoC_WaitReady(docptr); 725 726 /* Set device to appropriate plane of flash */ 727 fto = to; 728 WriteDOC(DoC_GetDataOffset(mtd, &fto), docptr, Mplus_FlashCmd); 729 730 /* On interleaved devices the flags for 2nd half 512 are before data */ 731 if (before) 732 fto -= 2; 733 734 /* issue the Serial Data In command to initial the Page Program process */ 735 DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); 736 DoC_Address(this, 3, fto, 0x00, 0x00); 737 738 /* Disable the ECC engine */ 739 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); 740 741 if (before) { 742 /* Write the block status BLOCK_USED (0x5555) */ 743 WriteDOC(0x55, docptr, Mil_CDSN_IO); 744 WriteDOC(0x55, docptr, Mil_CDSN_IO); 745 } 746 747 /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ 748 WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf); 749 750 MemWriteDOC(docptr, (unsigned char *) buf, len); 751 752 /* Write ECC data to flash, the ECC info is generated by 753 the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */ 754 DoC_Delay(docptr, 3); 755 756 /* Read the ECC data through the DiskOnChip ECC logic */ 757 for (i = 0; i < 6; i++) 758 eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); 759 760 /* disable the ECC engine */ 761 WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); 762 763 /* Write the ECC data to flash */ 764 MemWriteDOC(docptr, eccbuf, 6); 765 766 if (!before) { 767 /* Write the block status BLOCK_USED (0x5555) */ 768 WriteDOC(0x55, docptr, Mil_CDSN_IO+6); 769 WriteDOC(0x55, docptr, Mil_CDSN_IO+7); 770 } 771 772#ifdef PSYCHO_DEBUG 773 printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", 774 (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], 775 eccbuf[4], eccbuf[5]); 776#endif 777 778 WriteDOC(0x00, docptr, Mplus_WritePipeTerm); 779 WriteDOC(0x00, docptr, Mplus_WritePipeTerm); 780 781 /* Commit the Page Program command and wait for ready 782 see Software Requirement 11.4 item 1.*/ 783 DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00); 784 DoC_WaitReady(docptr); 785 786 /* Read the status of the flash device through CDSN IO register 787 see Software Requirement 11.4 item 5.*/ 788 DoC_Command(docptr, NAND_CMD_STATUS, 0); 789 dummy = ReadDOC(docptr, Mplus_ReadPipeInit); 790 dummy = ReadDOC(docptr, Mplus_ReadPipeInit); 791 DoC_Delay(docptr, 2); 792 if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) { 793 printk("MTD: Error 0x%x programming at 0x%x\n", dummy, (int)to); 794 /* Error in programming 795 FIXME: implement Bad Block Replacement (in nftl.c ??) */ 796 ret = -EIO; 797 } 798 dummy = ReadDOC(docptr, Mplus_LastDataRead); 799 800 /* Disable flash internally */ 801 WriteDOC(0, docptr, Mplus_FlashSelect); 802 803 /* Let the caller know we completed it */ 804 *retlen = len; 805 806 return ret; 807} 808 809static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, 810 struct mtd_oob_ops *ops) 811{ 812 loff_t fofs, base; 813 struct DiskOnChip *this = mtd->priv; 814 void __iomem * docptr = this->virtadr; 815 struct Nand *mychip = &this->chips[ofs >> this->chipshift]; 816 size_t i, size, got, want; 817 uint8_t *buf = ops->oobbuf; 818 size_t len = ops->len; 819 820 BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); 821 822 ofs += ops->ooboffs; 823 824 DoC_CheckASIC(docptr); 825 826 /* Find the chip which is to be used and select it */ 827 if (this->curfloor != mychip->floor) { 828 DoC_SelectFloor(docptr, mychip->floor); 829 DoC_SelectChip(docptr, mychip->chip); 830 } else if (this->curchip != mychip->chip) { 831 DoC_SelectChip(docptr, mychip->chip); 832 } 833 this->curfloor = mychip->floor; 834 this->curchip = mychip->chip; 835 836 /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ 837 WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect); 838 839 /* disable the ECC engine */ 840 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); 841 DoC_WaitReady(docptr); 842 843 /* Maximum of 16 bytes in the OOB region, so limit read to that */ 844 if (len > 16) 845 len = 16; 846 got = 0; 847 want = len; 848 849 for (i = 0; ((i < 3) && (want > 0)); i++) { 850 /* Figure out which region we are accessing... */ 851 fofs = ofs; 852 base = ofs & 0xf; 853 if (!this->interleave) { 854 DoC_Command(docptr, NAND_CMD_READOOB, 0); 855 size = 16 - base; 856 } else if (base < 6) { 857 DoC_Command(docptr, DoC_GetECCOffset(mtd, &fofs), 0); 858 size = 6 - base; 859 } else if (base < 8) { 860 DoC_Command(docptr, DoC_GetFlagsOffset(mtd, &fofs), 0); 861 size = 8 - base; 862 } else { 863 DoC_Command(docptr, DoC_GetHdrOffset(mtd, &fofs), 0); 864 size = 16 - base; 865 } 866 if (size > want) 867 size = want; 868 869 /* Issue read command */ 870 DoC_Address(this, 3, fofs, 0, 0x00); 871 WriteDOC(0, docptr, Mplus_FlashControl); 872 DoC_WaitReady(docptr); 873 874 ReadDOC(docptr, Mplus_ReadPipeInit); 875 ReadDOC(docptr, Mplus_ReadPipeInit); 876 MemReadDOC(docptr, &buf[got], size - 2); 877 buf[got + size - 2] = ReadDOC(docptr, Mplus_LastDataRead); 878 buf[got + size - 1] = ReadDOC(docptr, Mplus_LastDataRead); 879 880 ofs += size; 881 got += size; 882 want -= size; 883 } 884 885 /* Disable flash internally */ 886 WriteDOC(0, docptr, Mplus_FlashSelect); 887 888 ops->retlen = len; 889 return 0; 890} 891 892static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, 893 struct mtd_oob_ops *ops) 894{ 895 volatile char dummy; 896 loff_t fofs, base; 897 struct DiskOnChip *this = mtd->priv; 898 void __iomem * docptr = this->virtadr; 899 struct Nand *mychip = &this->chips[ofs >> this->chipshift]; 900 size_t i, size, got, want; 901 int ret = 0; 902 uint8_t *buf = ops->oobbuf; 903 size_t len = ops->len; 904 905 BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); 906 907 ofs += ops->ooboffs; 908 909 DoC_CheckASIC(docptr); 910 911 /* Find the chip which is to be used and select it */ 912 if (this->curfloor != mychip->floor) { 913 DoC_SelectFloor(docptr, mychip->floor); 914 DoC_SelectChip(docptr, mychip->chip); 915 } else if (this->curchip != mychip->chip) { 916 DoC_SelectChip(docptr, mychip->chip); 917 } 918 this->curfloor = mychip->floor; 919 this->curchip = mychip->chip; 920 921 /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ 922 WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect); 923 924 925 /* Maximum of 16 bytes in the OOB region, so limit write to that */ 926 if (len > 16) 927 len = 16; 928 got = 0; 929 want = len; 930 931 for (i = 0; ((i < 3) && (want > 0)); i++) { 932 /* Reset the chip, see Software Requirement 11.4 item 1. */ 933 DoC_Command(docptr, NAND_CMD_RESET, 0); 934 DoC_WaitReady(docptr); 935 936 /* Figure out which region we are accessing... */ 937 fofs = ofs; 938 base = ofs & 0x0f; 939 if (!this->interleave) { 940 WriteDOC(NAND_CMD_READOOB, docptr, Mplus_FlashCmd); 941 size = 16 - base; 942 } else if (base < 6) { 943 WriteDOC(DoC_GetECCOffset(mtd, &fofs), docptr, Mplus_FlashCmd); 944 size = 6 - base; 945 } else if (base < 8) { 946 WriteDOC(DoC_GetFlagsOffset(mtd, &fofs), docptr, Mplus_FlashCmd); 947 size = 8 - base; 948 } else { 949 WriteDOC(DoC_GetHdrOffset(mtd, &fofs), docptr, Mplus_FlashCmd); 950 size = 16 - base; 951 } 952 if (size > want) 953 size = want; 954 955 /* Issue the Serial Data In command to initial the Page Program process */ 956 DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); 957 DoC_Address(this, 3, fofs, 0, 0x00); 958 959 /* Disable the ECC engine */ 960 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); 961 962 /* Write the data via the internal pipeline through CDSN IO 963 register, see Pipelined Write Operations 11.2 */ 964 MemWriteDOC(docptr, (unsigned char *) &buf[got], size); 965 WriteDOC(0x00, docptr, Mplus_WritePipeTerm); 966 WriteDOC(0x00, docptr, Mplus_WritePipeTerm); 967 968 /* Commit the Page Program command and wait for ready 969 see Software Requirement 11.4 item 1.*/ 970 DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00); 971 DoC_WaitReady(docptr); 972 973 /* Read the status of the flash device through CDSN IO register 974 see Software Requirement 11.4 item 5.*/ 975 DoC_Command(docptr, NAND_CMD_STATUS, 0x00); 976 dummy = ReadDOC(docptr, Mplus_ReadPipeInit); 977 dummy = ReadDOC(docptr, Mplus_ReadPipeInit); 978 DoC_Delay(docptr, 2); 979 if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) { 980 printk("MTD: Error 0x%x programming oob at 0x%x\n", 981 dummy, (int)ofs); 982 /* FIXME: implement Bad Block Replacement */ 983 ops->retlen = 0; 984 ret = -EIO; 985 } 986 dummy = ReadDOC(docptr, Mplus_LastDataRead); 987 988 ofs += size; 989 got += size; 990 want -= size; 991 } 992 993 /* Disable flash internally */ 994 WriteDOC(0, docptr, Mplus_FlashSelect); 995 996 ops->retlen = len; 997 return ret; 998} 999 1000int doc_erase(struct mtd_info *mtd, struct erase_info *instr) 1001{ 1002 volatile char dummy; 1003 struct DiskOnChip *this = mtd->priv; 1004 __u32 ofs = instr->addr; 1005 __u32 len = instr->len; 1006 void __iomem * docptr = this->virtadr; 1007 struct Nand *mychip = &this->chips[ofs >> this->chipshift]; 1008 1009 DoC_CheckASIC(docptr); 1010 1011 if (len != mtd->erasesize) 1012 printk(KERN_WARNING "MTD: Erase not right size (%x != %x)n", 1013 len, mtd->erasesize); 1014 1015 /* Find the chip which is to be used and select it */ 1016 if (this->curfloor != mychip->floor) { 1017 DoC_SelectFloor(docptr, mychip->floor); 1018 DoC_SelectChip(docptr, mychip->chip); 1019 } else if (this->curchip != mychip->chip) { 1020 DoC_SelectChip(docptr, mychip->chip); 1021 } 1022 this->curfloor = mychip->floor; 1023 this->curchip = mychip->chip; 1024 1025 instr->state = MTD_ERASE_PENDING; 1026 1027 /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ 1028 WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect); 1029 1030 DoC_Command(docptr, NAND_CMD_RESET, 0x00); 1031 DoC_WaitReady(docptr); 1032 1033 DoC_Command(docptr, NAND_CMD_ERASE1, 0); 1034 DoC_Address(this, 2, ofs, 0, 0x00); 1035 DoC_Command(docptr, NAND_CMD_ERASE2, 0); 1036 DoC_WaitReady(docptr); 1037 instr->state = MTD_ERASING; 1038 1039 /* Read the status of the flash device through CDSN IO register 1040 see Software Requirement 11.4 item 5. */ 1041 DoC_Command(docptr, NAND_CMD_STATUS, 0); 1042 dummy = ReadDOC(docptr, Mplus_ReadPipeInit); 1043 dummy = ReadDOC(docptr, Mplus_ReadPipeInit); 1044 if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) { 1045 printk("MTD: Error 0x%x erasing at 0x%x\n", dummy, ofs); 1046 /* FIXME: implement Bad Block Replacement (in nftl.c ??) */ 1047 instr->state = MTD_ERASE_FAILED; 1048 } else { 1049 instr->state = MTD_ERASE_DONE; 1050 } 1051 dummy = ReadDOC(docptr, Mplus_LastDataRead); 1052 1053 /* Disable flash internally */ 1054 WriteDOC(0, docptr, Mplus_FlashSelect); 1055 1056 mtd_erase_callback(instr); 1057 1058 return 0; 1059} 1060 1061/**************************************************************************** 1062 * 1063 * Module stuff 1064 * 1065 ****************************************************************************/ 1066 1067static void __exit cleanup_doc2001plus(void) 1068{ 1069 struct mtd_info *mtd; 1070 struct DiskOnChip *this; 1071 1072 while ((mtd=docmilpluslist)) { 1073 this = mtd->priv; 1074 docmilpluslist = this->nextdoc; 1075 1076 mtd_device_unregister(mtd); 1077 1078 iounmap(this->virtadr); 1079 kfree(this->chips); 1080 kfree(mtd); 1081 } 1082} 1083 1084module_exit(cleanup_doc2001plus); 1085 1086MODULE_LICENSE("GPL"); 1087MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com> et al."); 1088MODULE_DESCRIPTION("Driver for DiskOnChip Millennium Plus");