From 24542257a3b987025d4b998ec2d15e556c98ad3f Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Fri, 20 Feb 2015 19:36:43 +0100 Subject: mtd: pxa3xx-nand: handle PIO in threaded interrupt Change the handling of the data stage in the driver : don't pump data in the top-half interrupt, but rather schedule a thread for non dma cases. This will enable latencies in the data pumping, especially if delays are required. Moreover platform shall be more reactive as other interrupts can be served while pumping data. No throughput degradation was observed, at least on the zylonite platform, while a slight degradation was being expected. Signed-off-by: Robert Jarzmik Tested-by: Maxime Ripard Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index bc677362bc73..3f09f2e9aeb4 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -605,11 +605,24 @@ static void start_data_dma(struct pxa3xx_nand_info *info) {} #endif +static irqreturn_t pxa3xx_nand_irq_thread(int irq, void *data) +{ + struct pxa3xx_nand_info *info = data; + + handle_data_pio(info); + + info->state = STATE_CMD_DONE; + nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ); + + return IRQ_HANDLED; +} + static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) { struct pxa3xx_nand_info *info = devid; unsigned int status, is_completed = 0, is_ready = 0; unsigned int ready, cmd_done; + irqreturn_t ret = IRQ_HANDLED; if (info->cs == 0) { ready = NDSR_FLASH_RDY; @@ -651,7 +664,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) } else { info->state = (status & NDSR_RDDREQ) ? STATE_PIO_READING : STATE_PIO_WRITING; - handle_data_pio(info); + ret = IRQ_WAKE_THREAD; + goto NORMAL_IRQ_EXIT; } } if (status & cmd_done) { @@ -692,7 +706,7 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) if (is_ready) complete(&info->dev_ready); NORMAL_IRQ_EXIT: - return IRQ_HANDLED; + return ret; } static inline int is_buf_blank(uint8_t *buf, size_t len) @@ -1708,7 +1722,9 @@ static int alloc_nand_resource(struct platform_device *pdev) /* initialize all interrupts to be disabled */ disable_int(info, NDSR_MASK); - ret = request_irq(irq, pxa3xx_nand_irq, 0, pdev->name, info); + ret = request_threaded_irq(irq, pxa3xx_nand_irq, + pxa3xx_nand_irq_thread, IRQF_ONESHOT, + pdev->name, info); if (ret < 0) { dev_err(&pdev->dev, "failed to request IRQ\n"); goto fail_free_buf; -- cgit v1.2.3 From 7c2f717668af10ab6d4aaed22a5d29f06812ee62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20T=C3=A9nart?= Date: Thu, 12 Feb 2015 15:53:27 +0100 Subject: mtd: pxa3xx_nand: initialiaze pxa3xx_flash_ids to 0 pxa3xx_flash_ids wasn't initialized to 0, which in certain cases could end up containing corrupted values in its members. Fix this to avoid possible issues. Signed-off-by: Antoine Tenart Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 57562c85cc8c..b1ecb570d154 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1522,6 +1522,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) return ret; } + memset(pxa3xx_flash_ids, 0, sizeof(pxa3xx_flash_ids)); + pxa3xx_flash_ids[0].name = f->name; pxa3xx_flash_ids[0].dev_id = (f->chip_id >> 8) & 0xffff; pxa3xx_flash_ids[0].pagesize = f->page_size; -- cgit v1.2.3 From a05973a79efe9152391065c87c12d5c1e146a736 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 6 Feb 2015 03:25:28 -0800 Subject: mtd: s3c2410: drop useless / misspelled debug prints s3c2410_nand_probe is not the name of the function. These prints have little utility, so let's just kill them. Reported-by: Julia Lawall Signed-off-by: Brian Norris --- drivers/mtd/nand/s3c2410.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 35aef5edb588..0e02be47ce1d 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -948,8 +948,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev) cpu_type = platform_get_device_id(pdev)->driver_data; - pr_debug("s3c2410_nand_probe(%p)\n", pdev); - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (info == NULL) { err = -ENOMEM; @@ -1045,7 +1043,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev) s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND); } - pr_debug("initialised ok\n"); return 0; exit_error: -- cgit v1.2.3 From 393d23c4e22996ad0c694577927bcf13ba31beda Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 28 Feb 2015 20:27:56 +0000 Subject: mtd: atmel_nand: fix typo in dev_err error message Fix typo, "Unkown" -> "Unknown" Signed-off-by: Colin Ian King Acked-by: Josh Wu Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index d93c849b70b5..13104507da63 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -1719,7 +1719,7 @@ static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag) comp[index++] = &host->nfc->comp_cmd_done; if (index == 0) { - dev_err(host->dev, "Unkown interrupt flag: 0x%08x\n", flag); + dev_err(host->dev, "Unknown interrupt flag: 0x%08x\n", flag); return -EINVAL; } -- cgit v1.2.3 From 111573ccd89b67fdef64d945cc0e611df85a6ac8 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 22 Jan 2015 18:21:30 +0800 Subject: mtd: atmel_nand: check NFC busy flag by HSMC_SR instead of NFC cmd regs Currently the driver read NFC command registers to get NFC busy flag. Actually this flag also can be get by reading HSMC_SR register. Use the read NFC command registers need mapping a huge memory region. To save the mapped memory region, we change to check NFC busy flag by reading HSMC_SR register. Signed-off-by: Boris Brezillon Signed-off-by: Josh Wu Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 5 ++--- drivers/mtd/nand/atmel_nand_nfc.h | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 13104507da63..feaac9099bb9 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -1752,11 +1752,10 @@ static int nfc_send_command(struct atmel_nand_host *host, cmd, addr, cycle0); timeout = jiffies + msecs_to_jiffies(NFC_TIME_OUT_MS); - while (nfc_cmd_readl(NFCADDR_CMD_NFCBUSY, host->nfc->base_cmd_regs) - & NFCADDR_CMD_NFCBUSY) { + while (nfc_readl(host->nfc->hsmc_regs, SR) & NFC_SR_BUSY) { if (time_after(jiffies, timeout)) { dev_err(host->dev, - "Time out to wait CMD_NFCBUSY ready!\n"); + "Time out to wait for NFC ready!\n"); return -ETIMEDOUT; } } diff --git a/drivers/mtd/nand/atmel_nand_nfc.h b/drivers/mtd/nand/atmel_nand_nfc.h index 85b8ca6af7d2..4d5d26221a7e 100644 --- a/drivers/mtd/nand/atmel_nand_nfc.h +++ b/drivers/mtd/nand/atmel_nand_nfc.h @@ -35,6 +35,7 @@ #define NFC_CTRL_DISABLE (1 << 1) #define ATMEL_HSMC_NFC_SR 0x08 /* NFC Status Register */ +#define NFC_SR_BUSY (1 << 8) #define NFC_SR_XFR_DONE (1 << 16) #define NFC_SR_CMD_DONE (1 << 17) #define NFC_SR_DTOE (1 << 20) -- cgit v1.2.3 From e35d1d8a1d16e9f56a9b54c96d0cb85ed621bb89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 10 Feb 2015 19:59:55 +0100 Subject: mtd: mxc-nand: Add a timeout when waiting for interrupt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While extending the mxc-nand driver it happend to me a few times that the device was stuck and this made the machine hang during boot. So implement a timeout and print a stack trace the first time this happens to make it debuggable. The return type of the waiting function is also changed to int to be able to handle the timeout in the caller. Signed-off-by: Uwe Kleine-König Signed-off-by: Brian Norris --- drivers/mtd/nand/mxc_nand.c | 47 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index a8f550fec35e..27ba07c07966 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -386,26 +386,51 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) /* This function polls the NANDFC to wait for the basic operation to * complete by checking the INT bit of config2 register. */ -static void wait_op_done(struct mxc_nand_host *host, int useirq) +static int wait_op_done(struct mxc_nand_host *host, int useirq) { - int max_retries = 8000; + int ret = 0; + + /* + * If operation is already complete, don't bother to setup an irq or a + * loop. + */ + if (host->devtype_data->check_int(host)) + return 0; if (useirq) { - if (!host->devtype_data->check_int(host)) { - reinit_completion(&host->op_completion); - irq_control(host, 1); - wait_for_completion(&host->op_completion); + unsigned long timeout; + + reinit_completion(&host->op_completion); + + irq_control(host, 1); + + timeout = wait_for_completion_timeout(&host->op_completion, HZ); + if (!timeout && !host->devtype_data->check_int(host)) { + dev_dbg(host->dev, "timeout waiting for irq\n"); + ret = -ETIMEDOUT; } } else { - while (max_retries-- > 0) { - if (host->devtype_data->check_int(host)) - break; + int max_retries = 8000; + int done; + do { udelay(1); + + done = host->devtype_data->check_int(host); + if (done) + break; + + } while (--max_retries); + + if (!done) { + dev_dbg(host->dev, "timeout polling for completion\n"); + ret = -ETIMEDOUT; } - if (max_retries < 0) - pr_debug("%s: INT not set\n", __func__); } + + WARN_ONCE(ret < 0, "timeout! useirq=%d\n", useirq); + + return ret; } static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq) -- cgit v1.2.3 From 1f42adc8880d0692c3cb7b6adb247f17c4983081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 10 Feb 2015 19:59:56 +0100 Subject: mtd: mxc-nand: Only enable hardware checksumming for fully detected flashes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At least on i.MX25 (i.e. NFCv2) preset_v2 is called with mtd->writesize == 0 that is before the connect flash chip is detected. It then configures for 8 bit ECC mode which needs 26 bytes of OOB per 512 bytes main section. For flashes with a smaller OOB area issuing a read page command makes the controller stuck with this config. Note that this currently doesn't hurt because the first read page command is issued only after detection is complete and preset is called once more. Signed-off-by: Uwe Kleine-König Signed-off-by: Brian Norris --- drivers/mtd/nand/mxc_nand.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 27ba07c07966..d9637ae34719 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -928,7 +928,7 @@ static void preset_v1(struct mtd_info *mtd) struct mxc_nand_host *host = nand_chip->priv; uint16_t config1 = 0; - if (nand_chip->ecc.mode == NAND_ECC_HW) + if (nand_chip->ecc.mode == NAND_ECC_HW && mtd->writesize) config1 |= NFC_V1_V2_CONFIG1_ECC_EN; if (!host->devtype_data->irqpending_quirk) @@ -956,9 +956,6 @@ static void preset_v2(struct mtd_info *mtd) struct mxc_nand_host *host = nand_chip->priv; uint16_t config1 = 0; - if (nand_chip->ecc.mode == NAND_ECC_HW) - config1 |= NFC_V1_V2_CONFIG1_ECC_EN; - config1 |= NFC_V2_CONFIG1_FP_INT; if (!host->devtype_data->irqpending_quirk) @@ -967,6 +964,9 @@ static void preset_v2(struct mtd_info *mtd) if (mtd->writesize) { uint16_t pages_per_block = mtd->erasesize / mtd->writesize; + if (nand_chip->ecc.mode == NAND_ECC_HW) + config1 |= NFC_V1_V2_CONFIG1_ECC_EN; + host->eccsize = get_eccsize(mtd); if (host->eccsize == 4) config1 |= NFC_V2_CONFIG1_ECC_MODE_4; @@ -1024,9 +1024,6 @@ static void preset_v3(struct mtd_info *mtd) NFC_V3_CONFIG2_INT_MSK | NFC_V3_CONFIG2_NUM_ADDR_PHASE0; - if (chip->ecc.mode == NAND_ECC_HW) - config2 |= NFC_V3_CONFIG2_ECC_EN; - addr_phases = fls(chip->pagemask) >> 3; if (mtd->writesize == 2048) { @@ -1041,6 +1038,9 @@ static void preset_v3(struct mtd_info *mtd) } if (mtd->writesize) { + if (chip->ecc.mode == NAND_ECC_HW) + config2 |= NFC_V3_CONFIG2_ECC_EN; + config2 |= NFC_V3_CONFIG2_PPB( ffs(mtd->erasesize / mtd->writesize) - 6, host->devtype_data->ppb_shift); -- cgit v1.2.3 From 3f410690f511f9531fdc0865a931522b049d7b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 10 Feb 2015 19:59:57 +0100 Subject: mtd: mxc-nand: Do the word to byte mangling in the read_byte callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the hardware operates in 16 bit mode it always reads 16 bits even for operations that only have the lower 8 bits defined. So the upper bits must be discarded. Do this in the read_byte callback instead of when reading the NAND id to support reading byte wise more than 5 bytes and at other occations (like reading the ONFI parameter page). Signed-off-by: Uwe Kleine-König Signed-off-by: Brian Norris --- drivers/mtd/nand/mxc_nand.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index d9637ae34719..aa98a0dddcfb 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -552,30 +552,17 @@ static void send_page_v1(struct mtd_info *mtd, unsigned int ops) static void send_read_id_v3(struct mxc_nand_host *host) { - struct nand_chip *this = &host->nand; - /* Read ID into main buffer */ writel(NFC_ID, NFC_V3_LAUNCH); wait_op_done(host, true); memcpy32_fromio(host->data_buf, host->main_area0, 16); - - if (this->options & NAND_BUSWIDTH_16) { - /* compress the ID info */ - host->data_buf[1] = host->data_buf[2]; - host->data_buf[2] = host->data_buf[4]; - host->data_buf[3] = host->data_buf[6]; - host->data_buf[4] = host->data_buf[8]; - host->data_buf[5] = host->data_buf[10]; - } } /* Request the NANDFC to perform a read of the NAND device ID. */ static void send_read_id_v1_v2(struct mxc_nand_host *host) { - struct nand_chip *this = &host->nand; - /* NANDFC buffer 0 is used for device ID output */ writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); @@ -585,15 +572,6 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) wait_op_done(host, true); memcpy32_fromio(host->data_buf, host->main_area0, 16); - - if (this->options & NAND_BUSWIDTH_16) { - /* compress the ID info */ - host->data_buf[1] = host->data_buf[2]; - host->data_buf[2] = host->data_buf[4]; - host->data_buf[3] = host->data_buf[6]; - host->data_buf[4] = host->data_buf[8]; - host->data_buf[5] = host->data_buf[10]; - } } static uint16_t get_dev_status_v3(struct mxc_nand_host *host) @@ -719,9 +697,17 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) if (host->status_request) return host->devtype_data->get_dev_status(host) & 0xFF; - ret = *(uint8_t *)(host->data_buf + host->buf_start); - host->buf_start++; + if (nand_chip->options & NAND_BUSWIDTH_16) { + /* only take the lower byte of each word */ + ret = *(uint16_t *)(host->data_buf + host->buf_start); + + host->buf_start += 2; + } else { + ret = *(uint8_t *)(host->data_buf + host->buf_start); + host->buf_start++; + } + pr_debug("%s: ret=0x%hhx (start=%u)\n", __func__, ret, host->buf_start); return ret; } -- cgit v1.2.3 From c4ca3997ef954bcba009cce0e325f3155bdde01a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 10 Feb 2015 19:59:58 +0100 Subject: mtd: mxc-nand: Allow to use column addresses different from 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mxc-nand controller works pagewise and so usually only sends commands to the flash chip with column == 0. A request with column != 0 from the upper layer is then fulfilled by indexing appropriately into the device's RAM buffer. To be able to access the ONFI marker at offset 0x20 in reply to the READID command however it's invalid to read 32 bytes starting from column 0. So let the function used to send the address cycles send the column address actually passed instead of 0 and fix all callers to pass 0 instead appropriately. Also add some warnings in case this patch changes the drivers semantics. Signed-off-by: Uwe Kleine-König Signed-off-by: Brian Norris --- drivers/mtd/nand/mxc_nand.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index aa98a0dddcfb..0afe5904a337 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -836,6 +836,12 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom) } } +/* + * MXC NANDFC can only perform full page+spare or spare-only read/write. When + * the upper layers perform a read/write buf operation, the saved column address + * is used to index into the full page. So usually this function is called with + * column == 0 (unless no column cycle is needed indicated by column == -1) + */ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) { struct nand_chip *nand_chip = mtd->priv; @@ -843,16 +849,13 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) /* Write out column address, if necessary */ if (column != -1) { - /* - * MXC NANDFC can only perform full page+spare or - * spare-only read/write. When the upper layers - * perform a read/write buf operation, the saved column - * address is used to index into the full page. - */ - host->devtype_data->send_addr(host, 0, page_addr == -1); + host->devtype_data->send_addr(host, column & 0xff, + page_addr == -1); if (mtd->writesize > 512) /* another col addr cycle for 2k page */ - host->devtype_data->send_addr(host, 0, false); + host->devtype_data->send_addr(host, + (column >> 8) & 0xff, + false); } /* Write out page address, if necessary */ @@ -1077,6 +1080,9 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, host->status_request = true; host->devtype_data->send_cmd(host, command, true); + WARN_ONCE(column != -1 || page_addr != -1, + "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n", + command, column, page_addr); mxc_do_addr_cycle(mtd, column, page_addr); break; @@ -1090,7 +1096,10 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, command = NAND_CMD_READ0; /* only READ0 is valid */ host->devtype_data->send_cmd(host, command, false); - mxc_do_addr_cycle(mtd, column, page_addr); + WARN_ONCE(column < 0, + "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n", + command, column, page_addr); + mxc_do_addr_cycle(mtd, 0, page_addr); if (mtd->writesize > 512) host->devtype_data->send_cmd(host, @@ -1111,7 +1120,10 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, host->buf_start = column; host->devtype_data->send_cmd(host, command, false); - mxc_do_addr_cycle(mtd, column, page_addr); + WARN_ONCE(column < -1, + "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n", + command, column, page_addr); + mxc_do_addr_cycle(mtd, 0, page_addr); break; case NAND_CMD_PAGEPROG: @@ -1119,6 +1131,9 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, copy_spare(mtd, false); host->devtype_data->send_page(mtd, NFC_INPUT); host->devtype_data->send_cmd(host, command, true); + WARN_ONCE(column != -1 || page_addr != -1, + "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n", + command, column, page_addr); mxc_do_addr_cycle(mtd, column, page_addr); break; @@ -1126,12 +1141,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, host->devtype_data->send_cmd(host, command, true); mxc_do_addr_cycle(mtd, column, page_addr); host->devtype_data->send_read_id(host); - host->buf_start = column; + host->buf_start = 0; break; case NAND_CMD_ERASE1: case NAND_CMD_ERASE2: host->devtype_data->send_cmd(host, command, false); + WARN_ONCE(column != -1, + "Unexpected column value (cmd=%u, col=%d)\n", + command, column); mxc_do_addr_cycle(mtd, column, page_addr); break; -- cgit v1.2.3 From 3d6e81c0c9827c86fd3fe4bcbc44155b1401f80e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 10 Feb 2015 19:59:59 +0100 Subject: mtd: mxc-nand: Implement support for PARAM command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mxc-nand driver never supported the PARAM command to read out the ONFI parameter page and so always relied on probing my manufacturer and device id (as provided by the READID command). This patch implements reading out the first parameter page copy at least which should be good enough in practise. This makes the boot log change from nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xb1 nand: Micron NAND 128MiB 1,8V 16-bit to nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xb1 nand: Micron MT29F1G16ABBDAH4 on my machine. Signed-off-by: Uwe Kleine-König Signed-off-by: Brian Norris --- drivers/mtd/nand/mxc_nand.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 0afe5904a337..0083b4ee4f33 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -1152,6 +1152,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, command, column); mxc_do_addr_cycle(mtd, column, page_addr); + break; + case NAND_CMD_PARAM: + host->devtype_data->send_cmd(host, command, false); + mxc_do_addr_cycle(mtd, column, page_addr); + host->devtype_data->send_page(mtd, NFC_OUTPUT); + memcpy32_fromio(host->data_buf, host->main_area0, 512); + host->buf_start = 0; break; } } -- cgit v1.2.3 From 98ebb521096f2d90c3e903ba79412cd92064795b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 10 Feb 2015 20:00:00 +0100 Subject: mtd: mxc-nand: Warn on unimplemented commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PARAM command was long unimplemented and it probably wasn't noticed because chip probing using only the few bytes returned by the READID command are good enough in most cases to determine the chip in use. Still to notice such a shortcoming earlier in the future would be nice in case it's something more vital. Signed-off-by: Uwe Kleine-König Signed-off-by: Brian Norris --- drivers/mtd/nand/mxc_nand.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 0083b4ee4f33..372e0e38f59b 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -1160,6 +1160,10 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, memcpy32_fromio(host->data_buf, host->main_area0, 512); host->buf_start = 0; break; + default: + WARN_ONCE(1, "Unimplemented command (cmd=%u)\n", + command); + break; } } -- cgit v1.2.3 From b1a2348a1ac1380adf429035dbf3fdad0d5367bc Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Sat, 28 Feb 2015 02:02:27 -0800 Subject: mtd: nand: fixup bounds checks for nand_{lock,unlock}() Coverity noticed that these 'ret' assignments weren't being used. Let's use them. Note that nand_lock() and nand_unlock() are still not officially used by any drivers. Coverity CIDs #1227054 and #1227037 Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index df7eb4ff07d1..5488a7ad63e7 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -968,7 +968,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) __func__, (unsigned long long)ofs, len); if (check_offs_len(mtd, ofs, len)) - ret = -EINVAL; + return -EINVAL; /* Align to last block address if size addresses end of the device */ if (ofs + len == mtd->size) @@ -1031,7 +1031,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) __func__, (unsigned long long)ofs, len); if (check_offs_len(mtd, ofs, len)) - ret = -EINVAL; + return -EINVAL; nand_get_device(mtd, FL_LOCKING); -- cgit v1.2.3 From 99f6d50dc81ef713f64abbb5ec6b94167203d8c5 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Sat, 28 Feb 2015 02:02:28 -0800 Subject: mtd: nand: denali: drop dead code TclsRising is always 1. Caught by Coverity. Signed-off-by: Brian Norris Cc: Masahiro Yamada --- drivers/mtd/nand/denali.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index f44c6061536a..09f51395f2c0 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -225,7 +225,6 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali, uint16_t Twhr[6] = {120, 80, 80, 60, 60, 60}; uint16_t Tcs[6] = {70, 35, 25, 25, 20, 15}; - uint16_t TclsRising = 1; uint16_t data_invalid_rhoh, data_invalid_rloh, data_invalid; uint16_t dv_window = 0; uint16_t en_lo, en_hi; @@ -276,8 +275,6 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali, re_2_re = CEIL_DIV(Trhz[mode], CLK_X); we_2_re = CEIL_DIV(Twhr[mode], CLK_X); cs_cnt = CEIL_DIV((Tcs[mode] - Trp[mode]), CLK_X); - if (!TclsRising) - cs_cnt = CEIL_DIV(Tcs[mode], CLK_X); if (cs_cnt == 0) cs_cnt = 1; -- cgit v1.2.3 From 0ec56dc4a1489d5b1d23d1c019b76a69ce153805 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Sat, 28 Feb 2015 02:02:30 -0800 Subject: mtd: nand: fully initialize mtd_oob_ops We're not initializing the ooblen field. Our users don't care, since they check that oobbuf == NULL first, but it's good practice to zero unused fields out. We can drop the NULL initializations since we're memset()ing the whole thing. Noticed by Coverity, CID #200821, #200822 Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5488a7ad63e7..d4cec2f8a016 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -386,7 +386,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) uint8_t buf[2] = { 0, 0 }; int ret = 0, res, i = 0; - ops.datbuf = NULL; + memset(&ops, 0, sizeof(ops)); ops.oobbuf = buf; ops.ooboffs = chip->badblockpos; if (chip->options & NAND_BUSWIDTH_16) { @@ -1716,9 +1716,9 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, int ret; nand_get_device(mtd, FL_READING); + memset(&ops, 0, sizeof(ops)); ops.len = len; ops.datbuf = buf; - ops.oobbuf = NULL; ops.mode = MTD_OPS_PLACE_OOB; ret = nand_do_read_ops(mtd, from, &ops); *retlen = ops.retlen; @@ -2508,9 +2508,9 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len, /* Grab the device */ panic_nand_get_device(chip, mtd, FL_WRITING); + memset(&ops, 0, sizeof(ops)); ops.len = len; ops.datbuf = (uint8_t *)buf; - ops.oobbuf = NULL; ops.mode = MTD_OPS_PLACE_OOB; ret = nand_do_write_ops(mtd, to, &ops); @@ -2536,9 +2536,9 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, int ret; nand_get_device(mtd, FL_WRITING); + memset(&ops, 0, sizeof(ops)); ops.len = len; ops.datbuf = (uint8_t *)buf; - ops.oobbuf = NULL; ops.mode = MTD_OPS_PLACE_OOB; ret = nand_do_write_ops(mtd, to, &ops); *retlen = ops.retlen; -- cgit v1.2.3 From 73c8aaf43629e83541332f66fd08699e20ea87bc Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Sat, 28 Feb 2015 02:04:18 -0800 Subject: mtd: nand: fix spelling of REPLACEABLE Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index d4cec2f8a016..ff5652211607 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2124,7 +2124,7 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, /** - * nand_write_subpage_hwecc - [REPLACABLE] hardware ECC based subpage write + * nand_write_subpage_hwecc - [REPLACEABLE] hardware ECC based subpage write * @mtd: mtd info structure * @chip: nand chip info structure * @offset: column address of subpage within the page -- cgit v1.2.3 From 60c70d66cdd39eb560bba5a95c429bf2ad5294d0 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Mon, 23 Feb 2015 17:26:39 +0200 Subject: mtd: nand: Prevent possible kernel lockup in nand_command() If a NAND device is not really present or pin muxes are not correctly configured we can lock up the kernel waiting infinitely for NAND_STATUS to be ready. This can be easily reproduced on TI's DRA7-evm board by booting it without NAND support in u-boot and disabling NAND pin muxes in the kernel. Add timeout when waiting for NAND_CMD_RESET completion. As per ONFi v4.0 tRST can be upto 250ms for EZ-NAND and 5ms for raw NAND. Signed-off-by: Roger Quadros Tested-by: Nishanth Menon Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index ff5652211607..c2e1232cd45c 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -565,6 +565,25 @@ void nand_wait_ready(struct mtd_info *mtd) } EXPORT_SYMBOL_GPL(nand_wait_ready); +/** + * nand_wait_status_ready - [GENERIC] Wait for the ready status after commands. + * @mtd: MTD device structure + * @timeo: Timeout in ms + * + * Wait for status ready (i.e. command done) or timeout. + */ +static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo) +{ + register struct nand_chip *chip = mtd->priv; + + timeo = jiffies + msecs_to_jiffies(timeo); + do { + if ((chip->read_byte(mtd) & NAND_STATUS_READY)) + break; + touch_softlockup_watchdog(); + } while (time_before(jiffies, timeo)); +}; + /** * nand_command - [DEFAULT] Send command to NAND device * @mtd: MTD device structure @@ -643,8 +662,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, NAND_CTRL_CLE | NAND_CTRL_CHANGE); chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); - while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) - ; + /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ + nand_wait_status_ready(mtd, 250); return; /* This applies to read commands */ @@ -740,8 +759,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); - while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) - ; + /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ + nand_wait_status_ready(mtd, 250); return; case NAND_CMD_RNDOUT: -- cgit v1.2.3 From 62b57f4c1475a4c452000192e5cad2ae86164be5 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 19 Mar 2015 14:34:29 +0100 Subject: mtd: fsmc_nand.c: Use default timings if none are provided in the dts Without this patch the timings are all set to 0 if not specified in the dts. With this patch the driver falls back to use the defaults that are already present in the driver and are known to work okay for some (older) boards. Tested on a custom SPEAr600 based board. Signed-off-by: Stefan Roese Acked-by: Linus Walleij Cc: Viresh Kumar Cc: Mian Yousaf Kaukab Signed-off-by: Brian Norris --- drivers/mtd/nand/fsmc_nand.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index edfaa21b1817..e58af4bfa8c8 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c @@ -873,6 +873,7 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev, { struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); u32 val; + int ret; /* Set default NAND width to 8 bits */ pdata->width = 8; @@ -891,8 +892,12 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev, sizeof(*pdata->nand_timings), GFP_KERNEL); if (!pdata->nand_timings) return -ENOMEM; - of_property_read_u8_array(np, "timings", (u8 *)pdata->nand_timings, + ret = of_property_read_u8_array(np, "timings", (u8 *)pdata->nand_timings, sizeof(*pdata->nand_timings)); + if (ret) { + dev_info(&pdev->dev, "No timings in dts specified, using default timings!\n"); + pdata->nand_timings = NULL; + } /* Set default NAND bank to 0 */ pdata->bank = 0; -- cgit v1.2.3 From 706d5b289924678de9d8af67bcb00e28c1a5000c Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sun, 8 Feb 2015 11:37:33 -0500 Subject: mtd: nand: gpmi: fixup return type of wait_for_completion_timeout return type of wait_for_completion_timeout is unsigned long not int. The return variable is renamed to reflect its use and the type adjusted to unsigned long. Signed-off-by: Nicholas Mc Guire Reviewed-by: Boris Brezillon Acked-by: Huang Shijie Signed-off-by: Brian Norris --- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 33f3c3c54dbc..6e44d3268fcb 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -446,7 +446,7 @@ int start_dma_without_bch_irq(struct gpmi_nand_data *this, struct dma_async_tx_descriptor *desc) { struct completion *dma_c = &this->dma_done; - int err; + unsigned long timeout; init_completion(dma_c); @@ -456,8 +456,8 @@ int start_dma_without_bch_irq(struct gpmi_nand_data *this, dma_async_issue_pending(get_dma_chan(this)); /* Wait for the interrupt from the DMA block. */ - err = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000)); - if (!err) { + timeout = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000)); + if (!timeout) { dev_err(this->dev, "DMA timeout, last DMA :%d\n", this->last_dma_type); gpmi_dump_info(this); @@ -477,7 +477,7 @@ int start_dma_with_bch_irq(struct gpmi_nand_data *this, struct dma_async_tx_descriptor *desc) { struct completion *bch_c = &this->bch_done; - int err; + unsigned long timeout; /* Prepare to receive an interrupt from the BCH block. */ init_completion(bch_c); @@ -486,8 +486,8 @@ int start_dma_with_bch_irq(struct gpmi_nand_data *this, start_dma_without_bch_irq(this, desc); /* Wait for the interrupt from the BCH block. */ - err = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000)); - if (!err) { + timeout = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000)); + if (!timeout) { dev_err(this->dev, "BCH timeout, last DMA :%d\n", this->last_dma_type); gpmi_dump_info(this); -- cgit v1.2.3 From 899b834a462921a087f92f705d9f85def5892242 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 9 Feb 2015 19:22:33 -0200 Subject: mtd: nand: gpmi: Check for scan_bbt() error In case of scan_bbt() failure, we should better propagate it. Signed-off-by: Fabio Estevam Acked-by: Huang Shijie Signed-off-by: Brian Norris --- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 6e44d3268fcb..1b8f3500e6d2 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -1950,7 +1950,9 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) ret = nand_boot_init(this); if (ret) goto err_out; - chip->scan_bbt(mtd); + ret = chip->scan_bbt(mtd); + if (ret) + goto err_out; ppdata.of_node = this->pdev->dev.of_node; ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); -- cgit v1.2.3 From e5860c18e68606446a10c3e926a2a0162c385cbf Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sun, 1 Feb 2015 11:55:37 -0500 Subject: mtd: pxa3xx_nand: cleanup wait_for_completion handling return type of wait_for_completion_timeout is unsigned long not int, this patch uses the return value of wait_for_completion_timeout in the condition directly rather than assigning it to an incorrect type variable. The variable used for handling the return of wait_for_cmpletion_timeout was int but should be unsigned long, where it was not in use for anything else and the return value in case of completion (>0) is not used it was removed and wait_for_completion_timeout() used directly in the if condition. To make the timeout values a bit simpler to read and also handle all of the corner cases correctly the declarations are moved to msecs_to_jiffies(). The timeout declaration cleanup is just for readability Signed-off-by: Nicholas Mc Guire Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index b1ecb570d154..a4615fcc3d00 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -38,8 +38,8 @@ #include -#define CHIP_DELAY_TIMEOUT (2 * HZ/10) -#define NAND_STOP_DELAY (2 * HZ/50) +#define CHIP_DELAY_TIMEOUT msecs_to_jiffies(200) +#define NAND_STOP_DELAY msecs_to_jiffies(40) #define PAGE_CHUNK_SIZE (2048) /* @@ -965,7 +965,7 @@ static void nand_cmdfunc(struct mtd_info *mtd, unsigned command, { struct pxa3xx_nand_host *host = mtd->priv; struct pxa3xx_nand_info *info = host->info_data; - int ret, exec_cmd; + int exec_cmd; /* * if this is a x16 device ,then convert the input @@ -997,9 +997,8 @@ static void nand_cmdfunc(struct mtd_info *mtd, unsigned command, info->need_wait = 1; pxa3xx_nand_start(info); - ret = wait_for_completion_timeout(&info->cmd_complete, - CHIP_DELAY_TIMEOUT); - if (!ret) { + if (!wait_for_completion_timeout(&info->cmd_complete, + CHIP_DELAY_TIMEOUT)) { dev_err(&info->pdev->dev, "Wait time out!!!\n"); /* Stop State Machine for next command cycle */ pxa3xx_nand_stop(info); @@ -1014,7 +1013,7 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd, { struct pxa3xx_nand_host *host = mtd->priv; struct pxa3xx_nand_info *info = host->info_data; - int ret, exec_cmd, ext_cmd_type; + int exec_cmd, ext_cmd_type; /* * if this is a x16 device then convert the input @@ -1077,9 +1076,8 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd, init_completion(&info->cmd_complete); pxa3xx_nand_start(info); - ret = wait_for_completion_timeout(&info->cmd_complete, - CHIP_DELAY_TIMEOUT); - if (!ret) { + if (!wait_for_completion_timeout(&info->cmd_complete, + CHIP_DELAY_TIMEOUT)) { dev_err(&info->pdev->dev, "Wait time out!!!\n"); /* Stop State Machine for next command cycle */ pxa3xx_nand_stop(info); @@ -1212,13 +1210,11 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) { struct pxa3xx_nand_host *host = mtd->priv; struct pxa3xx_nand_info *info = host->info_data; - int ret; if (info->need_wait) { - ret = wait_for_completion_timeout(&info->dev_ready, - CHIP_DELAY_TIMEOUT); info->need_wait = 0; - if (!ret) { + if (!wait_for_completion_timeout(&info->dev_ready, + CHIP_DELAY_TIMEOUT)) { dev_err(&info->pdev->dev, "Ready time out!!!\n"); return NAND_STATUS_FAIL; } -- cgit v1.2.3 From d99d72829ec00a96d2d71f30a704b901c198a673 Mon Sep 17 00:00:00 2001 From: Graham Moore Date: Wed, 14 Jan 2015 09:38:50 -0600 Subject: mtd: denali: Disable sub-page writes in Denali NAND driver The Denali Controller IP does not support sub-page writes. Signed-off-by: Graham Moore Signed-off-by: Dinh Nguyen Signed-off-by: Brian Norris --- drivers/mtd/nand/denali.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 09f51395f2c0..870c7fc0f759 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -1533,6 +1533,9 @@ int denali_init(struct denali_nand_info *denali) denali->nand.options |= NAND_SKIP_BBTSCAN; denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME; + /* no subpage writes on denali */ + denali->nand.options |= NAND_NO_SUBPAGE_WRITE; + /* * Denali Controller only support 15bit and 8bit ECC in MRST, * so just let controller do 15bit ECC for MLC and 8bit ECC for -- cgit v1.2.3 From 477478aedc8bdf1925785835609bc7e790f69aef Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Thu, 2 Apr 2015 14:12:33 +0800 Subject: mtd: atmel_nand: add a definition for the oob reserved bytes It's better to use a macro instead of just a number. Signed-off-by: Josh Wu Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 5 +++-- drivers/mtd/nand/atmel_nand_ecc.h | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index feaac9099bb9..0361c1992673 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -485,7 +485,7 @@ static void pmecc_config_ecc_layout(struct nand_ecclayout *layout, for (i = 0; i < ecc_len; i++) layout->eccpos[i] = oobsize - ecc_len + i; - layout->oobfree[0].offset = 2; + layout->oobfree[0].offset = PMECC_OOB_RESERVED_BYTES; layout->oobfree[0].length = oobsize - ecc_len - layout->oobfree[0].offset; } @@ -1254,7 +1254,8 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev, nand_chip->ecc.steps = mtd->writesize / sector_size; nand_chip->ecc.total = nand_chip->ecc.bytes * nand_chip->ecc.steps; - if (nand_chip->ecc.total > mtd->oobsize - 2) { + if (nand_chip->ecc.total > + mtd->oobsize - PMECC_OOB_RESERVED_BYTES) { dev_err(host->dev, "No room for ECC bytes\n"); err_no = -EINVAL; goto err; diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h index d4035e335ad8..668e7358f19b 100644 --- a/drivers/mtd/nand/atmel_nand_ecc.h +++ b/drivers/mtd/nand/atmel_nand_ecc.h @@ -152,4 +152,7 @@ /* Time out value for reading PMECC status register */ #define PMECC_MAX_TIMEOUT_MS 100 +/* Reserved bytes in oob area */ +#define PMECC_OOB_RESERVED_BYTES 2 + #endif -- cgit v1.2.3 From 41c7540d0c4e362212845aa2258c15aaa878665f Mon Sep 17 00:00:00 2001 From: "Wu, Josh" Date: Thu, 2 Apr 2015 14:13:47 +0800 Subject: mtd: atmel_nand: don't map the ROM table if no pmecc table offset in DT if atmel,pmecc-lookup-table-offset is not found in DT node, we don't need to map the ROM table as we will build a runtime gf table anyway. Reported-by: Nicolas Ferre Signed-off-by: Josh Wu Acked-by: Nicolas Ferre Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 0361c1992673..46010bd895b1 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -1204,14 +1204,14 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev, goto err; } - regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3); - host->pmecc_rom_base = devm_ioremap_resource(&pdev->dev, regs_rom); - if (IS_ERR(host->pmecc_rom_base)) { - if (!host->has_no_lookup_table) - /* Don't display the information again */ + if (!host->has_no_lookup_table) { + regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3); + host->pmecc_rom_base = devm_ioremap_resource(&pdev->dev, + regs_rom); + if (IS_ERR(host->pmecc_rom_base)) { dev_err(host->dev, "Can not get I/O resource for ROM, will build a lookup table in runtime!\n"); - - host->has_no_lookup_table = true; + host->has_no_lookup_table = true; + } } if (host->has_no_lookup_table) { -- cgit v1.2.3 From 95d706657311f24407d0f7a0cf79b55904ec6524 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Fri, 13 Mar 2015 07:23:47 -0400 Subject: mtd: fsl_ifc_nand: use msecs_to_jiffies for time conversion This is only an API consolidation and should make things more readable it replaces var * HZ / 1000 by msecs_to_jiffies(var) which helps readability and also handles all corner-cases properly. Signed-off-by: Nicholas Mc Guire Signed-off-by: Brian Norris --- drivers/mtd/nand/fsl_ifc_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 4c05f4f6a5c6..51394e59901b 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -317,7 +317,7 @@ static void fsl_ifc_run_command(struct mtd_info *mtd) /* wait for command complete flag or timeout */ wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat, - IFC_TIMEOUT_MSECS * HZ/1000); + msecs_to_jiffies(IFC_TIMEOUT_MSECS)); /* ctrl->nand_stat will be updated from IRQ context */ if (!ctrl->nand_stat) @@ -860,7 +860,7 @@ static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) /* wait for command complete flag or timeout */ wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat, - IFC_TIMEOUT_MSECS * HZ/1000); + msecs_to_jiffies(IFC_TIMEOUT_MSECS)); if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) printk(KERN_ERR "fsl-ifc: Failed to Initialise SRAM\n"); -- cgit v1.2.3