ARM: atmel: add sama5d4ek board support

The code for this board supports following features:
  - Boot media support: NAND flash/SD card/SPI flash
  - Support LCD display
  - Support ethernet
  - Support USB mass storage

Signed-off-by: Bo Shen <voice.shen@atmel.com>
Signed-off-by: Andreas Bießmann <andreas.devel@googlemail.com>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 20d521a..1a83683 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -509,6 +509,10 @@
 	select CPU_V7
 	select SUPPORT_SPL
 
+config TARGET_SAMA5D4EK
+	bool "Support sama5d4ek"
+	select CPU_V7
+
 config TARGET_BCM28155_AP
 	bool "Support bcm28155_ap"
 	select CPU_V7
@@ -844,6 +848,7 @@
 source "board/atmel/at91sam9x5ek/Kconfig"
 source "board/atmel/sama5d3_xplained/Kconfig"
 source "board/atmel/sama5d3xek/Kconfig"
+source "board/atmel/sama5d4ek/Kconfig"
 source "board/bachmann/ot1200/Kconfig"
 source "board/balloon3/Kconfig"
 source "board/barco/titanium/Kconfig"
diff --git a/arch/arm/cpu/armv7/at91/Makefile b/arch/arm/cpu/armv7/at91/Makefile
index 0a2e48d..f4f35a4 100644
--- a/arch/arm/cpu/armv7/at91/Makefile
+++ b/arch/arm/cpu/armv7/at91/Makefile
@@ -9,6 +9,7 @@
 #
 
 obj-$(CONFIG_SAMA5D3)	+= sama5d3_devices.o
+obj-$(CONFIG_SAMA5D4)	+= sama5d4_devices.o
 obj-y += clock.o
 obj-y += cpu.o
 obj-y += reset.o
diff --git a/arch/arm/cpu/armv7/at91/sama5d4_devices.c b/arch/arm/cpu/armv7/at91/sama5d4_devices.c
new file mode 100644
index 0000000..2708097
--- /dev/null
+++ b/arch/arm/cpu/armv7/at91/sama5d4_devices.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 Atmel
+ *		      Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/sama5d4.h>
+
+char *get_cpu_name()
+{
+	unsigned int extension_id = get_extension_chip_id();
+
+	if (cpu_is_sama5d4())
+		switch (extension_id) {
+		case ARCH_EXID_SAMA5D41:
+			return "SAMA5D41";
+		case ARCH_EXID_SAMA5D42:
+			return "SAMA5D42";
+		case ARCH_EXID_SAMA5D43:
+			return "SAMA5D43";
+		case ARCH_EXID_SAMA5D44:
+			return "SAMA5D44";
+		default:
+			return "Unknown CPU type";
+		}
+	else
+		return "Unknown CPU type";
+}
diff --git a/arch/arm/cpu/armv7/at91/timer.c b/arch/arm/cpu/armv7/at91/timer.c
index e3ebfe0..19bf80b 100644
--- a/arch/arm/cpu/armv7/at91/timer.c
+++ b/arch/arm/cpu/armv7/at91/timer.c
@@ -65,7 +65,8 @@
 	/* Enable PITC */
 	writel(TIMER_LOAD_VAL | AT91_PIT_MR_EN , &pit->mr);
 
-	gd->arch.timer_rate_hz = gd->arch.mck_rate_hz / 16;
+	gd->arch.timer_rate_hz = get_pit_clk_rate() / 16;
+
 	gd->arch.tbu = 0;
 	gd->arch.tbl = 0;
 
diff --git a/arch/arm/include/asm/arch-at91/at91_pmc.h b/arch/arm/include/asm/arch-at91/at91_pmc.h
index e206b55..53b5b2e 100644
--- a/arch/arm/include/asm/arch-at91/at91_pmc.h
+++ b/arch/arm/include/asm/arch-at91/at91_pmc.h
@@ -78,7 +78,7 @@
 #define AT91_PMC_PLLXR_DIV(x)		(x & 0xFF)
 #define AT91_PMC_PLLXR_PLLCOUNT(x)	((x & 0x3F) << 8)
 #define AT91_PMC_PLLXR_OUT(x)		((x & 0x03) << 14)
-#ifdef CONFIG_SAMA5D3
+#if defined(CONFIG_SAMA5D3) || defined(CONFIG_SAMA5D4)
 #define AT91_PMC_PLLXR_MUL(x)		((x & 0x7F) << 18)
 #else
 #define AT91_PMC_PLLXR_MUL(x)		((x & 0x7FF) << 16)
