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