diff mbox

[U-Boot,RFC] ARM: atmel: at91sam9m10g45ek: enable SPL

Message ID 1419839635-817-1-git-send-email-voice.shen@atmel.com
State RFC, archived
Delegated to: Andreas Bießmann
Headers show

Commit Message

Bo Shen Dec. 29, 2014, 7:53 a.m. UTC
Supports boot up from NAND flash with software ECC eanbled.
And supports boot up from SD/MMC card with FAT file system.

As the boot from SD/MMC card with FAT file system, the BSS
segment is too big to fit into SRAM, so, use the lds to put
it into SDRAM. So, we need to initialize the SDRAM as soon
as possible. Borrow the low level init code from
<arm/arm/cpu/armv7/lowlevel_init.S> for this purpose.

Signed-off-by: Bo Shen <voice.shen@atmel.com>
---

 arch/arm/Kconfig                                |  1 +
 arch/arm/cpu/arm926ejs/at91/Makefile            |  4 ++
 arch/arm/cpu/arm926ejs/at91/spl_lowlevel_init.S | 37 ++++++++++++
 arch/arm/cpu/at91-common/spl_at91.c             | 10 ++++
 arch/arm/cpu/at91-common/u-boot-spl-arm9.lds    | 48 +++++++++++++++
 board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c | 80 +++++++++++++++++++++++++
 configs/at91sam9m10g45ek_mmc_defconfig          |  5 +-
 configs/at91sam9m10g45ek_nandflash_defconfig    |  5 +-
 include/configs/at91sam9m10g45ek.h              | 64 ++++++++++++++++++++
 9 files changed, 250 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/at91/spl_lowlevel_init.S
 create mode 100644 arch/arm/cpu/at91-common/u-boot-spl-arm9.lds

Comments

Heiko Schocher Jan. 5, 2015, 7:59 a.m. UTC | #1
Hello Bo,

Am 29.12.2014 08:53, schrieb Bo Shen:
> Supports boot up from NAND flash with software ECC eanbled.
> And supports boot up from SD/MMC card with FAT file system.
>
> As the boot from SD/MMC card with FAT file system, the BSS
> segment is too big to fit into SRAM, so, use the lds to put
> it into SDRAM. So, we need to initialize the SDRAM as soon
> as possible. Borrow the low level init code from
> <arm/arm/cpu/armv7/lowlevel_init.S> for this purpose.
>
> Signed-off-by: Bo Shen <voice.shen@atmel.com>
> ---
>
>   arch/arm/Kconfig                                |  1 +
>   arch/arm/cpu/arm926ejs/at91/Makefile            |  4 ++
>   arch/arm/cpu/arm926ejs/at91/spl_lowlevel_init.S | 37 ++++++++++++
>   arch/arm/cpu/at91-common/spl_at91.c             | 10 ++++
>   arch/arm/cpu/at91-common/u-boot-spl-arm9.lds    | 48 +++++++++++++++
>   board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c | 80 +++++++++++++++++++++++++
>   configs/at91sam9m10g45ek_mmc_defconfig          |  5 +-
>   configs/at91sam9m10g45ek_nandflash_defconfig    |  5 +-
>   include/configs/at91sam9m10g45ek.h              | 64 ++++++++++++++++++++
>   9 files changed, 250 insertions(+), 4 deletions(-)
>   create mode 100644 arch/arm/cpu/arm926ejs/at91/spl_lowlevel_init.S
>   create mode 100644 arch/arm/cpu/at91-common/u-boot-spl-arm9.lds
>
[...]
> diff --git a/arch/arm/cpu/arm926ejs/at91/spl_lowlevel_init.S b/arch/arm/cpu/arm926ejs/at91/spl_lowlevel_init.S
> new file mode 100644
> index 0000000..f1b2ec9
> --- /dev/null
> +++ b/arch/arm/cpu/arm926ejs/at91/spl_lowlevel_init.S
> @@ -0,0 +1,37 @@
> +/*
> + * A lowlevel_init function that sets up the stack to call a C function to
> + * perform further init.
> + *
> + * (C) Copyright 2010
> + * Texas Instruments, <www.ti.com>
> + *
> + * Author :
> + *	Aneesh V	<aneesh@ti.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <asm-offsets.h>
> +#include <config.h>
> +#include <linux/linkage.h>
> +
> +ENTRY(lowlevel_init)
> +	/*
> +	 * Setup a temporary stack
> +	 */
> +	ldr	sp, =CONFIG_SYS_INIT_SP_ADDR
> +	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */
> +
> +	ldr	r9, =gdata
> +
> +	/*
> +	 * Save the old lr(passed in ip) and the current lr to stack
> +	 */
> +	push	{ip, lr}
> +
> +	/*
> +	 * go setup pll, mux, memory
> +	 */
> +	bl	s_init
> +	pop	{ip, pc}
> +ENDPROC(lowlevel_init)

