mtd: rawnand: brcmnand: Add support for v7.3 controller
authorKamal Dasu <kdasu.kdev@gmail.com>
Tue, 4 Jun 2019 14:36:30 +0000 (10:36 -0400)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Thu, 27 Jun 2019 18:06:41 +0000 (20:06 +0200)
This change adds support for brcm NAND v7.3 controller. This controller
uses a newer version of flash_dma engine and change mostly implements
these differences.

Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
drivers/mtd/nand/raw/brcmnand/brcmnand.c

index 357ef26..33310b8 100644 (file)
@@ -84,6 +84,12 @@ struct brcm_nand_dma_desc {
 #define FLASH_DMA_ECC_ERROR    (1 << 8)
 #define FLASH_DMA_CORR_ERROR   (1 << 9)
 
+/* Bitfields for DMA_MODE */
+#define FLASH_DMA_MODE_STOP_ON_ERROR   BIT(1) /* stop in Uncorr ECC error */
+#define FLASH_DMA_MODE_MODE            BIT(0) /* link list */
+#define FLASH_DMA_MODE_MASK            (FLASH_DMA_MODE_STOP_ON_ERROR | \
+                                               FLASH_DMA_MODE_MODE)
+
 /* 512B flash cache in the NAND controller HW */
 #define FC_SHIFT               9U
 #define FC_BYTES               512U
