mtd: atmel_nand: Support variable RB_EDGE interrupts
authorRomain Izard <romain.izard.pro@gmail.com>
Wed, 10 Feb 2016 09:56:23 +0000 (10:56 +0100)
committerBrian Norris <computersforpeace@gmail.com>
Fri, 12 Feb 2016 18:27:46 +0000 (10:27 -0800)
The NFC controller used to accelerate the NAND transfers on SAMA5 chips
can use either RB_EDGE0 or RB_EDGE3 as its ready/busy interrupt bit.

Use the controller's compatible string to select the correct bit.

For the binding:
Acked-by: Rob Herring <robh@kernel.org>
Reviewed-by: Wenyou Yang <Wenyou.yang@atmel.com>
Tested-by: Wenyou Yang <wenyou.yang@atmel.com>
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Romain Izard <romain.izard.pro@gmail.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Documentation/devicetree/bindings/mtd/atmel-nand.txt
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/atmel_nand_nfc.h

index 7d4c8eb775a5fff5da9861b632d11e18a6786eee..89b0db9801b0db350fae7c287db9f60aefb3cbce 100644 (file)
@@ -34,7 +34,7 @@ Optional properties:
 - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false
 - Nand Flash Controller(NFC) is a slave driver under Atmel nand flash
   - Required properties:
-    - compatible : "atmel,sama5d3-nfc".
+    - compatible : "atmel,sama5d3-nfc" or "atmel,sama5d4-nfc".
     - reg : should specify the address and size used for NFC command registers,
             NFC registers and NFC Sram. NFC Sram address and size can be absent
             if don't want to use it.
index affe7a7e9ad7dcefa1e25366b5a21cf07454f3ad..06a3e11f6684966da8d50c7a2201364e8ce0b9fe 100644 (file)
@@ -67,6 +67,10 @@ struct atmel_nand_caps {
        bool pmecc_correct_erase_page;
 };
 
+struct atmel_nand_nfc_caps {
+       uint32_t rb_mask;
+};
+
 /* oob layout for large page size
  * bad block info is on bytes 0 and 1
  * the bytes have to be consecutives to avoid
@@ -111,6 +115,7 @@ struct atmel_nfc {
        /* Point to the sram bank which include readed data via NFC */
        void                    *data_in_sram;
        bool                    will_write_sram;
+       const struct atmel_nand_nfc_caps *caps;
 };
 static struct atmel_nfc        nand_nfc;
 
@@ -1675,9 +1680,9 @@ static irqreturn_t hsmc_interrupt(int irq, void *dev_id)
                nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE);
                ret = IRQ_HANDLED;
        }
-       if (pending & NFC_SR_RB_EDGE) {
+       if (pending & host->nfc->caps->rb_mask) {
                complete(&host->nfc->comp_ready);
-               nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE);
+               nfc_writel(host->nfc->hsmc_regs, IDR, host->nfc->caps->rb_mask);
                ret = IRQ_HANDLED;
        }
        if (pending & NFC_SR_CMD_DONE) {
@@ -1695,7 +1700,7 @@ static void nfc_prepare_interrupt(struct atmel_nand_host *host, u32 flag)
        if (flag & NFC_SR_XFR_DONE)
                init_completion(&host->nfc->comp_xfer_done);
 
-       if (flag & NFC_SR_RB_EDGE)
+       if (flag & host->nfc->caps->rb_mask)
                init_completion(&host->nfc->comp_ready);
 
        if (flag & NFC_SR_CMD_DONE)
@@ -1713,7 +1718,7 @@ static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag)
        if (flag & NFC_SR_XFR_DONE)
                comp[index++] = &host->nfc->comp_xfer_done;
 
-       if (flag & NFC_SR_RB_EDGE)
+       if (flag & host->nfc->caps->rb_mask)
                comp[index++] = &host->nfc->comp_ready;
 
        if (flag & NFC_SR_CMD_DONE)
@@ -1781,7 +1786,7 @@ static int nfc_device_ready(struct mtd_info *mtd)
                dev_err(host->dev, "Lost the interrupt flags: 0x%08x\n",
                                mask & status);
 
-       return status & NFC_SR_RB_EDGE;
+       return status & host->nfc->caps->rb_mask;
 }
 
 static void nfc_select_chip(struct mtd_info *mtd, int chip)
@@ -1954,8 +1959,8 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
                }
                /* fall through */
        default:
-               nfc_prepare_interrupt(host, NFC_SR_RB_EDGE);
-               nfc_wait_interrupt(host, NFC_SR_RB_EDGE);
+               nfc_prepare_interrupt(host, host->nfc->caps->rb_mask);
+               nfc_wait_interrupt(host, host->nfc->caps->rb_mask);
        }
 }
 
@@ -2352,6 +2357,11 @@ static int atmel_nand_nfc_probe(struct platform_device *pdev)
                }
        }
 
+       nfc->caps = (const struct atmel_nand_nfc_caps *)
+               of_device_get_match_data(&pdev->dev);
+       if (!nfc->caps)
+               return -ENODEV;
+
        nfc_writel(nfc->hsmc_regs, IDR, 0xffffffff);
        nfc_readl(nfc->hsmc_regs, SR);  /* clear the NFC_SR */
 
@@ -2380,8 +2390,17 @@ static int atmel_nand_nfc_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct atmel_nand_nfc_caps sama5d3_nfc_caps = {
+       .rb_mask = NFC_SR_RB_EDGE0,
+};
+
+static const struct atmel_nand_nfc_caps sama5d4_nfc_caps = {
+       .rb_mask = NFC_SR_RB_EDGE3,
+};
+
 static const struct of_device_id atmel_nand_nfc_match[] = {
-       { .compatible = "atmel,sama5d3-nfc" },
+       { .compatible = "atmel,sama5d3-nfc", .data = &sama5d3_nfc_caps },
+       { .compatible = "atmel,sama5d4-nfc", .data = &sama5d4_nfc_caps },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, atmel_nand_nfc_match);
index 4d5d26221a7ee512d3d16e02441f0619d81ad900..0bbc1fa97dba5c930c77cf807e6ece759eff807f 100644 (file)
@@ -42,7 +42,8 @@
 #define                NFC_SR_UNDEF            (1 << 21)
 #define                NFC_SR_AWB              (1 << 22)
 #define                NFC_SR_ASE              (1 << 23)
-#define                NFC_SR_RB_EDGE          (1 << 24)
+#define                NFC_SR_RB_EDGE0         (1 << 24)
+#define                NFC_SR_RB_EDGE3         (1 << 27)
 
 #define ATMEL_HSMC_NFC_IER     0x0c
 #define ATMEL_HSMC_NFC_IDR     0x10