Skip to contentSkip to conversation

sunxi: nand: Basic NAND driver with SPL support

PATCH Superseded Piotr Zierhoffer 4 participants 24 messages Jul 16, 2015 – Jul 22, 2015

Subsystems (4)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

cover sunxi: nand: Basic NAND driver with SPL support

This is a basic driver for the sunxi NAND controller for Allwinner A20. It supports both SPL and U-Boot.

The driver uses DMA for data transfers. It does not support writing.

To enable user reading from NADN, the a20_nandread command was added.

Piotr Zierhoffer (4):
sunxi: nand: Add basic sunxi NAND driver with DMA support
sunxi: nand: Add board configuration options
sunxi: nand: Add a20_nandread command to load image from NAND in SPL
sunxi: nand: Add information to sunxi that it was run from NAND in SPL

 arch/arm/cpu/armv7/sunxi/board.c |   4 +
 board/sunxi/Kconfig              |  10 ++
 board/sunxi/Makefile             |   1 +
 board/sunxi/nand.c               | 315 +++++++++++++++++++++++++++++++++++++++
 board/sunxi/nand.h               | 146 ++++++++++++++++++
 common/Makefile                  |   1 +
 common/cmd_a20_nandread.c        |  25 ++++
 include/configs/sunxi-common.h   |  13 ++
 8 files changed, 515 insertions(+)
 create mode 100644 board/sunxi/nand.c
 create mode 100644 board/sunxi/nand.h
 create mode 100644 common/cmd_a20_nandread.c
Signature · 1 line
2.3.6
#1 lore raw

PATCH 1/4 sunxi: nand: Add basic sunxi NAND driver with DMA support

From: Piotr Zierhoffer <[email protected]>

This driver adds NAND support to both SPL and full U-Boot. It was tested on AllWinner A20.

---

 board/sunxi/Makefile |   1 +
 board/sunxi/nand.c   | 315 +++++++++++++++++++++++++++++++++++++++++++++++++++
 board/sunxi/nand.h   | 146 ++++++++++++++++++++++++
 3 files changed, 462 insertions(+)
 create mode 100644 board/sunxi/nand.c
 create mode 100644 board/sunxi/nand.h
board/sunxi/Makefile +1 -0
index 43766e0..6f1d571 100644
@@ -9,6 +9,7 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 obj-y	+= board.o
+obj-$(CONFIG_SUNXI_NAND)	+= nand.o
 obj-$(CONFIG_SUNXI_GMAC)	+= gmac.o
 obj-$(CONFIG_SUNXI_AHCI)	+= ahci.o
 obj-$(CONFIG_MACH_SUN4I)	+= dram_sun4i_auto.o
board/sunxi/nand.c new file +315 -0

315 lines not on this page · raw message

board/sunxi/nand.h new file +146 -0

146 lines not on this page · raw message

Signature · 1 line
2.3.6
#2 lore raw

PATCH 1/4 sunxi: nand: Add basic sunxi NAND driver with DMA support

Quoted 4 lines · Piotr Zierhoffer

From: Piotr Zierhoffer <[email protected]>

This driver adds NAND support to both SPL and full U-Boot. It was tested on AllWinner A20.

It looks a lot like an SPL-only driver to me...

Quoted 7 lines

---

Quoted 7 lines
 board/sunxi/Makefile |   1 +
 board/sunxi/nand.c   | 315 
+++++++++++++++++++++++++++++++++++++++++++++++++++
 board/sunxi/nand.h   | 146 ++++++++++++++++++++++++
 3 files changed, 462 insertions(+)
 create mode 100644 board/sunxi/nand.c
 create mode 100644 board/sunxi/nand.h

Please keep NAND drivers in drivers/mtd/nand/.

Quoted 32 lines
board/sunxi/Makefile +1 -0
index 43766e0..6f1d571 100644
@@ -9,6 +9,7 @@
 # SPDX-License-Identifier:   GPL-2.0+
 #
 obj-y        += board.o
+obj-$(CONFIG_SUNXI_NAND)     += nand.o
 obj-$(CONFIG_SUNXI_GMAC)     += gmac.o
 obj-$(CONFIG_SUNXI_AHCI)     += ahci.o
 obj-$(CONFIG_MACH_SUN4I)     += dram_sun4i_auto.o
board/sunxi/nand.c new file +13 -0
new file mode 100644
index 0000000..16e8e4d
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2014-2015, Antmicro Ltd <www.antmicro.com>
+ * Copyright (c) 2015, AW-SOM Technologies <www.aw-som.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <nand.h>
+#include "nand.h" /* sunxi specific header */
+

board/sunxi/nand.c line 23

Quoted 10 lines
board/sunxi/nand.c new file +10 -0
+/* minimal "boot0" style NAND support for Allwinner A20 */
+
+/* temporary buffer in internal ram */
+#ifdef CONFIG_SPL_BUILD
+/* in SPL temporary buffer cannot be @ 0x0 */
+unsigned char temp_buf[SPL_WRITE_SIZE] __aligned(0x10) __section(".text#");
+#else
+/* put temporary buffer @ 0x0 */
+unsigned char *temp_buf = (unsigned char *)0x0;
+#endif

If 0x0 is the address of an SRAM, its address should be symbolically defined.
Also consider mapping it to a different virtual address, to avoid potential
compiler mischief.

Quoted 23 lines
board/sunxi/nand.c new file +23 -0
+#define MAX_RETRIES 10
+
+static int check_value_inner(int offset, int expected_bits,
+                             int max_number_of_retries, int negation)
+{
+     int retries = 0;
+     do {
+             int val = readl(offset) & expected_bits;
+             if (negation ? !val : val)
+                     return 1;
+             mdelay(1);
+             retries++;
+     } while (retries < max_number_of_retries);
+
+     return 0;
+}
+
+static inline int check_value(int offset, int expected_bits,
+                             int max_number_of_retries)
+{
+     return check_value_inner(offset, expected_bits,
+                                     max_number_of_retries, 0);
+}

board/sunxi/nand.c line 57

