diff options
author | Miquel Raynal <miquel.raynal@bootlin.com> | 2019-04-08 03:41:46 -0400 |
---|---|---|
committer | Miquel Raynal <miquel.raynal@bootlin.com> | 2019-07-05 16:30:58 -0400 |
commit | c7a87ceb17aee9222c069a97aee4647260c7b3a6 (patch) | |
tree | df674985e61420d2e06abebd37588377d83f4964 | |
parent | 4f032640bf5751ce792b69d2abdf18e0f379b3ce (diff) |
mtd: rawnand: sunxi: Add A23/A33 DMA support with extra MBUS configuration
Allwinner NAND controllers can make use of DMA to enhance the I/O
throughput thanks to ECC pipelining. DMA handling with A23/A33 NAND IP
is a bit different than with the older SoCs, hence the introduction of
a new compatible to handle:
* the differences between register offsets,
* the burst length change from 4 to minimum 8,
* manage SRAM accesses through MBUS with extra configuration.
Fixes: c49836f05aa1 ("mtd: rawnand: sunxi: Add A23/A33 DMA support")
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-rw-r--r-- | drivers/mtd/nand/raw/sunxi_nand.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index e93f39bc2bc5..89773293c64d 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #define NFC_REG_RCMD_SET 0x0028 | 43 | #define NFC_REG_RCMD_SET 0x0028 |
44 | #define NFC_REG_WCMD_SET 0x002C | 44 | #define NFC_REG_WCMD_SET 0x002C |
45 | #define NFC_REG_A10_IO_DATA 0x0030 | 45 | #define NFC_REG_A10_IO_DATA 0x0030 |
46 | #define NFC_REG_A23_IO_DATA 0x0300 | ||
46 | #define NFC_REG_ECC_CTL 0x0034 | 47 | #define NFC_REG_ECC_CTL 0x0034 |
47 | #define NFC_REG_ECC_ST 0x0038 | 48 | #define NFC_REG_ECC_ST 0x0038 |
48 | #define NFC_REG_DEBUG 0x003C | 49 | #define NFC_REG_DEBUG 0x003C |
@@ -50,6 +51,7 @@ | |||
50 | #define NFC_REG_USER_DATA(x) (0x0050 + ((x) * 4)) | 51 | #define NFC_REG_USER_DATA(x) (0x0050 + ((x) * 4)) |
51 | #define NFC_REG_SPARE_AREA 0x00A0 | 52 | #define NFC_REG_SPARE_AREA 0x00A0 |
52 | #define NFC_REG_PAT_ID 0x00A4 | 53 | #define NFC_REG_PAT_ID 0x00A4 |
54 | #define NFC_REG_MDMA_CNT 0x00C4 | ||
53 | #define NFC_RAM0_BASE 0x0400 | 55 | #define NFC_RAM0_BASE 0x0400 |
54 | #define NFC_RAM1_BASE 0x0800 | 56 | #define NFC_RAM1_BASE 0x0800 |
55 | 57 | ||
@@ -68,6 +70,7 @@ | |||
68 | #define NFC_PAGE_SHIFT(x) (((x) < 10 ? 0 : (x) - 10) << 8) | 70 | #define NFC_PAGE_SHIFT(x) (((x) < 10 ? 0 : (x) - 10) << 8) |
69 | #define NFC_SAM BIT(12) | 71 | #define NFC_SAM BIT(12) |
70 | #define NFC_RAM_METHOD BIT(14) | 72 | #define NFC_RAM_METHOD BIT(14) |
73 | #define NFC_DMA_TYPE_NORMAL BIT(15) | ||
71 | #define NFC_DEBUG_CTL BIT(31) | 74 | #define NFC_DEBUG_CTL BIT(31) |
72 | 75 | ||
73 | /* define bit use in NFC_ST */ | 76 | /* define bit use in NFC_ST */ |
@@ -204,10 +207,13 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand) | |||
204 | * NAND Controller capabilities structure: stores NAND controller capabilities | 207 | * NAND Controller capabilities structure: stores NAND controller capabilities |
205 | * for distinction between compatible strings. | 208 | * for distinction between compatible strings. |
206 | * | 209 | * |
210 | * @extra_mbus_conf: Contrary to A10, A10s and A13, accessing internal RAM | ||
211 | * through MBUS on A23/A33 needs extra configuration. | ||
207 | * @reg_io_data: I/O data register | 212 | * @reg_io_data: I/O data register |
208 | * @dma_maxburst: DMA maxburst | 213 | * @dma_maxburst: DMA maxburst |
209 | */ | 214 | */ |
210 | struct sunxi_nfc_caps { | 215 | struct sunxi_nfc_caps { |
216 | bool extra_mbus_conf; | ||
211 | unsigned int reg_io_data; | 217 | unsigned int reg_io_data; |
212 | unsigned int dma_maxburst; | 218 | unsigned int dma_maxburst; |
213 | }; | 219 | }; |
@@ -367,6 +373,9 @@ static int sunxi_nfc_dma_op_prepare(struct sunxi_nfc *nfc, const void *buf, | |||
367 | nfc->regs + NFC_REG_CTL); | 373 | nfc->regs + NFC_REG_CTL); |
368 | writel(nchunks, nfc->regs + NFC_REG_SECTOR_NUM); | 374 | writel(nchunks, nfc->regs + NFC_REG_SECTOR_NUM); |
369 | writel(chunksize, nfc->regs + NFC_REG_CNT); | 375 | writel(chunksize, nfc->regs + NFC_REG_CNT); |
376 | if (nfc->caps->extra_mbus_conf) | ||
377 | writel(chunksize * nchunks, nfc->regs + NFC_REG_MDMA_CNT); | ||
378 | |||
370 | dmat = dmaengine_submit(dmad); | 379 | dmat = dmaengine_submit(dmad); |
371 | 380 | ||
372 | ret = dma_submit_error(dmat); | 381 | ret = dma_submit_error(dmat); |
@@ -2127,6 +2136,11 @@ static int sunxi_nfc_probe(struct platform_device *pdev) | |||
2127 | dmac_cfg.src_maxburst = nfc->caps->dma_maxburst; | 2136 | dmac_cfg.src_maxburst = nfc->caps->dma_maxburst; |
2128 | dmac_cfg.dst_maxburst = nfc->caps->dma_maxburst; | 2137 | dmac_cfg.dst_maxburst = nfc->caps->dma_maxburst; |
2129 | dmaengine_slave_config(nfc->dmac, &dmac_cfg); | 2138 | dmaengine_slave_config(nfc->dmac, &dmac_cfg); |
2139 | |||
2140 | if (nfc->caps->extra_mbus_conf) | ||
2141 | writel(readl(nfc->regs + NFC_REG_CTL) | | ||
2142 | NFC_DMA_TYPE_NORMAL, nfc->regs + NFC_REG_CTL); | ||
2143 | |||
2130 | } else { | 2144 | } else { |
2131 | dev_warn(dev, "failed to request rxtx DMA channel\n"); | 2145 | dev_warn(dev, "failed to request rxtx DMA channel\n"); |
2132 | } | 2146 | } |
@@ -2175,11 +2189,21 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = { | |||
2175 | .dma_maxburst = 4, | 2189 | .dma_maxburst = 4, |
2176 | }; | 2190 | }; |
2177 | 2191 | ||
2192 | static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = { | ||
2193 | .extra_mbus_conf = true, | ||
2194 | .reg_io_data = NFC_REG_A23_IO_DATA, | ||
2195 | .dma_maxburst = 8, | ||
2196 | }; | ||
2197 | |||
2178 | static const struct of_device_id sunxi_nfc_ids[] = { | 2198 | static const struct of_device_id sunxi_nfc_ids[] = { |
2179 | { | 2199 | { |
2180 | .compatible = "allwinner,sun4i-a10-nand", | 2200 | .compatible = "allwinner,sun4i-a10-nand", |
2181 | .data = &sunxi_nfc_a10_caps, | 2201 | .data = &sunxi_nfc_a10_caps, |
2182 | }, | 2202 | }, |
2203 | { | ||
2204 | .compatible = "allwinner,sun8i-a23-nand-controller", | ||
2205 | .data = &sunxi_nfc_a23_caps, | ||
2206 | }, | ||
2183 | { /* sentinel */ } | 2207 | { /* sentinel */ } |
2184 | }; | 2208 | }; |
2185 | MODULE_DEVICE_TABLE(of, sunxi_nfc_ids); | 2209 | MODULE_DEVICE_TABLE(of, sunxi_nfc_ids); |