[U-Boot] [PATCH 0/5] nand: sunxi: Add SPL support for booting from NAND.

This patchset adds minimal SPL driver for reading from A20 nand partitions utilizing DMA controller. It supports randomization and syndrome partitions.
Since BROM reads second syndrome partition, if first SPL checksum doesn't match, additional U-Boot offset may be provided to load backup U-boot from second block of second page.
To simplify loading many files (devicetree, kernel, sourcable boot script) additional parameter is added, which allows preloading multiboot image into memory directly from SPL.
Additionally conveniance function a20_nandread has been added, which utilizes SPL driver on normal U-Boot.
Best regards, Daniel Kochmański
Daniel Kochmański (5): nand: sunxi: change BLOCK_SIZE in mksunxiboot to match NAND block size nand: sunxi: Add support for booting from internal NAND memory nand: sunxi: Add secondary U-Boot offset on second syndrome partition nand: sunxi: Add multiimage preload option nand: sunxi: And a20_nandread command utilizing spl nand read driver
README | 10 ++ arch/arm/cpu/armv7/sunxi/board.c | 12 ++- board/sunxi/Kconfig | 12 +++ board/sunxi/Makefile | 1 + board/sunxi/nand.c | 219 +++++++++++++++++++++++++++++++++++++++ common/Kconfig | 7 ++ common/Makefile | 1 + common/cmd_a20_nandread.c | 27 +++++ common/spl/spl_nand.c | 51 +++++++-- include/configs/sunxi-common.h | 12 +++ tools/mksunxiboot.c | 2 +- 11 files changed, 344 insertions(+), 10 deletions(-) create mode 100644 board/sunxi/nand.c create mode 100644 common/cmd_a20_nandread.c

