linux/drivers/mtd/nand/bcm_umi_nand.c
<<
>>
Prefs
   1/*****************************************************************************
   2* Copyright 2004 - 2009 Broadcom Corporation.  All rights reserved.
   3*
   4* Unless you and Broadcom execute a separate written software license
   5* agreement governing use of this software, this software is licensed to you
   6* under the terms of the GNU General Public License version 2, available at
   7* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
   8*
   9* Notwithstanding the above, under no circumstances may you combine this
  10* software in any way with any other Broadcom software provided under a
  11* license other than the GPL, without Broadcom's express prior written
  12* consent.
  13*****************************************************************************/
  14
  15/* ---- Include Files ---------------------------------------------------- */
  16#include <linux/module.h>
  17#include <linux/types.h>
  18#include <linux/init.h>
  19#include <linux/kernel.h>
  20#include <linux/slab.h>
  21#include <linux/string.h>
  22#include <linux/ioport.h>
  23#include <linux/device.h>
  24#include <linux/delay.h>
  25#include <linux/err.h>
  26#include <linux/io.h>
  27#include <linux/platform_device.h>
  28#include <linux/mtd/mtd.h>
  29#include <linux/mtd/nand.h>
  30#include <linux/mtd/nand_ecc.h>
  31#include <linux/mtd/partitions.h>
  32
  33#include <asm/mach-types.h>
  34#include <asm/system.h>
  35
  36#include <mach/reg_nand.h>
  37#include <mach/reg_umi.h>
  38
  39#include "nand_bcm_umi.h"
  40
  41#include <mach/memory_settings.h>
  42
  43#define USE_DMA 1
  44#include <mach/dma.h>
  45#include <linux/dma-mapping.h>
  46#include <linux/completion.h>
  47
  48/* ---- External Variable Declarations ----------------------------------- */
  49/* ---- External Function Prototypes ------------------------------------- */
  50/* ---- Public Variables ------------------------------------------------- */
  51/* ---- Private Constants and Types -------------------------------------- */
  52static const __devinitconst char gBanner[] = KERN_INFO \
  53        "BCM UMI MTD NAND Driver: 1.00\n";
  54
  55const char *part_probes[] = { "cmdlinepart", NULL };
  56
  57#if NAND_ECC_BCH
  58static uint8_t scan_ff_pattern[] = { 0xff };
  59
  60static struct nand_bbt_descr largepage_bbt = {
  61        .options = 0,
  62        .offs = 0,
  63        .len = 1,
  64        .pattern = scan_ff_pattern
  65};
  66#endif
  67
  68/*
  69** Preallocate a buffer to avoid having to do this every dma operation.
  70** This is the size of the preallocated coherent DMA buffer.
  71*/
  72#if USE_DMA
  73#define DMA_MIN_BUFLEN  512
  74#define DMA_MAX_BUFLEN  PAGE_SIZE
  75#define USE_DIRECT_IO(len)      (((len) < DMA_MIN_BUFLEN) || \
  76        ((len) > DMA_MAX_BUFLEN))
  77
  78/*
  79 * The current NAND data space goes from 0x80001900 to 0x80001FFF,
  80 * which is only 0x700 = 1792 bytes long. This is too small for 2K, 4K page
  81 * size NAND flash. Need to break the DMA down to multiple 1Ks.
  82 *
  83 * Need to make sure REG_NAND_DATA_PADDR + DMA_MAX_LEN < 0x80002000
  84 */
  85#define DMA_MAX_LEN             1024
  86
  87#else /* !USE_DMA */
  88#define DMA_MIN_BUFLEN          0
  89#define DMA_MAX_BUFLEN          0
  90#define USE_DIRECT_IO(len)      1
  91#endif
  92/* ---- Private Function Prototypes -------------------------------------- */
  93static void bcm_umi_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len);
  94static void bcm_umi_nand_write_buf(struct mtd_info *mtd, const u_char * buf,
  95                                   int len);
  96
  97/* ---- Private Variables ------------------------------------------------ */
  98static struct mtd_info *board_mtd;
  99static void __iomem *bcm_umi_io_base;
 100static void *virtPtr;
 101static dma_addr_t physPtr;
 102static struct completion nand_comp;
 103
 104/* ---- Private Functions ------------------------------------------------ */
 105#if NAND_ECC_BCH
 106#include "bcm_umi_bch.c"
 107#else
 108#include "bcm_umi_hamming.c"
 109#endif
 110
 111#if USE_DMA
 112
 113/* Handler called when the DMA finishes. */
 114static void nand_dma_handler(DMA_Device_t dev, int reason, void *userData)
 115{
 116        complete(&nand_comp);
 117}
 118
 119static int nand_dma_init(void)
 120{
 121        int rc;
 122
 123        rc = dma_set_device_handler(DMA_DEVICE_NAND_MEM_TO_MEM,
 124                nand_dma_handler, NULL);
 125        if (rc != 0) {
 126                printk(KERN_ERR "dma_set_device_handler failed: %d\n", rc);
 127                return rc;
 128        }
 129
 130        virtPtr =
 131            dma_alloc_coherent(NULL, DMA_MAX_BUFLEN, &physPtr, GFP_KERNEL);
 132        if (virtPtr == NULL) {
 133                printk(KERN_ERR "NAND - Failed to allocate memory for DMA buffer\n");
 134                return -ENOMEM;
 135        }
 136
 137        return 0;
 138}
 139
 140static void nand_dma_term(void)
 141{
 142        if (virtPtr != NULL)
 143                dma_free_coherent(NULL, DMA_MAX_BUFLEN, virtPtr, physPtr);
 144}
 145
 146static void nand_dma_read(void *buf, int len)
 147{
 148        int offset = 0;
 149        int tmp_len = 0;
 150        int len_left = len;
 151        DMA_Handle_t hndl;
 152
 153        if (virtPtr == NULL)
 154                panic("nand_dma_read: virtPtr == NULL\n");
 155
 156        if ((void *)physPtr == NULL)
 157                panic("nand_dma_read: physPtr == NULL\n");
 158
 159        hndl = dma_request_channel(DMA_DEVICE_NAND_MEM_TO_MEM);
 160        if (hndl < 0) {
 161                printk(KERN_ERR
 162                       "nand_dma_read: unable to allocate dma channel: %d\n",
 163                       (int)hndl);
 164                panic("\n");
 165        }
 166
 167        while (len_left > 0) {
 168                if (len_left > DMA_MAX_LEN) {
 169                        tmp_len = DMA_MAX_LEN;
 170                        len_left -= DMA_MAX_LEN;
 171                } else {
 172                        tmp_len = len_left;
 173                        len_left = 0;
 174                }
 175
 176                init_completion(&nand_comp);
 177                dma_transfer_mem_to_mem(hndl, REG_NAND_DATA_PADDR,
 178                                        physPtr + offset, tmp_len);
 179                wait_for_completion(&nand_comp);
 180
 181                offset += tmp_len;
 182        }
 183
 184        dma_free_channel(hndl);
 185
 186        if (buf != NULL)
 187                memcpy(buf, virtPtr, len);
 188}
 189
 190static void nand_dma_write(const void *buf, int len)
 191{
 192        int offset = 0;
 193        int tmp_len = 0;
 194        int len_left = len;
 195        DMA_Handle_t hndl;
 196
 197        if (buf == NULL)
 198                panic("nand_dma_write: buf == NULL\n");
 199
 200        if (virtPtr == NULL)
 201                panic("nand_dma_write: virtPtr == NULL\n");
 202
 203        if ((void *)physPtr == NULL)
 204                panic("nand_dma_write: physPtr == NULL\n");
 205
 206        memcpy(virtPtr, buf, len);
 207
 208
 209        hndl = dma_request_channel(DMA_DEVICE_NAND_MEM_TO_MEM);
 210        if (hndl < 0) {
 211                printk(KERN_ERR
 212                       "nand_dma_write: unable to allocate dma channel: %d\n",
 213                       (int)hndl);
 214                panic("\n");
 215        }
 216
 217        while (len_left > 0) {
 218                if (len_left > DMA_MAX_LEN) {
 219                        tmp_len = DMA_MAX_LEN;
 220                        len_left -= DMA_MAX_LEN;
 221                } else {
 222                        tmp_len = len_left;
 223                        len_left = 0;
 224                }
 225
 226                init_completion(&nand_comp);
 227                dma_transfer_mem_to_mem(hndl, physPtr + offset,
 228                                        REG_NAND_DATA_PADDR, tmp_len);
 229                wait_for_completion(&nand_comp);
 230
 231                offset += tmp_len;
 232        }
 233
 234        dma_free_channel(hndl);
 235}
 236
 237#endif
 238
 239static int nand_dev_ready(struct mtd_info *mtd)
 240{
 241        return nand_bcm_umi_dev_ready();
 242}
 243
 244/****************************************************************************
 245*
 246*  bcm_umi_nand_inithw
 247*
 248*   This routine does the necessary hardware (board-specific)
 249*   initializations.  This includes setting up the timings, etc.
 250*
 251***************************************************************************/
 252int bcm_umi_nand_inithw(void)
 253{
 254        /* Configure nand timing parameters */
 255        REG_UMI_NAND_TCR &= ~0x7ffff;
 256        REG_UMI_NAND_TCR |= HW_CFG_NAND_TCR;
 257
 258#if !defined(CONFIG_MTD_NAND_BCM_UMI_HWCS)
 259        /* enable software control of CS */
 260        REG_UMI_NAND_TCR |= REG_UMI_NAND_TCR_CS_SWCTRL;
 261#endif
 262
 263        /* keep NAND chip select asserted */
 264        REG_UMI_NAND_RCSR |= REG_UMI_NAND_RCSR_CS_ASSERTED;
 265
 266        REG_UMI_NAND_TCR &= ~REG_UMI_NAND_TCR_WORD16;
 267        /* enable writes to flash */
 268        REG_UMI_MMD_ICR |= REG_UMI_MMD_ICR_FLASH_WP;
 269
 270        writel(NAND_CMD_RESET, bcm_umi_io_base + REG_NAND_CMD_OFFSET);
 271        nand_bcm_umi_wait_till_ready();
 272
 273#if NAND_ECC_BCH
 274        nand_bcm_umi_bch_config_ecc(NAND_ECC_NUM_BYTES);
 275#endif
 276
 277        return 0;
 278}
 279
 280/* Used to turn latch the proper register for access. */
 281static void bcm_umi_nand_hwcontrol(struct mtd_info *mtd, int cmd,
 282                                   unsigned int ctrl)
 283{
 284        /* send command to hardware */
 285        struct nand_chip *chip = mtd->priv;
 286        if (ctrl & NAND_CTRL_CHANGE) {
 287                if (ctrl & NAND_CLE) {
 288                        chip->IO_ADDR_W = bcm_umi_io_base + REG_NAND_CMD_OFFSET;
 289                        goto CMD;
 290                }
 291                if (ctrl & NAND_ALE) {
 292                        chip->IO_ADDR_W =
 293                            bcm_umi_io_base + REG_NAND_ADDR_OFFSET;
 294                        goto CMD;
 295                }
 296                chip->IO_ADDR_W = bcm_umi_io_base + REG_NAND_DATA8_OFFSET;
 297        }
 298
 299CMD:
 300        /* Send command to chip directly */
 301        if (cmd != NAND_CMD_NONE)
 302                writeb(cmd, chip->IO_ADDR_W);
 303}
 304
 305static void bcm_umi_nand_write_buf(struct mtd_info *mtd, const u_char * buf,
 306                                   int len)
 307{
 308        if (USE_DIRECT_IO(len)) {
 309                /* Do it the old way if the buffer is small or too large.
 310                 * Probably quicker than starting and checking dma. */
 311                int i;
 312                struct nand_chip *this = mtd->priv;
 313
 314                for (i = 0; i < len; i++)
 315                        writeb(buf[i], this->IO_ADDR_W);
 316        }
 317#if USE_DMA
 318        else
 319                nand_dma_write(buf, len);
 320#endif
 321}
 322
 323static void bcm_umi_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len)
 324{
 325        if (USE_DIRECT_IO(len)) {
 326                int i;
 327                struct nand_chip *this = mtd->priv;
 328
 329                for (i = 0; i < len; i++)
 330                        buf[i] = readb(this->IO_ADDR_R);
 331        }
 332#if USE_DMA
 333        else
 334                nand_dma_read(buf, len);
 335#endif
 336}
 337
 338static uint8_t readbackbuf[NAND_MAX_PAGESIZE];
 339static int bcm_umi_nand_verify_buf(struct mtd_info *mtd, const u_char * buf,
 340                                   int len)
 341{
 342        /*
 343         * Try to readback page with ECC correction. This is necessary
 344         * for MLC parts which may have permanently stuck bits.
 345         */
 346        struct nand_chip *chip = mtd->priv;
 347        int ret = chip->ecc.read_page(mtd, chip, readbackbuf, 0);
 348        if (ret < 0)
 349                return -EFAULT;
 350        else {
 351                if (memcmp(readbackbuf, buf, len) == 0)
 352                        return 0;
 353
 354                return -EFAULT;
 355        }
 356        return 0;
 357}
 358
 359static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
 360{
 361        struct nand_chip *this;
 362        struct resource *r;
 363        int err = 0;
 364
 365        printk(gBanner);
 366
 367        /* Allocate memory for MTD device structure and private data */
 368        board_mtd =
 369            kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
 370                    GFP_KERNEL);
 371        if (!board_mtd) {
 372                printk(KERN_WARNING
 373                       "Unable to allocate NAND MTD device structure.\n");
 374                return -ENOMEM;
 375        }
 376
 377        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 378
 379        if (!r)
 380                return -ENXIO;
 381
 382        /* map physical address */
 383        bcm_umi_io_base = ioremap(r->start, r->end - r->start + 1);
 384
 385        if (!bcm_umi_io_base) {
 386                printk(KERN_ERR "ioremap to access BCM UMI NAND chip failed\n");
 387                kfree(board_mtd);
 388                return -EIO;
 389        }
 390
 391        /* Get pointer to private data */
 392        this = (struct nand_chip *)(&board_mtd[1]);
 393
 394        /* Initialize structures */
 395        memset((char *)board_mtd, 0, sizeof(struct mtd_info));
 396        memset((char *)this, 0, sizeof(struct nand_chip));
 397
 398        /* Link the private data with the MTD structure */
 399        board_mtd->priv = this;
 400
 401        /* Initialize the NAND hardware.  */
 402        if (bcm_umi_nand_inithw() < 0) {
 403                printk(KERN_ERR "BCM UMI NAND chip could not be initialized\n");
 404                iounmap(bcm_umi_io_base);
 405                kfree(board_mtd);
 406                return -EIO;
 407        }
 408
 409        /* Set address of NAND IO lines */
 410        this->IO_ADDR_W = bcm_umi_io_base + REG_NAND_DATA8_OFFSET;
 411        this->IO_ADDR_R = bcm_umi_io_base + REG_NAND_DATA8_OFFSET;
 412
 413        /* Set command delay time, see datasheet for correct value */
 414        this->chip_delay = 0;
 415        /* Assign the device ready function, if available */
 416        this->dev_ready = nand_dev_ready;
 417        this->options = 0;
 418
 419        this->write_buf = bcm_umi_nand_write_buf;
 420        this->read_buf = bcm_umi_nand_read_buf;
 421        this->verify_buf = bcm_umi_nand_verify_buf;
 422
 423        this->cmd_ctrl = bcm_umi_nand_hwcontrol;
 424        this->ecc.mode = NAND_ECC_HW;
 425        this->ecc.size = 512;
 426        this->ecc.bytes = NAND_ECC_NUM_BYTES;
 427#if NAND_ECC_BCH
 428        this->ecc.read_page = bcm_umi_bch_read_page_hwecc;
 429        this->ecc.write_page = bcm_umi_bch_write_page_hwecc;
 430#else
 431        this->ecc.correct = nand_correct_data512;
 432        this->ecc.calculate = bcm_umi_hamming_get_hw_ecc;
 433        this->ecc.hwctl = bcm_umi_hamming_enable_hwecc;
 434#endif
 435
 436#if USE_DMA
 437        err = nand_dma_init();
 438        if (err != 0)
 439                return err;
 440#endif
 441
 442        /* Figure out the size of the device that we have.
 443         * We need to do this to figure out which ECC
 444         * layout we'll be using.
 445         */
 446
 447        err = nand_scan_ident(board_mtd, 1, NULL);
 448        if (err) {
 449                printk(KERN_ERR "nand_scan failed: %d\n", err);
 450                iounmap(bcm_umi_io_base);
 451                kfree(board_mtd);
 452                return err;
 453        }
 454
 455        /* Now that we know the nand size, we can setup the ECC layout */
 456
 457        switch (board_mtd->writesize) { /* writesize is the pagesize */
 458        case 4096:
 459                this->ecc.layout = &nand_hw_eccoob_4096;
 460                break;
 461        case 2048:
 462                this->ecc.layout = &nand_hw_eccoob_2048;
 463                break;
 464        case 512:
 465                this->ecc.layout = &nand_hw_eccoob_512;
 466                break;
 467        default:
 468                {
 469                        printk(KERN_ERR "NAND - Unrecognized pagesize: %d\n",
 470                                         board_mtd->writesize);
 471                        return -EINVAL;
 472                }
 473        }
 474
 475#if NAND_ECC_BCH
 476        if (board_mtd->writesize > 512) {
 477                if (this->options & NAND_USE_FLASH_BBT)
 478                        largepage_bbt.options = NAND_BBT_SCAN2NDPAGE;
 479                this->badblock_pattern = &largepage_bbt;
 480        }
 481#endif
 482
 483        /* Now finish off the scan, now that ecc.layout has been initialized. */
 484
 485        err = nand_scan_tail(board_mtd);
 486        if (err) {
 487                printk(KERN_ERR "nand_scan failed: %d\n", err);
 488                iounmap(bcm_umi_io_base);
 489                kfree(board_mtd);
 490                return err;
 491        }
 492
 493        /* Register the partitions */
 494        {
 495                int nr_partitions;
 496                struct mtd_partition *partition_info;
 497
 498                board_mtd->name = "bcm_umi-nand";
 499                nr_partitions =
 500                    parse_mtd_partitions(board_mtd, part_probes,
 501                                         &partition_info, 0);
 502
 503                if (nr_partitions <= 0) {
 504                        printk(KERN_ERR "BCM UMI NAND: Too few partitions - %d\n",
 505                               nr_partitions);
 506                        iounmap(bcm_umi_io_base);
 507                        kfree(board_mtd);
 508                        return -EIO;
 509                }
 510                mtd_device_register(board_mtd, partition_info, nr_partitions);
 511        }
 512
 513        /* Return happy */
 514        return 0;
 515}
 516
 517static int bcm_umi_nand_remove(struct platform_device *pdev)
 518{
 519#if USE_DMA
 520        nand_dma_term();
 521#endif
 522
 523        /* Release resources, unregister device */
 524        nand_release(board_mtd);
 525
 526        /* unmap physical address */
 527        iounmap(bcm_umi_io_base);
 528
 529        /* Free the MTD device structure */
 530        kfree(board_mtd);
 531
 532        return 0;
 533}
 534
 535#ifdef CONFIG_PM
 536static int bcm_umi_nand_suspend(struct platform_device *pdev,
 537                                pm_message_t state)
 538{
 539        printk(KERN_ERR "MTD NAND suspend is being called\n");
 540        return 0;
 541}
 542
 543static int bcm_umi_nand_resume(struct platform_device *pdev)
 544{
 545        printk(KERN_ERR "MTD NAND resume is being called\n");
 546        return 0;
 547}
 548#else
 549#define bcm_umi_nand_suspend   NULL
 550#define bcm_umi_nand_resume    NULL
 551#endif
 552
 553static struct platform_driver nand_driver = {
 554        .driver = {
 555                   .name = "bcm-nand",
 556                   .owner = THIS_MODULE,
 557                   },
 558        .probe = bcm_umi_nand_probe,
 559        .remove = bcm_umi_nand_remove,
 560        .suspend = bcm_umi_nand_suspend,
 561        .resume = bcm_umi_nand_resume,
 562};
 563
 564static int __init nand_init(void)
 565{
 566        return platform_driver_register(&nand_driver);
 567}
 568
 569static void __exit nand_exit(void)
 570{
 571        platform_driver_unregister(&nand_driver);
 572}
 573
 574module_init(nand_init);
 575module_exit(nand_exit);
 576
 577MODULE_LICENSE("GPL");
 578MODULE_AUTHOR("Broadcom");
 579MODULE_DESCRIPTION("BCM UMI MTD NAND driver");
 580