linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: eric.y.miao@gmail.com (Eric Miao)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 2/6] pxa3xx_nand: rework irq logic
Date: Fri, 17 Sep 2010 10:47:28 +0800	[thread overview]
Message-ID: <AANLkTinH_-2tdyfe_o6gzbWLKD5ahjVz4jJfapXsCkrL@mail.gmail.com> (raw)
In-Reply-To: <1283179285-6539-2-git-send-email-haojian.zhuang@marvell.com>

> + ? ? ? STATE_PAGE_DONE ? ? ? ? = (1 << 3),
> + ? ? ? STATE_CMD_DONE ? ? ? ? ?= (1 << 4),
> + ? ? ? STATE_READY ? ? ? ? ? ? = (1 << 5),
> + ? ? ? STATE_CMD_PREPARED ? ? ?= (1 << 6),
> + ? ? ? STATE_IS_WRITE ? ? ? ? ?= (1 << 7),

State isn't supposed to be a bit-or'ed value, if you have to use this in
the code, it just means the logic is broken. You should check it again.

> ?};
>
> ?struct pxa3xx_nand_info {
> @@ -292,7 +296,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);

Why clearing status bits every time before reading NDCR, does it have
some impact to the NDCR_ND_RUN bit?

> + ? ? ? ? ? ? ? ndcr = nand_readl(info, NDCR);
> + ? ? ? ? ? ? ? udelay(1);

Check the NDCR_ND_RUN bit before udelay() would be better, that would
leave a chance that udelay() will not be called at all if the bit is
already cleared (which is most likely the case in my understanding).

> + ? ? ? } while ((ndcr & NDCR_ND_RUN) && (timeout -- > 0));
> +
> + ? ? ? if (timeout <= 0) {
> + ? ? ? ? ? ? ? ndcr &= ~(NDCR_ND_RUN);

Feel picky, but no parentheses are needed here for a single constant.

> + ? ? ? ? ? ? ? nand_writel(info, NDCR, ndcr);
> + ? ? ? }
> +}
> +
> +static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
> ? ? ? ? ? ? ? ?uint16_t cmd, int column, int page_addr)
> ?{
> ? ? ? ?const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
> @@ -319,21 +363,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)
> ?{
> ? ? ? ?const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
>
> @@ -351,10 +392,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;
> + ? ? ? }
> ?}

If we want to remove the return type here, we must make sure that no
exception cases will happen, e.g. the *info and cmd passed to these
functions are absolute correct.

