From patchwork Thu May 6 09:04:27 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haojian Zhuang X-Patchwork-Id: 51802 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 64491B7D4A for ; Thu, 6 May 2010 19:06:07 +1000 (EST) Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) id 1O9x0V-0008U0-FE; Thu, 06 May 2010 09:04:35 +0000 Received: from mail-px0-f177.google.com ([209.85.212.177]) by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) id 1O9x0O-0008Q6-Pw; Thu, 06 May 2010 09:04:30 +0000 Received: by pxi1 with SMTP id 1so2819378pxi.36 for ; Thu, 06 May 2010 02:04:27 -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=OqB3NFkxS82XSPTyfQAv+ce4v/HhLCegVJ2BXBpUa2w=; b=c71y/VnIC2cvjlOdVD/J9r4IcUuAv0iJoe3XicywBjAZ9V2KxaFZQAJ7lybvxmhMaf K73VLM/qZtMTBmVaepTUGMu1u3Jw2/6myllZ6dgppqdlbomJlVzTNhOScUX494ZyumD2 R0Drak/P2RSSiIG3LgfDX2sfiAWgVku/WtJqI= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=mg553KU4J3E0/nyKJntcsEPv8tuwvt65zh0Xax9GcMy4TunUCW4kknr6LZFLRO94b8 sBY2AOSrhfl7IAvMgXfHFeaf6Lhbj+tLZ/Dl7M3EqthpoBy3wrkqk/0PgeOUMFs21Aoj gaRVUVA0q1cscwPGVlM5yaSDxpsPSNEbtPPZ0= MIME-Version: 1.0 Received: by 10.143.178.9 with SMTP id f9mr8361980wfp.338.1273136667754; Thu, 06 May 2010 02:04:27 -0700 (PDT) Received: by 10.142.252.16 with HTTP; Thu, 6 May 2010 02:04:27 -0700 (PDT) Date: Thu, 6 May 2010 05:04:27 -0400 Message-ID: Subject: [PATCH 05/20] pxa3xx_nand: rework irq logic From: Haojian Zhuang To: Eric Miao , linux-arm-kernel , David Woodhouse , linux-mtd@lists.infradead.org X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20100506_050429_239063_CF67CF3F X-CRM114-Status: GOOD ( 24.18 ) 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 75047a09866a2918de6ced654cbf1cc1cfa5ddcf Mon Sep 17 00:00:00 2001 From: Lei Wen Date: Mon, 22 Mar 2010 11:38:46 +0800 Subject: [PATCH] pxa3xx_nand: rework irq logic Enable all irq when we start the nand controller, and put all the transaction logic in the pxa3xx_nand_irq. By doing this way, we could dramatically increase the performance by avoid unnecessary delay. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- drivers/mtd/nand/pxa3xx_nand.c | 382 +++++++++++++++------------------------- 1 files changed, 140 insertions(+), 242 deletions(-) int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; @@ -337,7 +323,47 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) } } -static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, +/** + * NOTE: it is a must to set ND_RUN firstly, then write + * command buffer, otherwise, it does not work. + * We enable all the interrupt at the same time, and + * let pxa3xx_nand_irq to handle all logic. + */ +static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) +{ + uint32_t ndcr; + + ndcr = info->reg_ndcr; + ndcr |= NDCR_ECC_EN; + ndcr |= info->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR; + ndcr |= NDCR_ND_RUN; + + /* clear status bits and run */ + nand_writel(info, NDCR, 0); + nand_writel(info, NDSR, NDSR_MASK); + nand_writel(info, NDCR, ndcr); +} + +static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info) +{ + uint32_t ndcr; + int timeout = NAND_STOP_DELAY; + + /* wait RUN bit in NDCR become 0 */ + do { + /* clear status bits */ + nand_writel(info, NDSR, NDSR_MASK); + ndcr = nand_readl(info, NDCR); + udelay(1); + } while ((ndcr & NDCR_ND_RUN) && (timeout -- > 0)); + + if (timeout <= 0) { + ndcr &= ~(NDCR_ND_RUN); + nand_writel(info, NDCR, ndcr); + } +} + +static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info, uint16_t cmd, int column, int page_addr) { pxa3xx_set_datasize(info); @@ -363,21 +389,18 @@ static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, if (cmd == cmdset.program) info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS; - - return 0; } -static int prepare_erase_cmd(struct pxa3xx_nand_info *info, +static void prepare_erase_cmd(struct pxa3xx_nand_info *info, uint16_t cmd, int page_addr) { info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3); info->ndcb1 = page_addr; info->ndcb2 = 0; - return 0; } -static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) +static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) { info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); info->ndcb1 = 0; @@ -392,10 +415,7 @@ static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) } else if (cmd == cmdset.reset || cmd == cmdset.lock || cmd == cmdset.unlock) { info->ndcb0 |= NDCB0_CMD_TYPE(5); - } else - return -EINVAL; - - return 0; + } } static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) @@ -414,71 +434,23 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) nand_writel(info, NDCR, ndcr | int_mask); } -/* NOTE: it is a must to set ND_RUN firstly, then write command buffer - * otherwise, it does not work - */ -static int write_cmd(struct pxa3xx_nand_info *info) +static void handle_data_pio(struct pxa3xx_nand_info *info) { - uint32_t ndcr; - - /* clear status bits and run */ - nand_writel(info, NDSR, NDSR_MASK); - - ndcr = info->reg_ndcr; - - ndcr |= info->use_ecc ? NDCR_ECC_EN : 0; - ndcr |= info->use_dma ? NDCR_DMA_EN : 0; - ndcr |= NDCR_ND_RUN; - - nand_writel(info, NDCR, ndcr); - - if (wait_for_event(info, NDSR_WRCMDREQ)) { - printk(KERN_ERR "timed out writing command\n"); - return -ETIMEDOUT; - } - - nand_writel(info, NDCB0, info->ndcb0); - nand_writel(info, NDCB0, info->ndcb1); - nand_writel(info, NDCB0, info->ndcb2); - return 0; -} - -static int handle_data_pio(struct pxa3xx_nand_info *info) -{ - int ret, timeout = CHIP_DELAY_TIMEOUT; - - switch (info->state) { - case STATE_PIO_WRITING: + if (info->state & STATE_IS_WRITE) { __raw_writesl(info->mmio_base + NDDB, info->data_buff, DIV_ROUND_UP(info->data_size, 4)); if (info->oob_size > 0) __raw_writesl(info->mmio_base + NDDB, info->oob_buff, DIV_ROUND_UP(info->oob_size, 4)); - enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); - - ret = wait_for_completion_timeout(&info->cmd_complete, timeout); - if (!ret) { - printk(KERN_ERR "program command time out\n"); - return -1; - } - break; - case STATE_PIO_READING: + } + else { __raw_readsl(info->mmio_base + NDDB, info->data_buff, DIV_ROUND_UP(info->data_size, 4)); if (info->oob_size > 0) __raw_readsl(info->mmio_base + NDDB, info->oob_buff, DIV_ROUND_UP(info->oob_size, 4)); - - break; - default: - printk(KERN_ERR "%s: invalid state %d\n", __func__, - info->state); - return -EINVAL; } - - info->state = STATE_READY; - return 0; } static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) @@ -514,93 +486,59 @@ static void pxa3xx_nand_data_dma_irq(int channel, void *data) if (dcsr & DCSR_BUSERR) { info->retcode = ERR_DMABUSERR; - complete(&info->cmd_complete); } - if (info->state == STATE_DMA_WRITING) { - info->state = STATE_DMA_DONE; - enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); - } else { - info->state = STATE_READY; - complete(&info->cmd_complete); - } + enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); } static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) { struct pxa3xx_nand_info *info = devid; - unsigned int status; + unsigned int status, is_completed = 0; status = nand_readl(info, NDSR); - if (status & (NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR)) { - if (status & NDSR_DBERR) - info->retcode = ERR_DBERR; - else if (status & NDSR_SBERR) - info->retcode = ERR_SBERR; - - disable_int(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); + if (status & NDSR_DBERR) + info->retcode = ERR_DBERR; + if (status & NDSR_SBERR) + info->retcode = ERR_SBERR; + if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) { + info->state |= STATE_DATA_PROCESSING; + /* whether use dma to transfer data */ if (info->use_dma) { - info->state = STATE_DMA_READING; + disable_int(info, NDSR_WRDREQ); start_data_dma(info, 0); - } else { - info->state = STATE_PIO_READING; - complete(&info->cmd_complete); - } - } else if (status & NDSR_WRDREQ) { - disable_int(info, NDSR_WRDREQ); - if (info->use_dma) { - info->state = STATE_DMA_WRITING; - start_data_dma(info, 1); - } else { - info->state = STATE_PIO_WRITING; - complete(&info->cmd_complete); - } - } else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) { - if (status & NDSR_CS0_BBD) - info->retcode = ERR_BBERR; + goto NORMAL_IRQ_EXIT; + } else + handle_data_pio(info); - disable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); - info->state = STATE_READY; - complete(&info->cmd_complete); + info->state |= STATE_DATA_DONE; } - nand_writel(info, NDSR, status); - return IRQ_HANDLED; -} - -static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t event) -{ - uint32_t ndcr; - int ret, timeout = CHIP_DELAY_TIMEOUT; - - if (write_cmd(info)) { - info->retcode = ERR_SENDCMD; - goto fail_stop; + if (status & NDSR_CS0_CMDD) { + info->state |= STATE_CMD_DONE; + is_completed = 1; } - - info->state = STATE_CMD_HANDLE; - - enable_int(info, event); - - ret = wait_for_completion_timeout(&info->cmd_complete, timeout); - if (!ret) { - printk(KERN_ERR "command execution timed out\n"); - info->retcode = ERR_SENDCMD; - goto fail_stop; + if (status & NDSR_FLASH_RDY) + info->state |= STATE_READY; + if (status & NDSR_CS0_PAGED) + info->state |= STATE_PAGE_DONE; + + if (status & NDSR_WRCMDREQ) { + nand_writel(info, NDSR, NDSR_WRCMDREQ); + status &= ~NDSR_WRCMDREQ; + info->state |= STATE_CMD_WAIT_DONE; + nand_writel(info, NDCB0, info->ndcb0); + nand_writel(info, NDCB0, info->ndcb1); + nand_writel(info, NDCB0, info->ndcb2); } - if (info->use_dma == 0 && info->data_size > 0) - if (handle_data_pio(info)) - goto fail_stop; - - return 0; - -fail_stop: - ndcr = nand_readl(info, NDCR); - nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); - udelay(10); - return -ETIMEDOUT; + /* clear NDSR to let the controller exit the IRQ */ + nand_writel(info, NDSR, status); + if (is_completed) + complete(&info->cmd_complete); +NORMAL_IRQ_EXIT: + return IRQ_HANDLED; } static int pxa3xx_nand_dev_ready(struct mtd_info *mtd) @@ -621,14 +559,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct pxa3xx_nand_info *info = mtd->priv; - int ret; + int ret, exec_cmd = 0; info->use_dma = (use_dma) ? 1 : 0; info->use_ecc = 0; info->data_size = 0; - info->state = STATE_READY; - - init_completion(&info->cmd_complete); + info->state = 0; switch (command) { case NAND_CMD_READOOB: @@ -637,14 +573,13 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, info->buf_start = mtd->writesize + column; memset(info->data_buff, 0xFF, info->buf_count); - if (prepare_read_prog_cmd(info, cmdset.read1, column, page_addr)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); + prepare_read_prog_cmd(info, cmdset.read1, column, page_addr); /* We only are OOB, so if the data has error, does not matter */ if (info->retcode == ERR_DBERR) info->retcode = ERR_NONE; + + exec_cmd = 1; break; case NAND_CMD_READ0: @@ -654,11 +589,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, info->buf_count = mtd->writesize + mtd->oobsize; memset(info->data_buff, 0xFF, info->buf_count); - if (prepare_read_prog_cmd(info, cmdset.read1, column, page_addr)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); - + prepare_read_prog_cmd(info, cmdset.read1, column, page_addr); if (info->retcode == ERR_DBERR) { /* for blank page (all 0xff), HW will calculate its ECC as * 0, which is different from the ECC information within @@ -667,6 +598,8 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, if (is_buf_blank(info->data_buff, mtd->writesize)) info->retcode = ERR_NONE; } + + exec_cmd = 1; break; case NAND_CMD_SEQIN: info->buf_start = column; @@ -680,18 +613,14 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, case NAND_CMD_PAGEPROG: info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1; - if (prepare_read_prog_cmd(info, cmdset.program, - info->seqin_column, info->seqin_page_addr)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_WRDREQ); + prepare_read_prog_cmd(info, cmdset.program, + info->seqin_column, info->seqin_page_addr); + info->state |= STATE_IS_WRITE; + exec_cmd = 1; break; case NAND_CMD_ERASE1: - if (prepare_erase_cmd(info, cmdset.erase, page_addr)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); - break; + prepare_erase_cmd(info, cmdset.erase, page_addr); + exec_cmd = 1; case NAND_CMD_ERASE2: break; case NAND_CMD_READID: @@ -701,39 +630,37 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, info->buf_count = (command == NAND_CMD_READID) ? info->read_id_bytes : 1; - if (prepare_other_cmd(info, (command == NAND_CMD_READID) ? - cmdset.read_id : cmdset.read_status)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_RDDREQ); + prepare_other_cmd(info, (command == NAND_CMD_READID) ? + cmdset.read_id : cmdset.read_status); + exec_cmd = 1; break; case NAND_CMD_RESET: - if (prepare_other_cmd(info, cmdset.reset)) - break; - - ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD); - if (ret == 0) { - int timeout = 2; - uint32_t ndcr; - - while (timeout--) { - if (nand_readl(info, NDSR) & NDSR_RDY) - break; - msleep(10); - } - - ndcr = nand_readl(info, NDCR); - nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); - } + prepare_other_cmd(info, cmdset.reset); + exec_cmd = 1; break; default: printk(KERN_ERR "non-supported command.\n"); break; } - if (info->retcode == ERR_DBERR) { - printk(KERN_ERR "double bit error @ page %08x\n", page_addr); - info->retcode = ERR_NONE; + if (exec_cmd) { + init_completion(&info->cmd_complete); + info->state |= STATE_CMD_PREPARED; + pxa3xx_nand_start(info); + + ret = wait_for_completion_timeout(&info->cmd_complete, + CHIP_DELAY_TIMEOUT); + if (!ret) { + printk(KERN_ERR "Wait time out!!!\n"); + } + /* Stop State Machine for next command cycle */ + pxa3xx_nand_stop(info); + disable_int(info, NDCR_INT_MASK); + info->state &= ~STATE_CMD_PREPARED; + if (info->retcode == ERR_DBERR) { + printk(KERN_ERR "double bit error @ page %08x\n", page_addr); + info->retcode = ERR_NONE; + } } } @@ -842,41 +769,12 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd, return 0; } -static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) -{ - uint32_t ndcr; - uint8_t id_buff[8]; - - if (prepare_other_cmd(info, cmdset.read_id)) { - printk(KERN_ERR "failed to prepare command\n"); - return -EINVAL; - } - - /* Send command */ - if (write_cmd(info)) - goto fail_timeout; - - /* Wait for CMDDM(command done successfully) */ - if (wait_for_event(info, NDSR_RDDREQ)) - goto fail_timeout; - - __raw_readsl(info->mmio_base + NDDB, id_buff, 2); - *id = id_buff[0] | (id_buff[1] << 8); - return 0; - -fail_timeout: - ndcr = nand_readl(info, NDCR); - nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); - udelay(10); - return -ETIMEDOUT; -} - static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, const struct pxa3xx_nand_flash *f) { struct platform_device *pdev = info->pdev; struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; - uint32_t ndcr = 0x00000FFF; /* disable all interrupts */ + uint32_t ndcr = 0; /* calculate flash information */ info->page_size = f->page_size; @@ -943,8 +841,9 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2; info->reg_ndcr = ndcr; - if (__readid(info, &id)) - return -ENODEV; + + pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); + id = *((uint16_t *)(info->data_buff)); /* Lookup the flash id */ id = (id >> 8) & 0xff; /* device id is byte 2 */ @@ -991,8 +890,8 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, f = &builtin_flash_types[0]; pxa3xx_nand_config_flash(info, f); - if (__readid(info, &id)) - goto fail_detect; + pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); + id = *((uint16_t *)(info->data_buff)); for (i = 1; i < ARRAY_SIZE(builtin_flash_types); i++) { f = &builtin_flash_types[i]; @@ -1006,7 +905,6 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, dev_warn(&info->pdev->dev, "failed to detect configured nand flash; found %04x instead of\n", id); -fail_detect: return -ENODEV; } @@ -1283,7 +1181,7 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); struct mtd_info *mtd = info->mtd; - if (info->state != STATE_READY) { + if (info->state & STATE_CMD_PREPARED) { dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); return -EAGAIN; } diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 0ef9bf9..85de7f7 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -27,6 +27,7 @@ #include #define CHIP_DELAY_TIMEOUT (2 * HZ/10) +#define NAND_STOP_DELAY (2 * HZ/50) /* registers and bit definitions */ #define NDCR (0x00) /* Control register */ @@ -49,6 +50,7 @@ #define NDCR_DWIDTH_M (0x1 << 26) #define NDCR_PAGE_SZ (0x1 << 24) #define NDCR_NCSX (0x1 << 23) +#define NDCR_STOP_ON_UNCOR (0x1 << 22) #define NDCR_ND_MODE (0x3 << 21) #define NDCR_NAND_MODE (0x0) #define NDCR_CLR_PG_CNT (0x1 << 20) @@ -59,9 +61,11 @@ #define NDCR_RA_START (0x1 << 15) #define NDCR_PG_PER_BLK (0x1 << 14) #define NDCR_ND_ARB_EN (0x1 << 12) +#define NDCR_INT_MASK (0xFFF) #define NDSR_MASK (0xfff) -#define NDSR_RDY (0x1 << 11) +#define NDSR_RDY (0x1 << 12) +#define NDSR_FLASH_RDY (0x1 << 11) #define NDSR_CS0_PAGED (0x1 << 10) #define NDSR_CS1_PAGED (0x1 << 9) #define NDSR_CS0_CMDD (0x1 << 8) @@ -104,13 +108,14 @@ enum { }; enum { - STATE_READY = 0, - STATE_CMD_HANDLE, - STATE_DMA_READING, - STATE_DMA_WRITING, - STATE_DMA_DONE, - STATE_PIO_READING, - STATE_PIO_WRITING, + STATE_CMD_WAIT_DONE = 1, + STATE_DATA_PROCESSING = (1 << 1), + STATE_DATA_DONE = (1 << 2), + STATE_PAGE_DONE = (1 << 3), + STATE_CMD_DONE = (1 << 4), + STATE_READY = (1 << 5), + STATE_CMD_PREPARED = (1 << 6), + STATE_IS_WRITE = (1 << 7), }; struct pxa3xx_nand_timing { @@ -299,25 +304,6 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, nand_writel(info, NDTR1CS0, ndtr1); } -#define WAIT_EVENT_TIMEOUT 10 - -static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event) -{ - int timeout = WAIT_EVENT_TIMEOUT; - uint32_t ndsr; - - while (timeout--) { - ndsr = nand_readl(info, NDSR) & NDSR_MASK; - if (ndsr & event) { - nand_writel(info, NDSR, ndsr); - return 0; - } - udelay(10); - } - - return -ETIMEDOUT; -} - static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) {