This change is necessary to calculate correct checksum for NAND boot. Works both for MMC and NAND. Without it BROM rejects boot image as invalid (bad checksum). (Changes block size from 0x200 to 0x2000).
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com ---
tools/mksunxiboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/mksunxiboot.c b/tools/mksunxiboot.c index 0035f6e..bef0c79 100644 --- a/tools/mksunxiboot.c +++ b/tools/mksunxiboot.c @@ -65,7 +65,7 @@ int gen_check_sum(struct boot_file_head *head_p)
#define SUN4I_SRAM_SIZE 0x7600 /* 0x7748+ is used by BROM */ #define SRAM_LOAD_MAX_SIZE (SUN4I_SRAM_SIZE - sizeof(struct boot_file_head)) -#define BLOCK_SIZE 512 +#define BLOCK_SIZE 0x2000
struct boot_img { struct boot_file_head header;

On Wed, 2015-04-29 at 17:02 +0200, Daniel Kochmański wrote:
This change is necessary to calculate correct checksum for NAND boot. Works both for MMC and NAND. Without it BROM rejects boot image as invalid (bad checksum). (Changes block size from 0x200 to 0x2000).
I'm inferring here that for MMC boot this checksum is ignored by the BROM? If that is the case then I think it should be explicitly mentioned.
As well as the checksum this also changes the header's length field, FWIW.
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com
tools/mksunxiboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/mksunxiboot.c b/tools/mksunxiboot.c index 0035f6e..bef0c79 100644 --- a/tools/mksunxiboot.c +++ b/tools/mksunxiboot.c @@ -65,7 +65,7 @@ int gen_check_sum(struct boot_file_head *head_p)
#define SUN4I_SRAM_SIZE 0x7600 /* 0x7748+ is used by BROM */ #define SRAM_LOAD_MAX_SIZE (SUN4I_SRAM_SIZE - sizeof(struct boot_file_head)) -#define BLOCK_SIZE 512 +#define BLOCK_SIZE 0x2000
struct boot_img { struct boot_file_head header;

Ian Campbell writes:
On Wed, 2015-04-29 at 17:02 +0200, Daniel Kochmański wrote:
This change is necessary to calculate correct checksum for NAND boot. Works both for MMC and NAND. Without it BROM rejects boot image as invalid (bad checksum). (Changes block size from 0x200 to 0x2000).
I'm inferring here that for MMC boot this checksum is ignored by the BROM? If that is the case then I think it should be explicitly mentioned.
It isn't ignored, just larger block is taken into checksum and put in header (which is read by BROM). I think, that in NAND case BROM just ignores length field in header, and calculates checksum for whole page (8KB), while on MMC it respects this field, hence 0x2000 works for both.
I've tried to put garbage into checksum field, and MMC doesn't boot if checksum isn't correct.
As well as the checksum this also changes the header's length field, FWIW.
Yes, this is true. Should I change it to set block size conditionally depending on defines - if it's SPL NAND boot, then use 0x2000, in other occasion use 0x200? Whole `u-boot-sunxi-with-spl.bin` size doesn't increase tough (probably because of space between spl and proper u-boot).
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com
tools/mksunxiboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/mksunxiboot.c b/tools/mksunxiboot.c index 0035f6e..bef0c79 100644 --- a/tools/mksunxiboot.c +++ b/tools/mksunxiboot.c @@ -65,7 +65,7 @@ int gen_check_sum(struct boot_file_head *head_p)
#define SUN4I_SRAM_SIZE 0x7600 /* 0x7748+ is used by BROM */ #define SRAM_LOAD_MAX_SIZE (SUN4I_SRAM_SIZE - sizeof(struct boot_file_head)) -#define BLOCK_SIZE 512 +#define BLOCK_SIZE 0x2000
struct boot_img { struct boot_file_head header;

On Tue, 2015-05-05 at 11:02 +0200, Daniel Kochmański wrote:
Ian Campbell writes:
On Wed, 2015-04-29 at 17:02 +0200, Daniel Kochmański wrote:
This change is necessary to calculate correct checksum for NAND boot. Works both for MMC and NAND. Without it BROM rejects boot image as invalid (bad checksum). (Changes block size from 0x200 to 0x2000).
I'm inferring here that for MMC boot this checksum is ignored by the BROM? If that is the case then I think it should be explicitly mentioned.
It isn't ignored, just larger block is taken into checksum and put in header (which is read by BROM). I think, that in NAND case BROM just ignores length field in header, and calculates checksum for whole page (8KB), while on MMC it respects this field, hence 0x2000 works for both.
OK, please add an explanation along these lines to the commit message.
I've tried to put garbage into checksum field, and MMC doesn't boot if checksum isn't correct.
As well as the checksum this also changes the header's length field, FWIW.
Yes, this is true. Should I change it to set block size conditionally depending on defines - if it's SPL NAND boot, then use 0x2000, in other occasion use 0x200?
I don't think that is necessary assuming...
Whole `u-boot-sunxi-with-spl.bin` size doesn't increase tough (probably because of space between spl and proper u-boot).
... this is actually the case, then you could just say it in the commit log.

Adds minimal DMA NAND driver for booting from NAND internal memory. New config option SPL_NAND_SUPPORT is created for sunxi board, which enables introduced driver and sets ENV_IS_NOWHERE (instead of ENV_IS_IN_MMC).
NAND driver utilizes DMA interface to flash controller, which supports randomization. Reading from both syndrome and non-syndrom partitions is supported. Writing to flash isn't implemented for time being.
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com ---
arch/arm/cpu/armv7/sunxi/board.c | 12 ++- board/sunxi/Kconfig | 12 +++ board/sunxi/Makefile | 1 + board/sunxi/nand.c | 219 +++++++++++++++++++++++++++++++++++++++ common/spl/spl_nand.c | 13 +-- include/configs/sunxi-common.h | 9 ++ 6 files changed, 258 insertions(+), 8 deletions(-) create mode 100644 board/sunxi/nand.c
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c index c1b4cf5..ba81557 100644 --- a/arch/arm/cpu/armv7/sunxi/board.c +++ b/arch/arm/cpu/armv7/sunxi/board.c @@ -112,8 +112,10 @@ void s_init(void) #ifdef CONFIG_SPL_BUILD /* The sunxi internal brom will try to loader external bootloader * from mmc0, nand flash, mmc2. - * Unfortunately we can't check how SPL was loaded so assume - * it's always the first SD/MMC controller + * + * Unfortunately we can't check how SPL was loaded so assume it's + * always the first SD/MMC controller, unless it was explicitly + * stated that SPL is on nand flash. */ u32 spl_boot_device(void) { @@ -123,6 +125,12 @@ u32 spl_boot_device(void) * enabled build. It has many restrictions and can only boot over USB. */ return BOOT_DEVICE_BOARD; +#elif defined(CONFIG_SPL_NAND_SUPPORT) + /* + * This is compile time configuration informing SPL, that it + * was loaded from nand flash. + */ + return BOOT_DEVICE_NAND; #else /* * When booting from the SD card, the "eGON.BT0" signature is expected diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index 88e3358..1a30684 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -239,6 +239,18 @@ config MMC_SUNXI_SLOT_EXTRA slot or emmc on mmc1 - mmc3. Setting this to 1, 2 or 3 will enable support for this.
+config SPL_NAND_SUPPORT + bool "SPL/NAND mode support" + depends on SPL + default n + ---help--- + This enables support for booting from NAND internal + memory. U-Boot SPL doesn't detect where is it load from, + therefore this option is needed to properly load image from + flash. Option also disables MMC functionality on U-Boot due to + initialization errors encountered, when both controllers are + enabled. + config USB0_VBUS_PIN string "Vbus enable pin for usb0 (otg)" default "" diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile index 43766e0..7ad7412 100644 --- a/board/sunxi/Makefile +++ b/board/sunxi/Makefile @@ -9,6 +9,7 @@ # SPDX-License-Identifier: GPL-2.0+ # obj-y += board.o +obj-$(CONFIG_NAND_SUNXI) += nand.o obj-$(CONFIG_SUNXI_GMAC) += gmac.o obj-$(CONFIG_SUNXI_AHCI) += ahci.o obj-$(CONFIG_MACH_SUN4I) += dram_sun4i_auto.o diff --git a/board/sunxi/nand.c b/board/sunxi/nand.c new file mode 100644 index 0000000..e449da2 --- /dev/null +++ b/board/sunxi/nand.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2014, Antmicro Ltd <www.antmicro.com> + * Copyright (c) 2015, Turtle Solutions <www.turtle-solutions.eu> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <nand.h> + +/* minimal "boot0" style NAND support for Allwinner A20 */ +#define W32(a, b) (*(volatile unsigned int *)(a)) = b +#define R32(a) (*(volatile unsigned int *)(a)) + +/* temporary buffer for read of 1024 bytes */ +#ifdef CONFIG_SPL_BUILD +char temp_buf[0x400] __attribute__((aligned(0x10), section(".text#"))); +#else +void *temp_buf = 0x0; +#endif + +#define PORTC_BASE 0x01c20800 +#define CCMU_BASE 0x01c20000 +#define NANDFLASHC_BASE 0x01c03000 +#define DMAC_BASE 0x01c02000 + +#define NANDFLASHC_CTL 0x00000000 +#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 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 + +void nand_set_clocks(void) +{ + W32(PORTC_BASE + 0x48, 0x22222222); + W32(PORTC_BASE + 0x4C, 0x22222222); + W32(PORTC_BASE + 0x50, 0x2222222); + W32(PORTC_BASE + 0x54, 0x2); + W32(PORTC_BASE + 0x5C, 0x55555555); + W32(PORTC_BASE + 0x60, 0x15555); + W32(PORTC_BASE + 0x64, 0x5140); + W32(PORTC_BASE + 0x68, 0x4016); + + uint32_t val = R32(CCMU_BASE + 0x60); + W32(CCMU_BASE + 0x60, 0x2000 | val); + val = R32(CCMU_BASE + 0x80); + W32(CCMU_BASE + 0x80, val | 0x80000000 | 0x1); +} + +int initialized = 0; +void nand_init(void) +{ + initialized = 1; + uint32_t val; + nand_set_clocks(); + val = R32(NANDFLASHC_BASE + 0x00); + /* CTL = (1<<0 <-EN 1<<1 RESET) */ + W32(NANDFLASHC_BASE + 0x00, val | 0x3); /* enable and reset CTL */ + do { + val = R32(NANDFLASHC_BASE + 0x00); + if (val & (1<<1)) + break; + } while (1); +} + +/* random seed */ +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, + 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, +}; + +uint32_t ecc_errors = 0; + +/* read 0x400 bytes from real_addr to temp_buf */ +void nand_read_block(unsigned int real_addr, int syndrome) +{ + uint32_t val; + if (!initialized) + nand_init(); + + memset((void *)temp_buf, 0, 0x400); /* clear temp_buf */ + + /* set CMD */ + W32(NANDFLASHC_BASE + NANDFLASHC_CMD, 0xC000FF); + do { + val = R32(NANDFLASHC_BASE + NANDFLASHC_ST); + if (val & (1<<1)) + break; + udelay(1000); + } while (1); + + uint32_t page = real_addr / (8 * 1024); + if (page > 0xFFFF) { + /* TODO: currently this is not supported */ + printf("Reading from address >= %08X is not allowed.\n", + 0xFFFF * 8 * 1024); + return; + } + + uint32_t shift = real_addr % (8*1024); + W32(0x1C03038, 0); + + /* ECC_CTL, randomization */ + if (syndrome) { + W32(0x1C03034, (0x4A80<<16) | 0x0200 | 1 | (1<<3) | (1<<12)); + /* shift every 1kB in syndrome */ + shift += (shift / 0x400) * 0x2e; + + } else { + W32(0x1C03034, ((random_seed[page % 128]<<16) | + 0x0200 | 1 | (1<<3) | (1<<12))); + } + + uint32_t addr = (page << 16) | shift; + val = R32(NANDFLASHC_BASE + NANDFLASHC_CTL); + W32(NANDFLASHC_BASE + NANDFLASHC_CTL, val | (1<<14)); + + if (syndrome) { + W32(NANDFLASHC_BASE + NANDFLASHC_SPARE_AREA, 0x400); + } else { + uint32_t oob_offset = 0x2000 + (shift / 0x400) * 0x2e; + W32(NANDFLASHC_BASE + NANDFLASHC_SPARE_AREA, oob_offset); + } + + /* DMAC */ + W32(DMAC_BASE + 0x300, 0x0); /* clear dma cmd */ + /* read from REG_IO_DATA */ + W32(DMAC_BASE + 0x304, NANDFLASHC_BASE + NANDFLASHC_IO_DATA); + W32(DMAC_BASE + 0x308, (uint32_t)temp_buf); /* read to RAM */ + W32(DMAC_BASE + 0x318, 0x7F0F); + W32(DMAC_BASE + 0x30C, 0x400); /* 1kB */ + W32(DMAC_BASE + 0x300, 0x84000423); + + W32(NANDFLASHC_BASE + NANDFLASHC_RCMD_SET, 0x00E00530); + W32(NANDFLASHC_BASE + NANDFLASHC_SECTOR_NUM, 1); + W32(NANDFLASHC_BASE + NANDFLASHC_ADDR_LOW, addr); + W32(NANDFLASHC_BASE + NANDFLASHC_ADDR_HIGH, 0); + + /* CMD (PAGE READ) */ + W32(NANDFLASHC_BASE + NANDFLASHC_CMD, 0x85EC0000 + | (syndrome ? 0x02000000 : 0x0)); + do { /* wait for dma irq */ + val = R32(NANDFLASHC_BASE + NANDFLASHC_ST); + if (val & (1<<2)) + break; + udelay(1000); + } while (1); + + do { /* make sure cmd is finished */ + val = R32(DMAC_BASE + 300); + if (!(val & 0x80000000)) + break; + udelay(1000); + } while (1); + + if (R32(NANDFLASHC_BASE | NANDFLASHC_ECC_ST)) + ecc_errors++; +} + +int helper_load(uint32_t offs, unsigned int size, void *dest) +{ + uint32_t dst; + uint32_t adr = offs; + memset((void *)dest, 0x0, size); /* clean destination memory */ + ecc_errors = 0; + for (dst = (uint32_t)dest; dst < ((uint32_t)dest+size); dst += 0x400) { + /* if < 0x400000 then syndrome read */ + nand_read_block(adr, adr < 0x400000); + memcpy((void *)dst, (void *)temp_buf, 0x400); + adr += 0x400; + } + return ecc_errors; +} + +int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest) +{ + helper_load(offs, size, dest); + return 0; +} + +void nand_deselect(void) +{} diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index b8c369d..9d59fbb 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -74,24 +74,25 @@ void spl_nand_load_image(void) #endif #ifdef CONFIG_NAND_ENV_DST nand_spl_load_image(CONFIG_ENV_OFFSET, - sizeof(*header), (void *)header); + sizeof(*header), (void *)header); spl_parse_image_header(header); nand_spl_load_image(CONFIG_ENV_OFFSET, spl_image.size, - (void *)spl_image.load_addr); + (void *)spl_image.load_addr); #ifdef CONFIG_ENV_OFFSET_REDUND nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, - sizeof(*header), (void *)header); + sizeof(*header), (void *)header); spl_parse_image_header(header); nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, spl_image.size, - (void *)spl_image.load_addr); + (void *)spl_image.load_addr); #endif #endif /* Load u-boot */ nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS, - sizeof(*header), (void *)header); + sizeof(*header), (void *)header); spl_parse_image_header(header); nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS, - spl_image.size, (void *)(unsigned long)spl_image.load_addr); + spl_image.size, + (void *)(unsigned long)spl_image.load_addr); nand_deselect(); } #endif diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 365d9a5..b40cdd3 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -106,8 +106,10 @@ #define CONFIG_CMD_MMC #define CONFIG_MMC_SUNXI #define CONFIG_MMC_SUNXI_SLOT 0 +#if !defined(CONFIG_SPL_NAND_SUPPORT) #define CONFIG_ENV_IS_IN_MMC #define CONFIG_SYS_MMC_ENV_DEV 0 /* first detected MMC controller */ +#endif /* CONFIG_SPL_NAND_SUPPORT */ #endif
/* 4MB of malloc() pool */ @@ -323,6 +325,13 @@ extern int soft_i2c_gpio_scl; #define CONFIG_ENV_IS_NOWHERE #endif
+#ifdef CONFIG_SPL_NAND_SUPPORT +#define CONFIG_NAND +#define CONFIG_NAND_SUNXI +#define CONFIG_CMD_SPL_WRITE_SIZE 0x000400 +#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x008000 +#endif /* CONFIG_SPL_NAND_SUPPORT */ + #define CONFIG_MISC_INIT_R #define CONFIG_SYS_CONSOLE_IS_IN_ENV

On Wed, 2015-04-29 at 17:02 +0200, Daniel Kochmański wrote:
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index 88e3358..1a30684 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -239,6 +239,18 @@ config MMC_SUNXI_SLOT_EXTRA slot or emmc on mmc1 - mmc3. Setting this to 1, 2 or 3 will enable support for this.
+config SPL_NAND_SUPPORT
- bool "SPL/NAND mode support"
- depends on SPL
- default n
- ---help---
This enables support for booting from NAND internal
memory. U-Boot SPL doesn't detect where is it load from,
therefore this option is needed to properly load image from
flash. Option also disables MMC functionality on U-Boot due to
initialization errors encountered, when both controllers are
enabled.
Is this last bit a bug in the s/w or a hardware thing? Does this mean that MMC is not available in the main u-boot image too when NAND support is enabled?
config USB0_VBUS_PIN string "Vbus enable pin for usb0 (otg)" default "" diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile index 43766e0..7ad7412 100644 --- a/board/sunxi/Makefile +++ b/board/sunxi/Makefile @@ -9,6 +9,7 @@ # SPDX-License-Identifier: GPL-2.0+ # obj-y += board.o +obj-$(CONFIG_NAND_SUNXI) += nand.o
CONFIG_SUNXI_NAND would be more consistent with the rest I think.
obj-$(CONFIG_SUNXI_GMAC) += gmac.o obj-$(CONFIG_SUNXI_AHCI) += ahci.o
+void nand_set_clocks(void) +{
- W32(PORTC_BASE + 0x48, 0x22222222);
u-boot style is to declare a struct which matches the register layout and to do something like: struct nand_ctrl_foo *mcf = (void *)NANCFLASHC_BASE;
And use writel, set_bits, setclr_bits and friends.
Please also try and give sensible names to all the magic numbers, or at least include a comment explaining that these are magic numbers derived from $SOMEWHERE and we don't know what they mean (if that is the case).
Both of these apply to several bits of the code too.
- W32(PORTC_BASE + 0x4C, 0x22222222);
- W32(PORTC_BASE + 0x50, 0x2222222);
- W32(PORTC_BASE + 0x54, 0x2);
- W32(PORTC_BASE + 0x5C, 0x55555555);
- W32(PORTC_BASE + 0x60, 0x15555);
- W32(PORTC_BASE + 0x64, 0x5140);
- W32(PORTC_BASE + 0x68, 0x4016);
- uint32_t val = R32(CCMU_BASE + 0x60);
- W32(CCMU_BASE + 0x60, 0x2000 | val);
- val = R32(CCMU_BASE + 0x80);
- W32(CCMU_BASE + 0x80, val | 0x80000000 | 0x1);
+}
+int initialized = 0; +void nand_init(void) +{
- initialized = 1;
Please call this from somewhere during init e.g. board.c rather than from nand_read with a latch.
- uint32_t val;
- nand_set_clocks();
- val = R32(NANDFLASHC_BASE + 0x00);
- /* CTL = (1<<0 <-EN 1<<1 RESET) */
- W32(NANDFLASHC_BASE + 0x00, val | 0x3); /* enable and reset CTL */
- do {
val = R32(NANDFLASHC_BASE + 0x00);
if (val & (1<<1))
break;
- } while (1);
Potentially infinite loop?
There were some similar instances below which had a t/o. Perhaps combine them all into a helper similar to the dram code's mctl_await_completion()?
+uint32_t ecc_errors = 0;
+/* read 0x400 bytes from real_addr to temp_buf */ +void nand_read_block(unsigned int real_addr, int syndrome) +{
- uint32_t val;
- if (!initialized)
nand_init();
- memset((void *)temp_buf, 0, 0x400); /* clear temp_buf */
Can we not avoid going via this global temp_buf by setting DMAC_BASE + 0x308 to the correct address on each read?
Ian.

Ian Campbell writes:
On Wed, 2015-04-29 at 17:02 +0200, Daniel Kochmański wrote:
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index 88e3358..1a30684 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -239,6 +239,18 @@ config MMC_SUNXI_SLOT_EXTRA slot or emmc on mmc1 - mmc3. Setting this to 1, 2 or 3 will enable support for this.
+config SPL_NAND_SUPPORT
- bool "SPL/NAND mode support"
- depends on SPL
- default n
- ---help---
This enables support for booting from NAND internal
memory. U-Boot SPL doesn't detect where is it load from,
therefore this option is needed to properly load image from
flash. Option also disables MMC functionality on U-Boot due to
initialization errors encountered, when both controllers are
enabled.
Is this last bit a bug in the s/w or a hardware thing? Does this mean that MMC is not available in the main u-boot image too when NAND support is enabled?
I'm not sure what is a reason, but controller can't initialize MMC when SPL is loaded. MMC works in main u-boot allowing to boot from it and perform any other option (rescan, part, info, etc.). It is only SPL relevant.
config USB0_VBUS_PIN string "Vbus enable pin for usb0 (otg)" default "" diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile index 43766e0..7ad7412 100644 --- a/board/sunxi/Makefile +++ b/board/sunxi/Makefile @@ -9,6 +9,7 @@ # SPDX-License-Identifier: GPL-2.0+ # obj-y += board.o +obj-$(CONFIG_NAND_SUNXI) += nand.o
CONFIG_SUNXI_NAND would be more consistent with the rest I think.
OK.
obj-$(CONFIG_SUNXI_GMAC) += gmac.o obj-$(CONFIG_SUNXI_AHCI) += ahci.o
+void nand_set_clocks(void) +{
- W32(PORTC_BASE + 0x48, 0x22222222);
u-boot style is to declare a struct which matches the register layout and to do something like: struct nand_ctrl_foo *mcf = (void *)NANCFLASHC_BASE;
And use writel, set_bits, setclr_bits and friends.
OK, I'll read about it and try to adjust driver.
Please also try and give sensible names to all the magic numbers, or at least include a comment explaining that these are magic numbers derived from $SOMEWHERE and we don't know what they mean (if that is the case).
Both of these apply to several bits of the code too.
This work is mainly based on register guess-work from here: http://rhombus-tech.net/allwinner_a10/A10_register_guide/A10_NAND/ - so I can gather names from there and put them in source.
- W32(PORTC_BASE + 0x4C, 0x22222222);
- W32(PORTC_BASE + 0x50, 0x2222222);
- W32(PORTC_BASE + 0x54, 0x2);
- W32(PORTC_BASE + 0x5C, 0x55555555);
- W32(PORTC_BASE + 0x60, 0x15555);
- W32(PORTC_BASE + 0x64, 0x5140);
- W32(PORTC_BASE + 0x68, 0x4016);
- uint32_t val = R32(CCMU_BASE + 0x60);
- W32(CCMU_BASE + 0x60, 0x2000 | val);
- val = R32(CCMU_BASE + 0x80);
- W32(CCMU_BASE + 0x80, val | 0x80000000 | 0x1);
+}
+int initialized = 0; +void nand_init(void) +{
- initialized = 1;
Please call this from somewhere during init e.g. board.c rather than from nand_read with a latch.
Sure.
- uint32_t val;
- nand_set_clocks();
- val = R32(NANDFLASHC_BASE + 0x00);
- /* CTL = (1<<0 <-EN 1<<1 RESET) */
- W32(NANDFLASHC_BASE + 0x00, val | 0x3); /* enable and reset CTL */
- do {
val = R32(NANDFLASHC_BASE + 0x00);
if (val & (1<<1))
break;
- } while (1);
Potentially infinite loop?
There were some similar instances below which had a t/o. Perhaps combine them all into a helper similar to the dram code's mctl_await_completion()?
Ok, I'll look into that.
+uint32_t ecc_errors = 0;
+/* read 0x400 bytes from real_addr to temp_buf */ +void nand_read_block(unsigned int real_addr, int syndrome) +{
- uint32_t val;
- if (!initialized)
nand_init();
- memset((void *)temp_buf, 0, 0x400); /* clear temp_buf */
Can we not avoid going via this global temp_buf by setting DMAC_BASE + 0x308 to the correct address on each read?
I'll check this, I think I had problems with that, but if it works w/o temp_buf on both SPL and main U-Boot builds, then I'll get rid of it.
Ian.

(sorry for resending, used wrong mail here - not sure how mailing list will handle that).
Ian Campbell writes:
On Wed, 2015-04-29 at 17:02 +0200, Daniel Kochmański wrote:
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index 88e3358..1a30684 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -239,6 +239,18 @@ config MMC_SUNXI_SLOT_EXTRA slot or emmc on mmc1 - mmc3. Setting this to 1, 2 or 3 will enable support for this.
+config SPL_NAND_SUPPORT
- bool "SPL/NAND mode support"
- depends on SPL
- default n
- ---help---
This enables support for booting from NAND internal
memory. U-Boot SPL doesn't detect where is it load from,
therefore this option is needed to properly load image from
flash. Option also disables MMC functionality on U-Boot due to
initialization errors encountered, when both controllers are
enabled.
Is this last bit a bug in the s/w or a hardware thing? Does this mean that MMC is not available in the main u-boot image too when NAND support is enabled?
I'm not sure what is a reason, but controller can't initialize MMC when SPL is loaded. MMC works in main u-boot allowing to boot from it and perform any other option (rescan, part, info, etc.). It is only SPL relevant.
config USB0_VBUS_PIN string "Vbus enable pin for usb0 (otg)" default "" diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile index 43766e0..7ad7412 100644 --- a/board/sunxi/Makefile +++ b/board/sunxi/Makefile @@ -9,6 +9,7 @@ # SPDX-License-Identifier: GPL-2.0+ # obj-y += board.o +obj-$(CONFIG_NAND_SUNXI) += nand.o
CONFIG_SUNXI_NAND would be more consistent with the rest I think.
OK.
obj-$(CONFIG_SUNXI_GMAC) += gmac.o obj-$(CONFIG_SUNXI_AHCI) += ahci.o
+void nand_set_clocks(void) +{
- W32(PORTC_BASE + 0x48, 0x22222222);
u-boot style is to declare a struct which matches the register layout and to do something like: struct nand_ctrl_foo *mcf = (void *)NANCFLASHC_BASE;
And use writel, set_bits, setclr_bits and friends.
OK, I'll read about it and try to adjust driver.
Please also try and give sensible names to all the magic numbers, or at least include a comment explaining that these are magic numbers derived from $SOMEWHERE and we don't know what they mean (if that is the case).
Both of these apply to several bits of the code too.
This work is mainly based on register guess-work from here: http://rhombus-tech.net/allwinner_a10/A10_register_guide/A10_NAND/ - so I can gather names from there and put them in source.
- W32(PORTC_BASE + 0x4C, 0x22222222);
- W32(PORTC_BASE + 0x50, 0x2222222);
- W32(PORTC_BASE + 0x54, 0x2);
- W32(PORTC_BASE + 0x5C, 0x55555555);
- W32(PORTC_BASE + 0x60, 0x15555);
- W32(PORTC_BASE + 0x64, 0x5140);
- W32(PORTC_BASE + 0x68, 0x4016);
- uint32_t val = R32(CCMU_BASE + 0x60);
- W32(CCMU_BASE + 0x60, 0x2000 | val);
- val = R32(CCMU_BASE + 0x80);
- W32(CCMU_BASE + 0x80, val | 0x80000000 | 0x1);
+}
+int initialized = 0; +void nand_init(void) +{
- initialized = 1;
Please call this from somewhere during init e.g. board.c rather than from nand_read with a latch.
Sure.
- uint32_t val;
- nand_set_clocks();
- val = R32(NANDFLASHC_BASE + 0x00);
- /* CTL = (1<<0 <-EN 1<<1 RESET) */
- W32(NANDFLASHC_BASE + 0x00, val | 0x3); /* enable and reset CTL */
- do {
val = R32(NANDFLASHC_BASE + 0x00);
if (val & (1<<1))
break;
- } while (1);
Potentially infinite loop?
There were some similar instances below which had a t/o. Perhaps combine them all into a helper similar to the dram code's mctl_await_completion()?
Ok, I'll look into that.
+uint32_t ecc_errors = 0;
+/* read 0x400 bytes from real_addr to temp_buf */ +void nand_read_block(unsigned int real_addr, int syndrome) +{
- uint32_t val;
- if (!initialized)
nand_init();
- memset((void *)temp_buf, 0, 0x400); /* clear temp_buf */
Can we not avoid going via this global temp_buf by setting DMAC_BASE + 0x308 to the correct address on each read?
I'll check this, I think I had problems with that, but if it works w/o temp_buf on both SPL and main U-Boot builds, then I'll get rid of it.
Ian.

On Tue, 2015-05-05 at 11:19 +0200, Daniel Kochmański wrote:
(sorry for resending, used wrong mail here - not sure how mailing list will handle that).
Ian Campbell writes:
On Wed, 2015-04-29 at 17:02 +0200, Daniel Kochmański wrote:
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index 88e3358..1a30684 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -239,6 +239,18 @@ config MMC_SUNXI_SLOT_EXTRA slot or emmc on mmc1 - mmc3. Setting this to 1, 2 or 3 will enable support for this.
+config SPL_NAND_SUPPORT
- bool "SPL/NAND mode support"
- depends on SPL
- default n
- ---help---
This enables support for booting from NAND internal
memory. U-Boot SPL doesn't detect where is it load from,
therefore this option is needed to properly load image from
flash. Option also disables MMC functionality on U-Boot due to
initialization errors encountered, when both controllers are
enabled.
Is this last bit a bug in the s/w or a hardware thing? Does this mean that MMC is not available in the main u-boot image too when NAND support is enabled?
I'm not sure what is a reason, but controller can't initialize MMC when SPL is loaded. MMC works in main u-boot allowing to boot from it and perform any other option (rescan, part, info, etc.). It is only SPL relevant.
How strange! Hans, do you have any ideas about why this might be the case? Is there some overlap between MMC and NAND? I can't think what...

Hi,
On 09-05-15 15:53, Ian Campbell wrote:
On Tue, 2015-05-05 at 11:19 +0200, Daniel Kochmański wrote:
(sorry for resending, used wrong mail here - not sure how mailing list will handle that).
Ian Campbell writes:
On Wed, 2015-04-29 at 17:02 +0200, Daniel Kochmański wrote:
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index 88e3358..1a30684 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -239,6 +239,18 @@ config MMC_SUNXI_SLOT_EXTRA slot or emmc on mmc1 - mmc3. Setting this to 1, 2 or 3 will enable support for this.
+config SPL_NAND_SUPPORT
- bool "SPL/NAND mode support"
- depends on SPL
- default n
- ---help---
This enables support for booting from NAND internal
memory. U-Boot SPL doesn't detect where is it load from,
therefore this option is needed to properly load image from
flash. Option also disables MMC functionality on U-Boot due to
initialization errors encountered, when both controllers are
enabled.
Is this last bit a bug in the s/w or a hardware thing? Does this mean that MMC is not available in the main u-boot image too when NAND support is enabled?
I'm not sure what is a reason, but controller can't initialize MMC when SPL is loaded. MMC works in main u-boot allowing to boot from it and perform any other option (rescan, part, info, etc.). It is only SPL relevant.
How strange! Hans, do you have any ideas about why this might be the case? Is there some overlap between MMC and NAND? I can't think what...
Nope, I've no clue, things should work with both build-in, first thing which comes to mind is that we're running out of stack space / internal sram.
Second thing is, how did you test the SPL code with both build-in ? Did you boot from MMC or from NAND? It could be that the MMC code relies on some MMC setup done by the BROM, so that it will not work when booting from NAND.
Regards,
Hans

On Wed, 2015-04-29 at 17:02 +0200, Daniel Kochmański wrote:
Adds minimal DMA NAND driver for booting from NAND internal memory. New config option SPL_NAND_SUPPORT is created for sunxi board, which enables introduced driver and sets ENV_IS_NOWHERE (instead of ENV_IS_IN_MMC).
NAND driver utilizes DMA interface to flash controller, which supports randomization. Reading from both syndrome and non-syndrom partitions is supported. Writing to flash isn't implemented for time being.
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com
arch/arm/cpu/armv7/sunxi/board.c | 12 ++- board/sunxi/Kconfig | 12 +++ board/sunxi/Makefile | 1 + board/sunxi/nand.c | 219 +++++++++++++++++++++++++++++++++++++++ common/spl/spl_nand.c | 13 +-- include/configs/sunxi-common.h | 9 ++ 6 files changed, 258 insertions(+), 8 deletions(-) create mode 100644 board/sunxi/nand.c
NAND drivers go in drivers/mtd/nand (with "spl" in the name since it's an SPL driver).
-Scott

Introduces CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS, pointing to backup U-Boot instance in nand memory. In case if first header doesn't match, tries to load bootloader from this offset. In case of both failing, hang() is called.
Additionally define offset of backup U-boot for sunxi at start of second syndrome partition.
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com ---
README | 4 ++++ common/spl/spl_nand.c | 28 +++++++++++++++++++++++++--- include/configs/sunxi-common.h | 1 + 3 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/README b/README index ee65fdb..4ccf3cb 100644 --- a/README +++ b/README @@ -3722,6 +3722,10 @@ FIT uImage format: CONFIG_SYS_NAND_U_BOOT_OFFS Location in NAND to read U-Boot from
+ CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS + Location in NAND to read backup U-Boot from, if first + location doesn't contain valid image. + CONFIG_SYS_NAND_U_BOOT_DST Location in memory to load U-Boot to
diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 9d59fbb..7c44de1 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -2,6 +2,9 @@ * Copyright (C) 2011 * Corscience GmbH & Co. KG - Simon Schwarz schwarz@corscience.de * + * Copyright (C) 2015 + * Turtle Solutions - Daniel Kochmański dkochmanski@turtle-solutions.eu + * * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> @@ -90,9 +93,28 @@ void spl_nand_load_image(void) nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS, sizeof(*header), (void *)header); spl_parse_image_header(header); - nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS, - spl_image.size, - (void *)(unsigned long)spl_image.load_addr); + if (header->ih_os == IH_OS_U_BOOT) { + nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS, + spl_image.size, + (void *)(unsigned long)spl_image.load_addr); + nand_deselect(); + return; + } + puts("U-boot header didn't match.\n"); +#ifdef CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS + puts("Trying to start backup u-boot now...\n"); + nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS, + sizeof(*header), (void *)header); + spl_parse_image_header(header); + if (header->ih_os == IH_OS_U_BOOT) { + nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS, + spl_image.size, + (void *)(unsigned long)spl_image.load_addr); + nand_deselect(); + return; + } +#endif + puts("No valid u-boot image found.\n"); nand_deselect(); } #endif diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index b40cdd3..15fe512 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -330,6 +330,7 @@ extern int soft_i2c_gpio_scl; #define CONFIG_NAND_SUNXI #define CONFIG_CMD_SPL_WRITE_SIZE 0x000400 #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x008000 +#define CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS 0x208000 #endif /* CONFIG_SPL_NAND_SUPPORT */
#define CONFIG_MISC_INIT_R

On Wed, 2015-04-29 at 17:02 +0200, Daniel Kochmański wrote:
Introduces CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS, pointing to backup U-Boot instance in nand memory. In case if first header doesn't match, tries to load bootloader from this offset. In case of both failing, hang() is called.
Additionally define offset of backup U-boot for sunxi at start of second syndrome partition.
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com
README | 4 ++++ common/spl/spl_nand.c | 28 +++++++++++++++++++++++++---
This needs an ack from the maintainer of this file rather than Hans or I.
Adding CC of Simon who is mentioned in the header plus some people who touched the file recently in the hopes of finding out who that is.
Ian.

On Wed, Apr 29, 2015 at 8:02 AM, Daniel Kochmański dkochmanski@turtle-solutions.eu wrote:
Introduces CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS, pointing to backup U-Boot instance in nand memory. In case if first header doesn't match, tries to load bootloader from this offset. In case of both failing, hang() is called.
Additionally define offset of backup U-boot for sunxi at start of second syndrome partition.
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com
README | 4 ++++ common/spl/spl_nand.c | 28 +++++++++++++++++++++++++--- include/configs/sunxi-common.h | 1 + 3 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/README b/README index ee65fdb..4ccf3cb 100644 --- a/README +++ b/README @@ -3722,6 +3722,10 @@ FIT uImage format: CONFIG_SYS_NAND_U_BOOT_OFFS Location in NAND to read U-Boot from
CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS
Location in NAND to read backup U-Boot from, if first
location doesn't contain valid image.
CONFIG_SYS_NAND_U_BOOT_DST Location in memory to load U-Boot to
diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 9d59fbb..7c44de1 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -2,6 +2,9 @@
- Copyright (C) 2011
- Corscience GmbH & Co. KG - Simon Schwarz schwarz@corscience.de
- Copyright (C) 2015
- Turtle Solutions - Daniel Kochmański dkochmanski@turtle-solutions.eu
*/
- SPDX-License-Identifier: GPL-2.0+
#include <common.h> @@ -90,9 +93,28 @@ void spl_nand_load_image(void) nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS, sizeof(*header), (void *)header); spl_parse_image_header(header);
nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
spl_image.size,
(void *)(unsigned long)spl_image.load_addr);
if (header->ih_os == IH_OS_U_BOOT) {
nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
spl_image.size,
(void *)(unsigned long)spl_image.load_addr);
nand_deselect();
return;
}
puts("U-boot header didn't match.\n");
+#ifdef CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS
puts("Trying to start backup u-boot now...\n");
nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS,
sizeof(*header), (void *)header);
spl_parse_image_header(header);
if (header->ih_os == IH_OS_U_BOOT) {
nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS,
spl_image.size,
(void *)(unsigned long)spl_image.load_addr);
nand_deselect();
return;
}
+#endif
puts("No valid u-boot image found.\n"); nand_deselect();
} #endif
Daniel,
Under what circumstances would header->ih_os not be IH_OS_U_BOOT? It seems to me only if CONFIG_SYS_NAND_U_BOOT_OFFS pointed to the wrong place but wouldn't this be a board configuration error?
Are you trying to put some redundancy in for detecting a corrupted image? It seems to me that you would want to do more than check the header type in that case.
Tim

Hi,
Tim Harvey writes:
On Wed, Apr 29, 2015 at 8:02 AM, Daniel Kochmański dkochmanski@turtle-solutions.eu wrote:
Introduces CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS, pointing to backup U-Boot instance in nand memory. In case if first header doesn't match, tries to load bootloader from this offset. In case of both failing, hang() is called.
Additionally define offset of backup U-boot for sunxi at start of second syndrome partition.
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com
README | 4 ++++ common/spl/spl_nand.c | 28 +++++++++++++++++++++++++--- include/configs/sunxi-common.h | 1 + 3 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/README b/README index ee65fdb..4ccf3cb 100644 --- a/README +++ b/README @@ -3722,6 +3722,10 @@ FIT uImage format: CONFIG_SYS_NAND_U_BOOT_OFFS Location in NAND to read U-Boot from
CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS
Location in NAND to read backup U-Boot from, if first
location doesn't contain valid image.
CONFIG_SYS_NAND_U_BOOT_DST Location in memory to load U-Boot to
diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 9d59fbb..7c44de1 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -2,6 +2,9 @@
- Copyright (C) 2011
- Corscience GmbH & Co. KG - Simon Schwarz schwarz@corscience.de
- Copyright (C) 2015
- Turtle Solutions - Daniel Kochmański dkochmanski@turtle-solutions.eu
*/
- SPDX-License-Identifier: GPL-2.0+
#include <common.h> @@ -90,9 +93,28 @@ void spl_nand_load_image(void) nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS, sizeof(*header), (void *)header); spl_parse_image_header(header);
nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
spl_image.size,
(void *)(unsigned long)spl_image.load_addr);
if (header->ih_os == IH_OS_U_BOOT) {
nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
spl_image.size,
(void *)(unsigned long)spl_image.load_addr);
nand_deselect();
return;
}
puts("U-boot header didn't match.\n");
+#ifdef CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS
puts("Trying to start backup u-boot now...\n");
nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS,
sizeof(*header), (void *)header);
spl_parse_image_header(header);
if (header->ih_os == IH_OS_U_BOOT) {
nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS,
spl_image.size,
(void *)(unsigned long)spl_image.load_addr);
nand_deselect();
return;
}
+#endif
puts("No valid u-boot image found.\n"); nand_deselect();
} #endif
Daniel,
Under what circumstances would header->ih_os not be IH_OS_U_BOOT? It seems to me only if CONFIG_SYS_NAND_U_BOOT_OFFS pointed to the wrong place but wouldn't this be a board configuration error?
In case of sunxi boards so-called BROM when it reads bootloader from NAND it tries to load it from first block of NAND, and if header/checksum doesn't match, then it tries to read it from second one.
Are you trying to put some redundancy in for detecting a corrupted image? It seems to me that you would want to do more than check the header type in that case.
SPL can't detect, from which offset it was loaded, therefore even if image is correct and is placed on second block, it needs to check, if something it reads is actual U-Boot. If not, then it is placed at second one, and it should read U-Boot from second offset.
Tim

