+// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2012
* Konstantin Kozhevnikov, Cogent Embedded
*
* (C) Copyright 2006-2008
* Stefan Roese, DENX Software Engineering, sr@denx.de.
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
if (cmd == NAND_CMD_RESET) {
hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+
+ /*
+ * Apply this short delay always to ensure that we do wait
+ * tWB in any case on any machine.
+ */
+ ndelay(150);
+
while (!this->dev_ready(mtd))
;
return 0;
hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
- if (cmd == NAND_CMD_READ0) {
- /* Latch in address */
- hwctrl(mtd, NAND_CMD_READSTART,
- NAND_CTRL_CLE | NAND_CTRL_CHANGE);
- hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
- /*
- * Wait a while for the data to be ready
- */
- while (!this->dev_ready(mtd))
- ;
- } else if (cmd == NAND_CMD_RNDOUT) {
+ /*
+ * Program and erase have their own busy handlers status, sequential
+ * in and status need no delay.
+ */
+ switch (cmd) {
+ case NAND_CMD_CACHEDPROG:
+ case NAND_CMD_PAGEPROG:
+ case NAND_CMD_ERASE1:
+ case NAND_CMD_ERASE2:
+ case NAND_CMD_SEQIN:
+ case NAND_CMD_RNDIN:
+ case NAND_CMD_STATUS:
+ return 0;
+
+ case NAND_CMD_RNDOUT:
+ /* No ready / busy check necessary */
hwctrl(mtd, NAND_CMD_RNDOUTSTART, NAND_CTRL_CLE |
- NAND_CTRL_CHANGE);
+ NAND_CTRL_CHANGE);
+ hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+ return 0;
+
+ case NAND_CMD_READ0:
+ /* Latch in address */
+ hwctrl(mtd, NAND_CMD_READSTART,
+ NAND_CTRL_CLE | NAND_CTRL_CHANGE);
hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
}
+ /*
+ * Apply this short delay always to ensure that we do wait tWB in
+ * any case on any machine.
+ */
+ ndelay(150);
+
+ while (!this->dev_ready(mtd))
+ ;
+
return 0;
}
return 0;
}
-int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
-{
- unsigned int block, lastblock;
- unsigned int page, page_offset;
-
- /*
- * offs has to be aligned to a page address!
- */
- block = offs / CONFIG_SYS_NAND_BLOCK_SIZE;
- lastblock = (offs + size - 1) / CONFIG_SYS_NAND_BLOCK_SIZE;
- page = (offs % CONFIG_SYS_NAND_BLOCK_SIZE) / CONFIG_SYS_NAND_PAGE_SIZE;
- page_offset = offs % CONFIG_SYS_NAND_PAGE_SIZE;
-
- while (block <= lastblock) {
- if (!nand_is_bad_block(block)) {
- /*
- * Skip bad blocks
- */
- while (page < CONFIG_SYS_NAND_PAGE_COUNT) {
- nand_read_page(block, page, dst);
- /*
- * When offs is not aligned to page address the
- * extra offset is copied to dst as well. Copy
- * the image such that its first byte will be
- * at the dst.
- */
- if (unlikely(page_offset)) {
- memmove(dst, dst + page_offset,
- CONFIG_SYS_NAND_PAGE_SIZE);
- dst = (void *)((int)dst - page_offset);
- page_offset = 0;
- }
- dst += CONFIG_SYS_NAND_PAGE_SIZE;
- page++;
- }
-
- page = 0;
- } else {
- lastblock++;
- }
-
- block++;
- }
-
- return 0;
-}
-
/* nand_init() - initialize data to make nand usable by SPL */
void nand_init(void)
{
/*
* Init board specific nand support
*/
- mtd = &nand_chip.mtd;
+ mtd = nand_to_mtd(&nand_chip);
nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W =
(void __iomem *)CONFIG_SYS_NAND_BASE;
board_nand_init(&nand_chip);
if (nand_chip.select_chip)
nand_chip.select_chip(mtd, -1);
}
+
+#include "nand_spl_loaders.c"