@@ -96,6 +102,51 @@ struct brcm_nand_dma_desc {
 #define NAND_CTRL_RDY                  (INTFC_CTLR_READY | INTFC_FLASH_READY)
 #define NAND_POLL_STATUS_TIMEOUT_MS    100
 
+/* flash_dma registers */
+enum flash_dma_reg {
+       FLASH_DMA_REVISION = 0,
+       FLASH_DMA_FIRST_DESC,
+       FLASH_DMA_FIRST_DESC_EXT,
+       FLASH_DMA_CTRL,
+       FLASH_DMA_MODE,
+       FLASH_DMA_STATUS,
+       FLASH_DMA_INTERRUPT_DESC,
+       FLASH_DMA_INTERRUPT_DESC_EXT,
+       FLASH_DMA_ERROR_STATUS,
+       FLASH_DMA_CURRENT_DESC,
+       FLASH_DMA_CURRENT_DESC_EXT,
+};
+
+/* flash_dma registers v1*/
+static const u16 flash_dma_regs_v1[] = {
+       [FLASH_DMA_REVISION]            = 0x00,
+       [FLASH_DMA_FIRST_DESC]          = 0x04,
+       [FLASH_DMA_FIRST_DESC_EXT]      = 0x08,
+       [FLASH_DMA_CTRL]                = 0x0c,
+       [FLASH_DMA_MODE]                = 0x10,
+       [FLASH_DMA_STATUS]              = 0x14,
+       [FLASH_DMA_INTERRUPT_DESC]      = 0x18,
+       [FLASH_DMA_INTERRUPT_DESC_EXT]  = 0x1c,
+       [FLASH_DMA_ERROR_STATUS]        = 0x20,
+       [FLASH_DMA_CURRENT_DESC]        = 0x24,
+       [FLASH_DMA_CURRENT_DESC_EXT]    = 0x28,
+};
+
+/* flash_dma registers v4 */
+static const u16 flash_dma_regs_v4[] = {
+       [FLASH_DMA_REVISION]            = 0x00,
+       [FLASH_DMA_FIRST_DESC]          = 0x08,
+       [FLASH_DMA_FIRST_DESC_EXT]      = 0x0c,
+       [FLASH_DMA_CTRL]                = 0x10,
+       [FLASH_DMA_MODE]                = 0x14,
+       [FLASH_DMA_STATUS]              = 0x18,
+       [FLASH_DMA_INTERRUPT_DESC]      = 0x20,
+       [FLASH_DMA_INTERRUPT_DESC_EXT]  = 0x24,
+       [FLASH_DMA_ERROR_STATUS]        = 0x28,
+       [FLASH_DMA_CURRENT_DESC]        = 0x30,
+       [FLASH_DMA_CURRENT_DESC_EXT]    = 0x34,
+};
+
 /* Controller feature flags */
 enum {
        BRCMNAND_HAS_1K_SECTORS                 = BIT(0),
@@ -128,6 +179,8 @@ struct brcmnand_controller {
        /* List of NAND hosts (one for each chip-select) */
        struct list_head host_list;
 
+       /* flash_dma reg */
+       const u16               *flash_dma_offsets;
        struct brcm_nand_dma_desc *dma_desc;
        dma_addr_t              dma_pa;
 
@@ -463,7 +516,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
        /* Register offsets */
        if (ctrl->nand_version >= 0x0702)
                ctrl->reg_offsets = brcmnand_regs_v72;
-       else if (ctrl->nand_version >= 0x0701)
+       else if (ctrl->nand_version == 0x0701)
                ctrl->reg_offsets = brcmnand_regs_v71;
        else if (ctrl->nand_version >= 0x0600)
                ctrl->reg_offsets = brcmnand_regs_v60;
@@ -508,7 +561,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
        }
 
        /* Maximum spare area sector size (per 512B) */
-       if (ctrl->nand_version >= 0x0702)
+       if (ctrl->nand_version == 0x0702)
                ctrl->max_oob = 128;
        else if (ctrl->nand_version >= 0x0600)
                ctrl->max_oob = 64;
@@ -539,6 +592,15 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
        return 0;
 }
 
+static void brcmnand_flash_dma_revision_init(struct brcmnand_controller *ctrl)
+{
+       /* flash_dma register offsets */
+       if (ctrl->nand_version >= 0x0703)
+               ctrl->flash_dma_offsets = flash_dma_regs_v4;
+       else
+               ctrl->flash_dma_offsets = flash_dma_regs_v1;
+}
+
 static inline u32 brcmnand_read_reg(struct brcmnand_controller *ctrl,
                enum brcmnand_reg reg)
 {
@@ -661,7 +723,7 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val)
        enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD;
        int cs = host->cs;
 
-       if (ctrl->nand_version >= 0x0702)
+       if (ctrl->nand_version == 0x0702)
                bits = 7;
        else if (ctrl->nand_version >= 0x0600)
                bits = 6;
@@ -715,7 +777,7 @@ enum {
 
 static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
 {
-       if (ctrl->nand_version >= 0x0702)
+       if (ctrl->nand_version == 0x0702)
                return GENMASK(7, 0);
        else if (ctrl->nand_version >= 0x0600)
                return GENMASK(6, 0);
@@ -845,20 +907,6 @@ static inline void brcmnand_set_wp(struct brcmnand_controller *ctrl, bool en)
  * Flash DMA
  ***********************************************************************/
 
-enum flash_dma_reg {
-       FLASH_DMA_REVISION              = 0x00,
-       FLASH_DMA_FIRST_DESC            = 0x04,
-       FLASH_DMA_FIRST_DESC_EXT        = 0x08,
-       FLASH_DMA_CTRL                  = 0x0c,
-       FLASH_DMA_MODE                  = 0x10,
-       FLASH_DMA_STATUS                = 0x14,
-       FLASH_DMA_INTERRUPT_DESC        = 0x18,
-       FLASH_DMA_INTERRUPT_DESC_EXT    = 0x1c,
-       FLASH_DMA_ERROR_STATUS          = 0x20,
-       FLASH_DMA_CURRENT_DESC          = 0x24,
-       FLASH_DMA_CURRENT_DESC_EXT      = 0x28,
-};
-
 static inline bool has_flash_dma(struct brcmnand_controller *ctrl)
 {
        return ctrl->flash_dma_base;
@@ -884,14 +932,19 @@ static inline bool flash_dma_buf_ok(const void *buf)
                likely(IS_ALIGNED((uintptr_t)buf, 4));
 }
 
-static inline void flash_dma_writel(struct brcmnand_controller *ctrl, u8 offs,
-                                   u32 val)
+static inline void flash_dma_writel(struct brcmnand_controller *ctrl,
+                                   enum flash_dma_reg dma_reg, u32 val)
 {
+       u16 offs = ctrl->flash_dma_offsets[dma_reg];
+
        brcmnand_writel(val, ctrl->flash_dma_base + offs);
 }
 
-static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl, u8 offs)
+static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl,
+                                 enum flash_dma_reg dma_reg)
 {
+       u16 offs = ctrl->flash_dma_offsets[dma_reg];
+
        return brcmnand_readl(ctrl->flash_dma_base + offs);
 }
 
@@ -2472,6 +2525,7 @@ static const struct of_device_id brcmnand_of_match[] = {
        { .compatible = "brcm,brcmnand-v7.0" },
        { .compatible = "brcm,brcmnand-v7.1" },
        { .compatible = "brcm,brcmnand-v7.2" },
+       { .compatible = "brcm,brcmnand-v7.3" },
        {},
 };
 MODULE_DEVICE_TABLE(of, brcmnand_of_match);
@@ -2558,7 +2612,11 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
                        goto err;
                }
 
-               flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */
+               /* initialize the dma version */
+               brcmnand_flash_dma_revision_init(ctrl);
+
+               /* linked-list and stop on error */
+               flash_dma_writel(ctrl, FLASH_DMA_MODE, FLASH_DMA_MODE_MASK);
                flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0);
 
                /* Allocate descriptor(s) */