On Wed, 2015-04-29 at 17:02 +0200, Daniel Kochmański wrote:
diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 9d59fbb..7c44de1 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -2,6 +2,9 @@
- Copyright (C) 2011
- Corscience GmbH & Co. KG - Simon Schwarz schwarz@corscience.de
- Copyright (C) 2015
- Turtle Solutions - Daniel Kochmański dkochmanski@turtle-solutions.eu
*/
- SPDX-License-Identifier: GPL-2.0+
#include <common.h> @@ -90,9 +93,28 @@ void spl_nand_load_image(void) nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS, sizeof(*header), (void *)header); spl_parse_image_header(header);
- nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
spl_image.size,
(void *)(unsigned long)spl_image.load_addr);
- if (header->ih_os == IH_OS_U_BOOT) {
nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
spl_image.size,
(void *)(unsigned long)spl_image.load_addr);
nand_deselect();
return;
- }
- puts("U-boot header didn't match.\n");
+#ifdef CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS
- puts("Trying to start backup u-boot now...\n");
- nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS,
sizeof(*header), (void *)header);
- spl_parse_image_header(header);
- if (header->ih_os == IH_OS_U_BOOT) {
nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS,
spl_image.size,
(void *)(unsigned long)spl_image.load_addr);
nand_deselect();
return;
- }
+#endif
Factor this code into a function that is called twice rather than repeating everything.
-Scott

