]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/mtd/nand/denali.c
mtd: nand: denali: support 64bit capable DMA engine
[karo-tx-linux.git] / drivers / mtd / nand / denali.c
index b95e33a842015d8f826961a58134e4e369fa00ea..417a8950cf49c4e029589b9e00d63aa0f9c7e9e8 100644 (file)
@@ -979,8 +979,30 @@ static void denali_enable_dma(struct denali_nand_info *denali, bool en)
        ioread32(denali->flash_reg + DMA_ENABLE);
 }
 
-/* setups the HW to perform the data DMA */
-static void denali_setup_dma(struct denali_nand_info *denali, int op)
+static void denali_setup_dma64(struct denali_nand_info *denali, int op)
+{
+       uint32_t mode;
+       const int page_count = 1;
+       uint64_t addr = denali->buf.dma_buf;
+
+       mode = MODE_10 | BANK(denali->flash_bank) | denali->page;
+
+       /* DMA is a three step process */
+
+       /*
+        * 1. setup transfer type, interrupt when complete,
+        *    burst len = 64 bytes, the number of pages
+        */
+       index_addr(denali, mode, 0x01002000 | (64 << 16) | op | page_count);
+
+       /* 2. set memory low address */
+       index_addr(denali, mode, addr);
+
+       /* 3. set memory high address */
+       index_addr(denali, mode, addr >> 32);
+}
+
+static void denali_setup_dma32(struct denali_nand_info *denali, int op)
 {
        uint32_t mode;
        const int page_count = 1;
@@ -1003,6 +1025,14 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op)
        index_addr(denali, mode | 0x14000, 0x2400);
 }
 
+static void denali_setup_dma(struct denali_nand_info *denali, int op)
+{
+       if (denali->caps & DENALI_CAP_DMA_64BIT)
+               denali_setup_dma64(denali, op);
+       else
+               denali_setup_dma32(denali, op);
+}
+
 /*
  * writes a page. user specifies type, and this function handles the
  * configuration details.
@@ -1518,8 +1548,9 @@ int denali_init(struct denali_nand_info *denali)
                goto failed_req_irq;
        }
 
-       /* Is 32-bit DMA supported? */
-       ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32));
+       ret = dma_set_mask(denali->dev,
+                          DMA_BIT_MASK(denali->caps & DENALI_CAP_DMA_64BIT ?
+                                       64 : 32));
        if (ret) {
                dev_err(denali->dev, "No usable DMA configuration\n");
                goto failed_req_irq;