summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorMasahiro Yamada <yamada.masahiro@socionext.com>2017-03-30 02:45:54 -0400
committerBoris Brezillon <boris.brezillon@free-electrons.com>2017-04-25 08:18:35 -0400
commit210a2c876fe02c9440569c9282af43e7a85562e3 (patch)
tree9bf52dabe1c46e11efc47a1962e82793122deb60 /drivers/mtd/nand
parenta56609c4c3f34de76d905e39160511b3c53310ac (diff)
mtd: nand: denali: support 64bit capable DMA engine
The current driver only supports the DMA engine up to 32 bit physical address, but there also exists 64 bit capable DMA engine for this IP. The data DMA setup sequence is completely different, so I added the 64 bit DMA code as a new function denali_setup_dma64(). The 32 bit one has been renamed to denali_setup_dma32(). Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/denali.c39
-rw-r--r--drivers/mtd/nand/denali.h1
2 files changed, 36 insertions, 4 deletions
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index b95e33a84201..417a8950cf49 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -979,8 +979,30 @@ static void denali_enable_dma(struct denali_nand_info *denali, bool en)
979 ioread32(denali->flash_reg + DMA_ENABLE); 979 ioread32(denali->flash_reg + DMA_ENABLE);
980} 980}
981 981
982/* setups the HW to perform the data DMA */ 982static void denali_setup_dma64(struct denali_nand_info *denali, int op)
983static void denali_setup_dma(struct denali_nand_info *denali, int op) 983{
984 uint32_t mode;
985 const int page_count = 1;
986 uint64_t addr = denali->buf.dma_buf;
987
988 mode = MODE_10 | BANK(denali->flash_bank) | denali->page;
989
990 /* DMA is a three step process */
991
992 /*
993 * 1. setup transfer type, interrupt when complete,
994 * burst len = 64 bytes, the number of pages
995 */
996 index_addr(denali, mode, 0x01002000 | (64 << 16) | op | page_count);
997
998 /* 2. set memory low address */
999 index_addr(denali, mode, addr);
1000
1001 /* 3. set memory high address */
1002 index_addr(denali, mode, addr >> 32);
1003}
1004
1005static void denali_setup_dma32(struct denali_nand_info *denali, int op)
984{ 1006{
985 uint32_t mode; 1007 uint32_t mode;
986 const int page_count = 1; 1008 const int page_count = 1;
@@ -1003,6 +1025,14 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op)
1003 index_addr(denali, mode | 0x14000, 0x2400); 1025 index_addr(denali, mode | 0x14000, 0x2400);
1004} 1026}
1005 1027
1028static void denali_setup_dma(struct denali_nand_info *denali, int op)
1029{
1030 if (denali->caps & DENALI_CAP_DMA_64BIT)
1031 denali_setup_dma64(denali, op);
1032 else
1033 denali_setup_dma32(denali, op);
1034}
1035
1006/* 1036/*
1007 * writes a page. user specifies type, and this function handles the 1037 * writes a page. user specifies type, and this function handles the
1008 * configuration details. 1038 * configuration details.
@@ -1518,8 +1548,9 @@ int denali_init(struct denali_nand_info *denali)
1518 goto failed_req_irq; 1548 goto failed_req_irq;
1519 } 1549 }
1520 1550
1521 /* Is 32-bit DMA supported? */ 1551 ret = dma_set_mask(denali->dev,
1522 ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32)); 1552 DMA_BIT_MASK(denali->caps & DENALI_CAP_DMA_64BIT ?
1553 64 : 32));
1523 if (ret) { 1554 if (ret) {
1524 dev_err(denali->dev, "No usable DMA configuration\n"); 1555 dev_err(denali->dev, "No usable DMA configuration\n");
1525 goto failed_req_irq; 1556 goto failed_req_irq;
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index e532956b7177..1f413d05a010 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -347,6 +347,7 @@ struct denali_nand_info {
347}; 347};
348 348
349#define DENALI_CAP_HW_ECC_FIXUP BIT(0) 349#define DENALI_CAP_HW_ECC_FIXUP BIT(0)
350#define DENALI_CAP_DMA_64BIT BIT(1)
350 351
351extern int denali_init(struct denali_nand_info *denali); 352extern int denali_init(struct denali_nand_info *denali);
352extern void denali_remove(struct denali_nand_info *denali); 353extern void denali_remove(struct denali_nand_info *denali);