Patch adds support in spl_nand for preloading multiimage before loading u-boot into memory. It might be used in example to put in memory single image containing boot script, kernel and device tree.
Behavior is triggered, if CONFIG_SPL_NAND_MULTI_PRELOAD is defined - multiimage is loaded from CONFIG_SYS_NAND_MULTI_OFFS to address specified on image creation.
Additionally defines it in sunxi-common.h conditionally when CONFIG_SPL_NAND_SUPPORT is enabled. SPL tries to preload image from beginning of non-syndrome area.
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com ---
README | 6 ++++++ common/spl/spl_nand.c | 14 ++++++++++++++ include/configs/sunxi-common.h | 2 ++ 3 files changed, 22 insertions(+)
diff --git a/README b/README index 4ccf3cb..444b02f 100644 --- a/README +++ b/README @@ -3719,6 +3719,9 @@ FIT uImage format: CONFIG_SPL_NAND_BOOT Add support NAND boot
+ CONFIG_SPL_NAND_MULTI_PRELOAD + Preload multiimage from predefined offset in NAND. + CONFIG_SYS_NAND_U_BOOT_OFFS Location in NAND to read U-Boot from
@@ -3735,6 +3738,9 @@ FIT uImage format: CONFIG_SYS_NAND_U_BOOT_START Entry point in loaded image to jump to
+ CONFIG_SYS_NAND_MULTI_OFFS + Location in NAND to read multiimage from. + CONFIG_SYS_NAND_HW_ECC_OOBFIRST Define this if you need to first read the OOB and then the data. This is used, for example, on davinci platforms. diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 7c44de1..f87db0a 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -89,6 +89,20 @@ void spl_nand_load_image(void) (void *)spl_image.load_addr); #endif #endif +#ifdef CONFIG_SPL_NAND_MULTI_PRELOAD + /* Load multiimage */ + puts("Preloading multiimage.\n"); + nand_spl_load_image(CONFIG_SYS_NAND_MULTI_OFFS, + sizeof(*header), (void *)header); + spl_parse_image_header(header); + if (header->ih_type == IH_TYPE_MULTI) { + nand_spl_load_image(CONFIG_SYS_NAND_MULTI_OFFS, + spl_image.size, + (void *)(unsigned long)spl_image.load_addr); + } else { + puts("Multiimage header didn't match.\n"); + } +#endif /* CONFIG_SPL_NAND_MULTI_PRELOAD */ /* Load u-boot */ nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS, sizeof(*header), (void *)header); diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 15fe512..0b4ea7e 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -328,9 +328,11 @@ extern int soft_i2c_gpio_scl; #ifdef CONFIG_SPL_NAND_SUPPORT #define CONFIG_NAND #define CONFIG_NAND_SUNXI +#define CONFIG_SPL_NAND_MULTI_PRELOAD #define CONFIG_CMD_SPL_WRITE_SIZE 0x000400 #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x008000 #define CONFIG_SYS_NAND_U_BOOT_BACKUP_OFFS 0x208000 +#define CONFIG_SYS_NAND_MULTI_OFFS 0x400000 #endif /* CONFIG_SPL_NAND_SUPPORT */
#define CONFIG_MISC_INIT_R

