arm: atmel: sama5d3: spl boot from fat fs SD card

Enable Atmel sama5d3xek boart spl boot support, which can load u-boot
from SD card with FAT file system.

Signed-off-by: Bo Shen <voice.shen@atmel.com>
Signed-off-by: Andreas Bießmann <andreas.devel@googlemail.com>
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
index d3347b3..0467d00 100644
--- a/arch/arm/cpu/armv7/Makefile
+++ b/arch/arm/cpu/armv7/Makefile
@@ -12,7 +12,7 @@
 obj-y	+= cpu.o
 obj-y	+= syslib.o
 
-ifneq ($(CONFIG_AM43XX)$(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA)$(CONFIG_MX6)$(CONFIG_TI81XX),)
+ifneq ($(CONFIG_AM43XX)$(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA)$(CONFIG_MX6)$(CONFIG_TI81XX)$(CONFIG_AT91FAMILY),)
 ifneq ($(CONFIG_SKIP_LOWLEVEL_INIT),y)
 obj-y	+= lowlevel_init.o
 endif
diff --git a/arch/arm/cpu/at91-common/Makefile b/arch/arm/cpu/at91-common/Makefile
index 671a05e..d97053f 100644
--- a/arch/arm/cpu/at91-common/Makefile
+++ b/arch/arm/cpu/at91-common/Makefile
@@ -8,4 +8,4 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-$(CONFIG_SPL_BUILD) += mpddrc.o
+obj-$(CONFIG_SPL_BUILD) += mpddrc.o spl.o
diff --git a/arch/arm/cpu/at91-common/spl.c b/arch/arm/cpu/at91-common/spl.c
new file mode 100644
index 0000000..37c0cc4
--- /dev/null
+++ b/arch/arm/cpu/at91-common/spl.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2013 Atmel Corporation
+ *		      Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_wdt.h>
+#include <asm/arch/clk.h>
+#include <spl.h>
+
+static void at91_disable_wdt(void)
+{
+	struct at91_wdt *wdt = (struct at91_wdt *)ATMEL_BASE_WDT;
+
+	writel(AT91_WDT_MR_WDDIS, &wdt->mr);
+}
+
+void at91_plla_init(u32 pllar)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	writel(pllar, &pmc->pllar);
+	while (!(readl(&pmc->sr) & (AT91_PMC_LOCKA | AT91_PMC_MCKRDY)))
+		;
+}
+
+void at91_mck_init(u32 mckr)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	u32 tmp;
+
+	tmp = readl(&pmc->mckr);
+	tmp &= ~(AT91_PMC_MCKR_PRES_MASK |
+		 AT91_PMC_MCKR_MDIV_MASK |
+		 AT91_PMC_MCKR_PLLADIV_2);
+	tmp |= mckr & (AT91_PMC_MCKR_PRES_MASK |
+		       AT91_PMC_MCKR_MDIV_MASK |
+		       AT91_PMC_MCKR_PLLADIV_2);
+	writel(tmp, &pmc->mckr);
+
+	while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
+		;
+}
+
+
+u32 spl_boot_device(void)
+{
+#ifdef CONFIG_SYS_USE_MMC
+	return BOOT_DEVICE_MMC1;
+#endif
+	return BOOT_DEVICE_NONE;
+}
+
+u32 spl_boot_mode(void)
+{
+	switch (spl_boot_device()) {
+#ifdef CONFIG_SYS_USE_MMC
+	case BOOT_DEVICE_MMC1:
+		return MMCSD_MODE_FAT;
+		break;
+#endif
+	case BOOT_DEVICE_NONE:
+	default:
+		hang();
+	}
+}
+
+void s_init(void)
+{
+	/* disable watchdog */
+	at91_disable_wdt();
+
+	/* PMC configuration */
+	at91_pmc_init();
+
+	at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK);
+
+	timer_init();
+
+	board_early_init_f();
+
+	preloader_console_init();
+
+	mem_init();
+}
diff --git a/arch/arm/cpu/at91-common/u-boot-spl.lds b/arch/arm/cpu/at91-common/u-boot-spl.lds
new file mode 100644
index 0000000..038335d
--- /dev/null
+++ b/arch/arm/cpu/at91-common/u-boot-spl.lds
@@ -0,0 +1,50 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * (C) Copyright 2010
+ * Texas Instruments, <www.ti.com>
+ *	Aneesh V <aneesh@ti.com>
+ *
+ * (C) 2013 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 = .;
+		arch/arm/cpu/armv7/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 = .;
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start = .;
+		*(.bss*)
+		. = ALIGN(4);
+		__bss_end = .;
+	} >.sdram
+}
diff --git a/arch/arm/include/asm/arch-at91/at91_common.h b/arch/arm/include/asm/arch-at91/at91_common.h
index abcb97d..3ca4d5b 100644
--- a/arch/arm/include/asm/arch-at91/at91_common.h
+++ b/arch/arm/include/asm/arch-at91/at91_common.h
@@ -22,5 +22,9 @@
 void at91_udp_hw_init(void);
 void at91_uhp_hw_init(void);
 void at91_lcd_hw_init(void);
+void at91_plla_init(u32 pllar);
+void at91_mck_init(u32 mckr);
+void at91_pmc_init(void);
+void mem_init(void);
 
 #endif /* AT91_COMMON_H */
diff --git a/arch/arm/include/asm/arch-at91/spl.h b/arch/arm/include/asm/arch-at91/spl.h
new file mode 100644
index 0000000..68c5349
--- /dev/null
+++ b/arch/arm/include/asm/arch-at91/spl.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2013 Atmel Corporation
+ *		      Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef	_ASM_ARCH_SPL_H_
+#define	_ASM_ARCH_SPL_H_
+
+enum {
+	BOOT_DEVICE_NONE,
+#ifdef CONFIG_SYS_USE_MMC
+	BOOT_DEVICE_MMC1,
+	BOOT_DEVICE_MMC2,
+	BOOT_DEVICE_MMC2_2,
+#endif
+};
+
+#endif