From mboxrd@z Thu Jan 1 00:00:00 1970 From: Boris Brezillon Subject: Re: [PATCH 6/7] mtd: nand: sunxi: add support for DMA assisted operations Date: Thu, 17 Mar 2016 15:06:19 +0100 Message-ID: <20160317150619.7d6b5f37@bbrezillon> References: <1457435715-24740-1-git-send-email-boris.brezillon@free-electrons.com> <1457435715-24740-7-git-send-email-boris.brezillon@free-electrons.com> Reply-To: boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Cc: Mark Brown , linux-spi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org, Maxime Ripard , Chen-Yu Tsai , linux-sunxi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org, Vinod Koul , Dan Williams , dmaengine-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Mauro Carvalho Chehab , Hans Verkuil , Laurent Pinchart , linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala , devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: Andrew Morton , Dave Gordon , David Woodhouse , Brian Norris , linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org Return-path: Sender: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org In-Reply-To: <1457435715-24740-7-git-send-email-boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , List-Id: linux-spi.vger.kernel.org On Tue, 8 Mar 2016 12:15:14 +0100 Boris Brezillon wrote: > The sunxi NAND controller is able to pipeline ECC operations only when > operated in DMA mode, which improves a lot NAND throughput while keeping > CPU usage low. > > Signed-off-by: Boris Brezillon > --- > drivers/mtd/nand/sunxi_nand.c | 301 +++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 297 insertions(+), 4 deletions(-) > > diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c > index 07c3af7..7ba285e 100644 > --- a/drivers/mtd/nand/sunxi_nand.c > +++ b/drivers/mtd/nand/sunxi_nand.c [...] > +static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd, > + struct nand_chip *chip, > + const u8 *buf, > + int oob_required, > + int page) > +{ > + struct nand_chip *nand = mtd_to_nand(mtd); > + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); > + struct nand_ecc_ctrl *ecc = &nand->ecc; > + struct sg_table sgt; > + int ret, i; > + > + ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); > + if (ret) > + return ret; > + > + ret = sunxi_nfc_dma_op_prepare(mtd, buf, ecc->size, ecc->steps, > + DMA_TO_DEVICE, &sgt); > + if (ret) > + goto pio_fallback; > + > + for (i = 0; i < ecc->steps; i++) { > + const u8 *oob = nand->oob_poi + (i * (ecc->bytes + 4)); > + > + sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, i, !i, page); > + } > + > + sunxi_nfc_hw_ecc_enable(mtd); > + sunxi_nfc_randomizer_config(mtd, page, false); > + sunxi_nfc_randomizer_enable(mtd); > + > + writel((NAND_CMD_RNDIN << 8) | NAND_CMD_PAGEPROG, > + nfc->regs + NFC_REG_RCMD_SET); > + > + dma_async_issue_pending(nfc->dmac); > + > + writel(NFC_PAGE_OP | NFC_DATA_SWAP_METHOD | > + NFC_DATA_TRANS | NFC_ACCESS_DIR, > + nfc->regs + NFC_REG_CMD); > + > + ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0); > + if (ret) > + dmaengine_terminate_all(nfc->dmac); > + > + sunxi_nfc_randomizer_disable(mtd); > + sunxi_nfc_hw_ecc_disable(mtd); > + > + sunxi_nfc_dma_op_cleanup(mtd, DMA_FROM_DEVICE, &sgt); Should be DMA_TO_DEVICE here ^ > + > + if (ret) > + return ret; > + > + if (oob_required || (chip->options & NAND_NEED_SCRAMBLING)) > + /* TODO: use DMA to transfer extra OOB bytes ? */ > + sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, > + NULL, page); > + > + return 0; > + > +pio_fallback: > + return sunxi_nfc_hw_ecc_write_page(mtd, chip, buf, oob_required, page); > +} -- Boris Brezillon, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com