Hmm ... we have SPL support for at91sam9* boards without
such a file in U-Boot (and without an arch/arm/cpu/at91-common/u-boot-spl-arm9.lds),
see for example:

http://git.denx.de/?p=u-boot.git;a=blob;f=configs/corvus_defconfig;h=5d60847523487cac5e2e9421d9e6c6ff3fa2ce9e;hb=b7b3b8c6a0bfc87047cb18a7abfa06fb6e9d0331

The "spl_board_init" is called from ./common/spl/spl.c
from "board_init_r" which is called from "board_init_f"
in ./arch/arm/lib/spl.c, which is called from
./arch/arm/lib/crt0.S

Is this new file really needed? It should possible to remove
CONFIG_SKIP_LOWLEVEL_INIT
in include/configs/at91sam9m10g45ek.h ...

> diff --git a/arch/arm/cpu/at91-common/spl_at91.c b/arch/arm/cpu/at91-common/spl_at91.c
> index 89f588b..f044117 100644
> --- a/arch/arm/cpu/at91-common/spl_at91.c
> +++ b/arch/arm/cpu/at91-common/spl_at91.c
> @@ -71,7 +71,17 @@ void __weak at91_spl_board_init(void)
>   {
>   }
>
> +#ifndef CONFIG_SKIP_LOWLEVEL_INIT
> +__weak void spl_board_init(void)
> +{
> +}
> +#endif
> +
> +#ifdef CONFIG_SKIP_LOWLEVEL_INIT
>   void spl_board_init(void)
> +#else
> +void s_init(void)
> +#endif
>   {
>   	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;

... and adding this "ifdefs" could be prevented ...

What do you think?

Ah! you wrote:

 > As the boot from SD/MMC card with FAT file system, the BSS
 > segment is too big to fit into SRAM, so, use the lds to put
 > it into SDRAM. So, we need to initialize the SDRAM as soon
 > as possible. Borrow the low level init code from
 > <arm/arm/cpu/armv7/lowlevel_init.S> for this purpose.

Hmm... maybe we can include this in the existing code? So we
have BSS for all at91 boards in RAM?

Or, if not possible, we should convert the existing boards into
your framework ... if you can prepare such a patch I can test it
on  the corvus, taurus and axm boards ...

bye,
Heiko
>
> diff --git a/arch/arm/cpu/at91-common/u-boot-spl-arm9.lds b/arch/arm/cpu/at91-common/u-boot-spl-arm9.lds
> new file mode 100644
> index 0000000..6f350a9
> --- /dev/null
> +++ b/arch/arm/cpu/at91-common/u-boot-spl-arm9.lds
> @@ -0,0 +1,48 @@
> +/*
> + * Copyright (C) 2014 Atmel Corporation
> + *		      Bo Shen <voice.shen@atmel.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE, \
> +		LENGTH = CONFIG_SPL_MAX_SIZE }
> +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
> +		LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
> +
> +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
> +OUTPUT_ARCH(arm)
> +ENTRY(_start)
> +SECTIONS
> +{
> +	.text      :
> +	{
> +		__start = .;
> +		*(.vectors)
> +		arch/arm/cpu/arm926ejs/start.o	(.text*)
> +		*(.text*)
> +	} >.sram
> +
> +	. = ALIGN(4);
> +	.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
> +
> +	. = ALIGN(4);
> +	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
> +
> +	. = ALIGN(4);
> +	__image_copy_end = .;
> +
> +	.end :
> +	{
> +		*(.__end)
> +	} >.sram
> +
> +	.bss :
> +	{
> +		. = ALIGN(4);
> +		__bss_start = .;
> +		*(.bss*)
> +		. = ALIGN(4);
> +		__bss_end = .;
> +	} >.sdram
> +}
> diff --git a/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c b/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
> index b807ef9..4289179 100644
> --- a/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
> +++ b/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
> @@ -8,6 +8,7 @@
>
>   #include <common.h>
>   #include <asm/io.h>
> +#include <asm/arch/clk.h>
>   #include <asm/arch/at91sam9g45_matrix.h>
>   #include <asm/arch/at91sam9_smc.h>
>   #include <asm/arch/at91_common.h>
> @@ -15,6 +16,7 @@
>   #include <asm/arch/gpio.h>
>   #include <asm/arch/clk.h>
>   #include <lcd.h>
> +#include <linux/mtd/nand.h>
>   #include <atmel_lcdc.h>
>   #include <atmel_mci.h>
>   #if defined(CONFIG_RESET_PHY_R) && defined(CONFIG_MACB)
> @@ -71,6 +73,84 @@ void at91sam9m10g45ek_nand_hw_init(void)
>   }
>   #endif
>
> +#if defined(CONFIG_SPL_BUILD)
> +#include <spl.h>
> +#include <nand.h>
> +
> +void at91_spl_board_init(void)
> +{
> +	/*
> +	 * On the at91sam9m10g45ek board, the chip wm9711 stays in the
> +	 * test mode, so it needs do some action to exit test mode.
> +	 */
> +	at91_periph_clk_enable(ATMEL_ID_PIODE);
> +	at91_set_gpio_output(AT91_PIN_PD7, 0);
> +	at91_set_gpio_output(AT91_PIN_PD8, 0);
> +	at91_set_pio_pullup(AT91_PIO_PORTD, 7, 1);
> +	at91_set_pio_pullup(AT91_PIO_PORTD, 8, 1);
> +
> +#ifdef CONFIG_SYS_USE_MMC
> +	at91_mci_hw_init();
> +#elif CONFIG_SYS_USE_NANDFLASH
> +	at91sam9m10g45ek_nand_hw_init();
> +#endif
> +}
> +
> +#include <asm/arch/atmel_mpddrc.h>
> +static void ddr2_conf(struct atmel_mpddr *ddr2)
> +{
> +	ddr2->md = (ATMEL_MPDDRC_MD_DBW_16_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
> +
> +	ddr2->cr = (ATMEL_MPDDRC_CR_NC_COL_10 |
> +		    ATMEL_MPDDRC_CR_NR_ROW_14 |
> +		    ATMEL_MPDDRC_CR_DQMS_SHARED |
> +		    ATMEL_MPDDRC_CR_CAS_DDR_CAS3);
> +
> +	ddr2->rtr = 0x24b;
> +
> +	ddr2->tpr0 = (6 << ATMEL_MPDDRC_TPR0_TRAS_OFFSET |/* 6*7.5 = 45 ns */
> +		      2 << ATMEL_MPDDRC_TPR0_TRCD_OFFSET |/* 2*7.5 = 15 ns */
> +		      2 << ATMEL_MPDDRC_TPR0_TWR_OFFSET | /* 2*7.5 = 15 ns */
> +		      8 << ATMEL_MPDDRC_TPR0_TRC_OFFSET | /* 8*7.5 = 60 ns */
> +		      2 << ATMEL_MPDDRC_TPR0_TRP_OFFSET | /* 2*7.5 = 15 ns */
> +		      1 << ATMEL_MPDDRC_TPR0_TRRD_OFFSET | /* 1*7.5= 7.5 ns*/
> +		      1 << ATMEL_MPDDRC_TPR0_TWTR_OFFSET | /* 1 clk cycle */
> +		      2 << ATMEL_MPDDRC_TPR0_TMRD_OFFSET); /* 2 clk cycles */
> +
> +	ddr2->tpr1 = (2 << ATMEL_MPDDRC_TPR1_TXP_OFFSET | /* 2*7.5 = 15 ns */
> +		      200 << ATMEL_MPDDRC_TPR1_TXSRD_OFFSET |
> +		      16 << ATMEL_MPDDRC_TPR1_TXSNR_OFFSET |
> +		      14 << ATMEL_MPDDRC_TPR1_TRFC_OFFSET);
> +
> +	ddr2->tpr2 = (1 << ATMEL_MPDDRC_TPR2_TRTP_OFFSET |
> +		      0 << ATMEL_MPDDRC_TPR2_TRPA_OFFSET |
> +		      7 << ATMEL_MPDDRC_TPR2_TXARDS_OFFSET |
> +		      2 << ATMEL_MPDDRC_TPR2_TXARD_OFFSET);
> +}
> +
> +void mem_init(void)
> +{
> +	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
> +	struct at91_matrix *mat = (struct at91_matrix *)ATMEL_BASE_MATRIX;
> +	struct atmel_mpddr ddr2;
> +	unsigned long csa;
> +
> +	ddr2_conf(&ddr2);
> +
> +	/* enable DDR2 clock */
> +	writel(0x4, &pmc->scer);
> +
> +	/* Chip select 1 is for DDR2/SDRAM */
> +	csa = readl(&mat->ebicsa);
> +	csa |= AT91_MATRIX_EBI_CS1A_SDRAMC;
> +	csa &= ~AT91_MATRIX_EBI_VDDIOMSEL_3_3V;
> +	writel(csa, &mat->ebicsa);
> +
> +	/* DDRAM2 Controller initialize */
> +	ddr2_init(ATMEL_BASE_CS6, &ddr2);
> +}
> +#endif
> +
>   #ifdef CONFIG_CMD_USB
>   static void at91sam9m10g45ek_usb_hw_init(void)
>   {
> diff --git a/configs/at91sam9m10g45ek_mmc_defconfig b/configs/at91sam9m10g45ek_mmc_defconfig
> index 1681bc8..30d632d 100644
> --- a/configs/at91sam9m10g45ek_mmc_defconfig
> +++ b/configs/at91sam9m10g45ek_mmc_defconfig
> @@ -1,3 +1,4 @@
> +CONFIG_SPL=y
>   CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9M10G45,SYS_USE_MMC"
> -CONFIG_ARM=y
> -CONFIG_TARGET_AT91SAM9M10G45EK=y
> ++S:CONFIG_ARM=y
> ++S:CONFIG_TARGET_AT91SAM9M10G45EK=y
> diff --git a/configs/at91sam9m10g45ek_nandflash_defconfig b/configs/at91sam9m10g45ek_nandflash_defconfig
> index 61ae56e..b3de8a1 100644
> --- a/configs/at91sam9m10g45ek_nandflash_defconfig
> +++ b/configs/at91sam9m10g45ek_nandflash_defconfig
> @@ -1,3 +1,4 @@
> +CONFIG_SPL=y
>   CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9M10G45,SYS_USE_NANDFLASH"
> -CONFIG_ARM=y
> -CONFIG_TARGET_AT91SAM9M10G45EK=y
> ++S:CONFIG_ARM=y
> ++S:CONFIG_TARGET_AT91SAM9M10G45EK=y
> diff --git a/include/configs/at91sam9m10g45ek.h b/include/configs/at91sam9m10g45ek.h
> index db5d5ea..cb9a8f0 100644
> --- a/include/configs/at91sam9m10g45ek.h
> +++ b/include/configs/at91sam9m10g45ek.h
> @@ -26,7 +26,9 @@
>   #define CONFIG_CMDLINE_TAG		/* enable passing of ATAGs	*/
>   #define CONFIG_SETUP_MEMORY_TAGS
>   #define CONFIG_INITRD_TAG
> +#ifndef CONFIG_SPL_BUILD
>   #define CONFIG_SKIP_LOWLEVEL_INIT
> +#endif
>   #define CONFIG_BOARD_EARLY_INIT_F
>   #define CONFIG_DISPLAY_CPUINFO
>
> @@ -98,8 +100,12 @@
>   #define CONFIG_SYS_SDRAM_BASE           ATMEL_BASE_CS6
>   #define CONFIG_SYS_SDRAM_SIZE		0x08000000
>
> +#ifdef CONFIG_SPL_BUILD
> +#define CONFIG_SYS_INIT_SP_ADDR		0x310000
> +#else
>   #define CONFIG_SYS_INIT_SP_ADDR \
>   	(CONFIG_SYS_SDRAM_BASE + 4 * 1024 - GENERATED_GBL_DATA_SIZE)
> +#endif
>
>   /* NAND flash */
>   #ifdef CONFIG_CMD_NAND
> @@ -203,4 +209,62 @@
>    */
>   #define CONFIG_SYS_MALLOC_LEN		ROUND(3 * CONFIG_ENV_SIZE + 128*1024, 0x1000)
>
> +/* Defines for SPL */
> +#define CONFIG_SPL_FRAMEWORK
> +#define CONFIG_SPL_TEXT_BASE		0x300000
> +#define CONFIG_SPL_MAX_SIZE		0x010000
> +
> +#define CONFIG_SPL_BSS_START_ADDR	0x70000000
> +#define CONFIG_SPL_BSS_MAX_SIZE		0x00080000
> +#define CONFIG_SYS_SPL_MALLOC_START	0x70080000
> +#define CONFIG_SYS_SPL_MALLOC_SIZE	0x00080000
> +
> +#define CONFIG_SPL_LIBCOMMON_SUPPORT
> +#define CONFIG_SPL_LIBGENERIC_SUPPORT
> +#define CONFIG_SPL_SERIAL_SUPPORT
> +#define CONFIG_SPL_GPIO_SUPPORT
> +
> +#define CONFIG_SPL_BOARD_INIT
> +#define CONFIG_SYS_MONITOR_LEN		0x80000
> +
> +#ifdef CONFIG_SYS_USE_MMC
> +#define CONFIG_SPL_LDSCRIPT		arch/arm/cpu/at91-common/u-boot-spl-arm9.lds
> +#define CONFIG_SPL_MMC_SUPPORT
> +#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS	0x400
> +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x200
> +#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
> +#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.img"
> +#define CONFIG_SPL_FAT_SUPPORT
> +#define CONFIG_SPL_LIBDISK_SUPPORT
> +
> +#elif CONFIG_SYS_USE_NANDFLASH
> +#define CONFIG_SYS_NAND_ENABLE_PIN_SPL	(2*32 + 14)
> +#define CONFIG_SPL_NAND_SUPPORT
> +#define CONFIG_SPL_NAND_DRIVERS
> +#define CONFIG_SPL_NAND_BASE
> +#define CONFIG_SPL_NAND_ECC
> +#define CONFIG_SPL_NAND_SOFTECC
> +#define CONFIG_SYS_NAND_U_BOOT_OFFS	0x40000
> +#define CONFIG_SYS_NAND_U_BOOT_SIZE	0x80000
> +#define CONFIG_SYS_NAND_5_ADDR_CYCLE
> +
> +#define CONFIG_SYS_NAND_PAGE_SIZE	0x800
> +#define CONFIG_SYS_NAND_BLOCK_SIZE	0x20000
> +#define CONFIG_SYS_NAND_PAGE_COUNT	64
> +#define CONFIG_SYS_NAND_BAD_BLOCK_POS	NAND_LARGE_BADBLOCK_POS
> +#define CONFIG_SYS_NAND_ECCSIZE		256
> +#define CONFIG_SYS_NAND_ECCBYTES	3
> +#define CONFIG_SYS_NAND_OOBSIZE		64
> +#define CONFIG_SYS_NAND_ECCPOS		{ 40, 41, 42, 43, 44, 45, 46, 47, \
> +					  48, 49, 50, 51, 52, 53, 54, 55, \
> +					  56, 57, 58, 59, 60, 61, 62, 63, }
> +#endif
> +
> +#define CONFIG_SPL_ATMEL_SIZE
> +#define CONFIG_SYS_MASTER_CLOCK		132096000
> +#define CONFIG_SYS_AT91_PLLA		0x20c73f03
> +#define CONFIG_SYS_MCKR			0x1301
> +#define CONFIG_SYS_MCKR_CSS		0x1302
> +
> +#define ATMEL_BASE_MPDDRC		ATMEL_BASE_DDRSDRC0
>   #endif
>
Bo Shen Jan. 5, 2015, 8:19 a.m. UTC | #2
Hi Heiko,

On 01/05/2015 03:59 PM, Heiko Schocher wrote:
>> +#ifdef CONFIG_SKIP_LOWLEVEL_INIT
>>   void spl_board_init(void)
>> +#else
>> +void s_init(void)
>> +#endif
>>   {
>>       struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
>
> ... and adding this "ifdefs" could be prevented ...
>
> What do you think?
>
> Ah! you wrote:
>
>  > As the boot from SD/MMC card with FAT file system, the BSS
>  > segment is too big to fit into SRAM, so, use the lds to put
>  > it into SDRAM. So, we need to initialize the SDRAM as soon
>  > as possible. Borrow the low level init code from
>  > <arm/arm/cpu/armv7/lowlevel_init.S> for this purpose.
>
> Hmm... maybe we can include this in the existing code? So we

The existed code is located in <arch/arm/cpu/armv7> directory, I think 
it is difficult to include it.

I think we can put it into <arch/arm/cpu/arm926ejs> directory, I am not 
sure it will help others. As other SoC has low level init code. Or, as 
the patch, put it into <arch/arm/cpu/arm926ejs/at91> directory for at91 
series only.

> have BSS for all at91 boards in RAM?

It depends, we still can put the BSS into SRAM use the common 
u-boot-spl.lds.
Only put BSS into SDRAM/DDR, when use u-boot-spl-arm9.lds.


> Or, if not possible, we should convert the existing boards into
> your framework ... if you can prepare such a patch I can test it
> on  the corvus, taurus and axm boards ...

If the upper method for low level initialize code is chosen, I will 
prepare such patch for the boards you mentioned.

> bye,
> Heiko

Best Regards,
Bo Shen
Heiko Schocher Jan. 5, 2015, 8:46 a.m. UTC | #3
Hello Bo,

Am 05.01.2015 09:19, schrieb Bo Shen:
> Hi Heiko,
>
> On 01/05/2015 03:59 PM, Heiko Schocher wrote:
>>> +#ifdef CONFIG_SKIP_LOWLEVEL_INIT
>>>   void spl_board_init(void)
>>> +#else
>>> +void s_init(void)
>>> +#endif
>>>   {
>>>       struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
>>
>> ... and adding this "ifdefs" could be prevented ...
>>
>> What do you think?
>>
>> Ah! you wrote:
>>
>>  > As the boot from SD/MMC card with FAT file system, the BSS
>>  > segment is too big to fit into SRAM, so, use the lds to put
>>  > it into SDRAM. So, we need to initialize the SDRAM as soon
>>  > as possible. Borrow the low level init code from
>>  > <arm/arm/cpu/armv7/lowlevel_init.S> for this purpose.
>>
>> Hmm... maybe we can include this in the existing code? So we
>
> The existed code is located in <arch/arm/cpu/armv7> directory, I think it is difficult to include it.
>
> I think we can put it into <arch/arm/cpu/arm926ejs> directory, I am not sure it will help others. As other SoC has low level init code. Or, as the patch, put it into <arch/arm/cpu/arm926ejs/at91> directory for at91 series only.

I thought with "maybe we can include this in the existing code?"

adding into existing at91 code the earlier RAM initialization and
using BSS in RAM, without needing CONFIG_SKIP_LOWLEVEL_INIT ...

>> have BSS for all at91 boards in RAM?
>
> It depends, we still can put the BSS into SRAM use the common u-boot-spl.lds.
> Only put BSS into SDRAM/DDR, when use u-boot-spl-arm9.lds.

Ok, Yes.

>> Or, if not possible, we should convert the existing boards into
>> your framework ... if you can prepare such a patch I can test it
>> on  the corvus, taurus and axm boards ...
>
> If the upper method for low level initialize code is chosen, I will prepare such patch for the boards you mentioned.

I vote for having only one way for the at91 boards, so
your approach is also OK for me ... if andreas is fine
with it, please feel free to send me a patch for testing
on the mentioned boards, thanks!

bye,
Heiko
diff mbox

Patch

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5eb1d03..f4788c6 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -141,6 +141,7 @@  config TARGET_AT91SAM9263EK
 config TARGET_AT91SAM9M10G45EK
 	bool "Support at91sam9m10g45ek"
 	select CPU_ARM926EJS
+	select SUPPORT_SPL
 
 config TARGET_AT91SAM9N12EK
 	bool "Support at91sam9n12ek"
diff --git a/arch/arm/cpu/arm926ejs/at91/Makefile b/arch/arm/cpu/arm926ejs/at91/Makefile
index 698a28d..238434b 100644
--- a/arch/arm/cpu/arm926ejs/at91/Makefile
+++ b/arch/arm/cpu/arm926ejs/at91/Makefile
@@ -25,5 +25,9 @@  obj-y	+= reset.o
 obj-y	+= timer.o
 
 ifndef CONFIG_SKIP_LOWLEVEL_INIT
+ifdef CONFIG_SPL_BUILD
+obj-y	+= spl_lowlevel_init.o
+else
 obj-y	+= lowlevel_init.o
 endif
+endif
diff --git a/arch/arm/cpu/arm926ejs/at91/spl_lowlevel_init.S b/arch/arm/cpu/arm926ejs/at91/spl_lowlevel_init.S
new file mode 100644
index 0000000..f1b2ec9
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/at91/spl_lowlevel_init.S
@@ -0,0 +1,37 @@ 
+/*
+ * A lowlevel_init function that sets up the stack to call a C function to
+ * perform further init.
+ *
+ * (C) Copyright 2010
+ * Texas Instruments, <www.ti.com>
+ *
+ * Author :
+ *	Aneesh V	<aneesh@ti.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <linux/linkage.h>
+
+ENTRY(lowlevel_init)
+	/*
+	 * Setup a temporary stack
+	 */
+	ldr	sp, =CONFIG_SYS_INIT_SP_ADDR
+	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */
+
+	ldr	r9, =gdata
+
+	/*
+	 * Save the old lr(passed in ip) and the current lr to stack
+	 */
+	push	{ip, lr}
+
+	/*
+	 * go setup pll, mux, memory
+	 */
+	bl	s_init
+	pop	{ip, pc}
+ENDPROC(lowlevel_init)
diff --git a/arch/arm/cpu/at91-common/spl_at91.c b/arch/arm/cpu/at91-common/spl_at91.c
index 89f588b..f044117 100644
--- a/arch/arm/cpu/at91-common/spl_at91.c
+++ b/arch/arm/cpu/at91-common/spl_at91.c
@@ -71,7 +71,17 @@  void __weak at91_spl_board_init(void)
 {
 }
 
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+__weak void spl_board_init(void)
+{
+}
+#endif
+
+#ifdef CONFIG_SKIP_LOWLEVEL_INIT
 void spl_board_init(void)
+#else
+void s_init(void)
+#endif
 {
 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
 
diff --git a/arch/arm/cpu/at91-common/u-boot-spl-arm9.lds b/arch/arm/cpu/at91-common/u-boot-spl-arm9.lds
new file mode 100644
index 0000000..6f350a9
--- /dev/null
+++ b/arch/arm/cpu/at91-common/u-boot-spl-arm9.lds
@@ -0,0 +1,48 @@ 
+/*
+ * Copyright (C) 2014 Atmel Corporation
+ *		      Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE, \
+		LENGTH = CONFIG_SPL_MAX_SIZE }
+MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
+		LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	.text      :
+	{
+		__start = .;
+		*(.vectors)
+		arch/arm/cpu/arm926ejs/start.o	(.text*)
+		*(.text*)
+	} >.sram
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
+
+	. = ALIGN(4);
+	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
+
+	. = ALIGN(4);
+	__image_copy_end = .;
+
+	.end :
+	{
+		*(.__end)
+	} >.sram
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start = .;
+		*(.bss*)
+		. = ALIGN(4);
+		__bss_end = .;
+	} >.sdram
+}
diff --git a/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c b/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
index b807ef9..4289179 100644
--- a/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
+++ b/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
@@ -8,6 +8,7 @@ 
 
 #include <common.h>
 #include <asm/io.h>
+#include <asm/arch/clk.h>
 #include <asm/arch/at91sam9g45_matrix.h>
 #include <asm/arch/at91sam9_smc.h>
 #include <asm/arch/at91_common.h>
@@ -15,6 +16,7 @@ 
 #include <asm/arch/gpio.h>
 #include <asm/arch/clk.h>
 #include <lcd.h>
+#include <linux/mtd/nand.h>
 #include <atmel_lcdc.h>
 #include <atmel_mci.h>
 #if defined(CONFIG_RESET_PHY_R) && defined(CONFIG_MACB)
@@ -71,6 +73,84 @@  void at91sam9m10g45ek_nand_hw_init(void)
 }
 #endif
 
+#if defined(CONFIG_SPL_BUILD)
+#include <spl.h>
+#include <nand.h>
+
+void at91_spl_board_init(void)
+{
+	/*
+	 * On the at91sam9m10g45ek board, the chip wm9711 stays in the
+	 * test mode, so it needs do some action to exit test mode.
+	 */
+	at91_periph_clk_enable(ATMEL_ID_PIODE);
+	at91_set_gpio_output(AT91_PIN_PD7, 0);
+	at91_set_gpio_output(AT91_PIN_PD8, 0);
+	at91_set_pio_pullup(AT91_PIO_PORTD, 7, 1);
+	at91_set_pio_pullup(AT91_PIO_PORTD, 8, 1);
+
+#ifdef CONFIG_SYS_USE_MMC
+	at91_mci_hw_init();
+#elif CONFIG_SYS_USE_NANDFLASH
+	at91sam9m10g45ek_nand_hw_init();
+#endif
+}
+
+#include <asm/arch/atmel_mpddrc.h>
+static void ddr2_conf(struct atmel_mpddr *ddr2)
+{
+	ddr2->md = (ATMEL_MPDDRC_MD_DBW_16_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
+
+	ddr2->cr = (ATMEL_MPDDRC_CR_NC_COL_10 |
+		    ATMEL_MPDDRC_CR_NR_ROW_14 |
+		    ATMEL_MPDDRC_CR_DQMS_SHARED |
+		    ATMEL_MPDDRC_CR_CAS_DDR_CAS3);
+
+	ddr2->rtr = 0x24b;
+
+	ddr2->tpr0 = (6 << ATMEL_MPDDRC_TPR0_TRAS_OFFSET |/* 6*7.5 = 45 ns */
+		      2 << ATMEL_MPDDRC_TPR0_TRCD_OFFSET |/* 2*7.5 = 15 ns */
+		      2 << ATMEL_MPDDRC_TPR0_TWR_OFFSET | /* 2*7.5 = 15 ns */
+		      8 << ATMEL_MPDDRC_TPR0_TRC_OFFSET | /* 8*7.5 = 60 ns */
+		      2 << ATMEL_MPDDRC_TPR0_TRP_OFFSET | /* 2*7.5 = 15 ns */
+		      1 << ATMEL_MPDDRC_TPR0_TRRD_OFFSET | /* 1*7.5= 7.5 ns*/
+		      1 << ATMEL_MPDDRC_TPR0_TWTR_OFFSET | /* 1 clk cycle */
+		      2 << ATMEL_MPDDRC_TPR0_TMRD_OFFSET); /* 2 clk cycles */
+
+	ddr2->tpr1 = (2 << ATMEL_MPDDRC_TPR1_TXP_OFFSET | /* 2*7.5 = 15 ns */
+		      200 << ATMEL_MPDDRC_TPR1_TXSRD_OFFSET |
+		      16 << ATMEL_MPDDRC_TPR1_TXSNR_OFFSET |
+		      14 << ATMEL_MPDDRC_TPR1_TRFC_OFFSET);
+
+	ddr2->tpr2 = (1 << ATMEL_MPDDRC_TPR2_TRTP_OFFSET |
+		      0 << ATMEL_MPDDRC_TPR2_TRPA_OFFSET |
+		      7 << ATMEL_MPDDRC_TPR2_TXARDS_OFFSET |
+		      2 << ATMEL_MPDDRC_TPR2_TXARD_OFFSET);
+}
+
+void mem_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	struct at91_matrix *mat = (struct at91_matrix *)ATMEL_BASE_MATRIX;
+	struct atmel_mpddr ddr2;
+	unsigned long csa;
+
+	ddr2_conf(&ddr2);
+
+	/* enable DDR2 clock */
+	writel(0x4, &pmc->scer);
+
+	/* Chip select 1 is for DDR2/SDRAM */
+	csa = readl(&mat->ebicsa);
+	csa |= AT91_MATRIX_EBI_CS1A_SDRAMC;
+	csa &= ~AT91_MATRIX_EBI_VDDIOMSEL_3_3V;
+	writel(csa, &mat->ebicsa);
+
+	/* DDRAM2 Controller initialize */
+	ddr2_init(ATMEL_BASE_CS6, &ddr2);
+}
+#endif
+
 #ifdef CONFIG_CMD_USB
 static void at91sam9m10g45ek_usb_hw_init(void)
 {
diff --git a/configs/at91sam9m10g45ek_mmc_defconfig b/configs/at91sam9m10g45ek_mmc_defconfig
index 1681bc8..30d632d 100644
--- a/configs/at91sam9m10g45ek_mmc_defconfig
+++ b/configs/at91sam9m10g45ek_mmc_defconfig
@@ -1,3 +1,4 @@ 
+CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9M10G45,SYS_USE_MMC"
-CONFIG_ARM=y
-CONFIG_TARGET_AT91SAM9M10G45EK=y
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_AT91SAM9M10G45EK=y
diff --git a/configs/at91sam9m10g45ek_nandflash_defconfig b/configs/at91sam9m10g45ek_nandflash_defconfig
index 61ae56e..b3de8a1 100644
--- a/configs/at91sam9m10g45ek_nandflash_defconfig
+++ b/configs/at91sam9m10g45ek_nandflash_defconfig
@@ -1,3 +1,4 @@ 
+CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9M10G45,SYS_USE_NANDFLASH"
-CONFIG_ARM=y
-CONFIG_TARGET_AT91SAM9M10G45EK=y
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_AT91SAM9M10G45EK=y
diff --git a/include/configs/at91sam9m10g45ek.h b/include/configs/at91sam9m10g45ek.h
index db5d5ea..cb9a8f0 100644
--- a/include/configs/at91sam9m10g45ek.h
+++ b/include/configs/at91sam9m10g45ek.h
@@ -26,7 +26,9 @@ 
 #define CONFIG_CMDLINE_TAG		/* enable passing of ATAGs	*/
 #define CONFIG_SETUP_MEMORY_TAGS
 #define CONFIG_INITRD_TAG
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_SKIP_LOWLEVEL_INIT
+#endif
 #define CONFIG_BOARD_EARLY_INIT_F
 #define CONFIG_DISPLAY_CPUINFO
 
@@ -98,8 +100,12 @@ 
 #define CONFIG_SYS_SDRAM_BASE           ATMEL_BASE_CS6
 #define CONFIG_SYS_SDRAM_SIZE		0x08000000
 
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_INIT_SP_ADDR		0x310000
+#else
 #define CONFIG_SYS_INIT_SP_ADDR \
 	(CONFIG_SYS_SDRAM_BASE + 4 * 1024 - GENERATED_GBL_DATA_SIZE)
+#endif
 
 /* NAND flash */
 #ifdef CONFIG_CMD_NAND
@@ -203,4 +209,62 @@ 
  */
 #define CONFIG_SYS_MALLOC_LEN		ROUND(3 * CONFIG_ENV_SIZE + 128*1024, 0x1000)
 
+/* Defines for SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_TEXT_BASE		0x300000
+#define CONFIG_SPL_MAX_SIZE		0x010000
+
+#define CONFIG_SPL_BSS_START_ADDR	0x70000000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x00080000
+#define CONFIG_SYS_SPL_MALLOC_START	0x70080000
+#define CONFIG_SYS_SPL_MALLOC_SIZE	0x00080000
+
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_GPIO_SUPPORT
+
+#define CONFIG_SPL_BOARD_INIT
+#define CONFIG_SYS_MONITOR_LEN		0x80000
+
+#ifdef CONFIG_SYS_USE_MMC
+#define CONFIG_SPL_LDSCRIPT		arch/arm/cpu/at91-common/u-boot-spl-arm9.lds
+#define CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS	0x400
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x200
+#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
+#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.img"
+#define CONFIG_SPL_FAT_SUPPORT
+#define CONFIG_SPL_LIBDISK_SUPPORT
+
+#elif CONFIG_SYS_USE_NANDFLASH
+#define CONFIG_SYS_NAND_ENABLE_PIN_SPL	(2*32 + 14)
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_ECC
+#define CONFIG_SPL_NAND_SOFTECC
+#define CONFIG_SYS_NAND_U_BOOT_OFFS	0x40000
+#define CONFIG_SYS_NAND_U_BOOT_SIZE	0x80000
+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
+
+#define CONFIG_SYS_NAND_PAGE_SIZE	0x800
+#define CONFIG_SYS_NAND_BLOCK_SIZE	0x20000
+#define CONFIG_SYS_NAND_PAGE_COUNT	64
+#define CONFIG_SYS_NAND_BAD_BLOCK_POS	NAND_LARGE_BADBLOCK_POS
+#define CONFIG_SYS_NAND_ECCSIZE		256
+#define CONFIG_SYS_NAND_ECCBYTES	3
+#define CONFIG_SYS_NAND_OOBSIZE		64
+#define CONFIG_SYS_NAND_ECCPOS		{ 40, 41, 42, 43, 44, 45, 46, 47, \
+					  48, 49, 50, 51, 52, 53, 54, 55, \
+					  56, 57, 58, 59, 60, 61, 62, 63, }
+#endif
+
+#define CONFIG_SPL_ATMEL_SIZE
+#define CONFIG_SYS_MASTER_CLOCK		132096000
+#define CONFIG_SYS_AT91_PLLA		0x20c73f03
+#define CONFIG_SYS_MCKR			0x1301
+#define CONFIG_SYS_MCKR_CSS		0x1302
+
+#define ATMEL_BASE_MPDDRC		ATMEL_BASE_DDRSDRC0
 #endif