On Wed, 2015-04-29 at 17:03 +0200, Daniel Kochmański wrote:
Patch adds support in spl_nand for preloading multiimage before loading u-boot into memory. It might be used in example to put in memory single image containing boot script, kernel and device tree.
Behavior is triggered, if CONFIG_SPL_NAND_MULTI_PRELOAD is defined - multiimage is loaded from CONFIG_SYS_NAND_MULTI_OFFS to address specified on image creation.
Additionally defines it in sunxi-common.h conditionally when CONFIG_SPL_NAND_SUPPORT is enabled. SPL tries to preload image from beginning of non-syndrome area.
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com
README | 6 ++++++ common/spl/spl_nand.c | 14 ++++++++++++++
As with the previous patch this likely needs an Ack from someone else.
Ian.

On Wed, 2015-04-29 at 17:03 +0200, Daniel Kochmański wrote:
Patch adds support in spl_nand for preloading multiimage before loading u-boot into memory. It might be used in example to put in memory single image containing boot script, kernel and device tree.
Why can't the main U-Boot load it?
Behavior is triggered, if CONFIG_SPL_NAND_MULTI_PRELOAD is defined - multiimage is loaded from CONFIG_SYS_NAND_MULTI_OFFS to address specified on image creation.
Additionally defines it in sunxi-common.h conditionally when CONFIG_SPL_NAND_SUPPORT is enabled. SPL tries to preload image from beginning of non-syndrome area.
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com
README | 6 ++++++ common/spl/spl_nand.c | 14 ++++++++++++++ include/configs/sunxi-common.h | 2 ++ 3 files changed, 22 insertions(+)
diff --git a/README b/README index 4ccf3cb..444b02f 100644 --- a/README +++ b/README @@ -3719,6 +3719,9 @@ FIT uImage format: CONFIG_SPL_NAND_BOOT Add support NAND boot
CONFIG_SPL_NAND_MULTI_PRELOAD
Preload multiimage from predefined offset in NAND.
Why is this not implied by CONFIG_SYS_NAND_MULTI_OFFS not being defined?
- CONFIG_SYS_NAND_U_BOOT_OFFS Location in NAND to read U-Boot from
@@ -3735,6 +3738,9 @@ FIT uImage format: CONFIG_SYS_NAND_U_BOOT_START Entry point in loaded image to jump to
CONFIG_SYS_NAND_MULTI_OFFS
Location in NAND to read multiimage from.
Why SYS and not SPL? Why not using kconfig?
- CONFIG_SYS_NAND_HW_ECC_OOBFIRST Define this if you need to first read the OOB and then the data. This is used, for example, on davinci platforms.
diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 7c44de1..f87db0a 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -89,6 +89,20 @@ void spl_nand_load_image(void) (void *)spl_image.load_addr); #endif #endif +#ifdef CONFIG_SPL_NAND_MULTI_PRELOAD
- /* Load multiimage */
- puts("Preloading multiimage.\n");
This function isn't this verbose for any of the other images...
-Scott