Quoted 10 lines
board/sunxi/nand.c new file +10 -0
+
+static inline int check_value_negated(int offset, int unexpected_bits,
+                                     int max_number_of_retries)
+{
+     return check_value_inner(offset, unexpected_bits,
+                                     max_number_of_retries, 1);
+}
+
+void nand_set_clocks(void)
+{

Here and elsewhere, please either use static or less generic name.

+int nand_initialized;

static bool nand_initialized;

Or better yet, get rid of this and stop using init-on-first-use.

board/sunxi/nand.c line 102

Quoted 5 lines
board/sunxi/nand.c new file +5 -0
+
+void nand_init(void)
+{
+     board_nand_init(NULL);
+}

nand_init() is defined in drivers/mtd/nand/nand.c, which is only optional for SPL -- and I don't see an SPL ifdef here.

board/sunxi/nand.c line 104

Quoted 1 line
board/sunxi/nand.c new file +1 -0
+uint32_t ecc_errors;

static

board/sunxi/nand.c line 107

Quoted 3 lines
board/sunxi/nand.c new file +3 -0
+
+/* read 0x400 bytes from real_addr to temp_buf */
+void nand_read_block(unsigned int real_addr, int syndrome)

I don't know of any NAND chips whose erase blocks are as small as 0x400 bytes. The read/program unit is called a page, not a block.

Is there a reason to hardcode the page size here? Especially since the comment doesn't appear to match the code, which uses SPL_WRITE_SIZE.

board/sunxi/nand.c line 110

Quoted 3 lines
board/sunxi/nand.c new file +3 -0
+{
+     uint32_t val;
+     int ECC_OFF = 0;

Why is this capitalized?

board/sunxi/nand.c line 118

Quoted 8 lines
board/sunxi/nand.c new file +8 -0
+     uint16_t ecc_mode = 0;
+     uint16_t rand_seed;
+     uint32_t page;
+     uint16_t column;
+     uint32_t oob_offset;
+
+     if (!nand_initialized)
+             board_nand_init(NULL);

board_nand_init() is called from nand_init(). Why are you calling it here?

board/sunxi/nand.c line 120

Quoted 1 line
board/sunxi/nand.c new file +1 -0
+     switch (CONFIG_SUNXI_ECC_STRENGTH) {

No documentation for this symbol.

If it's an attribute of the hardware rather than something the user selects, it should be CONFIG_SYS_SUNXI_ECC_STRENGTH, or just SUNXI_ECC_STRENGTH if it doesn't need to integrate with kconfig or makefiles.

board/sunxi/nand.c line 169

Quoted 2 lines
board/sunxi/nand.c new file +2 -0
+     /* clear temp_buf */
+     memset((void *)temp_buf, 0, SPL_WRITE_SIZE);

Unnecessary cast.

board/sunxi/nand.c line 181

Quoted 12 lines
board/sunxi/nand.c new file +12 -0
+
+     /* set CMD  */
+     writel(NFC_SEND_CMD1 | NFC_WAIT_FLAG | 0xff,
+            NANDFLASHC_BASE + NANDFLASHC_CMD);
+
+     if (!check_value(NANDFLASHC_BASE + NANDFLASHC_ST, (1 << 1),
+                      MAX_RETRIES)) {
+             printf("Error while initilizing command interrupt\n");
+             return;
+     }
+
+     page = (real_addr / BLOCK_SIZE);

Unnecessary parens (and inconsistent with the following line).

Quoted 39 lines
board/sunxi/nand.c new file +39 -0
+     column = real_addr % BLOCK_SIZE;
+
+     if (syndrome) {
+             /* shift every 1kB in syndrome */
+             column += (column / SPL_WRITE_SIZE) * ECC_OFF;
+     }
+
+     /* clear ecc status */
+     writel(0, NANDFLASHC_BASE + NANDFLASHC_ECC_ST);
+
+     /* Choose correct seed */
+     if (syndrome)
+             rand_seed = random_seed_syndrome;
+     else
+             rand_seed = random_seed[page % 128];
+
+     writel((rand_seed << 16) | NFC_ECC_RANDOM_EN | NFC_ECC_EN
+             | NFC_ECC_PIPELINE | (ecc_mode << 12),
+             NANDFLASHC_BASE + NANDFLASHC_ECC_CTL);
+
+     val = readl(NANDFLASHC_BASE + NANDFLASHC_CTL);
+     writel(val | NFC_CTL_RAM_METHOD, NANDFLASHC_BASE + NANDFLASHC_CTL);
+
+     if (syndrome) {
+             writel(SPL_WRITE_SIZE, NANDFLASHC_BASE + NANDFLASHC_SPARE_AREA);
+     } else {
+             oob_offset = BLOCK_SIZE + (column / SPL_WRITE_SIZE) * ECC_OFF;
+             writel(oob_offset, NANDFLASHC_BASE + NANDFLASHC_SPARE_AREA);
+     }
+
+     /* DMAC */
+     writel(0x0, DMAC_BASE + DMAC_CFG_REG0); /* clr dma cmd */
+     /* read from REG_IO_DATA */
+     writel(NANDFLASHC_BASE + NANDFLASHC_IO_DATA,
+            DMAC_BASE + DMAC_SRC_START_ADDR_REG0);
+     writel((uint32_t)temp_buf,
+            DMAC_BASE + DMAC_DEST_START_ADDRR_REG0); /* read to RAM */
+     writel(DMAC_DDMA_PARA_REG_SRC_WAIT_CYC
+                     | DMAC_DDMA_PARA_REG_SRC_BLK_SIZE,

board/sunxi/nand.c line 230

Quoted 10 lines
board/sunxi/nand.c new file +10 -0
+                     DMAC_BASE + DMAC_DDMA_PARA_REG0);
+     writel(SPL_WRITE_SIZE, DMAC_BASE + DMAC_DDMA_BC_REG0); /* 1kB */
+     writel(DMAC_DDMA_CFG_REG_LOADING
+             | DMAC_DDMA_CFG_REG_DMA_DEST_DATA_WIDTH_32
+             | DMAC_DDMA_CFG_REG_DMA_SRC_DATA_WIDTH_32
+             | DMAC_DDMA_CFG_REG_DMA_SRC_ADDR_MODE_IO
+             | DMAC_DDMA_CFG_REG_DDMA_SRC_DRQ_TYPE_NFC,
+             DMAC_BASE + DMAC_CFG_REG0);
+
+     writel(0x00E00530, NANDFLASHC_BASE + NANDFLASHC_RCMD_SET); /* READ */

What is 0x00e00530? Define it symbolically.

board/sunxi/nand.c line 236

Quoted 6 lines
board/sunxi/nand.c new file +6 -0
+     writel(1, NANDFLASHC_BASE + NANDFLASHC_SECTOR_NUM);
+     writel(((page & 0xFFFF) << 16) | column,
+            NANDFLASHC_BASE + NANDFLASHC_ADDR_LOW);
+     writel((page >> 16) & 0xFF, NANDFLASHC_BASE + NANDFLASHC_ADDR_HIGH);
+     writel(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_DATA_TRANS |
+             NFC_PAGE_CMD | NFC_WAIT_FLAG | /* ADDR_CYCLE */ (4 << 16) |

Why is ADDR_CYCLE commented out, and a magic number used in its place?

board/sunxi/nand.c line 256

Quoted 1 line
board/sunxi/nand.c new file +1 -0
+int helper_load(uint32_t offs, unsigned int size, void *dest)

This name is not clear (in addition to being way too vague for a global symbol).

board/sunxi/nand.c line 258

Quoted 2 lines
board/sunxi/nand.c new file +2 -0
+{
+     uint32_t dst;

Don't have both "dest" and "dst". It's confusing.

board/sunxi/nand.c line 260

Quoted 2 lines
board/sunxi/nand.c new file +2 -0
+     uint32_t count;
+     uint32_t count_c;

What does the "_c" mean?

board/sunxi/nand.c line 261

Quoted 1 line
board/sunxi/nand.c new file +1 -0
+     uint32_t adr = offs;

So address is actually a NAND offset, not a memory address? Confusing.

Don't put addresses in uint32_t (even if it doesn't make a difference on this platform, it's a bad habit and a bad example to others). Use a pointer for virtual addresses, and phys_addr_t for physical addresses.

board/sunxi/nand.c line 154

Quoted 2 lines
board/sunxi/nand.c new file +2 -0
+
+     memset((void *)dest, 0x0, size); /* clean destination memory */

Unnecessary cast.

board/sunxi/nand.c line 269

Quoted 6 lines
board/sunxi/nand.c new file +6 -0
+     ecc_errors = 0;
+     for (dst = (uint32_t)dest;
+                     dst < ((uint32_t)dest + size);
+                     dst += SPL_WRITE_SIZE) {
+             /* if < 0x400000 then syndrome read */
+             nand_read_block(adr, adr < 0x400000);

What does 0x400000 represent?

board/sunxi/nand.c line 313

Quoted 5 lines
board/sunxi/nand.c new file +5 -0
+int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest)
+{
+     helper_load(offs, size, dest);
+     return 0;
+}

Why didn't you just call helper_load() nand_spl_load_image()?

board/sunxi/nand.h line 3

Quoted 11 lines
board/sunxi/nand.c new file +2 -0
+
+void nand_deselect(void) {}
board/sunxi/nand.h new file +3 -0
new file mode 100644
index 0000000..b3c1e93
@@ -0,0 +1,146 @@
+#ifndef NAND_H
+
+#define NAND_H

Don't use such a generic ifdef protector in a non-generic file. It's just chance that include/nand.h is using _NAND_H_ instead of NAND_H...

-Scott

#3 lore raw

PATCH 1/4 sunxi: nand: Add basic sunxi NAND driver with DMA support

On Thursday, July 16, 2015 at 11:15:58 PM, Scott Wood wrote:

[...]

Quoted 4 lines
Quoted 4 lines
board/sunxi/nand.c new file +4 -0
+/* temporary buffer in internal ram */
+#ifdef CONFIG_SPL_BUILD
+/* in SPL temporary buffer cannot be @ 0x0 */
+unsigned char temp_buf[SPL_WRITE_SIZE] __aligned(0x10)
Quoted 8 lines

board/sunxi/nand.c line 23

Quoted 4 lines

__section(".text#"); +#else

board/sunxi/nand.c new file +3 -0
+/* put temporary buffer @ 0x0 */
+unsigned char *temp_buf = (unsigned char *)0x0;
+#endif

If 0x0 is the address of an SRAM, its address should be symbolically defined. Also consider mapping it to a different virtual address, to avoid potential compiler mischief.

The DMA I believe accesses it via PA anyway, so mapping it elsewhere would only confuse everyone who's hacking on the driver. Just my 5 cents ;-)

[...]

Best regards,
Marek Vasut

#4 lore raw

PATCH 1/4 sunxi: nand: Add basic sunxi NAND driver with DMA support

Quoted 17 lines · Marek Vasut

On Thursday, July 16, 2015 at 11:15:58 PM, Scott Wood wrote:

[...]

Quoted 4 lines
Quoted 4 lines
board/sunxi/nand.c new file +4 -0
+/* temporary buffer in internal ram */
+#ifdef CONFIG_SPL_BUILD
+/* in SPL temporary buffer cannot be @ 0x0 */
+unsigned char temp_buf[SPL_WRITE_SIZE] __aligned(0x10)
Quoted 8 lines

board/sunxi/nand.c line 23

Quoted 4 lines

__section(".text#"); +#else

board/sunxi/nand.c new file +3 -0
+/* put temporary buffer @ 0x0 */
+unsigned char *temp_buf = (unsigned char *)0x0;
+#endif

If 0x0 is the address of an SRAM, its address should be symbolically defined. Also consider mapping it to a different virtual address, to avoid potential compiler mischief.

Quoted 2 lines

The DMA I believe accesses it via PA anyway, so mapping it elsewhere would only confuse everyone who's hacking on the driver. Just my 5 cents ;-)

Hey, if it wakes people up to the fact that they ought to be using virt_to_phys() (or better yet, something that distinguishes DMA addresses from physical), great! :-)

And yes, people go on to do the same "everything is u32" crap in non-platform- specific files. Just look at drivers/block/ahci.c.

-Scott

#5 lore raw

PATCH 1/4 sunxi: nand: Add basic sunxi NAND driver with DMA support

Quoted 18 lines · Scott Wood
Quoted 17 lines · Marek Vasut

On Thursday, July 16, 2015 at 11:15:58 PM, Scott Wood wrote:

[...]

Quoted 12 lines

board/sunxi/nand.c line 23

Quoted 8 lines
board/sunxi/nand.c new file +4 -0
+/* temporary buffer in internal ram */
+#ifdef CONFIG_SPL_BUILD
+/* in SPL temporary buffer cannot be @ 0x0 */
+unsigned char temp_buf[SPL_WRITE_SIZE] __aligned(0x10)

__section(".text#"); +#else

board/sunxi/nand.c new file +3 -0
+/* put temporary buffer @ 0x0 */
+unsigned char *temp_buf = (unsigned char *)0x0;
+#endif

If 0x0 is the address of an SRAM, its address should be symbolically defined. Also consider mapping it to a different virtual address, to avoid potential compiler mischief.

Quoted 7 lines
Quoted 3 lines

The DMA I believe accesses it via PA anyway, so mapping it elsewhere would only confuse everyone who's hacking on the driver. Just my 5 cents ;-)

Hey, if it wakes people up to the fact that they ought to be using virt_to_phys() (or better yet, something that distinguishes DMA addresses from physical), great! :-)

Not really useful here, but whatever.

Quoted 2 lines

And yes, people go on to do the same "everything is u32" crap in non-platform- specific files. Just look at drivers/block/ahci.c.

Errr, this file is platform specific.

Best regards,
Marek Vasut

#6 lore raw

PATCH 1/4 sunxi: nand: Add basic sunxi NAND driver with DMA support

Quoted 27 lines · Marek Vasut
Quoted 18 lines · Scott Wood
Quoted 17 lines · Marek Vasut

On Thursday, July 16, 2015 at 11:15:58 PM, Scott Wood wrote:

[...]

Quoted 12 lines

board/sunxi/nand.c line 23

Quoted 8 lines
board/sunxi/nand.c new file +4 -0
+/* temporary buffer in internal ram */
+#ifdef CONFIG_SPL_BUILD
+/* in SPL temporary buffer cannot be @ 0x0 */
+unsigned char temp_buf[SPL_WRITE_SIZE] __aligned(0x10)

__section(".text#"); +#else

board/sunxi/nand.c new file +3 -0
+/* put temporary buffer @ 0x0 */
+unsigned char *temp_buf = (unsigned char *)0x0;
+#endif

If 0x0 is the address of an SRAM, its address should be symbolically defined. Also consider mapping it to a different virtual address, to avoid potential compiler mischief.

Quoted 7 lines
Quoted 3 lines

The DMA I believe accesses it via PA anyway, so mapping it elsewhere would only confuse everyone who's hacking on the driver. Just my 5 cents ;-)

Hey, if it wakes people up to the fact that they ought to be using virt_to_phys() (or better yet, something that distinguishes DMA addresses from physical), great! :-)

Quoted 6 lines

Not really useful here, but whatever.

Quoted 2 lines

And yes, people go on to do the same "everything is u32" crap in non-platform- specific files. Just look at drivers/block/ahci.c.

Errr, this file is platform specific.

(I'm assuming that by "this file" you mean the sunxi file, not the ahci file.)

The point is that establishing good habits everywhere reduces the likelihood of the bad habits migrating to places where things break.

And no, I don't seriously expect my suggestion of remapping the virtual address to be implemented, but GCC has been known to do all sorts of weird stuff when it thinks it knows a NULL pointer is being dereferenced.

-Scott

#7 lore raw

PATCH 1/4 sunxi: nand: Add basic sunxi NAND driver with DMA support

Quoted 38 lines · Scott Wood
Quoted 27 lines · Marek Vasut
Quoted 18 lines · Scott Wood
Quoted 17 lines · Marek Vasut

On Thursday, July 16, 2015 at 11:15:58 PM, Scott Wood wrote:

[...]

Quoted 12 lines

board/sunxi/nand.c line 23

Quoted 8 lines
board/sunxi/nand.c new file +4 -0
+/* temporary buffer in internal ram */
+#ifdef CONFIG_SPL_BUILD
+/* in SPL temporary buffer cannot be @ 0x0 */
+unsigned char temp_buf[SPL_WRITE_SIZE] __aligned(0x10)

__section(".text#"); +#else

board/sunxi/nand.c new file +3 -0
+/* put temporary buffer @ 0x0 */
+unsigned char *temp_buf = (unsigned char *)0x0;
+#endif

If 0x0 is the address of an SRAM, its address should be symbolically defined. Also consider mapping it to a different virtual address, to avoid potential compiler mischief.

Quoted 7 lines
Quoted 3 lines

The DMA I believe accesses it via PA anyway, so mapping it elsewhere would only confuse everyone who's hacking on the driver. Just my 5 cents ;-)

Hey, if it wakes people up to the fact that they ought to be using virt_to_phys() (or better yet, something that distinguishes DMA addresses from physical), great! :-)

Quoted 6 lines

Not really useful here, but whatever.

Quoted 2 lines

And yes, people go on to do the same "everything is u32" crap in non-platform- specific files. Just look at drivers/block/ahci.c.

Errr, this file is platform specific.

(I'm assuming that by "this file" you mean the sunxi file, not the ahci file.)

Quoted 6 lines

The point is that establishing good habits everywhere reduces the likelihood of the bad habits migrating to places where things break.

And no, I don't seriously expect my suggestion of remapping the virtual address to be implemented, but GCC has been known to do all sorts of weird stuff when it thinks it knows a NULL pointer is being dereferenced.

OK, you have a point there.

Best regards,
Marek Vasut

#8 lore raw

PATCH 1/4 sunxi: nand: Add basic sunxi NAND driver with DMA support

In reply to Scott Wood

2015-07-16 23:15 GMT+02:00 Scott Wood <[email protected]>:

Quoted 8 lines · Piotr Zierhoffer
Quoted 4 lines

From: Piotr Zierhoffer <[email protected]>

This driver adds NAND support to both SPL and full U-Boot. It was tested on AllWinner A20.

It looks a lot like an SPL-only driver to me...

I am preparing a v2 patch set, that will have SPL-only code.

Quoted 4 lines
Quoted 1 line

+ writel(0x00E00530, NANDFLASHC_BASE + NANDFLASHC_RCMD_SET); /* READ */

What is 0x00e00530? Define it symbolically.

It's difficult because we do not have much explanation for this constant. This is how BROM operates.
We have tuned it according to http://linux-sunxi.org/NFC_Register_Guide

We have fixed the code according to your comments and will resubmit it shortly.

Best regards

Piotr Zierhoffer
Antmicro Ltd | www.antmicro.com

#9 lore raw

PATCH 2/4 sunxi: nand: Add board configuration options

In reply to Piotr Zierhoffer

From: Piotr Zierhoffer <[email protected]>

When SUNXI_NAND option is selected in config, set some configuration options for sunxi NAND.

This commit also introduces the configurable options in Kconfig.

---

 board/sunxi/Kconfig            | 10 ++++++++++
 include/configs/sunxi-common.h | 11 +++++++++++
 2 files changed, 21 insertions(+)
board/sunxi/Kconfig +10 -0
index 2a1cd3c..3b76d64 100644
@@ -227,6 +227,16 @@ config OLD_SUNXI_KERNEL_COMPAT
 	Set this to enable various workarounds for old kernels, this results in
 	sub-optimal settings for newer kernels, only enable if needed.
 
+config SUNXI_NAND
+	bool "Support for NAND on Allwinner A20"
+	depends on MACH_SUN7I
+	---help---
+	Enable support for internal NAND. This option allows U-Boot to read from
+	sunxi NAND using DMA transfers. It also adds the a20_nandread command
+	that allows user to transfer a specified amount of data from NAND to
+	memory. Both SPL and full U-Boot driver are enabled. Writing is not
+	supported.
+
 config MMC0_CD_PIN
 	string "Card detect pin for mmc0"
 	default ""
include/configs/sunxi-common.h +11 -0
index 9576bc1..83922ab 100644
@@ -139,6 +139,17 @@
 #define CONFIG_INITRD_TAG
 #define CONFIG_SERIAL_TAG
 
+#if defined(CONFIG_SUNXI_NAND)
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_CMD_SPL_WRITE_SIZE 0x000400 /* 1024 byte */
+
+#define CONFIG_SYS_NAND_SPL_KERNEL_OFFS 0x280000
+#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x008000
+#define CONFIG_SYS_NAND_PAGE_SIZE 0x002000 /* 8kb*/
+#define CONFIG_SUNXI_ECC_STRENGTH 40
+#endif
+
 /* mmc config */
 #if !defined(CONFIG_UART0_PORT_F)
 #define CONFIG_MMC
Signature · 1 line
2.3.6
#10 lore raw

PATCH 3/4 sunxi: nand: Add a20_nandread command to load image from NAND in SPL

In reply to Piotr Zierhoffer

From: Piotr Zierhoffer <[email protected]>

The usage of the command is:

a20_nandread <address> <offset> <bytes>

It allows user to copy data from NAND to memory. It employs nand_spl_load_image from the sunxi NAND driver.

It is added only when the NAND support is enabled.

---

 common/Makefile                |  1 +
 common/cmd_a20_nandread.c      | 25 +++++++++++++++++++++++++
 include/configs/sunxi-common.h |  2 ++
 3 files changed, 28 insertions(+)
 create mode 100644 common/cmd_a20_nandread.c
common/Makefile +1 -0
index d6c1d48..ef31646 100644
@@ -126,6 +126,7 @@ obj-$(CONFIG_ID_EEPROM) += cmd_mac.o
 obj-$(CONFIG_CMD_MD5SUM) += cmd_md5sum.o
 obj-$(CONFIG_CMD_MEMORY) += cmd_mem.o
 obj-$(CONFIG_CMD_IO) += cmd_io.o
+obj-$(CONFIG_CMD_A20_NANDREAD) += cmd_a20_nandread.o
 obj-$(CONFIG_CMD_MFSL) += cmd_mfsl.o
 obj-$(CONFIG_MII) += miiphyutil.o
 obj-$(CONFIG_CMD_MII) += miiphyutil.o
common/cmd_a20_nandread.c new file +25 -0
new file mode 100644
index 0000000..6469535
@@ -0,0 +1,25 @@
+#include <common.h>
+#include <command.h>
+#include <nand.h>
+
+static int do_a20_nandread(cmd_tbl_t *cmdtp, int flag, int argc,
+		char * const argv[])
+{
+	if (argc != 4) {
+		printf("usage: a20_nandread <destination> <source> <size>\n");
+		return 1;
+	}
+
+	uint32_t dst = simple_strtoul(argv[1], NULL, 16);
+	uint32_t src = simple_strtoul(argv[2], NULL, 16);
+	uint32_t cnt = simple_strtoul(argv[3], NULL, 16);
+	printf("Reading 0x%08X bytes from NAND @ 0x%08X to MEM @ 0x%08X...\n",
+	       cnt, src, dst);
+	nand_spl_load_image(src, cnt, (void *)dst);
+	printf("\n");
+	return 0;
+}
+
+U_BOOT_CMD(a20_nandread, CONFIG_SYS_MAXARGS, 3,
+	   do_a20_nandread, "a20_nandread", "[destination source size]\n" "   "
+);
include/configs/sunxi-common.h +2 -0
index 83922ab..e9cfa9a 100644
@@ -148,6 +148,8 @@
 #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x008000
 #define CONFIG_SYS_NAND_PAGE_SIZE 0x002000 /* 8kb*/
 #define CONFIG_SUNXI_ECC_STRENGTH 40
+
+#define CONFIG_CMD_A20_NANDREAD
 #endif
 
 /* mmc config */
Signature · 1 line
2.3.6
#11 lore raw

PATCH 3/4 sunxi: nand: Add a20_nandread command to load image from NAND in SPL

Quoted 10 lines · Piotr Zierhoffer

From: Piotr Zierhoffer <[email protected]>

The usage of the command is:

a20_nandread <address> <offset> <bytes>

It allows user to copy data from NAND to memory. It employs nand_spl_load_image from the sunxi NAND driver.

It is added only when the NAND support is enabled.

Please respond to the comments received when it was posted at
http://patchwork.ozlabs.org/patch/466149/

Quoted 4 lines

Why does the same code now have a completely different author and sign-off chain?

-Scott

#12 lore raw

PATCH 3/4 sunxi: nand: Add a20_nandread command to load image from NAND in SPL

Hello

2015-07-16 23:20 GMT+02:00 Scott Wood <[email protected]>:

Quoted 10 lines · Piotr Zierhoffer
Quoted 4 lines

Why does the same code now have a completely different author and sign-off chain?

-Scott

This code had a wrong copyright/Signed-off-by chain, and was reverted in da9971d1b3bdb554d4a4ac948119f8b2616bbcce.

I am going to resubmit a v2 patch set without this command.

Best regards

Piotr Zierhoffer
Antmicro Ltd | www.antmicro.com

#13 lore raw

PATCH 4/4 sunxi: nand: Add information to sunxi that it was run from NAND in SPL

In reply to Piotr Zierhoffer

As SPL does not know which source to choose when booting U-Boot, choose NAND if it is capable of doing so.

---

 arch/arm/cpu/armv7/sunxi/board.c | 4 ++++
 1 file changed, 4 insertions(+)
arch/arm/cpu/armv7/sunxi/board.c +4 -0
index 5f39aa0..e4b7d63 100644
@@ -128,6 +128,9 @@ void s_init(void)
  */
 u32 spl_boot_device(void)
 {
+#ifdef CONFIG_SPL_NAND_SUPPORT
+	return BOOT_DEVICE_NAND;
+#else
 	/*
 	 * When booting from the SD card, the "eGON.BT0" signature is expected
 	 * to be found in memory at the address 0x0004 (see the "mksunxiboot"
@@ -148,6 +151,7 @@ u32 spl_boot_device(void)
 		return BOOT_DEVICE_MMC1;
 	else
 		return BOOT_DEVICE_BOARD;
+#endif
 }
 
 /* No confirmation data available in SPL yet. Hardcode bootmode */
Signature · 1 line
2.3.6
#14 lore raw

v2 cover sunxi: nand: Basic NAND driver for SPL

In reply to Piotr Zierhoffer

This is a basic driver for the sunxi NAND controller for Allwinner A20. It supports only SPL.

The driver uses DMA for data transfers. It does not support writing.

Changes in v2:
- removed traces of non-SPL-specific code
- moved the driver from boards/sunxi to drivers/mtd/nand
- moved magic values to defines (whenever possible)
- removed unnecesary late initialisation code
- code style changes as suggested for the first patch set:
- changed visibility of some symbols
- renamed unclear variables
- renamed header protector
- changed types of pointer variables
- other minor changes
- renamed defines to be more relevant
- moved Kconfig entry for the driver to drivers/mtd/nand
- reworded Kconfig entry help

Piotr Zierhoffer (3):
sunxi: nand: Add basic sunxi NAND driver for SPL with DMA support
sunxi: nand: Add board configuration options
sunxi: nand: Add information to sunxi that it was run from NAND in SPL

 arch/arm/cpu/armv7/sunxi/board.c |   4 +
 drivers/mtd/nand/Kconfig         |   7 +
 drivers/mtd/nand/Makefile        |   1 +
 drivers/mtd/nand/sunxi_nand.c    | 289 +++++++++++++++++++++++++++++++++++++++
 drivers/mtd/nand/sunxi_nand.h    | 151 ++++++++++++++++++++
 include/configs/sunxi-common.h   |  11 ++
 6 files changed, 463 insertions(+)
 create mode 100644 drivers/mtd/nand/sunxi_nand.c
 create mode 100644 drivers/mtd/nand/sunxi_nand.h
Signature · 1 line
2.3.6
#15 lore raw

PATCH v2 1/3 sunxi: nand: Add basic sunxi NAND driver for SPL with DMA support

From: Piotr Zierhoffer <[email protected]>

This driver adds NAND support to SPL.
It was tested on AllWinner A20.

---

Changes in v2:
- removed traces of non-SPL-specific code
- moved the driver from boards/sunxi to drivers/mtd/nand
- moved magic values to defines (whenever possible)
- removed unnecesary late initialisation code
- code style changes as suggested for the first patch set:
- changed visibility of some symbols
- renamed unclear variables
- renamed header protector
- changed types of pointer variables
- other minor changes

 drivers/mtd/nand/Makefile     |   1 +
 drivers/mtd/nand/sunxi_nand.c | 289 ++++++++++++++++++++++++++++++++++++++++++
 drivers/mtd/nand/sunxi_nand.h | 151 ++++++++++++++++++++++
 3 files changed, 441 insertions(+)
 create mode 100644 drivers/mtd/nand/sunxi_nand.c
 create mode 100644 drivers/mtd/nand/sunxi_nand.h
drivers/mtd/nand/Makefile +1 -0
index 347ea62..4cf9cee 100644
@@ -12,6 +12,7 @@ NORMAL_DRIVERS=y
 endif
 
 obj-$(CONFIG_SPL_NAND_AM33XX_BCH) += am335x_spl_bch.o
+obj-$(CONFIG_SPL_NAND_SUNXI) += sunxi_nand.o
 obj-$(CONFIG_SPL_NAND_DENALI) += denali_spl.o
 obj-$(CONFIG_SPL_NAND_DOCG4) += docg4_spl.o
 obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
drivers/mtd/nand/sunxi_nand.c new file +289 -0

289 lines not on this page · raw message

drivers/mtd/nand/sunxi_nand.h new file +151 -0

151 lines not on this page · raw message

Signature · 1 line
2.3.6
#16 lore raw

PATCH v2 1/3 sunxi: nand: Add basic sunxi NAND driver for SPL with DMA support

Hi Piotr,

Here is a quick review.

Quoted 90 lines · On Mon, 20 Jul 2015 14:37:25 +0200 Piotr Zierhoffer <[email protected]>…

From: Piotr Zierhoffer <[email protected]>

This driver adds NAND support to SPL.
It was tested on AllWinner A20.

---

Changes in v2:
- removed traces of non-SPL-specific code
- moved the driver from boards/sunxi to drivers/mtd/nand
- moved magic values to defines (whenever possible)
- removed unnecesary late initialisation code
- code style changes as suggested for the first patch set:
- changed visibility of some symbols
- renamed unclear variables
- renamed header protector
- changed types of pointer variables
- other minor changes

 drivers/mtd/nand/Makefile     |   1 +
 drivers/mtd/nand/sunxi_nand.c | 289 ++++++++++++++++++++++++++++++++++++++++++
 drivers/mtd/nand/sunxi_nand.h | 151 ++++++++++++++++++++++
 3 files changed, 441 insertions(+)
 create mode 100644 drivers/mtd/nand/sunxi_nand.c
 create mode 100644 drivers/mtd/nand/sunxi_nand.h
drivers/mtd/nand/Makefile +1 -0
index 347ea62..4cf9cee 100644
@@ -12,6 +12,7 @@ NORMAL_DRIVERS=y
 endif
 
 obj-$(CONFIG_SPL_NAND_AM33XX_BCH) += am335x_spl_bch.o
+obj-$(CONFIG_SPL_NAND_SUNXI) += sunxi_nand.o
 obj-$(CONFIG_SPL_NAND_DENALI) += denali_spl.o
 obj-$(CONFIG_SPL_NAND_DOCG4) += docg4_spl.o
 obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
drivers/mtd/nand/sunxi_nand.c new file +41 -0
new file mode 100644
index 0000000..8d66d2b
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2014-2015, Antmicro Ltd <www.antmicro.com>
+ * Copyright (c) 2015, AW-SOM Technologies <www.aw-som.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <nand.h>
+#include "sunxi_nand.h"
+
+/* minimal "boot0" style NAND support for Allwinner A20 */
+
+/* temporary buffer in internal ram */
+unsigned char temp_buf[CONFIG_SYS_NAND_PAGE_SIZE]
+	__aligned(0x10) __section(".text#");
+
+#define MAX_RETRIES 10
+
+static int check_value_inner(int offset, int expected_bits,
+				int max_number_of_retries, int negation)
+{
+	int retries = 0;
+	do {
+		int val = readl(offset) & expected_bits;
+		if (negation ? !val : val)
+			return 1;
+		mdelay(1);
+		retries++;
+	} while (retries < max_number_of_retries);
+
+	return 0;
+}
+
+static inline int check_value(int offset, int expected_bits,
+				int max_number_of_retries)
+{
+	return check_value_inner(offset, expected_bits,
+					max_number_of_retries, 0);

drivers/mtd/nand/sunxi_nand.c line 51

Quoted 10 lines
drivers/mtd/nand/sunxi_nand.c new file +10 -0
+}
+
+static inline int check_value_negated(int offset, int unexpected_bits,
+					int max_number_of_retries)
+{
+	return check_value_inner(offset, unexpected_bits,
+					max_number_of_retries, 1);
+}
+
+static void nand_set_clocks(void)

You're setting more than the clks in there: you're also doing the pinmux.
Could you either rename the function or create a new one for the pinmux setting.

BTW, I'm not sure, but I think the pinmux should be done at the board level.

drivers/mtd/nand/sunxi_nand.c line 62

Quoted 11 lines
drivers/mtd/nand/sunxi_nand.c new file +11 -0
+{
+	uint32_t val;
+
+	writel(PORTC_PC_CFG0_NRB1 |
+		PORTC_PC_CFG0_NRB0 |
+		PORTC_PC_CFG0_NRE  |
+		PORTC_PC_CFG0_NCE0 |
+		PORTC_PC_CFG0_NCE1 |
+		PORTC_PC_CFG0_NCLE |
+		PORTC_PC_CFG0_NALE |
+		PORTC_PC_CFG0_NWE, PORTC_BASE + PORTC_PC_CFG0);

At least the NCEX and NRBX should be board specific ?

Quoted 7 lines
drivers/mtd/nand/sunxi_nand.c new file +7 -0
+
+	writel(PORTC_PC_CFG1_NDQ7 |
+		PORTC_PC_CFG1_NDQ6 |
+		PORTC_PC_CFG1_NDQ5 |
+		PORTC_PC_CFG1_NDQ4 |
+		PORTC_PC_CFG1_NDQ3 |
+		PORTC_PC_CFG1_NDQ2 |

drivers/mtd/nand/sunxi_nand.c line 79

Quoted 10 lines
drivers/mtd/nand/sunxi_nand.c new file +10 -0
+		PORTC_PC_CFG1_NDQ1 |
+		PORTC_PC_CFG1_NDQ0, PORTC_BASE + PORTC_PC_CFG1);
+
+	writel(PORTC_PC_CFG2_NCE7 |
+		PORTC_PC_CFG2_NCE6 |
+		PORTC_PC_CFG2_NCE5 |
+		PORTC_PC_CFG2_NCE4 |
+		PORTC_PC_CFG2_NCE3 |
+		PORTC_PC_CFG2_NCE2 |
+		PORTC_PC_CFG2_NWP, PORTC_BASE + PORTC_PC_CFG2);

Ditto

Quoted 19 lines
drivers/mtd/nand/sunxi_nand.c new file +19 -0
+
+	writel(PORTC_PC_CFG3_NDQS, PORTC_BASE + PORTC_PC_CFG3);
+
+	val = readl(CCU_BASE + CCU_AHB_GATING_REG0);
+	writel(CCU_AHB_GATING_REG0_NAND | val, CCU_BASE + CCU_AHB_GATING_REG0);
+
+	val = readl(CCU_BASE + CCU_NAND_SCLK_CFG_REG);
+	writel(val | CCU_NAND_SCLK_CFG_REG_SCLK_GATING
+		| CCU_NAND_SCLK_CFG_REG_CLK_DIV_RATIO,
+		CCU_BASE + CCU_NAND_SCLK_CFG_REG);
+}
+
+void nand_init(void)
+{
+	uint32_t val;
+
+	nand_set_clocks();
+	val = readl(NANDFLASHC_BASE + NANDFLASHC_CTL);
+	/* enable and reset CTL */

drivers/mtd/nand/sunxi_nand.c line 108

Quoted 10 lines
drivers/mtd/nand/sunxi_nand.c new file +10 -0
+	writel(val | NFC_CTL_EN | NFC_CTL_RESET,
+	       NANDFLASHC_BASE + NANDFLASHC_CTL);
+
+	if (!check_value_negated(NANDFLASHC_BASE + NANDFLASHC_CTL,
+				 NFC_CTL_RESET, MAX_RETRIES)) {
+		printf("Couldn't initialize nand\n");
+	}
+}
+
+static uint32_t ecc_errors;

You could get rid of this global variable if you pass an ecc_errors argument to the nand_read_page function.

Quoted 55 lines
drivers/mtd/nand/sunxi_nand.c new file +55 -0
+
+void nand_read_page(unsigned int real_addr, int syndrome)
+{
+	uint32_t val;
+	int ecc_off = 0;
+	uint16_t ecc_mode = 0;
+	uint16_t rand_seed;
+	uint32_t page;
+	uint16_t column;
+	uint32_t oob_offset;
+
+	switch (SUNXI_ECC_STRENGTH) {
+	case 16:
+		ecc_mode = 0;
+		ecc_off = 0x20;
+		break;
+	case 24:
+		ecc_mode = 1;
+		ecc_off = 0x2e;
+		break;
+	case 28:
+		ecc_mode = 2;
+		ecc_off = 0x32;
+		break;
+	case 32:
+		ecc_mode = 3;
+		ecc_off = 0x3c;
+		break;
+	case 40:
+		ecc_mode = 4;
+		ecc_off = 0x4a;
+		break;
+	case 48:
+		ecc_mode = 4;
+		ecc_off = 0x52;
+		break;
+	case 56:
+		ecc_mode = 4;
+		ecc_off = 0x60;
+		break;
+	case 60:
+		ecc_mode = 4;
+		ecc_off = 0x0;
+		break;
+	case 64:
+		ecc_mode = 4;
+		ecc_off = 0x0;
+		break;
+	default:
+		ecc_mode = 0;
+		ecc_off = 0;
+	}
+
+	if (ecc_off == 0) {
+		printf("Unsupported ECC strength (%d)!\n",

drivers/mtd/nand/sunxi_nand.c line 173

Quoted 10 lines
drivers/mtd/nand/sunxi_nand.c new file +10 -0
+		       SUNXI_ECC_STRENGTH);
+		return;
+	}
+
+	/* clear temp_buf */
+	memset(temp_buf, 0, CONFIG_SYS_NAND_PAGE_SIZE);
+
+	/* set CMD  */
+	writel(NFC_SEND_CMD1 | NFC_WAIT_FLAG | 0xff,
+	       NANDFLASHC_BASE + NANDFLASHC_CMD);

Could you replace the 0xff value by NAND_CMD_RESET, because what you're really trying to do is reset the NAND chip.

drivers/mtd/nand/sunxi_nand.c line 175

Quoted 2 lines
drivers/mtd/nand/sunxi_nand.c new file +2 -0
+
+	if (!check_value(NANDFLASHC_BASE + NANDFLASHC_ST, (1 << 1),

Please replace this magic value by the appropriate MACRO [1].

drivers/mtd/nand/sunxi_nand.c line 185

Quoted 10 lines
drivers/mtd/nand/sunxi_nand.c new file +10 -0
+			 MAX_RETRIES)) {
+		printf("Error while initilizing command interrupt\n");
+		return;
+	}
+
+	page = real_addr / CONFIG_SYS_NAND_BLOCK_SIZE;
+	column = real_addr % CONFIG_SYS_NAND_BLOCK_SIZE;
+
+	if (syndrome) {
+		/* shift every 1kB in syndrome */

Well, this scheme is not really related to the ECC syndrome scheme, it comes from the BROM implementation which can only really 1K of data per page.
Actually, this is not exactly true, depending on the BROM version it will try different things, see this description [2].
So once more, you're making assumptions that could be wrong on some boards.

Quoted 41 lines
drivers/mtd/nand/sunxi_nand.c new file +41 -0
+		column += (column / CONFIG_SYS_NAND_PAGE_SIZE) * ecc_off;
+	}
+
+	/* clear ecc status */
+	writel(0, NANDFLASHC_BASE + NANDFLASHC_ECC_ST);
+
+	/* Choose correct seed */
+	if (syndrome)
+		rand_seed = random_seed_syndrome;
+	else
+		rand_seed = random_seed[page % 128];
+
+	writel((rand_seed << 16) | NFC_ECC_RANDOM_EN | NFC_ECC_EN
+		| NFC_ECC_PIPELINE | (ecc_mode << 12),
+		NANDFLASHC_BASE + NANDFLASHC_ECC_CTL);
+
+	val = readl(NANDFLASHC_BASE + NANDFLASHC_CTL);
+	writel(val | NFC_CTL_RAM_METHOD, NANDFLASHC_BASE + NANDFLASHC_CTL);
+
+	if (syndrome) {
+		writel(CONFIG_SYS_NAND_PAGE_SIZE,
+		       NANDFLASHC_BASE + NANDFLASHC_SPARE_AREA);
+	} else {
+		oob_offset = CONFIG_SYS_NAND_BLOCK_SIZE
+			+ (column / CONFIG_SYS_NAND_PAGE_SIZE) * ecc_off;
+		writel(oob_offset, NANDFLASHC_BASE + NANDFLASHC_SPARE_AREA);
+	}
+
+	/* DMAC */
+	writel(0x0, DMAC_BASE + DMAC_CFG_REG0); /* clr dma cmd */
+	/* read from REG_IO_DATA */
+	writel(NANDFLASHC_BASE + NANDFLASHC_IO_DATA,
+	       DMAC_BASE + DMAC_SRC_START_ADDR_REG0);
+	writel((uint32_t)temp_buf,
+	       DMAC_BASE + DMAC_DEST_START_ADDRR_REG0); /* read to RAM */
+	writel(DMAC_DDMA_PARA_REG_SRC_WAIT_CYC
+			| DMAC_DDMA_PARA_REG_SRC_BLK_SIZE,
+			DMAC_BASE + DMAC_DDMA_PARA_REG0);
+	writel(CONFIG_SYS_NAND_PAGE_SIZE,
+	       DMAC_BASE + DMAC_DDMA_BC_REG0); /* 1kB */
+	writel(DMAC_DDMA_CFG_REG_LOADING

drivers/mtd/nand/sunxi_nand.c line 236

Quoted 10 lines
drivers/mtd/nand/sunxi_nand.c new file +10 -0
+		| DMAC_DDMA_CFG_REG_DMA_DEST_DATA_WIDTH_32
+		| DMAC_DDMA_CFG_REG_DMA_SRC_DATA_WIDTH_32
+		| DMAC_DDMA_CFG_REG_DMA_SRC_ADDR_MODE_IO
+		| DMAC_DDMA_CFG_REG_DDMA_SRC_DRQ_TYPE_NFC,
+		DMAC_BASE + DMAC_CFG_REG0);
+
+	writel((0xE0 << NFC_RANDOM_READ_CMD1_OFFSET)
+		| (0x05 << NFC_RANDOM_READ_CMD0_OFFSET)
+		| (0x30 | NFC_READ_CMD_OFFSET), NANDFLASHC_BASE
+			+ NANDFLASHC_RCMD_SET);

Same comment as above, please use the appropriate macros:

0xE0 => NAND_CMD_RNDOUTSTART
0x05 => NAND_CMD_RNDOUT
0x30 => NAND_CMD_READSTART

Quoted 40 lines
drivers/mtd/nand/sunxi_nand.c new file +40 -0
+	writel(1, NANDFLASHC_BASE + NANDFLASHC_SECTOR_NUM);
+	writel(((page & 0xFFFF) << 16) | column,
+	       NANDFLASHC_BASE + NANDFLASHC_ADDR_LOW);
+	writel((page >> 16) & 0xFF, NANDFLASHC_BASE + NANDFLASHC_ADDR_HIGH);
+	writel(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_DATA_TRANS |
+		NFC_PAGE_CMD | NFC_WAIT_FLAG | (4 << NFC_ADDR_NUM_OFFSET) |
+		NFC_SEND_ADR | NFC_DATA_SWAP_METHOD | (syndrome ? NFC_SEQ : 0),
+		NANDFLASHC_BASE + NANDFLASHC_CMD);
+
+	if (!check_value(NANDFLASHC_BASE + NANDFLASHC_ST, (1 << 2),
+			 MAX_RETRIES)) {
+		printf("Error while initializing dma interrupt\n");
+		return;
+	}
+
+	if (!check_value_negated(DMAC_BASE + DMAC_CFG_REG0,
+				 DMAC_DDMA_CFG_REG_LOADING, MAX_RETRIES)) {
+		printf("Error while waiting for dma transfer to finish\n");
+		return;
+	}
+
+	if (readl(NANDFLASHC_BASE + NANDFLASHC_ECC_ST))
+		ecc_errors++;
+}
+
+int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest)
+{
+	void *current_dest;
+	uint32_t count;
+	uint32_t current_count;
+
+	memset(dest, 0x0, size); /* clean destination memory */
+	ecc_errors = 0;
+	for (current_dest = dest;
+			current_dest < (dest + size);
+			current_dest += CONFIG_SYS_NAND_PAGE_SIZE) {
+		nand_read_page(offs, offs < SYNDROME_PARTITIONS_END);
+		count = current_dest - dest;
+
+		if (size - count > CONFIG_SYS_NAND_PAGE_SIZE)

drivers/mtd/nand/sunxi_nand.c line 286

Quoted 10 lines
drivers/mtd/nand/sunxi_nand.c new file +10 -0
+			current_count = CONFIG_SYS_NAND_PAGE_SIZE;
+		else
+			current_count = size - count;
+
+		memcpy(current_dest,
+		       temp_buf,
+		       current_count);
+		offs += CONFIG_SYS_NAND_PAGE_SIZE;
+	}
+	return ecc_errors;

I'm not sure what's the exact convention for nand_spl_load_image return code, but I'd say that returning a negative error code if ecc_errors != 0 is better than returning the number of ECC errors.

Quoted 9 lines
drivers/mtd/nand/sunxi_nand.c new file +3 -0
+}
+
+void nand_deselect(void) {}
drivers/mtd/nand/sunxi_nand.h new file +0 -0
new file mode 100644
index 0000000..d24f0ef

drivers/mtd/nand/sunxi_nand.h line 8

Quoted 8 lines
drivers/mtd/nand/sunxi_nand.h new file +8 -0
@@ -0,0 +1,151 @@
+#ifndef SUNXI_NAND_H
+
+#define SUNXI_NAND_H
+
+#define PORTC_BASE                 0x01c20800
+#define CCU_BASE                   0x01c20000
+#define NANDFLASHC_BASE            0x01c03000
+#define DMAC_BASE                  0x01c02000

I'm not sure how drivers are supposed to interact with a DMA controller, a clk controller or a gpio/pinmux controller in u-boot, but I would expect those definitions to be common to the sunxi platform and not directly defined in the NAND controller driver.

The same goes for all the following CCU_, PORTC_ and DMAC_ definitions.

drivers/mtd/nand/sunxi_nand.h line 11

Quoted 3 lines
drivers/mtd/nand/sunxi_nand.h new file +3 -0
+
+#define SYNDROME_PARTITIONS_END    0x00400000
+#define SUNXI_ECC_STRENGTH         40

These two variables should definitely not be defined in this headers:
they are representing NAND chip requirements and these ones are definitely board specific (they depends on the NAND chip you have on your board).

Quoted 105 lines
drivers/mtd/nand/sunxi_nand.h new file +105 -0
+
+#define CCU_AHB_GATING_REG0        0x60
+#define CCU_NAND_SCLK_CFG_REG      0x80
+#define CCU_AHB_GATING_REG0_NAND   (1 << 13)
+
+#define CCU_NAND_SCLK_CFG_REG_SCLK_GATING (1 << 31)
+#define CCU_NAND_SCLK_CFG_REG_CLK_DIV_RATIO (1 << 0)
+
+#define PORTC_PC_CFG0              0x48
+#define PORTC_PC_CFG1              0x4C
+#define PORTC_PC_CFG2              0x50
+#define PORTC_PC_CFG3              0x54
+
+#define PORTC_PC_CFG0_NRB1         (2 << 28)
+#define PORTC_PC_CFG0_NRB0         (2 << 24)
+#define PORTC_PC_CFG0_NRE          (2 << 20)
+#define PORTC_PC_CFG0_NCE0         (2 << 16)
+#define PORTC_PC_CFG0_NCE1         (2 << 12)
+#define PORTC_PC_CFG0_NCLE         (2 << 8)
+#define PORTC_PC_CFG0_NALE         (2 << 4)
+#define PORTC_PC_CFG0_NWE          (2 << 0)
+
+#define PORTC_PC_CFG1_NDQ7         (2 << 28)
+#define PORTC_PC_CFG1_NDQ6         (2 << 24)
+#define PORTC_PC_CFG1_NDQ5         (2 << 20)
+#define PORTC_PC_CFG1_NDQ4         (2 << 16)
+#define PORTC_PC_CFG1_NDQ3         (2 << 12)
+#define PORTC_PC_CFG1_NDQ2         (2 << 8)
+#define PORTC_PC_CFG1_NDQ1         (2 << 4)
+#define PORTC_PC_CFG1_NDQ0         (2 << 0)
+
+#define PORTC_PC_CFG2_NCE7         (2 << 24)
+#define PORTC_PC_CFG2_NCE6         (2 << 20)
+#define PORTC_PC_CFG2_NCE5         (2 << 16)
+#define PORTC_PC_CFG2_NCE4         (2 << 12)
+#define PORTC_PC_CFG2_NCE3         (2 << 8)
+#define PORTC_PC_CFG2_NCE2         (2 << 4)
+#define PORTC_PC_CFG2_NWP          (2 << 0)
+
+#define PORTC_PC_CFG3_NDQS         (2 << 0)
+
+#define DMAC_CFG_REG0              0x300
+#define DMAC_SRC_START_ADDR_REG0   0x304
+#define DMAC_DEST_START_ADDRR_REG0 0x308
+#define DMAC_DDMA_BC_REG0          0x30C
+#define DMAC_DDMA_PARA_REG0        0x318
+
+#define DMAC_DDMA_CFG_REG_LOADING  (1 << 31)
+#define DMAC_DDMA_CFG_REG_DMA_DEST_DATA_WIDTH_32 (2 << 25)
+#define DMAC_DDMA_CFG_REG_DMA_SRC_DATA_WIDTH_32 (2 << 9)
+#define DMAC_DDMA_CFG_REG_DMA_SRC_ADDR_MODE_IO (1 << 5)
+#define DMAC_DDMA_CFG_REG_DDMA_SRC_DRQ_TYPE_NFC (3 << 0)
+
+#define DMAC_DDMA_PARA_REG_SRC_WAIT_CYC (0x0F << 0)
+#define DMAC_DDMA_PARA_REG_SRC_BLK_SIZE (0x7F << 8)
+
+#define NANDFLASHC_CTL             0x00000000
+
+#define NFC_CTL_EN                 (1 << 0)
+#define NFC_CTL_RESET              (1 << 1)
+#define NFC_CTL_RAM_METHOD         (1 << 14)
+
+#define NANDFLASHC_ST              0x00000004
+#define NANDFLASHC_INT             0x00000008
+#define NANDFLASHC_TIMING_CTL      0x0000000C
+#define NANDFLASHC_TIMING_CFG      0x00000010
+#define NANDFLASHC_ADDR_LOW        0x00000014
+#define NANDFLASHC_ADDR_HIGH       0x00000018
+#define NANDFLASHC_SECTOR_NUM      0x0000001C
+#define NANDFLASHC_CNT             0x00000020
+#define NANDFLASHC_CMD             0x00000024
+#define NANDFLASHC_RCMD_SET        0x00000028
+#define NANDFLASHC_WCMD_SET        0x0000002C
+#define NANDFLASHC_IO_DATA         0x00000030
+#define NANDFLASHC_ECC_CTL         0x00000034
+
+#define NFC_ECC_EN                 (1 << 0)
+#define NFC_ECC_PIPELINE           (1 << 3)
+#define NFC_ECC_EXCEPTION          (1 << 4)
+#define NFC_ECC_BLOCK_SIZE         (1 << 5)
+#define NFC_ECC_RANDOM_EN          (1 << 9)
+#define NFC_ECC_RANDOM_DIRECTION   (1 << 10)
+
+#define NANDFLASHC_ECC_ST          0x00000038
+#define NANDFLASHC_DEBUG           0x0000003C
+#define NANDFLASHC_ECC_CNT0        0x00000040
+#define NANDFLASHC_ECC_CNT1        0x00000044
+#define NANDFLASHC_ECC_CNT2        0x00000048
+#define NANDFLASHC_ECC_CNT3        0x0000004C
+#define NANDFLASHC_USER_DATA_BASE  0x00000050
+#define NANDFLASHC_EFNAND_STATUS   0x00000090
+#define NANDFLASHC_SPARE_AREA      0x000000A0
+#define NANDFLASHC_PATTERN_ID      0x000000A4
+#define NANDFLASHC_RAM0_BASE       0x00000400
+#define NANDFLASHC_RAM1_BASE       0x00000800
+
+#define NFC_ADDR_NUM_OFFSET        16
+#define NFC_SEND_ADR               (1 << 19)
+#define NFC_ACCESS_DIR             (1 << 20)
+#define NFC_DATA_TRANS             (1 << 21)
+#define NFC_SEND_CMD1              (1 << 22)
+#define NFC_WAIT_FLAG              (1 << 23)
+#define NFC_SEND_CMD2              (1 << 24)
+#define NFC_SEQ                    (1 << 25)
+#define NFC_DATA_SWAP_METHOD       (1 << 26)

drivers/mtd/nand/sunxi_nand.h line 126

Quoted 10 lines
drivers/mtd/nand/sunxi_nand.h new file +10 -0
+#define NFC_ROW_AUTO_INC           (1 << 27)
+#define NFC_SEND_CMD3              (1 << 28)
+#define NFC_SEND_CMD4              (1 << 29)
+
+#define NFC_READ_CMD_OFFSET         0
+#define NFC_RANDOM_READ_CMD0_OFFSET 8
+#define NFC_RANDOM_READ_CMD1_OFFSET 16
+
+
+#define NFC_PAGE_CMD               (2 << 30)

Are all these NFC_ macros used outside of the driver itself. If that's not the case then I would recommend moving them direcly in the .c file.

Moreover, you're sometime mixing the NFC_ and NANDFLASHC_ prefix, is there a reason for doing that ?

Also, I haven't checked if the MACRO names are matching the one defined in the linux driver, but if that's not the case then I would recommend using the same definition since the final goal is to port the Linux driver to u-boot (I know you're just implementing the SPL part, but since you moved your code into drivers/mtd/nand/sunxi_nand* I'll have to merge the Linux implementation into this file).

Quoted 13 lines
drivers/mtd/nand/sunxi_nand.h new file +13 -0
+
+/* random seed used by linux */
+const uint16_t random_seed[128] = {
+	0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
+	0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
+	0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
+	0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
+	0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
+	0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
+	0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
+	0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
+	0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
+	0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,

drivers/mtd/nand/sunxi_nand.h line 149

Quoted 10 lines
drivers/mtd/nand/sunxi_nand.h new file +10 -0
+	0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
+	0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
+	0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
+	0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
+	0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
+	0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
+};
+
+/* random seed used for syndrome calls */
+const uint16_t random_seed_syndrome = 0x4a80;

The random_seed and random_seed_syndrome variables should not be defined in the header, because this implies duplicating the same global variable if the header is included multiple times (which should trigger a linker error).

drivers/mtd/nand/sunxi_nand.h line 151

Quoted 2 lines
drivers/mtd/nand/sunxi_nand.h new file +2 -0
+
+#endif /* end of include guard: SUNXI_NAND_H */

/* SUNXI_NAND_H */ should be enough.

Best Regards,

Boris

[1]http://lxr.free-electrons.com/source/drivers/mtd/nand/sunxi_nand.c#L84 [2]http://linux-sunxi.org/NAND#More_information_on_BROM_NAND

Signature · 3 lines
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
#17 lore raw

PATCH v2 1/3 sunxi: nand: Add basic sunxi NAND driver for SPL with DMA support

Hi Boris,

thanks for your review. I have applied most of your comments, but I have few remarks and questions.

2015-07-20 18:13 GMT+02:00 Boris Brezillon <[email protected]>:

Quoted 6 lines

drivers/mtd/nand/sunxi_nand.c line 185

Quoted 5 lines
drivers/mtd/nand/sunxi_nand.c new file +5 -0
+     page = real_addr / CONFIG_SYS_NAND_BLOCK_SIZE;
+     column = real_addr % CONFIG_SYS_NAND_BLOCK_SIZE;
+
+     if (syndrome) {
+             /* shift every 1kB in syndrome */
Quoted 7 lines

Well, this scheme is not really related to the ECC syndrome scheme, it comes from the BROM implementation which can only really 1K of data per page.
Actually, this is not exactly true, depending on the BROM version it will try different things, see this description [2].
So once more, you're making assumptions that could be wrong on some boards.

Actually, I have only one board and I wouldn't like to submit code that is supposed to be general and was never really tested.

I'd suggest removing the comment and making the following options configurable, with the default values as provided, in Kconfig:
CONFIG_NAND_PAGE_SIZE 0x2000
CONFIG_NAND_ECC_PAGE_SIZE 0x400 CONFIG_NAND_SUNXI_ECC_STRENGTH 40 CONFIG_NAND_SYNDROME_PARTITIONS_END 0x400000

Do you think that would be sensible?

Quoted 21 lines
Quoted 21 lines
drivers/mtd/nand/sunxi_nand.c new file +21 -0
+int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest)
+{
+     void *current_dest;
+     uint32_t count;
+     uint32_t current_count;
+
+     memset(dest, 0x0, size); /* clean destination memory */
+     ecc_errors = 0;
+     for (current_dest = dest;
+                     current_dest < (dest + size);
+                     current_dest += CONFIG_SYS_NAND_PAGE_SIZE) {
+             nand_read_page(offs, offs < SYNDROME_PARTITIONS_END);
+             count = current_dest - dest;
+
+             if (size - count > CONFIG_SYS_NAND_PAGE_SIZE)
+                     current_count = CONFIG_SYS_NAND_PAGE_SIZE;
+             else
+                     current_count = size - count;
+
+             memcpy(current_dest,
+                    temp_buf,
Quoted 9 lines

drivers/mtd/nand/sunxi_nand.c line 286

Quoted 4 lines
drivers/mtd/nand/sunxi_nand.c new file +4 -0
+                    current_count);
+             offs += CONFIG_SYS_NAND_PAGE_SIZE;
+     }
+     return ecc_errors;

I'm not sure what's the exact convention for nand_spl_load_image return code, but I'd say that returning a negative error code if ecc_errors != 0 is better than returning the number of ECC errors.

From my observations it seems that there is no established convention, but returning -1 as an error indicator can be found here and there, so I may do that.

It's not really interpreted anywhere, though.

Quoted 5 lines

Are all these NFC_ macros used outside of the driver itself. If that's not the case then I would recommend moving them direcly in the .c file.

In general you may find that constants regarding NANDs are kept in .h files around U-Boot, so I'd like stick with that convention.

Quoted 7 lines

Also, I haven't checked if the MACRO names are matching the one defined in the linux driver, but if that's not the case then I would recommend using the same definition since the final goal is to port the Linux driver to u-boot (I know you're just implementing the SPL part, but since you moved your code into drivers/mtd/nand/sunxi_nand* I'll have to merge the Linux implementation into this file).

I have made the macros consistent, but unfortunately I won't be able to verify them all with the Linux drivers, due to time constraints.
It can always be done later as a part of a separate patchset with a Linux driver.

I will submit another version of this patchset later today.

I will follow your suggestion to create a new thread for that.

Quoted 2 lines

Boris

Best regards

*Piotr Zierhoffer*
Antmicro Ltd | www.antmicro.com

#18 lore raw

PATCH v2 1/3 sunxi: nand: Add basic sunxi NAND driver for SPL with DMA support

Hi Piotr,

Quoted 20 lines · On Wed, 22 Jul 2015 13:27:37 +0200 Piotr Zierhoffer <[email protected]>…

Hi Boris,

thanks for your review. I have applied most of your comments, but I have few remarks and questions.

2015-07-20 18:13 GMT+02:00 Boris Brezillon <[email protected]>:

Quoted 6 lines

drivers/mtd/nand/sunxi_nand.c line 185

Quoted 5 lines
drivers/mtd/nand/sunxi_nand.c new file +5 -0
+     page = real_addr / CONFIG_SYS_NAND_BLOCK_SIZE;
+     column = real_addr % CONFIG_SYS_NAND_BLOCK_SIZE;
+
+     if (syndrome) {
+             /* shift every 1kB in syndrome */
Quoted 7 lines

Well, this scheme is not really related to the ECC syndrome scheme, it comes from the BROM implementation which can only really 1K of data per page.
Actually, this is not exactly true, depending on the BROM version it will try different things, see this description [2].
So once more, you're making assumptions that could be wrong on some boards.

Quoted 2 lines

Actually, I have only one board and I wouldn't like to submit code that is supposed to be general and was never really tested.

I understand, but I was not talking about testing your code on all existing boards, just making your code generic enough so that other users can test on their platforms without having to modify the SPL code. Of course if they detect that something is buggy or missing, they will provide follow-up patches to fix those problems.

Quoted 9 lines

I'd suggest removing the comment and making the following options configurable, with the default values as provided, in Kconfig:
CONFIG_NAND_PAGE_SIZE 0x2000
CONFIG_NAND_ECC_PAGE_SIZE 0x400 CONFIG_NAND_SUNXI_ECC_STRENGTH 40 CONFIG_NAND_SYNDROME_PARTITIONS_END 0x400000

Do you think that would be sensible?

Yep, that pretty much what I was expecting. Just put those definition into a board config header, or add a Kconfig entry.

Quoted 32 lines
Quoted 22 lines
Quoted 22 lines
drivers/mtd/nand/sunxi_nand.c new file +21 -0
+int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest)
+{
+     void *current_dest;
+     uint32_t count;
+     uint32_t current_count;
+
+     memset(dest, 0x0, size); /* clean destination memory */
+     ecc_errors = 0;
+     for (current_dest = dest;
+                     current_dest < (dest + size);
+                     current_dest += CONFIG_SYS_NAND_PAGE_SIZE) {
+             nand_read_page(offs, offs < SYNDROME_PARTITIONS_END);
+             count = current_dest - dest;
+
+             if (size - count > CONFIG_SYS_NAND_PAGE_SIZE)
+                     current_count = CONFIG_SYS_NAND_PAGE_SIZE;
+             else
+                     current_count = size - count;
+
+             memcpy(current_dest,
+                    temp_buf,
Quoted 9 lines

drivers/mtd/nand/sunxi_nand.c line 286

Quoted 4 lines
drivers/mtd/nand/sunxi_nand.c new file +4 -0
+                    current_count);
+             offs += CONFIG_SYS_NAND_PAGE_SIZE;
+     }
+     return ecc_errors;

I'm not sure what's the exact convention for nand_spl_load_image return code, but I'd say that returning a negative error code if ecc_errors != 0 is better than returning the number of ECC errors.

Quoted 5 lines

From my observations it seems that there is no established convention, but returning -1 as an error indicator can be found here and there, so I may do that.

It's not really interpreted anywhere, though.

Okay, then I'll let u-boot maintainers decide what should be done.

Quoted 9 lines
Quoted 6 lines

Are all these NFC_ macros used outside of the driver itself. If that's not the case then I would recommend moving them direcly in the .c file.

In general you may find that constants regarding NANDs are kept in .h files around U-Boot, so I'd like stick with that convention.

This is true for all generic definitions, not for driver specific ones.

Quoted 11 lines
Quoted 8 lines

Also, I haven't checked if the MACRO names are matching the one defined in the linux driver, but if that's not the case then I would recommend using the same definition since the final goal is to port the Linux driver to u-boot (I know you're just implementing the SPL part, but since you moved your code into drivers/mtd/nand/sunxi_nand* I'll have to merge the Linux implementation into this file).

I have made the macros consistent, but unfortunately I won't be able to verify them all with the Linux drivers, due to time constraints.

How about copying the definition from the Linux driver and fixing the mismatch in your implementation ?

Quoted 2 lines

It can always be done later as a part of a separate patchset with a Linux driver.

Hm, the merge will be even more complicated if you do that. Could you at least move your code to sunxi_nand_spl.c so that we can directly apply the linux commit adding support for the sunxi NAND controller ?

Thanks.

Best Regards,

Boris

Signature · 3 lines
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
#19 lore raw

PATCH v2 1/3 sunxi: nand: Add basic sunxi NAND driver for SPL with DMA support

Hello

2015-07-22 13:53 GMT+02:00 Boris Brezillon <[email protected]>:

Quoted 8 lines
Quoted 8 lines

I'd suggest removing the comment and making the following options configurable, with the default values as provided, in Kconfig:
CONFIG_NAND_PAGE_SIZE 0x2000
CONFIG_NAND_ECC_PAGE_SIZE 0x400 CONFIG_NAND_SUNXI_ECC_STRENGTH 40 CONFIG_NAND_SYNDROME_PARTITIONS_END 0x400000

Quoted 5 lines
Quoted 1 line

Do you think that would be sensible?

Yep, that pretty much what I was expecting. Just put those definition into a board config header, or add a Kconfig entry.

Ok, will be done.

Quoted 6 lines
Quoted 3 lines

In general you may find that constants regarding NANDs are kept in .h files around U-Boot, so I'd like stick with that convention.

This is true for all generic definitions, not for driver specific ones.

Well, that's not true for all the drivers, as we have tegra_nand.h and atmel_nand_ecc.h, never used elsewhere apart from their corresponding *.c files.

Especially if we'd have two drivers, one header will be needed.

But if that would ease your work, I'll merge sunxi_nand.h to sunxi_nand.c and rename it as you suggest.

Best regards

Piotr Zierhoffer
Antmicro Ltd | www.antmicro.com

#20 lore raw

PATCH v2 2/3 sunxi: nand: Add board configuration options

In reply to Piotr Zierhoffer

From: Piotr Zierhoffer <[email protected]>

When SPL_NAND_SUNXI option is selected in config, set some configuration options for sunxi NAND.

This commit also introduces the configurable options in Kconfig.

---

Changes in v2:
- removed traces of non-SPL specific code
- renamed defines to be more relevant
- moved Kconfig entry for the driver to drivers/mtd/nand
- reworded Kconfig entry help

 drivers/mtd/nand/Kconfig       |  7 +++++++
 include/configs/sunxi-common.h | 11 +++++++++++
 2 files changed, 18 insertions(+)
drivers/mtd/nand/Kconfig +7 -0
index 3024357..2f8dbaf 100644
@@ -85,6 +85,13 @@ config SPL_NAND_DENALI
 	  This is a small implementation of the Denali NAND controller
 	  for use on SPL.
 
+config SPL_NAND_SUNXI
+	bool "Support for NAND on Allwinner A20 in SPL"
+	depends on MACH_SUN7I
+	---help---
+	Enable support for internal NAND. This option allows SPL to read from
+	sunxi NAND using DMA transfers. Writing is not supported.
+
 endif
 
 endmenu
include/configs/sunxi-common.h +11 -0
index 9576bc1..c230cff 100644
@@ -139,6 +139,17 @@
 #define CONFIG_INITRD_TAG
 #define CONFIG_SERIAL_TAG
 
+#if defined(CONFIG_SPL_NAND_SUNXI)
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_SUPPORT
+
+#define CONFIG_SYS_NAND_SPL_KERNEL_OFFS 0x280000
+#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x008000
+
+#define CONFIG_SYS_NAND_PAGE_SIZE 0x000400 /* 1kb */
+#define CONFIG_SYS_NAND_BLOCK_SIZE 0x002000 /* 8kb*/
+#endif
+
 /* mmc config */
 #if !defined(CONFIG_UART0_PORT_F)
 #define CONFIG_MMC
Signature · 1 line
2.3.6
#21 lore raw

PATCH v2 3/3 sunxi: nand: Add information to sunxi that it was run from NAND in SPL

In reply to Piotr Zierhoffer

As SPL does not know which source to choose when booting U-Boot, choose NAND if it is capable of doing so.

---

Changes in v2:
- none

 arch/arm/cpu/armv7/sunxi/board.c | 4 ++++
 1 file changed, 4 insertions(+)
arch/arm/cpu/armv7/sunxi/board.c +4 -0
index 5f39aa0..e4b7d63 100644
@@ -128,6 +128,9 @@ void s_init(void)
  */
 u32 spl_boot_device(void)
 {
+#ifdef CONFIG_SPL_NAND_SUPPORT
+	return BOOT_DEVICE_NAND;
+#else
 	/*
 	 * When booting from the SD card, the "eGON.BT0" signature is expected
 	 * to be found in memory at the address 0x0004 (see the "mksunxiboot"
@@ -148,6 +151,7 @@ u32 spl_boot_device(void)
 		return BOOT_DEVICE_MMC1;
 	else
 		return BOOT_DEVICE_BOARD;
+#endif
 }
 
 /* No confirmation data available in SPL yet. Hardcode bootmode */
Signature · 1 line
2.3.6
#22 lore raw

v2 cover sunxi: nand: Basic NAND driver for SPL

In reply to Piotr Zierhoffer

Hi Piotr,

I don't know what's the policy in u-boot, but in most open source projects we usually start a new thread when sending a new version of a specific patch series.

Quoted 6 lines · On Mon, 20 Jul 2015 14:37:24 +0200 Piotr Zierhoffer <[email protected]>…

This is a basic driver for the sunxi NAND controller for Allwinner A20. It supports only SPL.

The driver uses DMA for data transfers. It does not support writing.

Quoted 14 lines

Changes in v2:
- removed traces of non-SPL-specific code
- moved the driver from boards/sunxi to drivers/mtd/nand
- moved magic values to defines (whenever possible)
- removed unnecesary late initialisation code
- code style changes as suggested for the first patch set:
- changed visibility of some symbols
- renamed unclear variables
- renamed header protector
- changed types of pointer variables
- other minor changes
- renamed defines to be more relevant
- moved Kconfig entry for the driver to drivers/mtd/nand
- reworded Kconfig entry help

You also completely dropped the a20_nandread command (which is a good thing IMHO), right ?

Best Regards,

Boris

Signature · 3 lines
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
#23 lore raw

v2 cover sunxi: nand: Basic NAND driver for SPL

Hello Boris

2015-07-20 17:05 GMT+02:00 Boris Brezillon <[email protected]>:

Quoted 3 lines

I don't know what's the policy in u-boot, but in most open source projects we usually start a new thread when sending a new version of a specific patch series.

I have tried to follow the guidelines from
http://www.denx.de/wiki/U-Boot/Patches and understood
that I should set -r option in patman to the message-id of my previous cover letter - like in
the documentation of git-send-email (http://git-scm.com/docs/git-send-email)

Sorry if I got it wrong, should I resubmit it?

Quoted 2 lines

You also completely dropped the a20_nandread command (which is a good thing IMHO), right ?

This is true. The command was the only non-SPL part, and since it was not a full driver we have
decided to remove it from this patch set.

Best regards

Piotr Zierhoffer
Antmicro Ltd | www.antmicro.com