Drivers: MTD: NAND: restore to the NAND controller
Ramalingam C [Mon, 19 Mar 2012 06:18:27 +0000 (11:18 +0530)]
On entering the power saving mode NAND controller registers are getting reset.
With this change resume will restore the controller registers' values.

Bug 933291

Change-Id: Ia1a43827b4b4a91ab1383bf07c3c0fe3068b666b
Signed-off-by: Ramalingam C <ramalingamc@nvidia.com>
Reviewed-on: http://git-master/r/90883
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Venu Byravarasu <vbyravarasu@nvidia.com>
Reviewed-by: Preetham Chandru <pchandru@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>

drivers/mtd/devices/tegra_nand.c

index ba90925..c8a3e70 100644 (file)
@@ -132,6 +132,7 @@ struct tegra_nand_info {
        uint32_t is_data_bus_width_16;
        uint32_t device_id;
        uint32_t vendor_id;
+       uint32_t dev_parms;
        uint32_t num_bad_blocks;
 };
 #define MTD_TO_INFO(mtd)       container_of((mtd), struct tegra_nand_info, mtd)
@@ -1288,38 +1289,6 @@ static int tegra_nand_suspend(struct mtd_info *mtd)
        return 0;
 }
 
-static void tegra_nand_resume(struct mtd_info *mtd)
-{
-}
-
-static int scan_bad_blocks(struct tegra_nand_info *info)
-{
-       struct mtd_info *mtd = &info->mtd;
-       int num_blocks = mtd->size >> info->chip.block_shift;
-       uint32_t block;
-       int is_bad = 0;
-       info->num_bad_blocks = 0;
-
-       for (block = 0; block < num_blocks; ++block) {
-               /* make sure the bit is cleared, meaning it's bad/unknown before
-                * we check. */
-               clear_bit(block, info->bb_bitmap);
-               is_bad = mtd->block_isbad(mtd, block << info->chip.block_shift);
-
-               if (is_bad == 0)
-                       set_bit(block, info->bb_bitmap);
-               else if (is_bad > 0) {
-                       info->num_bad_blocks++;
-                       pr_debug("block 0x%08x is bad.\n", block);
-               } else {
-                       pr_err("Fatal error (%d) while scanning for "
-                              "bad blocks\n", is_bad);
-                       return is_bad;
-               }
-       }
-       return 0;
-}
-
 static void
 set_chip_timing(struct tegra_nand_info *info, uint32_t vendor_id,
                uint32_t dev_id, uint32_t fourth_id_field)
@@ -1357,6 +1326,60 @@ set_chip_timing(struct tegra_nand_info *info, uint32_t vendor_id,
 #undef CNT
 }
 
+static void tegra_nand_resume(struct mtd_info *mtd)
+{
+       struct tegra_nand_info *info = MTD_TO_INFO(mtd);
+
+       cfg_hwstatus_mon(info);
+
+       /* clear all pending interrupts */
+       writel(readl(ISR_REG), ISR_REG);
+
+       /* clear dma interrupt */
+       writel(DMA_CTRL_IS_DMA_DONE, DMA_MST_CTRL_REG);
+
+       /* enable interrupts */
+       disable_ints(info, 0xffffffff);
+       enable_ints(info,
+                   IER_ERR_TRIG_VAL(4) | IER_UND | IER_OVR | IER_CMD_DONE |
+                   IER_ECC_ERR | IER_GIE);
+
+       writel(0, CONFIG_REG);
+
+       set_chip_timing(info, info->vendor_id,
+                               info->device_id, info->dev_parms);
+
+       return;
+}
+
+static int scan_bad_blocks(struct tegra_nand_info *info)
+{
+       struct mtd_info *mtd = &info->mtd;
+       int num_blocks = mtd->size >> info->chip.block_shift;
+       uint32_t block;
+       int is_bad = 0;
+       info->num_bad_blocks = 0;
+
+       for (block = 0; block < num_blocks; ++block) {
+               /* make sure the bit is cleared, meaning it's bad/unknown before
+                * we check. */
+               clear_bit(block, info->bb_bitmap);
+               is_bad = mtd->block_isbad(mtd, block << info->chip.block_shift);
+
+               if (is_bad == 0)
+                       set_bit(block, info->bb_bitmap);
+               else if (is_bad > 0) {
+                       info->num_bad_blocks++;
+                       pr_debug("block 0x%08x is bad.\n", block);
+               } else {
+                       pr_err("Fatal error (%d) while scanning for "
+                              "bad blocks\n", is_bad);
+                       return is_bad;
+               }
+       }
+       return 0;
+}
+
 /* Scans for nand flash devices, identifies them, and fills in the
  * device info. */
 static int tegra_nand_scan(struct mtd_info *mtd, int maxchips)
@@ -1419,6 +1442,7 @@ static int tegra_nand_scan(struct mtd_info *mtd, int maxchips)
                dev_info->name);
        info->vendor_id = vendor_id;
        info->device_id = dev_id;
+       info->dev_parms = dev_parms;
        info->chip.num_chips = cnt;
        info->chip.chipsize = dev_info->chipsize << 20;
        mtd->size = info->chip.num_chips * info->chip.chipsize;