>
> ?static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
> @@ -402,41 +440,22 @@ static int write_cmd(struct pxa3xx_nand_info *info)
> ? ? ? ?return 0;
> ?}
>
> -static int handle_data_pio(struct pxa3xx_nand_info *info)
> +static void 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) {

As mentioned, this isn't a correct state encoding. Taking an example, a
state here can never be STATE_IS_WRITE | STATE_IS_READING. Try avoid
using states like this.

> ? ? ? ? ? ? ? ?__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)
> @@ -472,93 +491,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)
> @@ -580,14 +565,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
> ?{
> ? ? ? ?struct pxa3xx_nand_info *info = mtd->priv;
> ? ? ? ?const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
> - ? ? ? 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:
> @@ -596,14 +579,12 @@ 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:
> @@ -613,11 +594,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
> @@ -626,6 +603,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;
> @@ -639,17 +618,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);
> + ? ? ? ? ? ? ? prepare_erase_cmd(info, cmdset->erase, page_addr);
> + ? ? ? ? ? ? ? exec_cmd = 1;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case NAND_CMD_ERASE2:
> ? ? ? ? ? ? ? ?break;
> @@ -660,39 +636,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;
> + ? ? ? ? ? ? ? }
> ? ? ? ?}
> ?}
>
> @@ -807,10 +781,7 @@ 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;
> - ? ? ? }
> + ? ? ? prepare_other_cmd(info, cmdset->read_id);
>
> ? ? ? ?/* Send command */
> ? ? ? ?if (write_cmd(info))
> @@ -836,7 +807,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
> ?{
> ? ? ? ?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 = 0x0; /* enable all interrupts */
>
> ? ? ? ?if (f->page_size != 2048 && f->page_size != 512)
> ? ? ? ? ? ? ? ?return -EINVAL;
> @@ -887,11 +858,12 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
> ? ? ? ?info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
> ? ? ? ?info->reg_ndcr = ndcr;
>
> - ? ? ? if (__readid(info, &id))
> + ? ? ? pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
> + ? ? ? id = *((uint16_t *)(info->data_buff));
> + ? ? ? if (id == 0)
> ? ? ? ? ? ? ? ?return -ENODEV;
>
> ? ? ? ?/* Lookup the flash id */
> - ? ? ? id = (id >> 8) & 0xff; ? ? ? ? ?/* device id is byte 2 */
> ? ? ? ?for (i = 0; nand_flash_ids[i].name != NULL; i++) {
> ? ? ? ? ? ? ? ?if (id == nand_flash_ids[i].id) {
> ? ? ? ? ? ? ? ? ? ? ? ?type = ?&nand_flash_ids[i];
> @@ -935,8 +907,8 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info,
> ? ? ? ?/* we use default timing to detect id */
> ? ? ? ?f = DEFAULT_FLASH_TYPE;
> ? ? ? ?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=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
> ? ? ? ? ? ? ? ?/* we first choose the flash definition from platfrom */
> @@ -954,7 +926,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;
> ?}
>
> @@ -1176,8 +1147,6 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
>
> ? ? ? ?platform_set_drvdata(pdev, NULL);
>
> - ? ? ? del_mtd_device(mtd);
> - ? ? ? del_mtd_partitions(mtd);
> ? ? ? ?irq = platform_get_irq(pdev, 0);
> ? ? ? ?if (irq >= 0)
> ? ? ? ? ? ? ? ?free_irq(irq, info);
> @@ -1195,7 +1164,11 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
> ? ? ? ?clk_disable(info->clk);
> ? ? ? ?clk_put(info->clk);
>
> - ? ? ? kfree(mtd);
> + ? ? ? if (mtd) {
> + ? ? ? ? ? ? ? del_mtd_device(mtd);
> + ? ? ? ? ? ? ? del_mtd_partitions(mtd);
> + ? ? ? ? ? ? ? kfree(mtd);
> + ? ? ? }
> ? ? ? ?return 0;
> ?}
>
> @@ -1242,7 +1215,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;
> ? ? ? ?}
> --
> 1.7.0.4
>
>

  parent reply	other threads:[~2010-09-17  2:47 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-08-30 14:41 [PATCH 1/6] pxa3xx_nand: make scan procedure more clear Haojian Zhuang
2010-08-30 14:41 ` [PATCH 2/6] pxa3xx_nand: rework irq logic Haojian Zhuang
2010-08-30 14:41   ` [PATCH 3/6] pxa3xx_nand: discard wait_for_event, write_cmd, __readid function Haojian Zhuang
2010-08-30 14:41     ` [PATCH 4/6] pxa3xx_nand: unify prepare command Haojian Zhuang
2010-08-30 14:41       ` [PATCH 5/6] pxa3xx_nand: mtd scan id process could be defined by driver itself Haojian Zhuang
2010-08-30 14:41         ` [PATCH 6/6] pxa3xx_nand: clean the keep configure code Haojian Zhuang
2010-09-17  2:47   ` Eric Miao [this message]
2010-09-21 16:28     ` [PATCH 2/6 V2] pxa3xx_nand: rework irq logic Lei Wen
2010-09-07 11:20 ` [PATCH 1/6] pxa3xx_nand: make scan procedure more clear Lei Wen
2010-09-09 13:59 ` Eric Miao
2010-09-13 11:56   ` Lei Wen
2010-09-21 16:21   ` [PATCH 1/6 V2] " Lei Wen
  -- strict thread matches above, loose matches on Subject: below --
2011-02-18  8:57 [PATCH V4 0/6] pxa3xx_nand update series set version 4 Lei Wen
2011-07-08 14:56 ` [PATCH 2/6] pxa3xx_nand: rework irq logic Lei Wen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=AANLkTinH_-2tdyfe_o6gzbWLKD5ahjVz4jJfapXsCkrL@mail.gmail.com \
    --to=eric.y.miao@gmail.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).