All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 2/5][v4] powerpc/mpc85xx: new SPL support for IFC NAND
@ 2013-04-15 10:13 Prabhakar Kushwaha
  0 siblings, 0 replies; only message in thread
From: Prabhakar Kushwaha @ 2013-04-15 10:13 UTC (permalink / raw)
  To: u-boot

Linker script is not able find start.o binary. So add its absolute path in
u-boot-spl.lds. This change is similar to u-boot-nand.lds

common/Makefile: Avoid compiling unnecssary files

fsl_ifc_spl.c : It is is responsible for reading u-boot binary from
NAND flash and copying into DDR. It also transfer cotrol from NAND SPL
to u-boot image present in DDR.

Signed-off-by: Prabhakar Kushwaha <prabhakar@freescale.com>
---
Based upon git://git.denx.de/u-boot.git branch master

 Changes for v2: Sending as it is
 Changes for v3: Fix tools/checkpatch errors
 Changes for v4: Sending as it is

 arch/powerpc/cpu/mpc85xx/u-boot-spl.lds |    2 +-
 board/freescale/common/Makefile         |   10 ++
 drivers/mtd/nand/Makefile               |    1 +
 drivers/mtd/nand/fsl_ifc_spl.c          |  258 +++++++++++++++++++++++++++++++
 4 files changed, 270 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mtd/nand/fsl_ifc_spl.c

diff --git a/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds b/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds
index f2b7bff..cf6fa7c 100644
--- a/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds
+++ b/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds
@@ -60,7 +60,7 @@ SECTIONS
 #if defined(CONFIG_FSL_IFC) /* Restrict bootpg at 4K boundry for IFC */
 	.bootpg ADDR(.text) + 0x1000 :
 	{
-		start.o	(.bootpg)
+		arch/powerpc/cpu/mpc85xx/start.o (.bootpg)
 	}
 #define RESET_VECTOR_OFFSET 0x1ffc /* IFC has 8K sram */
 #elif defined(CONFIG_FSL_ELBC)
diff --git a/board/freescale/common/Makefile b/board/freescale/common/Makefile
index 75725b4..a4d521c 100644
--- a/board/freescale/common/Makefile
+++ b/board/freescale/common/Makefile
@@ -29,6 +29,15 @@ endif
 
 LIB	= $(obj)libfreescale.o
 
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifndef MINIMAL
 COBJS-$(CONFIG_FSL_CADMUS)	+= cadmus.o
 COBJS-$(CONFIG_FSL_VIA)		+= cds_via.o
 COBJS-$(CONFIG_FMAN_ENET)	+= fman.o
@@ -62,6 +71,7 @@ SUBLIB-$(CONFIG_P3041DS)	+= p_corenet/libp_corenet.o
 SUBLIB-$(CONFIG_P4080DS)	+= p_corenet/libp_corenet.o
 SUBLIB-$(CONFIG_P5020DS)	+= p_corenet/libp_corenet.o
 SUBLIB-$(CONFIG_P5040DS)	+= p_corenet/libp_corenet.o
+endif
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS-y))
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index c77c0c4..9d7deb8 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -82,6 +82,7 @@ COBJS-$(CONFIG_NAND_PLAT) += nand_plat.o
 else  # minimal SPL drivers
 
 COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_spl.o
+COBJS-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_spl.o
 
 endif # drivers
 endif # nand
