[U-Boot] [PATCH v2 0/3] arm: atmel: sama5d3: add spi and nand spl boot support

This patch enable spi and nand spl boot support on sama5d3xek
Changes in v2: - Address the comments from Scott Wood
Bo Shen (3): arm: atmel: sama5d3: add spi spl boot support mtd: nand: atmel: prepare for nand spl boot support arm: atmel: sama5d3: add nand spl boot support
arch/arm/cpu/at91-common/spl.c | 4 + arch/arm/include/asm/arch-at91/spl.h | 4 + board/atmel/sama5d3xek/sama5d3xek.c | 4 + drivers/mtd/nand/atmel_nand.c | 208 +++++++++++++++++++++++++++++++++++ include/configs/sama5d3xek.h | 23 ++++ include/nand.h | 6 + 6 files changed, 249 insertions(+)

Add SPI SPL boot support for sama5d3xek board.
Signed-off-by: Bo Shen voice.shen@atmel.com --- Changes in v2: - NONE
arch/arm/cpu/at91-common/spl.c | 2 ++ arch/arm/include/asm/arch-at91/spl.h | 2 ++ board/atmel/sama5d3xek/sama5d3xek.c | 2 ++ include/configs/sama5d3xek.h | 11 +++++++++++ 4 files changed, 17 insertions(+)
diff --git a/arch/arm/cpu/at91-common/spl.c b/arch/arm/cpu/at91-common/spl.c index 37c0cc4..2598e09 100644 --- a/arch/arm/cpu/at91-common/spl.c +++ b/arch/arm/cpu/at91-common/spl.c @@ -52,6 +52,8 @@ u32 spl_boot_device(void) { #ifdef CONFIG_SYS_USE_MMC return BOOT_DEVICE_MMC1; +#elif CONFIG_SYS_USE_SERIALFLASH + return BOOT_DEVICE_SPI; #endif return BOOT_DEVICE_NONE; } diff --git a/arch/arm/include/asm/arch-at91/spl.h b/arch/arm/include/asm/arch-at91/spl.h index 68c5349..f4ced49 100644 --- a/arch/arm/include/asm/arch-at91/spl.h +++ b/arch/arm/include/asm/arch-at91/spl.h @@ -14,6 +14,8 @@ enum { BOOT_DEVICE_MMC1, BOOT_DEVICE_MMC2, BOOT_DEVICE_MMC2_2, +#elif CONFIG_SYS_USE_SERIALFLASH + BOOT_DEVICE_SPI, #endif };
diff --git a/board/atmel/sama5d3xek/sama5d3xek.c b/board/atmel/sama5d3xek/sama5d3xek.c index eff94a4..8a214de 100644 --- a/board/atmel/sama5d3xek/sama5d3xek.c +++ b/board/atmel/sama5d3xek/sama5d3xek.c @@ -307,6 +307,8 @@ void spl_board_init(void) { #ifdef CONFIG_SYS_USE_MMC sama5d3xek_mci_hw_init(); +#elif CONFIG_SYS_USE_SERIALFLASH + at91_spi0_hw_init(1 << 0); #endif }
diff --git a/include/configs/sama5d3xek.h b/include/configs/sama5d3xek.h index c34feb5..510f22c 100644 --- a/include/configs/sama5d3xek.h +++ b/include/configs/sama5d3xek.h @@ -258,6 +258,8 @@ #define CONFIG_SPL_SERIAL_SUPPORT
#define CONFIG_SPL_BOARD_INIT +#define CONFIG_SYS_MONITOR_LEN (512 << 10) + #ifdef CONFIG_SYS_USE_MMC #define CONFIG_SPL_LDSCRIPT arch/arm/cpu/at91-common/u-boot-spl.lds #define CONFIG_SPL_MMC_SUPPORT @@ -267,6 +269,15 @@ #define CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME "u-boot.img" #define CONFIG_SPL_FAT_SUPPORT #define CONFIG_SPL_LIBDISK_SUPPORT + +#elif CONFIG_SYS_USE_SERIALFLASH +#define CONFIG_SPL_SPI_SUPPORT +#define CONFIG_SPL_SPI_FLASH_SUPPORT +#define CONFIG_SPL_SPI_LOAD +#define CONFIG_SPL_SPI_BUS 0 +#define CONFIG_SPL_SPI_CS 0 +#define CONFIG_SYS_SPI_U_BOOT_OFFS 0x8400 + #endif
#endif

Dear Bo Shen,
Bo Shen voice.shen@atmel.com writes:
Add SPI SPL boot support for sama5d3xek board.
Signed-off-by: Bo Shen voice.shen@atmel.com
Changes in v2:
- NONE
arch/arm/cpu/at91-common/spl.c | 2 ++ arch/arm/include/asm/arch-at91/spl.h | 2 ++ board/atmel/sama5d3xek/sama5d3xek.c | 2 ++ include/configs/sama5d3xek.h | 11 +++++++++++ 4 files changed, 17 insertions(+)
applied to u-boot-atmel/master, thanks!
Best regards, Andreas Bießmann

Prepare for nand spl boot support. It supports nand software ECC and hardware PMECC. This patch is take <drivers/mtd/nand/nand_spl_simple.c> as reference.
Signed-off-by: Bo Shen voice.shen@atmel.com --- Changes in v2: - Address the comments from Scott Wood
drivers/mtd/nand/atmel_nand.c | 208 ++++++++++++++++++++++++++++++++++++++++++ include/nand.h | 6 ++ 2 files changed, 214 insertions(+)
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 05ddfbb..e1fc48f 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -31,6 +31,10 @@
#ifdef CONFIG_ATMEL_NAND_HW_PMECC
+#ifdef CONFIG_SPL_BUILD +#undef CONFIG_SYS_NAND_ONFI_DETECTION +#endif + struct atmel_nand_host { struct pmecc_regs __iomem *pmecc; struct pmecc_errloc_regs __iomem *pmerrloc; @@ -1169,6 +1173,209 @@ static int at91_nand_ready(struct mtd_info *mtd) } #endif
+#ifdef CONFIG_SPL_BUILD +/* The following code is for SPL */ +static nand_info_t mtd; +static struct nand_chip nand_chip; + +static int nand_command(int block, int page, uint32_t offs, u8 cmd) +{ + struct nand_chip *this = mtd.priv; + int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT; + void (*hwctrl)(struct mtd_info *mtd, int cmd, + unsigned int ctrl) = this->cmd_ctrl; + + while (this->dev_ready(&mtd)) + ; + + if (cmd == NAND_CMD_READOOB) { + offs += CONFIG_SYS_NAND_PAGE_SIZE; + cmd = NAND_CMD_READ0; + } + + hwctrl(&mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE); + + if (this->options & NAND_BUSWIDTH_16) + offs >>= 1; + + hwctrl(&mtd, offs & 0xff, NAND_CTRL_ALE | NAND_CTRL_CHANGE); + hwctrl(&mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE); + hwctrl(&mtd, (page_addr & 0xff), NAND_CTRL_ALE); + hwctrl(&mtd, ((page_addr >> 8) & 0xff), NAND_CTRL_ALE); +#ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE + hwctrl(&mtd, (page_addr >> 16) & 0x0f, NAND_CTRL_ALE); +#endif + hwctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); + + hwctrl(&mtd, NAND_CMD_READSTART, NAND_CTRL_CLE | NAND_CTRL_CHANGE); + hwctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); + + while (this->dev_ready(&mtd)) + ; + + return 0; +} + +static int nand_is_bad_block(int block) +{ + struct nand_chip *this = mtd.priv; + + nand_command(block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS, NAND_CMD_READOOB); + + if (this->options & NAND_BUSWIDTH_16) { + if (readw(this->IO_ADDR_R) != 0xffff) + return 1; + } else { + if (readb(this->IO_ADDR_R) != 0xff) + return 1; + } + + return 0; +} + +#ifdef CONFIG_SPL_NAND_ECC +static int nand_ecc_pos[] = CONFIG_SYS_NAND_ECCPOS; +#define ECCSTEPS (CONFIG_SYS_NAND_PAGE_SIZE / \ + CONFIG_SYS_NAND_ECCSIZE) +#define ECCTOTAL (ECCSTEPS * CONFIG_SYS_NAND_ECCBYTES) + +static int nand_read_page(int block, int page, void *dst) +{ + struct nand_chip *this = mtd.priv; + u_char ecc_calc[ECCTOTAL]; + u_char ecc_code[ECCTOTAL]; + u_char oob_data[CONFIG_SYS_NAND_OOBSIZE]; + int eccsize = CONFIG_SYS_NAND_ECCSIZE; + int eccbytes = CONFIG_SYS_NAND_ECCBYTES; + int eccsteps = ECCSTEPS; + int i; + uint8_t *p = dst; + nand_command(block, page, 0, NAND_CMD_READ0); + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + if (this->ecc.mode != NAND_ECC_SOFT) + this->ecc.hwctl(&mtd, NAND_ECC_READ); + this->read_buf(&mtd, p, eccsize); + this->ecc.calculate(&mtd, p, &ecc_calc[i]); + } + this->read_buf(&mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE); + + for (i = 0; i < ECCTOTAL; i++) + ecc_code[i] = oob_data[nand_ecc_pos[i]]; + + eccsteps = ECCSTEPS; + p = dst; + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) + this->ecc.correct(&mtd, p, &ecc_code[i], &ecc_calc[i]); + + return 0; +} +#else +static int nand_read_page(int block, int page, void *dst) +{ + struct nand_chip *this = mtd.priv; + + nand_command(block, page, 0, NAND_CMD_READ0); + atmel_nand_pmecc_read_page(&mtd, this, dst, 0, page); + + return 0; +} +#endif /* CONFIG_SPL_NAND_ECC */ + +int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst) +{ + unsigned int block, lastblock; + unsigned int page; + + block = offs / CONFIG_SYS_NAND_BLOCK_SIZE; + lastblock = (offs + size - 1) / CONFIG_SYS_NAND_BLOCK_SIZE; + page = (offs % CONFIG_SYS_NAND_BLOCK_SIZE) / CONFIG_SYS_NAND_PAGE_SIZE; + + while (block <= lastblock) { + if (!nand_is_bad_block(block)) { + while (page < CONFIG_SYS_NAND_PAGE_COUNT) { + nand_read_page(block, page, dst); + dst += CONFIG_SYS_NAND_PAGE_SIZE; + page++; + } + + page = 0; + } else { + lastblock++; + } + + block++; + } + + return 0; +} + +int at91_nand_wait_ready(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + + udelay(this->chip_delay); + + return 0; +} + +int board_nand_init(struct nand_chip *nand) +{ + int ret = 0; + + nand->ecc.mode = NAND_ECC_SOFT; +#ifdef CONFIG_SYS_NAND_DBW_16 + nand->options = NAND_BUSWIDTH_16; + nand->read_buf = nand_read_buf16; +#else + nand->read_buf = nand_read_buf; +#endif + nand->cmd_ctrl = at91_nand_hwcontrol; +#ifdef CONFIG_SYS_NAND_READY_PIN + nand->dev_ready = at91_nand_ready; +#else + nand->dev_ready = at91_nand_wait_ready; +#endif + nand->chip_delay = 20; + +#ifdef CONFIG_ATMEL_NAND_HWECC +#ifdef CONFIG_ATMEL_NAND_HW_PMECC + ret = atmel_pmecc_nand_init_params(nand, &mtd); +#endif +#endif + + return ret; +} + +void nand_init(void) +{ + mtd.writesize = CONFIG_SYS_NAND_PAGE_SIZE; + mtd.oobsize = CONFIG_SYS_NAND_OOBSIZE; + mtd.priv = &nand_chip; + nand_chip.IO_ADDR_R = (void __iomem *)CONFIG_SYS_NAND_BASE; + nand_chip.IO_ADDR_W = (void __iomem *)CONFIG_SYS_NAND_BASE; + board_nand_init(&nand_chip); + +#ifdef CONFIG_SPL_NAND_ECC + if (nand_chip.ecc.mode == NAND_ECC_SOFT) { + nand_chip.ecc.calculate = nand_calculate_ecc; + nand_chip.ecc.correct = nand_correct_data; + } +#endif + + if (nand_chip.select_chip) + nand_chip.select_chip(&mtd, 0); +} + +void nand_deselect(void) +{ + if (nand_chip.select_chip) + nand_chip.select_chip(&mtd, -1); +} + +#else + #ifndef CONFIG_SYS_NAND_BASE_LIST #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } #endif @@ -1227,3 +1434,4 @@ void board_nand_init(void) dev_err(host->dev, "atmel_nand: Fail to initialize #%d chip", i); } +#endif /* CONFIG_SPL_BUILD */ diff --git a/include/nand.h b/include/nand.h index 84116f4..fc735d1 100644 --- a/include/nand.h +++ b/include/nand.h @@ -21,10 +21,16 @@ * at the same time, so do it here. When all drivers are * converted, this will go away. */ +#ifdef CONFIG_SPL_BUILD +#if defined(CONFIG_NAND_FSL_ELBC) || defined(CONFIG_NAND_FSL_IFC) +#define CONFIG_SYS_NAND_SELF_INIT +#endif +#else #if defined(CONFIG_NAND_FSL_ELBC) || defined(CONFIG_NAND_ATMEL)\ || defined(CONFIG_NAND_FSL_IFC) #define CONFIG_SYS_NAND_SELF_INIT #endif +#endif
extern void nand_init(void);

Dear Bo Shen,
Bo Shen voice.shen@atmel.com writes:
Prepare for nand spl boot support. It supports nand software ECC and hardware PMECC. This patch is take <drivers/mtd/nand/nand_spl_simple.c> as reference.
Signed-off-by: Bo Shen voice.shen@atmel.com
Changes in v2:
- Address the comments from Scott Wood
drivers/mtd/nand/atmel_nand.c | 208 ++++++++++++++++++++++++++++++++++++++++++ include/nand.h | 6 ++ 2 files changed, 214 insertions(+)
applied to u-boot-atmel/master, thanks!
Best regards, Andreas Bießmann

Add NAND SPL boot support with hardware PMECC.
Signed-off-by: Bo Shen voice.shen@atmel.com --- Changes in v2: - NONE
arch/arm/cpu/at91-common/spl.c | 2 ++ arch/arm/include/asm/arch-at91/spl.h | 2 ++ board/atmel/sama5d3xek/sama5d3xek.c | 2 ++ include/configs/sama5d3xek.h | 12 ++++++++++++ 4 files changed, 18 insertions(+)
diff --git a/arch/arm/cpu/at91-common/spl.c b/arch/arm/cpu/at91-common/spl.c index 2598e09..7f4debb 100644 --- a/arch/arm/cpu/at91-common/spl.c +++ b/arch/arm/cpu/at91-common/spl.c @@ -52,6 +52,8 @@ u32 spl_boot_device(void) { #ifdef CONFIG_SYS_USE_MMC return BOOT_DEVICE_MMC1; +#elif CONFIG_SYS_USE_NANDFLASH + return BOOT_DEVICE_NAND; #elif CONFIG_SYS_USE_SERIALFLASH return BOOT_DEVICE_SPI; #endif diff --git a/arch/arm/include/asm/arch-at91/spl.h b/arch/arm/include/asm/arch-at91/spl.h index f4ced49..d8a87da 100644 --- a/arch/arm/include/asm/arch-at91/spl.h +++ b/arch/arm/include/asm/arch-at91/spl.h @@ -14,6 +14,8 @@ enum { BOOT_DEVICE_MMC1, BOOT_DEVICE_MMC2, BOOT_DEVICE_MMC2_2, +#elif CONFIG_SYS_USE_NANDFLASH + BOOT_DEVICE_NAND, #elif CONFIG_SYS_USE_SERIALFLASH BOOT_DEVICE_SPI, #endif diff --git a/board/atmel/sama5d3xek/sama5d3xek.c b/board/atmel/sama5d3xek/sama5d3xek.c index 8a214de..c835c12 100644 --- a/board/atmel/sama5d3xek/sama5d3xek.c +++ b/board/atmel/sama5d3xek/sama5d3xek.c @@ -307,6 +307,8 @@ void spl_board_init(void) { #ifdef CONFIG_SYS_USE_MMC sama5d3xek_mci_hw_init(); +#elif CONFIG_SYS_USE_NANDFLASH + sama5d3xek_nand_hw_init(); #elif CONFIG_SYS_USE_SERIALFLASH at91_spi0_hw_init(1 << 0); #endif diff --git a/include/configs/sama5d3xek.h b/include/configs/sama5d3xek.h index 510f22c..516be85 100644 --- a/include/configs/sama5d3xek.h +++ b/include/configs/sama5d3xek.h @@ -270,6 +270,18 @@ #define CONFIG_SPL_FAT_SUPPORT #define CONFIG_SPL_LIBDISK_SUPPORT
+#elif CONFIG_SYS_USE_NANDFLASH +#define CONFIG_SPL_NAND_SUPPORT +#define CONFIG_SPL_NAND_DRIVERS +#define CONFIG_SPL_NAND_BASE +#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x40000 +#define CONFIG_SYS_NAND_5_ADDR_CYCLE +#define CONFIG_SYS_NAND_PAGE_SIZE 0x800 +#define CONFIG_SYS_NAND_PAGE_COUNT 64 +#define CONFIG_SYS_NAND_OOBSIZE 64 +#define CONFIG_SYS_NAND_BLOCK_SIZE 0x20000 +#define CONFIG_SYS_NAND_BAD_BLOCK_POS 0x0 + #elif CONFIG_SYS_USE_SERIALFLASH #define CONFIG_SPL_SPI_SUPPORT #define CONFIG_SPL_SPI_FLASH_SUPPORT

Dear Bo Shen,
Bo Shen voice.shen@atmel.com writes:
Add NAND SPL boot support with hardware PMECC.
Signed-off-by: Bo Shen voice.shen@atmel.com
Changes in v2:
- NONE
arch/arm/cpu/at91-common/spl.c | 2 ++ arch/arm/include/asm/arch-at91/spl.h | 2 ++ board/atmel/sama5d3xek/sama5d3xek.c | 2 ++ include/configs/sama5d3xek.h | 12 ++++++++++++ 4 files changed, 18 insertions(+)
applied to u-boot-atmel/master, thanks!
Best regards, Andreas Bießmann
participants (2)
-
Andreas Bießmann
-
Bo Shen