diff options
Diffstat (limited to 'target/linux/mvebu/patches-3.10/0140-mtd-nand-pxa3xx-Use-a-completion-to-signal-device-re.patch')
-rw-r--r-- | target/linux/mvebu/patches-3.10/0140-mtd-nand-pxa3xx-Use-a-completion-to-signal-device-re.patch | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/target/linux/mvebu/patches-3.10/0140-mtd-nand-pxa3xx-Use-a-completion-to-signal-device-re.patch b/target/linux/mvebu/patches-3.10/0140-mtd-nand-pxa3xx-Use-a-completion-to-signal-device-re.patch new file mode 100644 index 0000000000..7f5108fd2f --- /dev/null +++ b/target/linux/mvebu/patches-3.10/0140-mtd-nand-pxa3xx-Use-a-completion-to-signal-device-re.patch @@ -0,0 +1,138 @@ +From b5289e9cb18e6c254e13826e6bcfbfe95b819d77 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> +Date: Thu, 14 Nov 2013 18:25:26 -0300 +Subject: [PATCH 140/203] mtd: nand: pxa3xx: Use a completion to signal device + ready + +The expected behavior of the waitfunc() NAND chip call is to wait +for the device to be READY (this is a standard chip line). +However, the current implementation does almost nothing, which opens +the possibility of issuing a command to a non-ready device. + +Fix this by adding a new completion to wait for the ready event to arrive. + +Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> +Tested-by: Daniel Mack <zonque@gmail.com> +Signed-off-by: Brian Norris <computersforpeace@gmail.com> +--- + drivers/mtd/nand/pxa3xx_nand.c | 38 ++++++++++++++++++++++++-------------- + 1 file changed, 24 insertions(+), 14 deletions(-) + +--- a/drivers/mtd/nand/pxa3xx_nand.c ++++ b/drivers/mtd/nand/pxa3xx_nand.c +@@ -37,6 +37,7 @@ + + #include <linux/platform_data/mtd-nand-pxa3xx.h> + ++#define NAND_DEV_READY_TIMEOUT 50 + #define CHIP_DELAY_TIMEOUT (2 * HZ/10) + #define NAND_STOP_DELAY (2 * HZ/50) + #define PAGE_CHUNK_SIZE (2048) +@@ -168,7 +169,7 @@ struct pxa3xx_nand_info { + struct clk *clk; + void __iomem *mmio_base; + unsigned long mmio_phys; +- struct completion cmd_complete; ++ struct completion cmd_complete, dev_ready; + + unsigned int buf_start; + unsigned int buf_count; +@@ -198,7 +199,7 @@ struct pxa3xx_nand_info { + int use_ecc; /* use HW ECC ? */ + int use_dma; /* use DMA ? */ + int use_spare; /* use spare ? */ +- int is_ready; ++ int need_wait; + + unsigned int fifo_size; /* max. data size in the FIFO */ + unsigned int data_size; /* data to be read from FIFO */ +@@ -480,7 +481,7 @@ static void start_data_dma(struct pxa3xx + static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) + { + struct pxa3xx_nand_info *info = devid; +- unsigned int status, is_completed = 0; ++ unsigned int status, is_completed = 0, is_ready = 0; + unsigned int ready, cmd_done; + + if (info->cs == 0) { +@@ -516,8 +517,8 @@ static irqreturn_t pxa3xx_nand_irq(int i + is_completed = 1; + } + if (status & ready) { +- info->is_ready = 1; + info->state = STATE_READY; ++ is_ready = 1; + } + + if (status & NDSR_WRCMDREQ) { +@@ -546,6 +547,8 @@ static irqreturn_t pxa3xx_nand_irq(int i + nand_writel(info, NDSR, status); + if (is_completed) + complete(&info->cmd_complete); ++ if (is_ready) ++ complete(&info->dev_ready); + NORMAL_IRQ_EXIT: + return IRQ_HANDLED; + } +@@ -576,7 +579,6 @@ static int prepare_command_pool(struct p + info->oob_size = 0; + info->use_ecc = 0; + info->use_spare = 1; +- info->is_ready = 0; + info->retcode = ERR_NONE; + if (info->cs != 0) + info->ndcb0 = NDCB0_CSEL; +@@ -749,6 +751,8 @@ static void pxa3xx_nand_cmdfunc(struct m + exec_cmd = prepare_command_pool(info, command, column, page_addr); + if (exec_cmd) { + init_completion(&info->cmd_complete); ++ init_completion(&info->dev_ready); ++ info->need_wait = 1; + pxa3xx_nand_start(info); + + ret = wait_for_completion_timeout(&info->cmd_complete, +@@ -863,21 +867,27 @@ static int pxa3xx_nand_waitfunc(struct m + { + 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) { ++ dev_err(&info->pdev->dev, "Ready time out!!!\n"); ++ return NAND_STATUS_FAIL; ++ } ++ } + + /* pxa3xx_nand_send_command has waited for command complete */ + if (this->state == FL_WRITING || this->state == FL_ERASING) { + if (info->retcode == ERR_NONE) + return 0; +- else { +- /* +- * any error make it return 0x01 which will tell +- * the caller the erase and write fail +- */ +- return 0x01; +- } ++ else ++ return NAND_STATUS_FAIL; + } + +- return 0; ++ return NAND_STATUS_READY; + } + + static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, +@@ -1030,7 +1040,7 @@ static int pxa3xx_nand_sensing(struct px + return ret; + + chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0); +- if (info->is_ready) ++ if (!info->need_wait) + return 0; + + return -ENODEV; |