diff --git a/drivers/mtd/nand/fsl_ifc_spl.c b/drivers/mtd/nand/fsl_ifc_spl.c
new file mode 100644
index 0000000..adfe7b1
--- /dev/null
+++ b/drivers/mtd/nand/fsl_ifc_spl.c
@@ -0,0 +1,258 @@
+/*
+ * NAND boot for Freescale Integrated Flash Controller, NAND FCM
+ *
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Author: Dipen Dudhat <dipen.dudhat@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_ifc.h>
+#include <linux/mtd/nand.h>
+
+static inline int is_blank(uchar *addr, int page_size)
+{
+	int i;
+
+	for (i = 0; i < page_size; i++) {
+		if (__raw_readb(&addr[i]) != 0xff)
+			return 0;
+	}
+
+	/*
+	 * For the SPL, don't worry about uncorrectable errors
+	 * where the main area is all FFs but shouldn't be.
+	 */
+	return 1;
+}
+
+/* returns nonzero if entire page is blank */
+static inline int check_read_ecc(uchar *buf, u32 *eccstat,
+				 unsigned int bufnum, int page_size)
+{
+	u32 reg = eccstat[bufnum / 4];
+	int errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
+
+	if (errors == 15) { /* uncorrectable */
+		/* Blank pages fail hw ECC checks */
+		if (is_blank(buf, page_size))
+			return 1;
+
+		puts("ecc error\n");
+		for (;;)
+			;
+	}
+
+	return 0;
+}
+
+static inline void nand_wait(uchar *buf, int bufnum, int page_size)
+{
+	struct fsl_ifc *ifc = IFC_BASE_ADDR;
+	u32 status;
+	u32 eccstat[4];
+	int bufperpage = page_size / 512;
+	int bufnum_end, i;
+
+	bufnum *= bufperpage;
+	bufnum_end = bufnum + bufperpage - 1;
+
+	do {
+		status = in_be32(&ifc->ifc_nand.nand_evter_stat);
+	} while (!(status & IFC_NAND_EVTER_STAT_OPC));
+
+	if (status & IFC_NAND_EVTER_STAT_FTOER) {
+		puts("flash time out error\n");
+		for (;;)
+			;
+	}
+
+	for (i = bufnum / 4; i <= bufnum_end / 4; i++)
+		eccstat[i] = in_be32(&ifc->ifc_nand.nand_eccstat[i]);
+
+	for (i = bufnum; i <= bufnum_end; i++) {
+		if (check_read_ecc(buf, eccstat, i, page_size))
+			break;
+	}
+
+	out_be32(&ifc->ifc_nand.nand_evter_stat, status);
+}
+
+static inline int bad_block(uchar *marker, int port_size)
+{
+	if (port_size == 8)
+		return __raw_readb(marker) != 0xff;
+	else
+		return __raw_readw((u16 *)marker) != 0xffff;
+}
+
+static void nand_load(unsigned int offs, int uboot_size, uchar *dst)
+{
+	struct fsl_ifc *ifc = IFC_BASE_ADDR;
+	uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE;
+	int page_size;
+	int port_size;
+	int pages_per_blk;
+	int blk_size;
+	int bad_marker = 0;
+	int bufnum_mask, bufnum;
+
+	int csor, cspr;
+	int pos = 0;
+	int j = 0;
+
+	int sram_addr;
+	int pg_no;
+
+	/* Get NAND Flash configuration */
+	csor = CONFIG_SYS_NAND_CSOR;
+	cspr = CONFIG_SYS_NAND_CSPR;
+
+	port_size = (cspr & CSPR_PORT_SIZE_16) ? 16 : 8;
+
+	if (csor & CSOR_NAND_PGS_4K) {
+		page_size = 4096;
+		bufnum_mask = 1;
+	} else if (csor & CSOR_NAND_PGS_2K) {
+		page_size = 2048;
+		bufnum_mask = 3;
+	} else {
+		page_size = 512;
+		bufnum_mask = 15;
+
+		if (port_size == 8)
+			bad_marker = 5;
+	}
+
+	pages_per_blk =
+		32 << ((csor & CSOR_NAND_PB_MASK) >> CSOR_NAND_PB_SHIFT);
+
+	blk_size = pages_per_blk * page_size;
+
+	/* Open Full SRAM mapping for spare are access */
+	out_be32(&ifc->ifc_nand.ncfgr, 0x0);
+
+	/* Clear Boot events */
+	out_be32(&ifc->ifc_nand.nand_evter_stat, 0xffffffff);
+
+	/* Program FIR/FCR for Large/Small page */
+	if (page_size > 512) {
+		out_be32(&ifc->ifc_nand.nand_fir0,
+			 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+			 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
+			 (IFC_FIR_OP_BTRD << IFC_NAND_FIR0_OP4_SHIFT));
+		out_be32(&ifc->ifc_nand.nand_fir1, 0x0);
+
+		out_be32(&ifc->ifc_nand.nand_fcr0,
+			 (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
+			 (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
+	} else {
+		out_be32(&ifc->ifc_nand.nand_fir0,
+			 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			 (IFC_FIR_OP_RA0  << IFC_NAND_FIR0_OP2_SHIFT) |
+			 (IFC_FIR_OP_BTRD << IFC_NAND_FIR0_OP3_SHIFT));
+		out_be32(&ifc->ifc_nand.nand_fir1, 0x0);
+
+		out_be32(&ifc->ifc_nand.nand_fcr0,
+			 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
+	}
+
+	/* Program FBCR = 0 for full page read */
+	out_be32(&ifc->ifc_nand.nand_fbcr, 0);
+
+	/* Read and copy u-boot on SDRAM from NAND device, In parallel
+	 * check for Bad block if found skip it and read continue to
+	 * next Block
+	 */
+	while (pos < uboot_size) {
+		int i = 0;
+		do {
+			pg_no = offs / page_size;
+			bufnum = pg_no & bufnum_mask;
+			sram_addr = bufnum * page_size * 2;
+
+			out_be32(&ifc->ifc_nand.row0, pg_no);
+			out_be32(&ifc->ifc_nand.col0, 0);
+			/* start read */
+			out_be32(&ifc->ifc_nand.nandseq_strt,
+				 IFC_NAND_SEQ_STRT_FIR_STRT);
+
+			/* wait for read to complete */
+			nand_wait(&buf[sram_addr], bufnum, page_size);
+
+			/*
+			 * If either of the first two pages are marked bad,
+			 * continue to the next block.
+			 */
+			if (i++ < 2 &&
+			    bad_block(&buf[sram_addr + page_size + bad_marker],
+				      port_size)) {
+				puts("skipping\n");
+				offs = (offs + blk_size) & ~(blk_size - 1);
+				pos &= ~(blk_size - 1);
+				break;
+			}
+
+			for (j = 0; j < page_size; j++)
+				dst[pos + j] = __raw_readb(&buf[sram_addr + j]);
+
+			pos += page_size;
+			offs += page_size;
+		} while ((offs & (blk_size - 1)) && (pos < uboot_size));
+	}
+}
+
+/*
+ * Main entrypoint for NAND Boot. It's necessary that SDRAM is already
+ * configured and available since this code loads the main U-boot image
+ * from NAND into SDRAM and starts from there.
+ */
+void nand_boot(void)
+{
+	__attribute__((noreturn)) void (*uboot)(void);
+	/*
+	 * Load U-Boot image from NAND into RAM
+	 */
+	nand_load(CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
+		  (uchar *)CONFIG_SYS_NAND_U_BOOT_DST);
+
+#ifdef CONFIG_NAND_ENV_DST
+	nand_load(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
+		  (uchar *)CONFIG_NAND_ENV_DST);
+
+#ifdef CONFIG_ENV_OFFSET_REDUND
+	nand_load(CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
+		  (uchar *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
+#endif
+#endif
+	/*
+	 * Jump to U-Boot image
+	 */
+#ifdef CONFIG_SPL_FLUSH_IMAGE
+	/*
+	 * Clean d-cache and invalidate i-cache, to
+	 * make sure that no stale data is executed.
+	 */
+	flush_cache(CONFIG_SYS_NAND_U_BOOT_DST, CONFIG_SYS_NAND_U_BOOT_SIZE);
+#endif
+	uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
+	uboot();
+}
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2013-04-15 10:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-15 10:13 [U-Boot] [PATCH 2/5][v4] powerpc/mpc85xx: new SPL support for IFC NAND Prabhakar Kushwaha

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.