@@ -97,7 +97,7 @@
 #define AT91_PMC_MCKR_CSS_PLLB		0x00000003
 #define AT91_PMC_MCKR_CSS_MASK		0x00000003
 
-#ifdef CONFIG_SAMA5D3
+#if defined(CONFIG_SAMA5D3) || defined(CONFIG_SAMA5D4)
 #define AT91_PMC_MCKR_PRES_1		0x00000000
 #define AT91_PMC_MCKR_PRES_2		0x00000010
 #define AT91_PMC_MCKR_PRES_4		0x00000020
@@ -126,7 +126,7 @@
 #else
 #define AT91_PMC_MCKR_MDIV_1		0x00000000
 #define AT91_PMC_MCKR_MDIV_2		0x00000100
-#ifdef CONFIG_SAMA5D3
+#if defined(CONFIG_SAMA5D3) || defined(CONFIG_SAMA5D4)
 #define AT91_PMC_MCKR_MDIV_3		0x00000300
 #endif
 #define AT91_PMC_MCKR_MDIV_4		0x00000200
@@ -137,6 +137,8 @@
 #define AT91_PMC_MCKR_PLLADIV_1		0x00000000
 #define AT91_PMC_MCKR_PLLADIV_2		0x00001000
 
+#define AT91_PMC_MCKR_H32MXDIV		0x01000000
+
 #define AT91_PMC_IXR_MOSCS		0x00000001
 #define AT91_PMC_IXR_LOCKA		0x00000002
 #define AT91_PMC_IXR_LOCKB		0x00000004
diff --git a/arch/arm/include/asm/arch-at91/clk.h b/arch/arm/include/asm/arch-at91/clk.h
index 4076a78..1d45e2d 100644
--- a/arch/arm/include/asm/arch-at91/clk.h
+++ b/arch/arm/include/asm/arch-at91/clk.h
@@ -10,6 +10,7 @@
 #define __ASM_ARM_ARCH_CLK_H__
 
 #include <asm/arch/hardware.h>
+#include <asm/arch/at91_pmc.h>
 #include <asm/global_data.h>
 
 static inline unsigned long get_cpu_clk_rate(void)
@@ -48,14 +49,34 @@
 	return gd->arch.at91_pllb_usb_init;
 }
 
+#ifdef CPU_HAS_H32MXDIV
+static inline unsigned int get_h32mxdiv(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	return readl(&pmc->mckr) & AT91_PMC_MCKR_H32MXDIV;
+}
+#else
+static inline unsigned int get_h32mxdiv(void)
+{
+	return 0;
+}
+#endif
+
 static inline unsigned long get_macb_pclk_rate(unsigned int dev_id)
 {
-	return get_mck_clk_rate();
+	if (get_h32mxdiv())
+		return get_mck_clk_rate() / 2;
+	else
+		return get_mck_clk_rate();
 }
 
 static inline unsigned long get_usart_clk_rate(unsigned int dev_id)
 {
-	return get_mck_clk_rate();
+	if (get_h32mxdiv())
+		return get_mck_clk_rate() / 2;
+	else
+		return get_mck_clk_rate();
 }
 
 static inline unsigned long get_lcdc_clk_rate(unsigned int dev_id)
@@ -65,17 +86,34 @@
 
 static inline unsigned long get_spi_clk_rate(unsigned int dev_id)
 {
-	return get_mck_clk_rate();
+	if (get_h32mxdiv())
+		return get_mck_clk_rate() / 2;
+	else
+		return get_mck_clk_rate();
 }
 
 static inline unsigned long get_twi_clk_rate(unsigned int dev_id)
 {
-	return get_mck_clk_rate();
+	if (get_h32mxdiv())
+		return get_mck_clk_rate() / 2;
+	else
+		return get_mck_clk_rate();
 }
 
 static inline unsigned long get_mci_clk_rate(void)
 {
-	return get_mck_clk_rate();
+	if (get_h32mxdiv())
+		return get_mck_clk_rate() / 2;
+	else
+		return get_mck_clk_rate();
+}
+
+static inline unsigned long get_pit_clk_rate(void)
+{
+	if (get_h32mxdiv())
+		return get_mck_clk_rate() / 2;
+	else
+		return get_mck_clk_rate();
 }
 
 int at91_clock_init(unsigned long main_clock);
