@@ -27,6 +27,7 @@
#include <plat/pxa3xx_nand.h>
#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_info {
@@ -293,7 +298,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)
{