I figured out the why SPL was not loading U-Boot from NAND.

Apparently the logic to use PIO instead of DMA that was introduced in
6ddbb1e936c78cdef1e7395039fa7020c5c75326
<https://github.com/u-boot/u-boot/commit/6ddbb1e936c78cdef1e7395039fa7020c5c75326>
may
be was not as generic as it was supposed to be. I tried adding hexdump in
nand_read_page and found that on CHIP the logic was not reading and real
data. Instead all of the bytes were set to 0s.

I have created a patch to provide an option to use the older version of
nand_read_page function that was present just before the above mentioned
commit.

With the attached patches and some config changes the Upstream U-Boot works
fine on CHIP. I have tested the attached patches on CHIP with 8GB Hynix
nand along with the following extra configurations.

CONFIG_MTD=y
CONFIG_CMD_MTD=y
CONFIG_CMD_MTDPARTS=y
CONFIG_MTDIDS_DEFAULT="nand0=sunxi-nand.0"
CONFIG_MTDPARTS_DEFAULT="mtdparts=sunxi-nand.0:4m(spl),4m(spl-backup),4m(uboot),4m(env),-(yaffs2)"
CONFIG_MTD_RAW_NAND=y
CONFIG_SYS_NAND_BLOCK_SIZE=0x400000
CONFIG_SYS_NAND_PAGE_SIZE=0x4000
CONFIG_SYS_NAND_OOBSIZE=0x680
CONFIG_ENV_IS_IN_NAND=y
CONFIG_ENV_SIZE=0x400000
CONFIG_ENV_OFFSET=0xc00000
CONFIG_FASTBOOT_FLASH_NAND=y
CONFIG_YAFFS2=y

@Andre will it be possible to get the attached patches merged into the
U-Boot?

Thanks & Regards
Gunjan Gupta

On Thu, Mar 18, 2021 at 1:25 AM Gunjan Gupta <viran...@gmail.com> wrote:

> Its not really like uboot is not working. Just spl fails to load it from
> nand. I tried replacing the 2021.01 spl with the original spl of chip's
> firmware(based on uboot 2016.01) and it loaded the 2021.01 u-boot
> correctly.
>
> On Thu, Mar 18, 2021, 1:20 AM Alexandre GRIVEAUX <agrive...@deutnet.info>
> wrote:
>
>> Hello,
>> Le 10/03/2021 à 19:58, Gunjan Gupta a écrit :
>>
>> PFA my dts file. I have added the nfc section there as without that U-Boot
>> was giving a message about nfc being disabled in the dts.
>>
>> Regarding trying the default config, I can't really do that as that doesn't
>> support booting from NAND and I want to be able to boot from NAND. Also I
>> don't think having different MTDPARTS value should create an issue, as I
>> didn't notice that being used in the SPL code. Please feel free to correct
>> me if I am wrong. Even if it was being used, I am flashing U-Boot to the
>> uboot partition and that is the same location that gets populated in
>> the CONFIG_SYS_NAND_U_BOOT_OFFS variable of the .config file.
>>
>>
>>
>>
>>
>> I've tried with a CHIP, same problem, the SPL work main u-boot not.
>>
>> I don't think it's a defconfig limitation, sadly i don't know how this
>> can be corrected.
>>
>>
>> Thanks.
>>
>
From 513117e4b4b96dc6985fc32452c2818e786cdf8f Mon Sep 17 00:00:00 2001
From: Gunjan Gupta <viran...@gmail.com>
Date: Sun, 21 Mar 2021 19:06:53 +0530
Subject: [PATCH 1/2] The generic PIO based nand_read_page function was not
 working on R8 based C.H.I.P. The SPL was failing to read the U-Boot correctly
 from nand. When I used hexdump, I found that all the U-Boot pages that SPL
 read was containing zero. The previous DMA based logic however worked fine.

This commit provides the option of using the legacy nand_read_page
function that was present removed in the following commit:-

https://github.com/u-boot/u-boot/commit/6ddbb1e936c78cdef1e7395039fa7020c5c75326
---
 drivers/mtd/nand/raw/Kconfig          |  5 ++
 drivers/mtd/nand/raw/sunxi_nand_spl.c | 91 +++++++++++++++++++++++++++
 2 files changed, 96 insertions(+)

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index ed151ee0a5..1b985d9465 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -219,6 +219,11 @@ config NAND_SUNXI
 
 if NAND_SUNXI
 