This patch adds a20_nandread command. It is simple function utilizing function from SPL nand driver `nand_spl_load_image`.
Usage: a20_nandread <address> <offset> <bytes>
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com ---
common/Kconfig | 7 +++++++ common/Makefile | 1 + common/cmd_a20_nandread.c | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 common/cmd_a20_nandread.c
diff --git a/common/Kconfig b/common/Kconfig index 5d7e48a..8edabb6 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -204,6 +204,13 @@ config CMD_NAND help NAND support.
+config CMD_A20_NANDREAD + depends on SPL_NAND_SUPPORT + bool "a20_nandread" + help + NAND read support for A20 SoC. Depends on SPL driver. + Usage: a20_nandread <address> <offset> <size> + config CMD_SPI bool "sspi" help diff --git a/common/Makefile b/common/Makefile index fba3830..9286518 100644 --- a/common/Makefile +++ b/common/Makefile @@ -138,6 +138,7 @@ obj-$(CONFIG_CMD_MMC) += cmd_mmc.o obj-$(CONFIG_CMD_MMC_SPI) += cmd_mmc_spi.o obj-$(CONFIG_MP) += cmd_mp.o obj-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o +obj-$(CONFIG_CMD_A20_NANDREAD) += cmd_a20_nandread.o obj-$(CONFIG_CMD_NAND) += cmd_nand.o obj-$(CONFIG_CMD_NET) += cmd_net.o obj-$(CONFIG_CMD_ONENAND) += cmd_onenand.o diff --git a/common/cmd_a20_nandread.c b/common/cmd_a20_nandread.c new file mode 100644 index 0000000..7361be7 --- /dev/null +++ b/common/cmd_a20_nandread.c @@ -0,0 +1,27 @@ +#include <common.h> +#include <command.h> + +int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest); + +static int do_a20_nandread(cmd_tbl_t *cmdtp, int flag, + int argc, char *const argv[]) +{ + if (argc != 4) { + printf("usage: a20_nandread <address> <offset> <bytes>\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("Loading 0x%08XB @ 0x%08X -> 0x%08X...\n", cnt, src, dst); + nand_spl_load_image(src, cnt, (void *)dst); + return 0; +} + +U_BOOT_CMD( + a20_nandread, CONFIG_SYS_MAXARGS, 3, do_a20_nandread, + "a20_nandread", + "[offset size bytes]\n" + " " +);

