From patchwork Fri Jun 18 05:37:37 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haojian Zhuang X-Patchwork-Id: 56130 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 726171007D3 for ; Fri, 18 Jun 2010 15:45:47 +1000 (EST) Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.72 #1 (Red Hat Linux)) id 1OPUMb-0000xd-7r; Fri, 18 Jun 2010 05:43:38 +0000 Received: from mail-px0-f177.google.com ([209.85.212.177]) by bombadil.infradead.org with esmtp (Exim 4.72 #1 (Red Hat Linux)) id 1OPUGo-0001Gz-76; Fri, 18 Jun 2010 05:37:39 +0000 Received: by mail-px0-f177.google.com with SMTP id 11so11212pxi.36 for ; Thu, 17 Jun 2010 22:37:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:received:date:message-id :subject:from:to:content-type; bh=r/ImXRRUB9aEcnYP0QwpTZzdWW22Y0aMMeFDgsHDS8M=; b=XnC+2HJQfHTePEWoLV1MZ3SXlvm+IVML/yr6370byxGcta0YCUXBWiDtVdtUMfZamU EDk6aP+3njhwoonGG3/L2PNx9D3Qu+EBkD7UIjaXSmDN0yNVwWgG8tYfebzZ6iE7+UQU cARpJplX7hlHSDqHy015ErMLsKIJ+U7xAFxP4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=sYJW6SP9klFke74dBjDkA4aRMhWAe6nKVmq+AxJVE1VcuCc9/uBpk5XJBvpKYW8ayr UgsdD2PUa+2bfLbx1HNhb4V9r+RvVuIOquXIeCVgdZXXOWAm6TJjpNkRXghtjDMY7hvs w4k5k+TIeilMjzsu1maP1u1IG6ZlCh31DdM+M= MIME-Version: 1.0 Received: by 10.142.122.9 with SMTP id u9mr360337wfc.339.1276839457771; Thu, 17 Jun 2010 22:37:37 -0700 (PDT) Received: by 10.142.114.3 with HTTP; Thu, 17 Jun 2010 22:37:37 -0700 (PDT) Date: Fri, 18 Jun 2010 13:37:37 +0800 Message-ID: Subject: [PATCH 21/25] pxa3xx_nand: add polling mode support From: Haojian Zhuang To: Marc Kleine-Budde , David Woodhouse , David Woodhouse , linux-mtd@lists.infradead.org, Eric Miao , linux-arm-kernel X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20100618_013738_595029_5DDAF9C2 X-CRM114-Status: GOOD ( 23.04 ) X-Spam-Score: -0.1 (/) X-Spam-Report: SpamAssassin version 3.3.1 on bombadil.infradead.org summary: Content analysis details: (-0.1 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.212.177 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is freemail (haojian.zhuang[at]gmail.com) -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From 8dbf7973d92d1ee0c02281360b70fb930712f787 Mon Sep 17 00:00:00 2001 From: Lei Wen Date: Tue, 8 Jun 2010 15:10:41 +0800 Subject: [PATCH 21/25] pxa3xx_nand: add polling mode support Add polling mode to facilitate debugging. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | 1 + drivers/mtd/nand/pxa3xx_nand.c | 55 +++++++++++++++++++++---- 2 files changed, 47 insertions(+), 9 deletions(-) unsigned int ready, cmd_done, page_done, badblock_detect; @@ -654,13 +658,20 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) if (status & ready) { nand->state |= STATE_READY; if (nand->wait_ready[cmd_seqs]) { - enable_int(nand, NDCR_WRCMDREQM); + if (!use_polling) + enable_int(nand, NDCR_WRCMDREQM | NDCR_CS0_CMDDM + | NDCR_CS1_CMDDM); if (cmd_seqs == nand->total_cmds) is_completed = 1; } } if (status & cmd_done) { nand->state |= STATE_CMD_DONE; + if (nand->wait_ready[cmd_seqs] && !(nand->state & STATE_READY)) { + status &= ~cmd_done; + if (!use_polling) + disable_int(nand, NDCR_CS0_CMDDM | NDCR_CS1_CMDDM); + } if (cmd_seqs == nand->total_cmds && !nand->wait_ready[cmd_seqs]) is_completed = 1; } @@ -668,7 +679,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) if (status & NDSR_WRCMDREQ) { status &= ~NDSR_WRCMDREQ; if (nand->wait_ready[cmd_seqs] && !(nand->state & STATE_READY)) { - disable_int(nand, NDCR_WRCMDREQM); + if (!use_polling) + disable_int(nand, NDCR_WRCMDREQM); goto IRQ_FORCE_EXIT; } @@ -698,12 +710,32 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) IRQ_FORCE_EXIT: /* clear NDSR to let the controller exit the IRQ */ nand_writel(nand, NDSR, status); - if (is_completed) - complete(&nand->cmd_complete); NORMAL_IRQ_EXIT: + return is_completed; +} + +static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) +{ + struct pxa3xx_nand *nand = devid; + if (pxa3xx_nand_transaction(nand)) + complete(&nand->cmd_complete); return IRQ_HANDLED; } +static int pxa3xx_nand_polling(struct pxa3xx_nand *nand, unsigned long timeout) +{ + int i, ret = 0; + + for (i = 0; i < timeout; i++) { + ret = pxa3xx_nand_transaction(nand); + if (ret) + break; + udelay(10); + } + + return ret; +} + static inline int is_buf_blank(uint8_t *buf, size_t len) { for (; len > 0; len--) @@ -973,8 +1005,11 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, nand->state |= STATE_CMD_PREPARED; pxa3xx_nand_start(nand); - ret = wait_for_completion_timeout(&nand->cmd_complete, - CHIP_DELAY_TIMEOUT); + if (!use_polling) + ret = wait_for_completion_timeout(&nand->cmd_complete, + CHIP_DELAY_TIMEOUT); + else + ret = pxa3xx_nand_polling(nand, CHIP_DELAY_TIMEOUT); if (!ret) { dev_err(&nand->pdev->dev, "Wait time out!!!\n"); nand_error_dump(nand); @@ -1582,7 +1617,9 @@ static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) return -ENODEV; } - if (!(pdata->controller_attrs & PXA3XX_DMA_EN)) + if (pdata->controller_attrs & PXA3XX_POOLING_MODE) + use_polling = 1; + if (!(pdata->controller_attrs & PXA3XX_DMA_EN) || use_polling) use_dma = 0; ret = alloc_nand_resource(pdev); if (ret) diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h index 72bb70e..ae63a5f 100644 --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h @@ -17,6 +17,7 @@ * enable such tuning for those platform which support it */ #define PXA3XX_ADV_TIME_TUNING (1 << 4) #define PXA3XX_KEEP_CONFIG (1 << 5) +#define PXA3XX_POOLING_MODE (1 << 6) struct pxa3xx_nand_platform_data { unsigned int controller_attrs; const struct mtd_partition *parts[NUM_CHIP_SELECT]; diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 834422d..7f8bae7 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -274,6 +274,10 @@ static int use_dma = 1; module_param(use_dma, bool, 0444); MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW"); +static int use_polling = 0; +module_param(use_polling, bool, 0444); +MODULE_PARM_DESC(use_polling, "Use full polling mode"); + const static struct pxa3xx_nand_cmdset cmdset = { .read1 = 0x3000, .read2 = 0x0050, @@ -444,6 +448,7 @@ static void pxa3xx_nand_start(struct pxa3xx_nand *nand) info = nand->info[nand->chip_select]; ndcr = info->reg_ndcr; ndcr |= nand->use_dma ? NDCR_DMA_EN : 0; + ndcr |= use_polling ? NDCR_INT_MASK : 0; ndcr |= NDCR_ND_RUN; switch (nand->ecc_strength) { @@ -615,9 +620,8 @@ static void pxa3xx_nand_data_dma_irq(int channel, void *data) nand_writel(nand, NDSR, NDSR_WRDREQ | NDSR_RDDREQ); } -static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) +static int pxa3xx_nand_transaction(struct pxa3xx_nand *nand) { - struct pxa3xx_nand *nand = devid; struct pxa3xx_nand_info *info; unsigned int status, is_completed = 0, cs, cmd_seqs, ndcb1, ndcb2;