From patchwork Wed Aug 7 15:33:50 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Mack X-Patchwork-Id: 2840370 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 72C959F3B9 for ; Wed, 7 Aug 2013 15:36:28 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5BB8920213 for ; Wed, 7 Aug 2013 15:36:23 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 64A742020F for ; Wed, 7 Aug 2013 15:36:18 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1V75m8-0005sn-KL; Wed, 07 Aug 2013 15:35:49 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1V75lu-0003oD-Ag; Wed, 07 Aug 2013 15:35:34 +0000 Received: from svenfoo.org ([82.94.215.22] helo=mail.zonque.de) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1V75lB-0003gX-Pv; Wed, 07 Aug 2013 15:34:53 +0000 Received: from localhost (localhost [127.0.0.1]) by mail.zonque.de (Postfix) with ESMTP id 575E1C059B; Wed, 7 Aug 2013 17:34:27 +0200 (CEST) Received: from mail.zonque.de ([127.0.0.1]) by localhost (rambrand.bugwerft.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id xQ1K27VzshT0; Wed, 7 Aug 2013 17:34:27 +0200 (CEST) Received: from tamtam.fritz.box (p5DDC7ADB.dip0.t-ipconnect.de [93.220.122.219]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.zonque.de (Postfix) with ESMTPSA id 9D914C0599; Wed, 7 Aug 2013 17:34:25 +0200 (CEST) From: Daniel Mack To: haojian.zhuang@linaro.org, eric.y.miao@gmail.com, linux-arm-kernel@lists.infradead.org Subject: [PATCH 01/20] mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine Date: Wed, 7 Aug 2013 17:33:50 +0200 Message-Id: <1375889649-14638-2-git-send-email-zonque@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1375889649-14638-1-git-send-email-zonque@gmail.com> References: <1375889649-14638-1-git-send-email-zonque@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130807_113450_843319_FA63E9C4 X-CRM114-Status: GOOD ( 16.65 ) X-Spam-Score: 1.5 (+) Cc: mark.rutland@arm.com, s.neumann@raumfeld.com, linux-mtd@lists.infradead.org, Daniel Mack , cxie4@marvell.com, lars@metafoo.de, nico@linaro.org, vinod.koul@intel.com, marek.vasut@gmail.com, ezequiel.garcia@free-electrons.com, rmk+kernel@arm.linux.org.uk, devicetree@vger.kernel.org, samuel@sortiz.org, arnd@arndb.de, broonie@kernel.org, Zhangfei Gao , mika.westerberg@linux.intel.com, thomas.petazzoni@free-electrons.com, gregkh@linuxfoundation.org, g.liakhovetski@gmx.de, sachin.kamat@linaro.org, kernel@pengutronix.de, djbw@fb.com, davem@davemloft.net X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, FREEMAIL_FROM,KHOP_BIG_TO_CC,RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Zhangfei Gao [zonque@gmail.com: rebased in top of l2-mtd.git. The newly introduced ARCH_HAS_DMA hack was changed into a check for CONFIG_HAS_DMA] Signed-off-by: Zhangfei Gao Signed-off-by: Daniel Mack --- drivers/mtd/nand/pxa3xx_nand.c | 115 ++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 52 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index a2a54f6..736673a 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -24,14 +24,7 @@ #include #include #include - -#if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP) -#define ARCH_HAS_DMA -#endif - -#ifdef ARCH_HAS_DMA -#include -#endif +#include #include @@ -172,9 +165,7 @@ struct pxa3xx_nand_info { unsigned char *data_buff; unsigned char *oob_buff; dma_addr_t data_buff_phys; - int data_dma_ch; - struct pxa_dma_desc *data_desc; - dma_addr_t data_desc_addr; + struct dma_chan *data_dma_ch; struct pxa3xx_nand_host *host[NUM_CHIP_SELECT]; unsigned int state; @@ -388,25 +379,39 @@ static void handle_data_pio(struct pxa3xx_nand_info *info) } } -#ifdef ARCH_HAS_DMA +#ifdef CONFIG_HAS_DMA +static void dma_complete_func(void *data) +{ + struct pxa3xx_nand_info *info = data; + + info->state = STATE_DMA_DONE; +} + static void start_data_dma(struct pxa3xx_nand_info *info) { - struct pxa_dma_desc *desc = info->data_desc; + struct dma_device *dma_dev; + struct dma_async_tx_descriptor *tx = NULL; + dma_addr_t dma_src_addr, dma_dst_addr; + dma_cookie_t cookie; int dma_len = ALIGN(info->data_size + info->oob_size, 32); + struct dma_slave_config conf; - desc->ddadr = DDADR_STOP; - desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; + dma_dev = info->data_dma_ch->device; switch (info->state) { case STATE_DMA_WRITING: - desc->dsadr = info->data_buff_phys; - desc->dtadr = info->mmio_phys + NDDB; - desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG; + dma_src_addr = info->data_buff_phys; + dma_dst_addr = info->mmio_phys + NDDB; + conf.direction = DMA_MEM_TO_DEV; + conf.dst_maxburst = 32; + conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break; case STATE_DMA_READING: - desc->dtadr = info->data_buff_phys; - desc->dsadr = info->mmio_phys + NDDB; - desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; + dma_src_addr = info->mmio_phys + NDDB; + dma_dst_addr = info->data_buff_phys; + conf.direction = DMA_DEV_TO_MEM; + conf.src_maxburst = 32; + conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break; default: dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__, @@ -414,26 +419,25 @@ static void start_data_dma(struct pxa3xx_nand_info *info) BUG(); } - DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch; - DDADR(info->data_dma_ch) = info->data_desc_addr; - DCSR(info->data_dma_ch) |= DCSR_RUN; -} - -static void pxa3xx_nand_data_dma_irq(int channel, void *data) -{ - struct pxa3xx_nand_info *info = data; - uint32_t dcsr; + conf.slave_id = info->drcmr_dat; + dmaengine_slave_config(info->data_dma_ch, &conf); + tx = dma_dev->device_prep_dma_memcpy(info->data_dma_ch, dma_dst_addr, + dma_src_addr, dma_len, 0); + if (!tx) { + dev_err(&info->pdev->dev, "Failed to prepare DMA memcpy\n"); + return; + } - dcsr = DCSR(channel); - DCSR(channel) = dcsr; + tx->callback = dma_complete_func; + tx->callback_param = info; - if (dcsr & DCSR_BUSERR) { - info->retcode = ERR_DMABUSERR; + cookie = tx->tx_submit(tx); + if (dma_submit_error(cookie)) { + dev_err(&info->pdev->dev, "Failed to do DMA tx_submit\n"); + return; } - info->state = STATE_DMA_DONE; - enable_int(info, NDCR_INT_MASK); - nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ); + dma_async_issue_pending(info->data_dma_ch); } #else static void start_data_dma(struct pxa3xx_nand_info *info) @@ -455,6 +459,7 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) } status = nand_readl(info, NDSR); + nand_writel(info, NDSR, status); if (status & NDSR_DBERR) info->retcode = ERR_DBERR; @@ -463,7 +468,6 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) { /* whether use dma to transfer data */ if (info->use_dma) { - disable_int(info, NDCR_INT_MASK); info->state = (status & NDSR_RDDREQ) ? STATE_DMA_READING : STATE_DMA_WRITING; start_data_dma(info); @@ -792,6 +796,9 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) struct pxa3xx_nand_info *info = host->info_data; int real_len = min_t(size_t, len, info->buf_count - info->buf_start); + if (len > mtd->oobsize) + info->use_dma = use_dma; + memcpy(buf, info->data_buff + info->buf_start, real_len); info->buf_start += real_len; } @@ -803,6 +810,9 @@ static void pxa3xx_nand_write_buf(struct mtd_info *mtd, struct pxa3xx_nand_info *info = host->info_data; int real_len = min_t(size_t, len, info->buf_count - info->buf_start); + if (len > mtd->oobsize) + info->use_dma = use_dma; + memcpy(info->data_buff + info->buf_start, buf, real_len); info->buf_start += real_len; } @@ -908,11 +918,11 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) */ #define MAX_BUFF_SIZE (PAGE_SIZE*2) -#ifdef ARCH_HAS_DMA +#ifdef CONFIG_HAS_DMA static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) { struct platform_device *pdev = info->pdev; - int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc); + dma_cap_mask_t mask; if (use_dma == 0) { info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL); @@ -928,26 +938,27 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) return -ENOMEM; } - info->data_desc = (void *)info->data_buff + data_desc_offset; - info->data_desc_addr = info->data_buff_phys + data_desc_offset; - - info->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW, - pxa3xx_nand_data_dma_irq, info); - if (info->data_dma_ch < 0) { - dev_err(&pdev->dev, "failed to request data dma\n"); - dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, - info->data_buff, info->data_buff_phys); - return info->data_dma_ch; + dma_cap_zero(mask); + dma_cap_set(DMA_MEMCPY, mask); + info->data_dma_ch = dma_request_channel(mask, NULL, NULL); + if (!info->data_dma_ch) { + dev_info(&pdev->dev, "Failed to request DMA channel\n"); + goto dma_request_fail; } return 0; + +dma_request_fail: + dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, + info->data_buff, info->data_buff_phys); + return -EAGAIN; } static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info) { struct platform_device *pdev = info->pdev; if (use_dma) { - pxa_free_dma(info->data_dma_ch); + dma_release_channel(info->data_dma_ch); dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, info->data_buff, info->data_buff_phys); } else { @@ -1295,7 +1306,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) struct pxa3xx_nand_info *info; int ret, cs, probe_success; -#ifndef ARCH_HAS_DMA +#ifndef CONFIG_HAS_DMA if (use_dma) { use_dma = 0; dev_warn(&pdev->dev,