]> Pileus Git - ~andy/linux/blobdiff - drivers/mtd/nand/mxc_nand.c
Merge branch 'reiserfs/kill-bkl' of git://git.kernel.org/pub/scm/linux/kernel/git...
[~andy/linux] / drivers / mtd / nand / mxc_nand.c
index 2e3f3fbcd67cd08e8adc55be727444c0d787fc54..45dec5770da0b93ea560bc812b482d7e34951a56 100644 (file)
@@ -118,9 +118,6 @@ struct mxc_nand_host {
        int                     spare_len;
 };
 
-/* Define delays in microsec for NAND device operations */
-#define TROP_US_DELAY   2000
-
 /* OOB placement block for use with hardware ecc generation */
 static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
        .eccbytes = 5,
@@ -185,10 +182,10 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
 /* This function polls the NANDFC to wait for the basic operation to
  * complete by checking the INT bit of config2 register.
  */
-static void wait_op_done(struct mxc_nand_host *host, int max_retries,
-                               int useirq)
+static void wait_op_done(struct mxc_nand_host *host, int useirq)
 {
        uint32_t tmp;
+       int max_retries = 2000;
 
        if (useirq) {
                if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) {
@@ -230,7 +227,7 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
        writew(NFC_CMD, host->regs + NFC_CONFIG2);
 
        /* Wait for operation to complete */
-       wait_op_done(host, TROP_US_DELAY, useirq);
+       wait_op_done(host, useirq);
 }
 
 /* This function sends an address (or partial address) to the
@@ -244,7 +241,7 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast)
        writew(NFC_ADDR, host->regs + NFC_CONFIG2);
 
        /* Wait for operation to complete */
-       wait_op_done(host, TROP_US_DELAY, islast);
+       wait_op_done(host, islast);
 }
 
 static void send_page(struct mtd_info *mtd, unsigned int ops)
@@ -266,7 +263,7 @@ static void send_page(struct mtd_info *mtd, unsigned int ops)
                writew(ops, host->regs + NFC_CONFIG2);
 
                /* Wait for operation to complete */
-               wait_op_done(host, TROP_US_DELAY, true);
+               wait_op_done(host, true);
        }
 }
 
@@ -281,7 +278,7 @@ static void send_read_id(struct mxc_nand_host *host)
        writew(NFC_ID, host->regs + NFC_CONFIG2);
 
        /* Wait for operation to complete */
-       wait_op_done(host, TROP_US_DELAY, true);
+       wait_op_done(host, true);
 
        if (this->options & NAND_BUSWIDTH_16) {
                void __iomem *main_buf = host->main_area0;
@@ -313,7 +310,7 @@ static uint16_t get_dev_status(struct mxc_nand_host *host)
        writew(NFC_STATUS, host->regs + NFC_CONFIG2);
 
        /* Wait for operation to complete */
-       wait_op_done(host, TROP_US_DELAY, true);
+       wait_op_done(host, true);
 
        /* Status is placed in first word of main buffer */
        /* get status, then recovery area 1 data */
@@ -648,6 +645,33 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
        }
 }
 
+/*
+ * The generic flash bbt decriptors overlap with our ecc
+ * hardware, so define some i.MX specific ones.
+ */
+static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
+static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+           | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+       .offs = 0,
+       .len = 4,
+       .veroffs = 4,
+       .maxblocks = 4,
+       .pattern = bbt_pattern,
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+           | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+       .offs = 0,
+       .len = 4,
+       .veroffs = 4,
+       .maxblocks = 4,
+       .pattern = mirror_pattern,
+};
+
 static int __init mxcnd_probe(struct platform_device *pdev)
 {
        struct nand_chip *this;
@@ -674,7 +698,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
        mtd->priv = this;
        mtd->owner = THIS_MODULE;
        mtd->dev.parent = &pdev->dev;
-       mtd->name = "mxc_nand";
+       mtd->name = DRIVER_NAME;
 
        /* 50 us command delay time */
        this->chip_delay = 5;
@@ -738,7 +762,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 
        host->irq = platform_get_irq(pdev, 0);
 
-       err = request_irq(host->irq, mxc_nfc_irq, 0, "mxc_nd", host);
+       err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host);
        if (err)
                goto eirq;
 
@@ -786,6 +810,13 @@ static int __init mxcnd_probe(struct platform_device *pdev)
        if (pdata->width == 2)
                this->options |= NAND_BUSWIDTH_16;
 
+       if (pdata->flash_bbt) {
+               this->bbt_td = &bbt_main_descr;
+               this->bbt_md = &bbt_mirror_descr;
+               /* update flash based bbt */
+               this->options |= NAND_USE_FLASH_BBT;
+       }
+
        /* first scan to find the device and get the page size */
        if (nand_scan_ident(mtd, 1)) {
                err = -ENXIO;
@@ -830,7 +861,7 @@ eclk:
        return err;
 }
 
-static int __exit mxcnd_remove(struct platform_device *pdev)
+static int __devexit mxcnd_remove(struct platform_device *pdev)
 {
        struct mxc_nand_host *host = platform_get_drvdata(pdev);
 
@@ -891,7 +922,7 @@ static struct platform_driver mxcnd_driver = {
        .driver = {
                   .name = DRIVER_NAME,
                   },
-       .remove = __exit_p(mxcnd_remove),
+       .remove = __devexit_p(mxcnd_remove),
        .suspend = mxcnd_suspend,
        .resume = mxcnd_resume,
 };