diff --git a/arch/arm/include/asm/arch-at91/hardware.h b/arch/arm/include/asm/arch-at91/hardware.h
index d712a0d..bf0a1bd 100644
--- a/arch/arm/include/asm/arch-at91/hardware.h
+++ b/arch/arm/include/asm/arch-at91/hardware.h
@@ -27,6 +27,8 @@
 # include <asm/arch/at91cap9.h>
 #elif defined(CONFIG_SAMA5D3)
 # include <asm/arch/sama5d3.h>
+#elif defined(CONFIG_SAMA5D4)
+# include <asm/arch/sama5d4.h>
 #else
 # error "Unsupported AT91 processor"
 #endif
diff --git a/arch/arm/include/asm/arch-at91/sama5d4.h b/arch/arm/include/asm/arch-at91/sama5d4.h
new file mode 100644
index 0000000..d851568
--- /dev/null
+++ b/arch/arm/include/asm/arch-at91/sama5d4.h
@@ -0,0 +1,206 @@
+/*
+ * Chip-specific header file for the SAMA5D4 SoC
+ *
+ * Copyright (C) 2014 Atmel
+ *		      Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __SAMA5D4_H
+#define __SAMA5D4_H
+
+/*
+ * defines to be used in other places
+ */
+#define CONFIG_AT91FAMILY	/* It's a member of AT91 */
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define ATMEL_ID_FIQ	0	/* FIQ Interrupt */
+#define ATMEL_ID_SYS	1	/* System Controller */
+#define ATMEL_ID_ARM	2	/* Performance Monitor Unit */
+#define ATMEL_ID_PIT	3	/* Periodic Interval Timer */
+#define ATMEL_ID_WDT	4	/* Watchdog timer */
+#define ATMEL_ID_PIOD	5	/* Parallel I/O Controller D */
+#define ATMEL_ID_USART0	6	/* USART 0 */
+#define ATMEL_ID_USART1	7	/* USART 1 */
+#define ATMEL_ID_DMA0	8	/* DMA Controller 0 */
+#define ATMEL_ID_ICM	9	/* Integrity Check Monitor */
+#define ATMEL_ID_PKCC	10	/* Public Key Crypto Controller */
+#define ATMEL_ID_AES	12	/* Advanced Encryption Standard */
+#define ATMEL_ID_AESB	13	/* AES Bridge*/
+#define ATMEL_ID_TDES	14	/* Triple Data Encryption Standard */
+#define ATMEL_ID_SHA    15	/* SHA Signature */
+#define ATMEL_ID_MPDDRC	16	/* MPDDR controller */
+#define ATMEL_ID_MATRIX1	17	/* H32MX, 32-bit AHB Matrix */
+#define ATMEL_ID_MATRIX0	18	/* H64MX, 64-bit AHB Matrix */
+#define ATMEL_ID_VDEC	19	/* Video Decoder */
+#define ATMEL_ID_SBM	20	/* Secure Box Module */
+#define ATMEL_ID_SMC	22	/* Multi-bit ECC interrupt */
+#define ATMEL_ID_PIOA	23	/* Parallel I/O Controller A */
+#define ATMEL_ID_PIOB	24	/* Parallel I/O Controller B */
+#define ATMEL_ID_PIOC	25	/* Parallel I/O Controller C */
+#define ATMEL_ID_PIOE	26	/* Parallel I/O Controller E */
+#define ATMEL_ID_UART0	27	/* UART 0 */
+#define ATMEL_ID_UART1	28	/* UART 1 */
+#define ATMEL_ID_USART2	29	/* USART 2 */
+#define ATMEL_ID_USART3	30	/* USART 3 */
+#define ATMEL_ID_USART4	31	/* USART 4 */
+#define ATMEL_ID_TWI0	32	/* Two-Wire Interface 0 */
+#define ATMEL_ID_TWI1	33	/* Two-Wire Interface 1 */
+#define ATMEL_ID_TWI2	34	/* Two-Wire Interface 2 */
+#define ATMEL_ID_MCI0	35	/* High Speed Multimedia Card Interface 0 */
+#define ATMEL_ID_MCI1	36	/* High Speed Multimedia Card Interface 1 */
+#define ATMEL_ID_SPI0	37	/* Serial Peripheral Interface 0 */
+#define ATMEL_ID_SPI1	38	/* Serial Peripheral Interface 1 */
+#define ATMEL_ID_SPI2	39	/* Serial Peripheral Interface 2 */
+#define ATMEL_ID_TC0	40	/* Timer Counter 0 (ch. 0, 1, 2) */
+#define ATMEL_ID_TC1	41	/* Timer Counter 1 (ch. 3, 4, 5) */
+#define ATMEL_ID_TC2	42	/* Timer Counter 2 (ch. 6, 7, 8) */
+#define ATMEL_ID_PWMC	43	/* Pulse Width Modulation Controller */
+#define ATMEL_ID_ADC	44	/* Touch Screen ADC Controller */
+#define ATMEL_ID_DBGU	45	/* Debug Unit Interrupt */
+#define ATMEL_ID_UHPHS	46	/* USB Host High Speed */
+#define ATMEL_ID_UDPHS	47	/* USB Device High Speed */
+#define ATMEL_ID_SSC0	48	/* Synchronous Serial Controller 0 */
+#define ATMEL_ID_SSC1	49	/* Synchronous Serial Controller 1 */
+#define ATMEL_ID_XDMAC1	50	/* DMA Controller 1 */
+#define ATMEL_ID_LCDC	51	/* LCD Controller */
+#define ATMEL_ID_ISI	52	/* Image Sensor Interface */
+#define ATMEL_ID_TRNG	53	/* True Random Number Generator */
+#define ATMEL_ID_GMAC0	54	/* Ethernet MAC 0 */
+#define ATMEL_ID_GMAC1	55	/* Ethernet MAC 1 */
+#define ATMEL_ID_IRQ	56	/* IRQ Interrupt ID */
+#define ATMEL_ID_SFC	57	/* Fuse Controller */
+#define ATMEL_ID_SECURAM	59	/* Secured RAM */
+#define ATMEL_ID_SMD	61	/* SMD Soft Modem */
+#define ATMEL_ID_TWI3	62	/* Two-Wire Interface 3 */
+#define ATMEL_ID_CATB	63	/* Capacitive Touch Controller */
+#define ATMEL_ID_SFR	64	/* Special Funcion Register */
+#define ATMEL_ID_AIC	65	/* Advanced Interrupt Controller */
+#define ATMEL_ID_SAIC	66	/* Secured Advanced Interrupt Controller */
+#define ATMEL_ID_L2CC	67	/* L2 Cache Controller */
+
+/*
+ * User Peripherals physical base addresses.
+ */
+#define ATMEL_BASE_LCDC		0xf0000000
+#define ATMEL_BASE_DMAC1	0xf0004000
+#define ATMEL_BASE_ISI		0xf0008000
+#define ATMEL_BASE_PKCC		0xf000C000
+#define ATMEL_BASE_MPDDRC	0xf0010000
+#define ATMEL_BASE_DMAC0	0xf0014000
+#define ATMEL_BASE_PMC		0xf0018000
+#define ATMEL_BASE_MATRIX0	0xf001c000
+#define ATMEL_BASE_AESB		0xf0020000
+/* Reserved: 0xf0024000 - 0xf8000000 */
+#define ATMEL_BASE_MCI0		0xf8000000
+#define ATMEL_BASE_UART0	0xf8004000
+#define ATMEL_BASE_SSC0		0xf8008000
+#define ATMEL_BASE_PWMC		0xf800c000
+#define ATMEL_BASE_SPI0		0xf8010000
+#define ATMEL_BASE_TWI0		0xf8014000
+#define ATMEL_BASE_TWI1		0xf8018000
+#define ATMEL_BASE_TC0		0xf801c000
+#define ATMEL_BASE_GMAC0	0xf8020000
+#define ATMEL_BASE_TWI2		0xf8024000
+#define ATMEL_BASE_SFR		0xf8028000
+#define ATMEL_BASE_USART0	0xf802c000
+#define ATMEL_BASE_USART1	0xf8030000
+/* Reserved:	0xf8034000 - 0xfc000000 */
+#define ATMEL_BASE_MCI1		0xfc000000
+#define ATMEL_BASE_UART1	0xfc004000
+#define ATMEL_BASE_USART2	0xfc008000
+#define ATMEL_BASE_USART3	0xfc00c000
+#define ATMEL_BASE_USART4	0xfc010000
+#define ATMEL_BASE_SSC1		0xfc014000
+#define ATMEL_BASE_SPI1		0xfc018000
+#define ATMEL_BASE_SPI2		0xfc01c000
+#define ATMEL_BASE_TC1		0xfc020000
+#define ATMEL_BASE_TC2		0xfc024000
+#define ATMEL_BASE_GMAC1	0xfc028000
+#define ATMEL_BASE_UDPHS	0xfc02c000
+#define ATMEL_BASE_TRNG		0xfc030000
+#define ATMEL_BASE_ADC		0xfc034000
+#define ATMEL_BASE_TWI3		0xfc038000
+
+#define ATMEL_BASE_SMC		0xfc05c000
+#define ATMEL_BASE_PMECC	(ATMEL_BASE_SMC + 0x070)
+#define ATMEL_BASE_PMERRLOC	(ATMEL_BASE_SMC + 0x500)
+
+#define ATMEL_BASE_PIOD		0xfc068000
+#define ATMEL_BASE_RSTC		0xfc068600
+#define ATMEL_BASE_PIT		0xfc068630
+#define ATMEL_BASE_WDT		0xfc068640
+
+#define ATMEL_BASE_DBGU		0xfc069000
+#define ATMEL_BASE_PIOA		0xfc06a000
+#define ATMEL_BASE_PIOB		0xfc06b000
+#define ATMEL_BASE_PIOC		0xfc06c000
+#define ATMEL_BASE_PIOE		0xfc06d000
+#define ATMEL_BASE_AIC		0xfc06e000
+
+/*
+ * Internal Memory.
+ */
+#define ATMEL_BASE_ROM		0x00000000	/* Internal ROM base address */
+#define ATMEL_BASE_NFC		0x00100000	/* NFC SRAM */
+#define ATMEL_BASE_SRAM		0x00200000	/* Internal ROM base address */
+#define ATMEL_BASE_VDEC		0x00300000	/* Video Decoder Controller */
+#define ATMEL_BASE_UDPHS_FIFO	0x00400000	/* USB Device HS controller */
+#define ATMEL_BASE_OHCI		0x00500000	/* USB Host controller (OHCI) */
+#define ATMEL_BASE_EHCI		0x00600000	/* USB Host controller (EHCI) */
+#define ATMEL_BASE_AXI		0x00700000
+#define ATMEL_BASE_DAP		0x00800000
+#define ATMEL_BASE_SMD		0x00900000
+
+/*
+ * External memory
+ */
+#define ATMEL_BASE_CS0		0x10000000
+#define ATMEL_BASE_DDRCS	0x20000000
+#define ATMEL_BASE_CS1		0x60000000
+#define ATMEL_BASE_CS2		0x70000000
+#define ATMEL_BASE_CS3		0x80000000
+
+/*
+ * Other misc defines
+ */
+#define ATMEL_PIO_PORTS		5
+#define CPU_HAS_PIO3
+#define PIO_SCDR_DIV		0x3fff
+#define CPU_HAS_PCR
+#define CPU_HAS_H32MXDIV
+
+/* sama5d4 series chip id definitions */
+#define ARCH_ID_SAMA5D4		0x8a5c07c0
+#define ARCH_EXID_SAMA5D41	0x00000001
+#define ARCH_EXID_SAMA5D42	0x00000002
+#define ARCH_EXID_SAMA5D43	0x00000003
+#define ARCH_EXID_SAMA5D44	0x00000004
+
+#define cpu_is_sama5d4()	(get_chip_id() == ARCH_ID_SAMA5D4)
+#define cpu_is_sama5d41()	(cpu_is_sama5d4() && \
+		(get_extension_chip_id() == ARCH_EXID_SAMA5D41))
+#define cpu_is_sama5d42()	(cpu_is_sama5d4() && \
+		(get_extension_chip_id() == ARCH_EXID_SAMA5D42))
+#define cpu_is_sama5d43()	(cpu_is_sama5d4() && \
+		(get_extension_chip_id() == ARCH_EXID_SAMA5D43))
+#define cpu_is_sama5d44()	(cpu_is_sama5d4() && \
+		(get_extension_chip_id() == ARCH_EXID_SAMA5D44))
+
+/*
+ * No PMECC Galois table in ROM
+ */
+#define NO_GALOIS_TABLE_IN_ROM
+
+#ifndef __ASSEMBLY__
+unsigned int get_chip_id(void);
+unsigned int get_extension_chip_id(void);
+unsigned int has_lcdc(void);
+char *get_cpu_name(void);
+#endif
+
+#endif