On Wed, 2015-04-29 at 17:03 +0200, Daniel Kochmański wrote:
This patch adds a20_nandread command. It is simple function utilizing function from SPL nand driver `nand_spl_load_image`.
Usage: a20_nandread <address> <offset> <bytes>
This stuff should really be integrated with cmd_nand.c rather than adding an adhoc SoC specific interface.
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com
common/Kconfig | 7 +++++++ common/Makefile | 1 + common/cmd_a20_nandread.c | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 common/cmd_a20_nandread.c
diff --git a/common/Kconfig b/common/Kconfig index 5d7e48a..8edabb6 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -204,6 +204,13 @@ config CMD_NAND help NAND support.
+config CMD_A20_NANDREAD
- depends on SPL_NAND_SUPPORT
- bool "a20_nandread"
- help
NAND read support for A20 SoC. Depends on SPL driver.
Usage: a20_nandread <address> <offset> <size>
config CMD_SPI bool "sspi" help diff --git a/common/Makefile b/common/Makefile index fba3830..9286518 100644 --- a/common/Makefile +++ b/common/Makefile @@ -138,6 +138,7 @@ obj-$(CONFIG_CMD_MMC) += cmd_mmc.o obj-$(CONFIG_CMD_MMC_SPI) += cmd_mmc_spi.o obj-$(CONFIG_MP) += cmd_mp.o obj-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o +obj-$(CONFIG_CMD_A20_NANDREAD) += cmd_a20_nandread.o obj-$(CONFIG_CMD_NAND) += cmd_nand.o obj-$(CONFIG_CMD_NET) += cmd_net.o obj-$(CONFIG_CMD_ONENAND) += cmd_onenand.o diff --git a/common/cmd_a20_nandread.c b/common/cmd_a20_nandread.c new file mode 100644 index 0000000..7361be7 --- /dev/null +++ b/common/cmd_a20_nandread.c @@ -0,0 +1,27 @@ +#include <common.h> +#include <command.h>
+int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest);
+static int do_a20_nandread(cmd_tbl_t *cmdtp, int flag,
int argc, char *const argv[])
+{
- if (argc != 4) {
printf("usage: a20_nandread <address> <offset> <bytes>\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("Loading 0x%08XB @ 0x%08X -> 0x%08X...\n", cnt, src, dst);
- nand_spl_load_image(src, cnt, (void *)dst);
- return 0;
+}
+U_BOOT_CMD(
- a20_nandread, CONFIG_SYS_MAXARGS, 3, do_a20_nandread,
- "a20_nandread",
- "[offset size bytes]\n"
- " "
+);

Hi,
On 05/02/2015 04:26 PM, Ian Campbell wrote:
On Wed, 2015-04-29 at 17:03 +0200, Daniel Kochmański wrote:
This patch adds a20_nandread command. It is simple function utilizing function from SPL nand driver `nand_spl_load_image`.
Usage: a20_nandread <address> <offset> <bytes>
This stuff should really be integrated with cmd_nand.c rather than adding an adhoc SoC specific interface.
I want to go even further and I see that this really needs to be integrated with the blkdev code so that one can just do:
ls nand 0:1
And things will just work, these way we can also just have the standard boot cmds from config_distro_bootcmd.h work rather then needing special nand boot commands.
Regards,
Hans
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com
common/Kconfig | 7 +++++++ common/Makefile | 1 + common/cmd_a20_nandread.c | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 common/cmd_a20_nandread.c
diff --git a/common/Kconfig b/common/Kconfig index 5d7e48a..8edabb6 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -204,6 +204,13 @@ config CMD_NAND help NAND support.
+config CMD_A20_NANDREAD
- depends on SPL_NAND_SUPPORT
- bool "a20_nandread"
- help
NAND read support for A20 SoC. Depends on SPL driver.
Usage: a20_nandread <address> <offset> <size>
- config CMD_SPI bool "sspi" help
diff --git a/common/Makefile b/common/Makefile index fba3830..9286518 100644 --- a/common/Makefile +++ b/common/Makefile @@ -138,6 +138,7 @@ obj-$(CONFIG_CMD_MMC) += cmd_mmc.o obj-$(CONFIG_CMD_MMC_SPI) += cmd_mmc_spi.o obj-$(CONFIG_MP) += cmd_mp.o obj-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o +obj-$(CONFIG_CMD_A20_NANDREAD) += cmd_a20_nandread.o obj-$(CONFIG_CMD_NAND) += cmd_nand.o obj-$(CONFIG_CMD_NET) += cmd_net.o obj-$(CONFIG_CMD_ONENAND) += cmd_onenand.o diff --git a/common/cmd_a20_nandread.c b/common/cmd_a20_nandread.c new file mode 100644 index 0000000..7361be7 --- /dev/null +++ b/common/cmd_a20_nandread.c @@ -0,0 +1,27 @@ +#include <common.h> +#include <command.h>
+int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest);
+static int do_a20_nandread(cmd_tbl_t *cmdtp, int flag,
int argc, char *const argv[])
+{
- if (argc != 4) {
printf("usage: a20_nandread <address> <offset> <bytes>\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("Loading 0x%08XB @ 0x%08X -> 0x%08X...\n", cnt, src, dst);
- nand_spl_load_image(src, cnt, (void *)dst);
- return 0;
+}
+U_BOOT_CMD(
- a20_nandread, CONFIG_SYS_MAXARGS, 3, do_a20_nandread,
- "a20_nandread",
- "[offset size bytes]\n"
- " "
+);

Hans de Goede writes:
Hi,
On 05/02/2015 04:26 PM, Ian Campbell wrote:
On Wed, 2015-04-29 at 17:03 +0200, Daniel Kochmański wrote:
This patch adds a20_nandread command. It is simple function utilizing function from SPL nand driver `nand_spl_load_image`.
Usage: a20_nandread <address> <offset> <bytes>
This stuff should really be integrated with cmd_nand.c rather than adding an adhoc SoC specific interface.
I want to go even further and I see that this really needs to be integrated with the blkdev code so that one can just do:
ls nand 0:1
And things will just work, these way we can also just have the standard boot cmds from config_distro_bootcmd.h work rather then needing special nand boot commands.
Regards,
Hans
It was more a convenient function then proper integration. I'll look into that, but it may take time - I'm quite unfamiliar with U-Boot nand interface.
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com
common/Kconfig | 7 +++++++ common/Makefile | 1 + common/cmd_a20_nandread.c | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 common/cmd_a20_nandread.c
diff --git a/common/Kconfig b/common/Kconfig index 5d7e48a..8edabb6 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -204,6 +204,13 @@ config CMD_NAND help NAND support.
+config CMD_A20_NANDREAD
- depends on SPL_NAND_SUPPORT
- bool "a20_nandread"
- help
NAND read support for A20 SoC. Depends on SPL driver.
Usage: a20_nandread <address> <offset> <size>
- config CMD_SPI bool "sspi" help
diff --git a/common/Makefile b/common/Makefile index fba3830..9286518 100644 --- a/common/Makefile +++ b/common/Makefile @@ -138,6 +138,7 @@ obj-$(CONFIG_CMD_MMC) += cmd_mmc.o obj-$(CONFIG_CMD_MMC_SPI) += cmd_mmc_spi.o obj-$(CONFIG_MP) += cmd_mp.o obj-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o +obj-$(CONFIG_CMD_A20_NANDREAD) += cmd_a20_nandread.o obj-$(CONFIG_CMD_NAND) += cmd_nand.o obj-$(CONFIG_CMD_NET) += cmd_net.o obj-$(CONFIG_CMD_ONENAND) += cmd_onenand.o diff --git a/common/cmd_a20_nandread.c b/common/cmd_a20_nandread.c new file mode 100644 index 0000000..7361be7 --- /dev/null +++ b/common/cmd_a20_nandread.c @@ -0,0 +1,27 @@ +#include <common.h> +#include <command.h>
+int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest);
+static int do_a20_nandread(cmd_tbl_t *cmdtp, int flag,
int argc, char *const argv[])
+{
- if (argc != 4) {
printf("usage: a20_nandread <address> <offset> <bytes>\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("Loading 0x%08XB @ 0x%08X -> 0x%08X...\n", cnt, src, dst);
- nand_spl_load_image(src, cnt, (void *)dst);
- return 0;
+}
+U_BOOT_CMD(
- a20_nandread, CONFIG_SYS_MAXARGS, 3, do_a20_nandread,
- "a20_nandread",
- "[offset size bytes]\n"
- " "
+);

Hi,
On 05-05-15 11:17, Daniel Kochmański wrote:
Hans de Goede writes:
Hi,
On 05/02/2015 04:26 PM, Ian Campbell wrote:
On Wed, 2015-04-29 at 17:03 +0200, Daniel Kochmański wrote:
This patch adds a20_nandread command. It is simple function utilizing function from SPL nand driver `nand_spl_load_image`.
Usage: a20_nandread <address> <offset> <bytes>
This stuff should really be integrated with cmd_nand.c rather than adding an adhoc SoC specific interface.
I want to go even further and I see that this really needs to be integrated with the blkdev code so that one can just do:
ls nand 0:1
And things will just work, these way we can also just have the standard boot cmds from config_distro_bootcmd.h work rather then needing special nand boot commands.
Regards,
Hans
It was more a convenient function then proper integration.
I understand but for upstream nand support we really want a proper solution, note that I'm find with having the nand support being read only, but it should really be integrated enough that things like:
ls nand 0:1
Will work.
I'll look into that, but it may take time - I'm quite unfamiliar with U-Boot nand interface.
Thanks!
Regards,
Hans

On Wed, 2015-04-29 at 17:03 +0200, Daniel Kochmański wrote:
This patch adds a20_nandread command. It is simple function utilizing function from SPL nand driver `nand_spl_load_image`.
Usage: a20_nandread <address> <offset> <bytes>
Signed-off-by: Daniel Kochmański dkochmanski@turtle-solutions.eu Cc: Ian Campbell ijc@hellion.org.uk Cc: Hans De Goede hdegoede@redhat.com
common/Kconfig | 7 +++++++ common/Makefile | 1 + common/cmd_a20_nandread.c | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 common/cmd_a20_nandread.c
Obviously a real NAND driver would be preferred (even if some functionality is missing at first), but if for some reason we do need to support simple read-only access using SPL code in the main U-Boot, what is a20-specific about this file beyond the use case?
-Scott
participants (6)
-
Daniel Kochmański
-
Daniel Kochmański
-
Hans de Goede
-
Ian Campbell
-
Scott Wood
-
Tim Harvey