+config NAND_SUNXI_SPL_LEGACY_DMA_READ_PAGE
+	bool "Use legacy DMA based read page logic instead of using PIO"
+	default ARCH_SUNXI
+	depends on MACH_SUN4I || MACH_SUN5I
+
 config NAND_SUNXI_SPL_ECC_STRENGTH
 	int "Allwinner NAND SPL ECC Strength"
 	default 64
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index 85d8013b1a..7df9bae5f2 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -84,6 +84,24 @@
 #define NFC_CMD_RNDOUT             0x05
 #define NFC_CMD_READSTART          0x30
 
+#ifdef CONFIG_NAND_SUNXI_SPL_LEGACY_DMA_READ_PAGE
+#define SUNXI_DMA_CFG_REG0              0x300
+#define SUNXI_DMA_SRC_START_ADDR_REG0   0x304
+#define SUNXI_DMA_DEST_START_ADDRR_REG0 0x308
+#define SUNXI_DMA_DDMA_BC_REG0          0x30C
+#define SUNXI_DMA_DDMA_PARA_REG0        0x318
+
+#define SUNXI_DMA_DDMA_CFG_REG_LOADING  (1 << 31)
+#define SUNXI_DMA_DDMA_CFG_REG_DMA_DEST_DATA_WIDTH_32 (2 << 25)
+#define SUNXI_DMA_DDMA_CFG_REG_DDMA_DST_DRQ_TYPE_DRAM (1 << 16)
+#define SUNXI_DMA_DDMA_CFG_REG_DMA_SRC_DATA_WIDTH_32 (2 << 9)
+#define SUNXI_DMA_DDMA_CFG_REG_DMA_SRC_ADDR_MODE_IO (1 << 5)
+#define SUNXI_DMA_DDMA_CFG_REG_DDMA_SRC_DRQ_TYPE_NFC (3 << 0)
+
+#define SUNXI_DMA_DDMA_PARA_REG_SRC_WAIT_CYC (0x0F << 0)
+#define SUNXI_DMA_DDMA_PARA_REG_SRC_BLK_SIZE (0x7F << 8)
+#endif
+
 struct nfc_config {
 	int page_size;
 	int ecc_strength;
@@ -253,6 +271,78 @@ static int nand_change_column(u16 column)
 
 static const int ecc_bytes[] = {32, 46, 54, 60, 74, 88, 102, 110, 116};
 
+#ifdef CONFIG_NAND_SUNXI_SPL_LEGACY_DMA_READ_PAGE
+static int nand_read_page(const struct nfc_config *conf, u32 offs,
+			  void *dest, int len)
+{
+	dma_addr_t dst = (dma_addr_t)dest;
+	int nsectors = len / conf->ecc_size;
+	u16 rand_seed = 0;
+	u32 val;
+	int page;
+	page = offs / conf->page_size;
+	if (offs % conf->page_size || len % conf->ecc_size ||
+	    len > conf->page_size || len < 0)
+		return -EINVAL;
+	/* clear ecc status */
+	writel(0, SUNXI_NFC_BASE + NFC_ECC_ST);
+	/* Choose correct seed if randomized */
+	if (conf->randomize)
+		rand_seed = random_seed[page % conf->nseeds];
+	writel((rand_seed << 16) | (conf->ecc_strength << 12) |
+		(conf->randomize ? NFC_ECC_RANDOM_EN : 0) |
+		(conf->ecc_size == 512 ? NFC_ECC_BLOCK_SIZE : 0) |
+		NFC_ECC_EN | NFC_ECC_PIPELINE | NFC_ECC_EXCEPTION,
+		SUNXI_NFC_BASE + NFC_ECC_CTL);
+	flush_dcache_range(dst, ALIGN(dst + conf->ecc_size, ARCH_DMA_MINALIGN));
+	/* SUNXI_DMA */
+	writel(0x0, SUNXI_DMA_BASE + SUNXI_DMA_CFG_REG0); /* clr dma cmd */
+	/* read from REG_IO_DATA */
+	writel(SUNXI_NFC_BASE + NFC_IO_DATA,
+	       SUNXI_DMA_BASE + SUNXI_DMA_SRC_START_ADDR_REG0);
+	/* read to RAM */
+	writel(dst, SUNXI_DMA_BASE + SUNXI_DMA_DEST_START_ADDRR_REG0);
+	writel(SUNXI_DMA_DDMA_PARA_REG_SRC_WAIT_CYC |
+	       SUNXI_DMA_DDMA_PARA_REG_SRC_BLK_SIZE,
+	       SUNXI_DMA_BASE + SUNXI_DMA_DDMA_PARA_REG0);
+	writel(len, SUNXI_DMA_BASE + SUNXI_DMA_DDMA_BC_REG0);
+	writel(SUNXI_DMA_DDMA_CFG_REG_LOADING |
+	       SUNXI_DMA_DDMA_CFG_REG_DMA_DEST_DATA_WIDTH_32 |
+	       SUNXI_DMA_DDMA_CFG_REG_DDMA_DST_DRQ_TYPE_DRAM |
+	       SUNXI_DMA_DDMA_CFG_REG_DMA_SRC_DATA_WIDTH_32 |
+	       SUNXI_DMA_DDMA_CFG_REG_DMA_SRC_ADDR_MODE_IO |
+	       SUNXI_DMA_DDMA_CFG_REG_DDMA_SRC_DRQ_TYPE_NFC,
+	       SUNXI_DMA_BASE + SUNXI_DMA_CFG_REG0);
+	writel(nsectors, SUNXI_NFC_BASE + NFC_SECTOR_NUM);
+	writel(NFC_ST_DMA_INT_FLAG, SUNXI_NFC_BASE + NFC_ST);
+	writel(NFC_DATA_TRANS |	NFC_PAGE_CMD | NFC_DATA_SWAP_METHOD,
+	       SUNXI_NFC_BASE + NFC_CMD);
+	if (!check_value(SUNXI_NFC_BASE + NFC_ST, NFC_ST_DMA_INT_FLAG,
+			 DEFAULT_TIMEOUT_US)) {
+		printf("Error while initializing dma interrupt\n");
+		return -EIO;
+	}
+	writel(NFC_ST_DMA_INT_FLAG, SUNXI_NFC_BASE + NFC_ST);
+	if (!check_value_negated(SUNXI_DMA_BASE + SUNXI_DMA_CFG_REG0,
+				 SUNXI_DMA_DDMA_CFG_REG_LOADING,
+				 DEFAULT_TIMEOUT_US)) {
+		printf("Error while waiting for dma transfer to finish\n");
+		return -EIO;
+	}
+	invalidate_dcache_range(dst,
+				ALIGN(dst + conf->ecc_size, ARCH_DMA_MINALIGN));
+	val = readl(SUNXI_NFC_BASE + NFC_ECC_ST);
+	/* ECC error detected. */
+	if (val & 0xffff)
+		return -EIO;
+	/*
+	 * Return 1 if the page is empty.
+	 * We consider the page as empty if the first ECC block is marked
+	 * empty.
+	 */
+	return (val & 0x10000) ? 1 : 0;
+}
+#else
 static int nand_read_page(const struct nfc_config *conf, u32 offs,
 			  void *dest, int len)
 {
@@ -325,6 +415,7 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
 
 	return 0;
 }
+#endif
 
 static int nand_max_ecc_strength(struct nfc_config *conf)
 {
-- 
2.20.1

From 9753a6ce96aa449b90fd78a550661fbe1b5e30b0 Mon Sep 17 00:00:00 2001
From: Gunjan Gupta <viran...@gmail.com>
Date: Sun, 21 Mar 2021 19:51:45 +0530
Subject: [PATCH 2/2] Enable NFC in sun5i-r8-chip.dts

---
 arch/arm/dts/sun5i-r8-chip.dts | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm/dts/sun5i-r8-chip.dts b/arch/arm/dts/sun5i-r8-chip.dts
index 879a4b0f3b..f1cad4cf30 100644
--- a/arch/arm/dts/sun5i-r8-chip.dts
+++ b/arch/arm/dts/sun5i-r8-chip.dts
@@ -175,6 +175,20 @@
 	status = "okay";
 };
 
+&nfc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&nand_pins_a &nand_cs0_pins_a &nand_rb0_pins_a>;
+	status = "okay";
+
+	nand@0 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		reg = <0>;
+		allwinner,rb = <0>;
+		nand-ecc-mode = "hw";
+	};
+};
+
 &ohci0 {
 	status = "okay";
 };
-- 
2.20.1

Reply via email to