mtd: nand: denali: use interrupt instead of polling for bank reset
authorMasahiro Yamada <yamada.masahiro@socionext.com>
Tue, 13 Jun 2017 13:45:41 +0000 (22:45 +0900)
committerBoris Brezillon <boris.brezillon@free-electrons.com>
Tue, 20 Jun 2017 07:14:37 +0000 (09:14 +0200)
The current bank reset implementation polls the INTR_STATUS register
until interested bits are set.  This is not good because:

- polling simply wastes time-slice of the thread

- The while() loop may continue eternally if no bit is set, for
  example, due to the controller problem.  The denali_wait_for_irq()
  uses wait_for_completion_timeout(), which is safer.

We can use interrupt by moving the denali_reset_bank() call below
the interrupt setup.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
drivers/mtd/nand/denali.c

index 3169ba58c58af80911065c8a2ce36c7ed1128a89..31d987d26e1293a9575b481a6edaa12f09801730 100644 (file)
@@ -1028,24 +1028,25 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
 
 static void denali_reset_banks(struct denali_nand_info *denali)
 {
+       u32 irq_status;
        int i;
 
-       denali_clear_irq_all(denali);
-
        for (i = 0; i < denali->max_banks; i++) {
-               iowrite32(1 << i, denali->flash_reg + DEVICE_RESET);
-               while (!(ioread32(denali->flash_reg + INTR_STATUS(i)) &
-                       (INTR__RST_COMP | INTR__TIME_OUT)))
-                       cpu_relax();
-               if (!(ioread32(denali->flash_reg + INTR_STATUS(i)) &
-                     INTR__INT_ACT))
+               denali->flash_bank = i;
+
+               denali_reset_irq(denali);
+
+               iowrite32(DEVICE_RESET__BANK(i),
+                         denali->flash_reg + DEVICE_RESET);
+
+               irq_status = denali_wait_for_irq(denali,
+                       INTR__RST_COMP | INTR__INT_ACT | INTR__TIME_OUT);
+               if (!(irq_status & INTR__INT_ACT))
                        break;
        }
 
        dev_dbg(denali->dev, "%d chips connected\n", i);
        denali->max_banks = i;
-
-       denali_clear_irq_all(denali);
 }
 
 static void denali_hw_init(struct denali_nand_info *denali)
@@ -1067,7 +1068,6 @@ static void denali_hw_init(struct denali_nand_info *denali)
        denali->bbtskipbytes = ioread32(denali->flash_reg +
                                                SPARE_AREA_SKIP_BYTES);
        detect_max_banks(denali);
-       denali_reset_banks(denali);
        iowrite32(0x0F, denali->flash_reg + RB_PIN_ENABLED);
        iowrite32(CHIP_EN_DONT_CARE__FLAG,
                        denali->flash_reg + CHIP_ENABLE_DONT_CARE);
@@ -1185,9 +1185,6 @@ static void denali_drv_init(struct denali_nand_info *denali)
         * element that might be access shared data (interrupt status)
         */
        spin_lock_init(&denali->irq_lock);
-
-       /* indicate that MTD has not selected a valid bank yet */
-       denali->flash_bank = CHIP_SELECT_INVALID;
 }
 
 static int denali_multidev_fixup(struct denali_nand_info *denali)
@@ -1262,6 +1259,9 @@ int denali_init(struct denali_nand_info *denali)
        }
 
        denali_enable_irq(denali);
+       denali_reset_banks(denali);
+
+       denali->flash_bank = CHIP_SELECT_INVALID;
 
        nand_set_flash_node(chip, denali->dev->of_node);
        /* Fallback to the default name if DT did not give "label" property */