Commit 210a2c87 authored by Masahiro Yamada's avatar Masahiro Yamada Committed by Boris Brezillon

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: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
parent a56609c4
...@@ -979,8 +979,30 @@ static void denali_enable_dma(struct denali_nand_info *denali, bool en) ...@@ -979,8 +979,30 @@ static void denali_enable_dma(struct denali_nand_info *denali, bool en)
ioread32(denali->flash_reg + DMA_ENABLE); ioread32(denali->flash_reg + DMA_ENABLE);
} }
/* setups the HW to perform the data DMA */ static void denali_setup_dma64(struct denali_nand_info *denali, int op)
static void denali_setup_dma(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; uint32_t mode;
const int page_count = 1; const int page_count = 1;
...@@ -1003,6 +1025,14 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op) ...@@ -1003,6 +1025,14 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op)
index_addr(denali, mode | 0x14000, 0x2400); 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 * writes a page. user specifies type, and this function handles the
* configuration details. * configuration details.
...@@ -1518,8 +1548,9 @@ int denali_init(struct denali_nand_info *denali) ...@@ -1518,8 +1548,9 @@ int denali_init(struct denali_nand_info *denali)
goto failed_req_irq; goto failed_req_irq;
} }
/* Is 32-bit DMA supported? */ ret = dma_set_mask(denali->dev,
ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32)); DMA_BIT_MASK(denali->caps & DENALI_CAP_DMA_64BIT ?
64 : 32));
if (ret) { if (ret) {
dev_err(denali->dev, "No usable DMA configuration\n"); dev_err(denali->dev, "No usable DMA configuration\n");
goto failed_req_irq; goto failed_req_irq;
......
...@@ -347,6 +347,7 @@ struct denali_nand_info { ...@@ -347,6 +347,7 @@ struct denali_nand_info {
}; };
#define DENALI_CAP_HW_ECC_FIXUP BIT(0) #define DENALI_CAP_HW_ECC_FIXUP BIT(0)
#define DENALI_CAP_DMA_64BIT BIT(1)
extern int denali_init(struct denali_nand_info *denali); extern int denali_init(struct denali_nand_info *denali);
extern void denali_remove(struct denali_nand_info *denali); extern void denali_remove(struct denali_nand_info *denali);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment