ARM: at91: collect SoC sources into mach-at91

This commit moves source files as follows:

  arch/arm/cpu/arm920t/at91/*   -> arch/arm/mach-at91/arm920t/*
  arch/arm/cpu/arm926ejs/at91/* -> arch/arm/mach-at91/arm926ejs/*
  arch/arm/cpu/armv7/at91/*     -> arch/arm/mach-at91/armv7/*
  arch/arm/cpu/at91-common/*    -> arch/arm/mach-at91/*

Signed-off-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
Acked-by: Andreas Bießmann <andreas.devel@googlemail.co>
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
new file mode 100644
index 0000000..e596ba6
--- /dev/null
+++ b/arch/arm/mach-at91/Makefile
@@ -0,0 +1,12 @@
+obj-$(CONFIG_AT91_WANTS_COMMON_PHY) += phy.o
+ifneq ($(CONFIG_SPL_BUILD),)
+obj-$(CONFIG_AT91SAM9G20) += sdram.o spl_at91.o
+obj-$(CONFIG_AT91SAM9M10G45) += mpddrc.o spl_at91.o
+obj-$(CONFIG_SAMA5D3) += mpddrc.o spl_atmel.o
+obj-$(CONFIG_SAMA5D4) += mpddrc.o spl_atmel.o
+obj-y += spl.o
+endif
+
+obj-$(CONFIG_CPU_ARM920T)	+= arm920t/
+obj-$(CONFIG_CPU_ARM926EJS)	+= arm926ejs/
+obj-$(CONFIG_CPU_V7)		+= armv7/
diff --git a/arch/arm/mach-at91/arm920t/Makefile b/arch/arm/mach-at91/arm920t/Makefile
new file mode 100644
index 0000000..561b4b4
--- /dev/null
+++ b/arch/arm/mach-at91/arm920t/Makefile
@@ -0,0 +1,13 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	+= lowlevel_init.o
+obj-y	+= reset.o
+obj-y	+= timer.o
+obj-y	+= clock.o
+obj-y	+= cpu.o
+obj-y	+= at91rm9200_devices.o
diff --git a/arch/arm/mach-at91/arm920t/at91rm9200_devices.c b/arch/arm/mach-at91/arm920t/at91rm9200_devices.c
new file mode 100644
index 0000000..fc54327
--- /dev/null
+++ b/arch/arm/mach-at91/arm920t/at91rm9200_devices.c
@@ -0,0 +1,67 @@
+/*
+ * [partely copied from arch/arm/cpu/arm926ejs/at91/arm9260_devices.c]
+ *
+ * (C) Copyright 2011
+ * Andreas Bießmann <andreas.devel@googlemail.com>
+ *
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.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/gpio.h>
+
+/*
+ * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all
+ * peripheral pins. Good to have if hardware is soldered optionally
+ * or in case of SPI no slave is selected. Avoid lines to float
+ * needlessly. Use a short local PUP define.
+ *
+ * Due to errata "TXD floats when CTS is inactive" pullups are always
+ * on for TXD pins.
+ */
+#ifdef CONFIG_AT91_GPIO_PULLUP
+# define PUP CONFIG_AT91_GPIO_PULLUP
+#else
+# define PUP 0
+#endif
+
+void at91_serial0_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 17, 1);		/* TXD0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 18, PUP);		/* RXD0 */
+	writel(1 << ATMEL_ID_USART0, &pmc->pcer);
+}
+
+void at91_serial1_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTB, 20, PUP);		/* RXD1 */
+	at91_set_a_periph(AT91_PIO_PORTB, 21, 1);		/* TXD1 */
+	writel(1 << ATMEL_ID_USART1, &pmc->pcer);
+}
+
+void at91_serial2_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 22, PUP);		/* RXD2 */
+	at91_set_a_periph(AT91_PIO_PORTA, 23, 1);		/* TXD2 */
+	writel(1 << ATMEL_ID_USART2, &pmc->pcer);
+}
+
+void at91_seriald_hw_init(void)
+{
+	at91_set_a_periph(AT91_PIO_PORTA, 30, PUP);		/* DRXD */
+	at91_set_a_periph(AT91_PIO_PORTA, 31, 1);		/* DTXD */
+	/* writing SYS to PCER has no effect on AT91RM9200 */
+}
diff --git a/arch/arm/mach-at91/arm920t/clock.c b/arch/arm/mach-at91/arm920t/clock.c
new file mode 100644
index 0000000..2813bf7
--- /dev/null
+++ b/arch/arm/mach-at91/arm920t/clock.c
@@ -0,0 +1,157 @@
+/*
+ * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c]
+ *
+ * Copyright (C) 2011 Andreas Bießmann
+ * Copyright (C) 2005 David Brownell
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/clk.h>
+
+#if !defined(CONFIG_AT91FAMILY)
+# error You need to define CONFIG_AT91FAMILY in your board config!
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static unsigned long at91_css_to_rate(unsigned long css)
+{
+	switch (css) {
+	case AT91_PMC_MCKR_CSS_SLOW:
+		return CONFIG_SYS_AT91_SLOW_CLOCK;
+	case AT91_PMC_MCKR_CSS_MAIN:
+		return gd->arch.main_clk_rate_hz;
+	case AT91_PMC_MCKR_CSS_PLLA:
+		return gd->arch.plla_rate_hz;
+	case AT91_PMC_MCKR_CSS_PLLB:
+		return gd->arch.pllb_rate_hz;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_USB_ATMEL
+static unsigned at91_pll_calc(unsigned main_freq, unsigned out_freq)
+{
+	unsigned i, div = 0, mul = 0, diff = 1 << 30;
+	unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00;
+
+	/* PLL output max 240 MHz (or 180 MHz per errata) */
+	if (out_freq > 240000000)
+		goto fail;
+
+	for (i = 1; i < 256; i++) {
+		int diff1;
+		unsigned input, mul1;
+
+		/*
+		 * PLL input between 1MHz and 32MHz per spec, but lower
+		 * frequences seem necessary in some cases so allow 100K.
+		 * Warning: some newer products need 2MHz min.
+		 */
+		input = main_freq / i;
+		if (input < 100000)
+			continue;
+		if (input > 32000000)
+			continue;
+
+		mul1 = out_freq / input;
+		if (mul1 > 2048)
+			continue;
+		if (mul1 < 2)
+			goto fail;
+
+		diff1 = out_freq - input * mul1;
+		if (diff1 < 0)
+			diff1 = -diff1;
+		if (diff > diff1) {
+			diff = diff1;
+			div = i;
+			mul = mul1;
+			if (diff == 0)
+				break;
+		}
+	}
+	if (i == 256 && diff > (out_freq >> 5))
+		goto fail;
+	return ret | ((mul - 1) << 16) | div;
+fail:
+	return 0;
+}
+#endif
+
+static u32 at91_pll_rate(u32 freq, u32 reg)
+{
+	unsigned mul, div;
+
+	div = reg & 0xff;
+	mul = (reg >> 16) & 0x7ff;
+	if (div && mul) {
+		freq /= div;
+		freq *= mul + 1;
+	} else
+		freq = 0;
+
+	return freq;
+}
+
+int at91_clock_init(unsigned long main_clock)
+{
+	unsigned freq, mckr;
+	at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
+#ifndef CONFIG_SYS_AT91_MAIN_CLOCK
+	unsigned tmp;
+	/*
+	 * When the bootloader initialized the main oscillator correctly,
+	 * there's no problem using the cycle counter.  But if it didn't,
+	 * or when using oscillator bypass mode, we must be told the speed
+	 * of the main clock.
+	 */
+	if (!main_clock) {
+		do {
+			tmp = readl(&pmc->mcfr);
+		} while (!(tmp & AT91_PMC_MCFR_MAINRDY));
+		tmp &= AT91_PMC_MCFR_MAINF_MASK;
+		main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16);
+	}
+#endif
+	gd->arch.main_clk_rate_hz = main_clock;
+
+	/* report if PLLA is more than mildly overclocked */
+	gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
+
+#ifdef CONFIG_USB_ATMEL
+	/*
+	 * USB clock init:  choose 48 MHz PLLB value,
+	 * disable 48MHz clock during usb peripheral suspend.
+	 *
+	 * REVISIT:  assumes MCK doesn't derive from PLLB!
+	 */
+	gd->arch.at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
+			     AT91_PMC_PLLBR_USBDIV_2;
+	gd->arch.pllb_rate_hz = at91_pll_rate(main_clock,
+					      gd->arch.at91_pllb_usb_init);
+#endif
+
+	/*
+	 * MCK and CPU derive from one of those primary clocks.
+	 * For now, assume this parentage won't change.
+	 */
+	mckr = readl(&pmc->mckr);
+	gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
+	freq = gd->arch.mck_rate_hz;
+
+	freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2));	/* prescale */
+	/* mdiv */
+	gd->arch.mck_rate_hz = freq /
+			(1 + ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
+	gd->arch.cpu_clk_rate_hz = freq;
+
+	return 0;
+}
diff --git a/arch/arm/mach-at91/arm920t/cpu.c b/arch/arm/mach-at91/arm920t/cpu.c
new file mode 100644
index 0000000..b0f411b
--- /dev/null
+++ b/arch/arm/mach-at91/arm920t/cpu.c
@@ -0,0 +1,26 @@
+/*
+ * [origin: arch/arm/cpu/arm926ejs/at91/cpu.c]
+ *
+ * (C) Copyright 2011
+ * Andreas Bießmann, andreas.devel@googlemail.com
+ * (C) Copyright 2010
+ * Reinhard Meyer, reinhard.meyer@emk-elektronik.de
+ * (C) Copyright 2009
+ * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/clk.h>
+
+#ifndef CONFIG_SYS_AT91_MAIN_CLOCK
+#define CONFIG_SYS_AT91_MAIN_CLOCK 0
+#endif
+
+int arch_cpu_init(void)
+{
+	return at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK);
+}
diff --git a/arch/arm/mach-at91/arm920t/lowlevel_init.S b/arch/arm/mach-at91/arm920t/lowlevel_init.S
new file mode 100644
index 0000000..d2934a3
--- /dev/null
+++ b/arch/arm/mach-at91/arm920t/lowlevel_init.S
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and
+ *		       Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
+ *
+ * Modified for the at91rm9200dk board by
+ * (C) Copyright 2004
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_mc.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_pio.h>
+
+#define ARM920T_CONTROL	0xC0000000	/* @ set bit 31 (iA) and 30 (nF) */
+
+_MTEXT_BASE:
+#undef START_FROM_MEM
+#ifdef START_FROM_MEM
+	.word	CONFIG_SYS_TEXT_BASE-PHYS_FLASH_1
+#else
+	.word	CONFIG_SYS_TEXT_BASE
+#endif
+
+.globl lowlevel_init
+lowlevel_init:
+	ldr     r1, =AT91_ASM_PMC_MOR
+	/* Main oscillator Enable register */
+#ifdef CONFIG_SYS_USE_MAIN_OSCILLATOR
+	ldr     r0, =0x0000FF01		/* Enable main oscillator */
+#else
+	ldr     r0, =0x0000FF00		/* Disable main oscillator */
+#endif
+	str     r0, [r1] /*AT91C_CKGR_MOR] */
+	/* Add loop to compensate Main Oscillator startup time */
+	ldr     r0, =0x00000010
+LoopOsc:
+	subs    r0, r0, #1
+	bhi     LoopOsc
+
+	/* memory control configuration */
+	/* this isn't very elegant, but	 what the heck */
+	ldr	r0, =SMRDATA
+	ldr	r1, _MTEXT_BASE
+	sub	r0, r0, r1
+	ldr	r2, =SMRDATAE
+	sub	r2, r2, r1
+pllloop:
+	/* the address */
+	ldr	r1, [r0], #4
+	/* the value */
+	ldr	r3, [r0], #4
+	str	r3, [r1]
+	cmp	r2, r0
+	bne	pllloop
+	/* delay - this is all done by guess */
+	ldr	r0, =0x00010000
+	/* (vs reading PMC_SR for LOCKA, LOCKB ... or MOSCS earlier) */
+lock:
+	subs	r0, r0, #1
+	bhi	lock
+	ldr	r0, =SMRDATA1
+	ldr	r1, _MTEXT_BASE
+	sub	r0, r0, r1
+	ldr	r2, =SMRDATA1E
+	sub	r2, r2, r1
+sdinit:
+	/* the address */
+	ldr	r1, [r0], #4
+	/* the value */
+	ldr	r3, [r0], #4
+	str	r3, [r1]
+	cmp	r2, r0
+	bne	sdinit
+
+	/* switch from FastBus to Asynchronous clock mode */
+	mrc	p15, 0, r0, c1, c0, 0
+	orr	r0, r0, #ARM920T_CONTROL
+	mcr	p15, 0, r0, c1, c0, 0
+
+	/* everything is fine now */
+	mov	pc, lr
+
+	.ltorg
+
+SMRDATA:
+	.word AT91_ASM_MC_EBI_CFG
+	.word CONFIG_SYS_EBI_CFGR_VAL
+	.word AT91_ASM_MC_SMC_CSR0
+	.word CONFIG_SYS_SMC_CSR0_VAL
+	.word AT91_ASM_PMC_PLLAR
+	.word CONFIG_SYS_PLLAR_VAL
+	.word AT91_ASM_PMC_PLLBR
+	.word CONFIG_SYS_PLLBR_VAL
+	.word AT91_ASM_PMC_MCKR
+	.word CONFIG_SYS_MCKR_VAL
+SMRDATAE:
+	/* here there's a delay */
+SMRDATA1:
+	.word AT91_ASM_PIOC_ASR
+	.word CONFIG_SYS_PIOC_ASR_VAL
+	.word AT91_ASM_PIOC_BSR
+	.word CONFIG_SYS_PIOC_BSR_VAL
+	.word AT91_ASM_PIOC_PDR
+	.word CONFIG_SYS_PIOC_PDR_VAL
+	.word AT91_ASM_MC_EBI_CSA
+	.word CONFIG_SYS_EBI_CSA_VAL
+	.word AT91_ASM_MC_SDRAMC_CR
+	.word CONFIG_SYS_SDRC_CR_VAL
+	.word AT91_ASM_MC_SDRAMC_MR
+	.word CONFIG_SYS_SDRC_MR_VAL
+	.word CONFIG_SYS_SDRAM
+	.word CONFIG_SYS_SDRAM_VAL
+	.word AT91_ASM_MC_SDRAMC_MR
+	.word CONFIG_SYS_SDRC_MR_VAL1
+	.word CONFIG_SYS_SDRAM
+	.word CONFIG_SYS_SDRAM_VAL
+	.word CONFIG_SYS_SDRAM
+	.word CONFIG_SYS_SDRAM_VAL
+	.word CONFIG_SYS_SDRAM
+	.word CONFIG_SYS_SDRAM_VAL
+	.word CONFIG_SYS_SDRAM
+	.word CONFIG_SYS_SDRAM_VAL
+	.word CONFIG_SYS_SDRAM
+	.word CONFIG_SYS_SDRAM_VAL
+	.word CONFIG_SYS_SDRAM
+	.word CONFIG_SYS_SDRAM_VAL
+	.word CONFIG_SYS_SDRAM
+	.word CONFIG_SYS_SDRAM_VAL
+	.word CONFIG_SYS_SDRAM
+	.word CONFIG_SYS_SDRAM_VAL
+	.word AT91_ASM_MC_SDRAMC_MR
+	.word CONFIG_SYS_SDRC_MR_VAL2
+	.word CONFIG_SYS_SDRAM1
+	.word CONFIG_SYS_SDRAM_VAL
+	.word AT91_ASM_MC_SDRAMC_TR
+	.word CONFIG_SYS_SDRC_TR_VAL
+	.word CONFIG_SYS_SDRAM
+	.word CONFIG_SYS_SDRAM_VAL
+	.word AT91_ASM_MC_SDRAMC_MR
+	.word CONFIG_SYS_SDRC_MR_VAL3
+	.word CONFIG_SYS_SDRAM
+	.word CONFIG_SYS_SDRAM_VAL
+SMRDATA1E:
+	/* SMRDATA1 is 176 bytes long */
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
diff --git a/arch/arm/mach-at91/arm920t/reset.c b/arch/arm/mach-at91/arm920t/reset.c
new file mode 100644
index 0000000..d47777a
--- /dev/null
+++ b/arch/arm/mach-at91/arm920t/reset.c
@@ -0,0 +1,41 @@
+/*
+ * (C) Copyright 2002
+ * Lineo, Inc. <www.lineo.com>
+ * Bernhard Kuhn <bkuhn@lineo.com>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_st.h>
+
+void  __attribute__((weak)) board_reset(void)
+{
+	/* true empty function for defining weak symbol */
+}
+
+void reset_cpu(ulong ignored)
+{
+	at91_st_t *st = (at91_st_t *) ATMEL_BASE_ST;
+
+	board_reset();
+
+	/* Reset the cpu by setting up the watchdog timer */
+	writel(AT91_ST_WDMR_RSTEN | AT91_ST_WDMR_EXTEN | AT91_ST_WDMR_WDV(2),
+		&st->wdmr);
+	writel(AT91_ST_CR_WDRST, &st->cr);
+	/* and let it timeout */
+	while (1)
+		;
+	/* Never reached */
+}
diff --git a/arch/arm/mach-at91/arm920t/timer.c b/arch/arm/mach-at91/arm920t/timer.c
new file mode 100644
index 0000000..6aa2994
--- /dev/null
+++ b/arch/arm/mach-at91/arm920t/timer.c
@@ -0,0 +1,127 @@
+/*
+ * (C) Copyright 2002
+ * Lineo, Inc. <www.lineo.com>
+ * Bernhard Kuhn <bkuhn@lineo.com>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_tc.h>
+#include <asm/arch/at91_pmc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* the number of clocks per CONFIG_SYS_HZ */
+#define TIMER_LOAD_VAL (CONFIG_SYS_HZ_CLOCK/CONFIG_SYS_HZ)
+
+int timer_init(void)
+{
+	at91_tc_t *tc = (at91_tc_t *) ATMEL_BASE_TC;
+	at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	/* enables TC1.0 clock */
+	writel(1 << ATMEL_ID_TC0, &pmc->pcer);	/* enable clock */
+
+	writel(0, &tc->bcr);
+	writel(AT91_TC_BMR_TC0XC0S_NONE | AT91_TC_BMR_TC1XC1S_NONE |
+		AT91_TC_BMR_TC2XC2S_NONE , &tc->bmr);
+
+	writel(AT91_TC_CCR_CLKDIS, &tc->tc[0].ccr);
+	/* set to MCLK/2 and restart the timer
+	when the value in TC_RC is reached */
+	writel(AT91_TC_CMR_TCCLKS_CLOCK1 | AT91_TC_CMR_CPCTRG, &tc->tc[0].cmr);
+
+	writel(0xFFFFFFFF, &tc->tc[0].idr); /* disable interrupts */
+	writel(TIMER_LOAD_VAL, &tc->tc[0].rc);
+
+	writel(AT91_TC_CCR_SWTRG | AT91_TC_CCR_CLKEN, &tc->tc[0].ccr);
+	gd->arch.lastinc = 0;
+	gd->arch.tbl = 0;
+
+	return 0;
+}
+
+/*
+ * timer without interrupts
+ */
+ulong get_timer(ulong base)
+{
+	return get_timer_masked() - base;
+}
+
+void __udelay(unsigned long usec)
+{
+	udelay_masked(usec);
+}
+
+ulong get_timer_raw(void)
+{
+	at91_tc_t *tc = (at91_tc_t *) ATMEL_BASE_TC;
+	u32 now;
+
+	now = readl(&tc->tc[0].cv) & 0x0000ffff;
+
+	if (now >= gd->arch.lastinc) {
+		/* normal mode */
+		gd->arch.tbl += now - gd->arch.lastinc;
+	} else {
+		/* we have an overflow ... */
+		gd->arch.tbl += now + TIMER_LOAD_VAL - gd->arch.lastinc;
+	}
+	gd->arch.lastinc = now;
+
+	return gd->arch.tbl;
+}
+
+ulong get_timer_masked(void)
+{
+	return get_timer_raw()/TIMER_LOAD_VAL;
+}
+
+void udelay_masked(unsigned long usec)
+{
+	u32 tmo;
+	u32 endtime;
+	signed long diff;
+
+	tmo = CONFIG_SYS_HZ_CLOCK / 1000;
+	tmo *= usec;
+	tmo /= 1000;
+
+	endtime = get_timer_raw() + tmo;
+
+	do {
+		u32 now = get_timer_raw();
+		diff = endtime - now;
+	} while (diff >= 0);
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	return CONFIG_SYS_HZ;
+}
diff --git a/arch/arm/mach-at91/arm926ejs/Makefile b/arch/arm/mach-at91/arm926ejs/Makefile
new file mode 100644
index 0000000..ddc323f
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/Makefile
@@ -0,0 +1,28 @@
+#
+# (C) Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_AT91SAM9260)	+= at91sam9260_devices.o
+obj-$(CONFIG_AT91SAM9G20)	+= at91sam9260_devices.o
+obj-$(CONFIG_AT91SAM9XE)	+= at91sam9260_devices.o
+obj-$(CONFIG_AT91SAM9261)	+= at91sam9261_devices.o
+obj-$(CONFIG_AT91SAM9G10)	+= at91sam9261_devices.o
+obj-$(CONFIG_AT91SAM9263)	+= at91sam9263_devices.o
+obj-$(CONFIG_AT91SAM9RL)	+= at91sam9rl_devices.o
+obj-$(CONFIG_AT91SAM9M10G45)	+= at91sam9m10g45_devices.o
+obj-$(CONFIG_AT91SAM9G45)	+= at91sam9m10g45_devices.o
+obj-$(CONFIG_AT91SAM9N12)	+= at91sam9n12_devices.o
+obj-$(CONFIG_AT91SAM9X5)	+= at91sam9x5_devices.o
+obj-$(CONFIG_AT91_EFLASH)	+= eflash.o
+obj-$(CONFIG_AT91_LED)	+= led.o
+obj-y += clock.o
+obj-y += cpu.o
+obj-y	+= reset.o
+obj-y	+= timer.o
+
+ifndef CONFIG_SKIP_LOWLEVEL_INIT
+obj-y	+= lowlevel_init.o
+endif
diff --git a/arch/arm/mach-at91/arm926ejs/at91sam9260_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9260_devices.c
new file mode 100644
index 0000000..efb53d6
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/at91sam9260_devices.c
@@ -0,0 +1,245 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <asm/arch/at91sam9260_matrix.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91sam9_sdramc.h>
+#include <asm/arch/gpio.h>
+
+/*
+ * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all
+ * peripheral pins. Good to have if hardware is soldered optionally
+ * or in case of SPI no slave is selected. Avoid lines to float
+ * needlessly. Use a short local PUP define.
+ *
+ * Due to errata "TXD floats when CTS is inactive" pullups are always
+ * on for TXD pins.
+ */
+#ifdef CONFIG_AT91_GPIO_PULLUP
+# define PUP CONFIG_AT91_GPIO_PULLUP
+#else
+# define PUP 0
+#endif
+
+void at91_serial0_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTB, 4, 1);		/* TXD0 */
+	at91_set_a_periph(AT91_PIO_PORTB, 5, PUP);		/* RXD0 */
+	writel(1 << ATMEL_ID_USART0, &pmc->pcer);
+}
+
+void at91_serial1_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTB, 6, 1);		/* TXD1 */
+	at91_set_a_periph(AT91_PIO_PORTB, 7, PUP);		/* RXD1 */
+	writel(1 << ATMEL_ID_USART1, &pmc->pcer);
+}
+
+void at91_serial2_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTB, 8, 1);		/* TXD2 */
+	at91_set_a_periph(AT91_PIO_PORTB, 9, PUP);		/* RXD2 */
+	writel(1 << ATMEL_ID_USART2, &pmc->pcer);
+}
+
+void at91_seriald_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTB, 14, PUP);		/* DRXD */
+	at91_set_a_periph(AT91_PIO_PORTB, 15, 1);		/* DTXD */
+	writel(1 << ATMEL_ID_SYS, &pmc->pcer);
+}
+
+#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI)
+void at91_spi0_hw_init(unsigned long cs_mask)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 0, PUP);	/* SPI0_MISO */
+	at91_set_a_periph(AT91_PIO_PORTA, 1, PUP);	/* SPI0_MOSI */
+	at91_set_a_periph(AT91_PIO_PORTA, 2, PUP);	/* SPI0_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI0, &pmc->pcer);
+
+	if (cs_mask & (1 << 0)) {
+		at91_set_a_periph(AT91_PIO_PORTA, 3, 1);
+	}
+	if (cs_mask & (1 << 1)) {
+		at91_set_b_periph(AT91_PIO_PORTC, 11, 1);
+	}
+	if (cs_mask & (1 << 2)) {
+		at91_set_b_periph(AT91_PIO_PORTC, 16, 1);
+	}
+	if (cs_mask & (1 << 3)) {
+		at91_set_b_periph(AT91_PIO_PORTC, 17, 1);
+	}
+	if (cs_mask & (1 << 4)) {
+		at91_set_pio_output(AT91_PIO_PORTA, 3, 1);
+	}
+	if (cs_mask & (1 << 5)) {
+		at91_set_pio_output(AT91_PIO_PORTC, 11, 1);
+	}
+	if (cs_mask & (1 << 6)) {
+		at91_set_pio_output(AT91_PIO_PORTC, 16, 1);
+	}
+	if (cs_mask & (1 << 7)) {
+		at91_set_pio_output(AT91_PIO_PORTC, 17, 1);
+	}
+}
+
+void at91_spi1_hw_init(unsigned long cs_mask)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTB, 0, PUP);	/* SPI1_MISO */
+	at91_set_a_periph(AT91_PIO_PORTB, 1, PUP);	/* SPI1_MOSI */
+	at91_set_a_periph(AT91_PIO_PORTB, 2, PUP);	/* SPI1_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI1, &pmc->pcer);
+
+	if (cs_mask & (1 << 0)) {
+		at91_set_a_periph(AT91_PIO_PORTB, 3, 1);
+	}
+	if (cs_mask & (1 << 1)) {
+		at91_set_b_periph(AT91_PIO_PORTC, 5, 1);
+	}
+	if (cs_mask & (1 << 2)) {
+		at91_set_b_periph(AT91_PIO_PORTC, 4, 1);
+	}
+	if (cs_mask & (1 << 3)) {
+		at91_set_b_periph(AT91_PIO_PORTC, 3, 1);
+	}
+	if (cs_mask & (1 << 4)) {
+		at91_set_pio_output(AT91_PIO_PORTB, 3, 1);
+	}
+	if (cs_mask & (1 << 5)) {
+		at91_set_pio_output(AT91_PIO_PORTC, 5, 1);
+	}
+	if (cs_mask & (1 << 6)) {
+		at91_set_pio_output(AT91_PIO_PORTC, 4, 1);
+	}
+	if (cs_mask & (1 << 7)) {
+		at91_set_pio_output(AT91_PIO_PORTC, 3, 1);
+	}
+}
+#endif
+
+#ifdef CONFIG_MACB
+void at91_macb_hw_init(void)
+{
+	/* Enable EMAC clock */
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	writel(1 << ATMEL_ID_EMAC0, &pmc->pcer);
+
+	at91_set_a_periph(AT91_PIO_PORTA, 19, 0);	/* ETXCK_EREFCK */
+	at91_set_a_periph(AT91_PIO_PORTA, 17, 0);	/* ERXDV */
+	at91_set_a_periph(AT91_PIO_PORTA, 14, 0);	/* ERX0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 15, 0);	/* ERX1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 18, 0);	/* ERXER */
+	at91_set_a_periph(AT91_PIO_PORTA, 16, 0);	/* ETXEN */
+	at91_set_a_periph(AT91_PIO_PORTA, 12, 0);	/* ETX0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 13, 0);	/* ETX1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 21, 0);	/* EMDIO */
+	at91_set_a_periph(AT91_PIO_PORTA, 20, 0);	/* EMDC */
+
+#ifndef CONFIG_RMII
+	at91_set_b_periph(AT91_PIO_PORTA, 28, 0);	/* ECRS */
+	at91_set_b_periph(AT91_PIO_PORTA, 29, 0);	/* ECOL */
+	at91_set_b_periph(AT91_PIO_PORTA, 25, 0);	/* ERX2 */
+	at91_set_b_periph(AT91_PIO_PORTA, 26, 0);	/* ERX3 */
+	at91_set_b_periph(AT91_PIO_PORTA, 27, 0);	/* ERXCK */
+#if defined(CONFIG_AT91SAM9260EK) || defined(CONFIG_AFEB9260)
+	/*
+	 * use PA10, PA11 for ETX2, ETX3.
+	 * PA23 and PA24 are for TWI EEPROM
+	 */
+	at91_set_b_periph(AT91_PIO_PORTA, 10, 0);	/* ETX2 */
+	at91_set_b_periph(AT91_PIO_PORTA, 11, 0);	/* ETX3 */
+#else
+	at91_set_b_periph(AT91_PIO_PORTA, 23, 0);	/* ETX2 */
+	at91_set_b_periph(AT91_PIO_PORTA, 24, 0);	/* ETX3 */
+#if defined(CONFIG_AT91SAM9G20)
+	/* 9G20 BOOT ROM initializes those pins to multi-drive, undo that */
+	at91_set_pio_multi_drive(AT91_PIO_PORTA, 23, 0);
+	at91_set_pio_multi_drive(AT91_PIO_PORTA, 24, 0);
+#endif
+#endif
+	at91_set_b_periph(AT91_PIO_PORTA, 22, 0);	/* ETXER */
+#endif
+}
+#endif
+
+#if defined(CONFIG_GENERIC_ATMEL_MCI)
+void at91_mci_hw_init(void)
+{
+	/* Enable mci clock */
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	writel(1 << ATMEL_ID_MCI, &pmc->pcer);
+
+	at91_set_a_periph(AT91_PIO_PORTA, 8, 1);	/* MCCK */
+#if defined(CONFIG_ATMEL_MCI_PORTB)
+	at91_set_b_periph(AT91_PIO_PORTA, 1, 1);	/* MCCDB */
+	at91_set_b_periph(AT91_PIO_PORTA, 0, 1);	/* MCDB0 */
+	at91_set_b_periph(AT91_PIO_PORTA, 5, 1);	/* MCDB1 */
+	at91_set_b_periph(AT91_PIO_PORTA, 4, 1);	/* MCDB2 */
+	at91_set_b_periph(AT91_PIO_PORTA, 3, 1);	/* MCDB3 */
+#else
+	at91_set_a_periph(AT91_PIO_PORTA, 7, 1);	/* MCCDA */
+	at91_set_a_periph(AT91_PIO_PORTA, 6, 1);	/* MCDA0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 9, 1);	/* MCDA1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 10, 1);	/* MCDA2 */
+	at91_set_a_periph(AT91_PIO_PORTA, 11, 1);	/* MCDA3 */
+#endif
+}
+#endif
+
+void at91_sdram_hw_init(void)
+{
+	at91_set_a_periph(AT91_PIO_PORTC, 16, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 17, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 18, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 19, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 20, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 21, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 22, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 23, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 24, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 25, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 26, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 27, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 28, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 29, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 30, 0);
+	at91_set_a_periph(AT91_PIO_PORTC, 31, 0);
+}
+
+/* Platform data for the GPIOs */
+static const struct at91_port_platdata at91sam9260_plat[] = {
+	{ ATMEL_BASE_PIOA, "PA" },
+	{ ATMEL_BASE_PIOB, "PB" },
+	{ ATMEL_BASE_PIOC, "PC" },
+};
+
+U_BOOT_DEVICES(at91sam9260_gpios) = {
+	{ "gpio_at91", &at91sam9260_plat[0] },
+	{ "gpio_at91", &at91sam9260_plat[1] },
+	{ "gpio_at91", &at91sam9260_plat[2] },
+};
diff --git a/arch/arm/mach-at91/arm926ejs/at91sam9261_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9261_devices.c
new file mode 100644
index 0000000..a445c75
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/at91sam9261_devices.c
@@ -0,0 +1,140 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.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/gpio.h>
+
+/*
+ * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all
+ * peripheral pins. Good to have if hardware is soldered optionally
+ * or in case of SPI no slave is selected. Avoid lines to float
+ * needlessly. Use a short local PUP define.
+ *
+ * Due to errata "TXD floats when CTS is inactive" pullups are always
+ * on for TXD pins.
+ */
+#ifdef CONFIG_AT91_GPIO_PULLUP
+# define PUP CONFIG_AT91_GPIO_PULLUP
+#else
+# define PUP 0
+#endif
+
+void at91_serial0_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTC, 8, 1);		/* TXD0 */
+	at91_set_a_periph(AT91_PIO_PORTC, 9, 0);		/* RXD0 */
+	writel(1 << ATMEL_ID_USART0, &pmc->pcer);
+}
+
+void at91_serial1_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTC, 12, 1);		/* TXD1 */
+	at91_set_a_periph(AT91_PIO_PORTC, 13, 0);		/* RXD1 */
+	writel(1 << ATMEL_ID_USART1, &pmc->pcer);
+}
+
+void at91_serial2_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTC, 14, 1);		/* TXD2 */
+	at91_set_a_periph(AT91_PIO_PORTC, 15, 0);		/* RXD2 */
+	writel(1 << ATMEL_ID_USART2, &pmc->pcer);
+}
+
+void at91_seriald_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 9, 0);		/* DRXD */
+	at91_set_a_periph(AT91_PIO_PORTA, 10, 1);		/* DTXD */
+	writel(1 << ATMEL_ID_SYS, &pmc->pcer);
+}
+
+#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI)
+void at91_spi0_hw_init(unsigned long cs_mask)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 0, PUP);	/* SPI0_MISO */
+	at91_set_a_periph(AT91_PIO_PORTA, 1, PUP);	/* SPI0_MOSI */
+	at91_set_a_periph(AT91_PIO_PORTA, 2, PUP);	/* SPI0_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI0, &pmc->pcer);
+
+	if (cs_mask & (1 << 0)) {
+		at91_set_a_periph(AT91_PIO_PORTA, 3, 1);
+	}
+	if (cs_mask & (1 << 1)) {
+		at91_set_a_periph(AT91_PIO_PORTA, 4, 1);
+	}
+	if (cs_mask & (1 << 2)) {
+		at91_set_a_periph(AT91_PIO_PORTA, 5, 1);
+	}
+	if (cs_mask & (1 << 3)) {
+		at91_set_a_periph(AT91_PIO_PORTA, 6, 1);
+	}
+	if (cs_mask & (1 << 4)) {
+		at91_set_pio_output(AT91_PIO_PORTA, 3, 1);
+	}
+	if (cs_mask & (1 << 5)) {
+		at91_set_pio_output(AT91_PIO_PORTA, 4, 1);
+	}
+	if (cs_mask & (1 << 6)) {
+		at91_set_pio_output(AT91_PIO_PORTA, 5, 1);
+	}
+	if (cs_mask & (1 << 7)) {
+		at91_set_pio_output(AT91_PIO_PORTA, 6, 1);
+	}
+}
+
+void at91_spi1_hw_init(unsigned long cs_mask)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTB, 30, PUP);	/* SPI1_MISO */
+	at91_set_a_periph(AT91_PIO_PORTB, 31, PUP);	/* SPI1_MOSI */
+	at91_set_a_periph(AT91_PIO_PORTB, 29, PUP);	/* SPI1_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI1, &pmc->pcer);
+
+	if (cs_mask & (1 << 0)) {
+		at91_set_a_periph(AT91_PIO_PORTB, 28, 1);
+	}
+	if (cs_mask & (1 << 1)) {
+		at91_set_b_periph(AT91_PIO_PORTA, 24, 1);
+	}
+	if (cs_mask & (1 << 2)) {
+		at91_set_b_periph(AT91_PIO_PORTA, 25, 1);
+	}
+	if (cs_mask & (1 << 3)) {
+		at91_set_a_periph(AT91_PIO_PORTA, 26, 1);
+	}
+	if (cs_mask & (1 << 4)) {
+		at91_set_pio_output(AT91_PIO_PORTB, 28, 1);
+	}
+	if (cs_mask & (1 << 5)) {
+		at91_set_pio_output(AT91_PIO_PORTA, 24, 1);
+	}
+	if (cs_mask & (1 << 6)) {
+		at91_set_pio_output(AT91_PIO_PORTA, 25, 1);
+	}
+	if (cs_mask & (1 << 7)) {
+		at91_set_pio_output(AT91_PIO_PORTA, 26, 1);
+	}
+}
+#endif
diff --git a/arch/arm/mach-at91/arm926ejs/at91sam9263_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9263_devices.c
new file mode 100644
index 0000000..6b51d5f
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/at91sam9263_devices.c
@@ -0,0 +1,218 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.com>
+ *
+ * (C) Copyright 2009-2011
+ * Daniel Gorsulowski <daniel.gorsulowski@esd.eu>
+ * esd electronic system design gmbh <www.esd.eu>
+ *
+ * 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/gpio.h>
+
+/*
+ * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all
+ * peripheral pins. Good to have if hardware is soldered optionally
+ * or in case of SPI no slave is selected. Avoid lines to float
+ * needlessly. Use a short local PUP define.
+ *
+ * Due to errata "TXD floats when CTS is inactive" pullups are always
+ * on for TXD pins.
+ */
+#ifdef CONFIG_AT91_GPIO_PULLUP
+# define PUP CONFIG_AT91_GPIO_PULLUP
+#else
+# define PUP 0
+#endif
+
+void at91_serial0_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 26, 1);		/* TXD0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 27, PUP);		/* RXD0 */
+	writel(1 << ATMEL_ID_USART0, &pmc->pcer);
+}
+
+void at91_serial1_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTD, 0, 1);		/* TXD1 */
+	at91_set_a_periph(AT91_PIO_PORTD, 1, PUP);		/* RXD1 */
+	writel(1 << ATMEL_ID_USART1, &pmc->pcer);
+}
+
+void at91_serial2_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTD, 2, 1);		/* TXD2 */
+	at91_set_a_periph(AT91_PIO_PORTD, 3, PUP);		/* RXD2 */
+	writel(1 << ATMEL_ID_USART2, &pmc->pcer);
+}
+
+void at91_seriald_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTC, 30, PUP);		/* DRXD */
+	at91_set_a_periph(AT91_PIO_PORTC, 31, 1);		/* DTXD */
+	writel(1 << ATMEL_ID_SYS, &pmc->pcer);
+}
+
+#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI)
+void at91_spi0_hw_init(unsigned long cs_mask)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_b_periph(AT91_PIO_PORTA, 0, PUP);	/* SPI0_MISO */
+	at91_set_b_periph(AT91_PIO_PORTA, 1, PUP);	/* SPI0_MOSI */
+	at91_set_b_periph(AT91_PIO_PORTA, 2, PUP);	/* SPI0_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI0, &pmc->pcer);
+
+	if (cs_mask & (1 << 0)) {
+		at91_set_b_periph(AT91_PIO_PORTA, 5, 1);
+	}
+	if (cs_mask & (1 << 1)) {
+		at91_set_b_periph(AT91_PIO_PORTA, 3, 1);
+	}
+	if (cs_mask & (1 << 2)) {
+		at91_set_b_periph(AT91_PIO_PORTA, 4, 1);
+	}
+	if (cs_mask & (1 << 3)) {
+		at91_set_b_periph(AT91_PIO_PORTB, 11, 1);
+	}
+	if (cs_mask & (1 << 4)) {
+		at91_set_pio_output(AT91_PIO_PORTA, 5, 1);
+	}
+	if (cs_mask & (1 << 5)) {
+		at91_set_pio_output(AT91_PIO_PORTA, 3, 1);
+	}
+	if (cs_mask & (1 << 6)) {
+		at91_set_pio_output(AT91_PIO_PORTA, 4, 1);
+	}
+	if (cs_mask & (1 << 7)) {
+		at91_set_pio_output(AT91_PIO_PORTB, 11, 1);
+	}
+}
+
+void at91_spi1_hw_init(unsigned long cs_mask)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTB, 12, PUP);	/* SPI1_MISO */
+	at91_set_a_periph(AT91_PIO_PORTB, 13, PUP);	/* SPI1_MOSI */
+	at91_set_a_periph(AT91_PIO_PORTB, 14, PUP);	/* SPI1_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI1, &pmc->pcer);
+
+	if (cs_mask & (1 << 0)) {
+		at91_set_a_periph(AT91_PIO_PORTB, 15, 1);
+	}
+	if (cs_mask & (1 << 1)) {
+		at91_set_a_periph(AT91_PIO_PORTB, 16, 1);
+	}
+	if (cs_mask & (1 << 2)) {
+		at91_set_a_periph(AT91_PIO_PORTB, 17, 1);
+	}
+	if (cs_mask & (1 << 3)) {
+		at91_set_a_periph(AT91_PIO_PORTB, 18, 1);
+	}
+	if (cs_mask & (1 << 4)) {
+		at91_set_pio_output(AT91_PIO_PORTB, 15, 1);
+	}
+	if (cs_mask & (1 << 5)) {
+		at91_set_pio_output(AT91_PIO_PORTB, 16, 1);
+	}
+	if (cs_mask & (1 << 6)) {
+		at91_set_pio_output(AT91_PIO_PORTB, 17, 1);
+	}
+	if (cs_mask & (1 << 7)) {
+		at91_set_pio_output(AT91_PIO_PORTB, 18, 1);
+	}
+}
+#endif
+
+#if defined(CONFIG_GENERIC_ATMEL_MCI)
+void at91_mci_hw_init(void)
+{
+	/* Enable mci clock */
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	writel(1 << ATMEL_ID_MCI1, &pmc->pcer);
+
+	at91_set_a_periph(AT91_PIO_PORTA, 6, PUP);	/* MCI1_CK */
+
+#if defined(CONFIG_ATMEL_MCI_PORTB)
+	at91_set_a_periph(AT91_PIO_PORTA, 21, PUP);	/* MCI1_CDB */
+	at91_set_a_periph(AT91_PIO_PORTA, 22, PUP);	/* MCI1_DB0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 23, PUP);	/* MCI1_DB1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 24, PUP);	/* MCI1_DB2 */
+	at91_set_a_periph(AT91_PIO_PORTA, 25, PUP);	/* MCI1_DB3 */
+#else
+	at91_set_a_periph(AT91_PIO_PORTA, 7, PUP);	/* MCI1_CDA */
+	at91_set_a_periph(AT91_PIO_PORTA, 8, PUP);	/* MCI1_DA0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 9, PUP);	/* MCI1_DA1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 10, PUP);	/* MCI1_DA2 */
+	at91_set_a_periph(AT91_PIO_PORTA, 11, PUP);	/* MCI1_DA3 */
+#endif
+}
+#endif
+
+#ifdef CONFIG_MACB
+void at91_macb_hw_init(void)
+{
+	at91_set_a_periph(AT91_PIO_PORTE, 21, 0);	/* ETXCK_EREFCK */
+	at91_set_b_periph(AT91_PIO_PORTC, 25, 0);	/* ERXDV */
+	at91_set_a_periph(AT91_PIO_PORTE, 25, 0);	/* ERX0 */
+	at91_set_a_periph(AT91_PIO_PORTE, 26, 0);	/* ERX1 */
+	at91_set_a_periph(AT91_PIO_PORTE, 27, 0);	/* ERXER */
+	at91_set_a_periph(AT91_PIO_PORTE, 28, 0);	/* ETXEN */
+	at91_set_a_periph(AT91_PIO_PORTE, 23, 0);	/* ETX0 */
+	at91_set_a_periph(AT91_PIO_PORTE, 24, 0);	/* ETX1 */
+	at91_set_a_periph(AT91_PIO_PORTE, 30, 0);	/* EMDIO */
+	at91_set_a_periph(AT91_PIO_PORTE, 29, 0);	/* EMDC */
+
+#ifndef CONFIG_RMII
+	at91_set_a_periph(AT91_PIO_PORTE, 22, 0);	/* ECRS */
+	at91_set_b_periph(AT91_PIO_PORTC, 26, 0);	/* ECOL */
+	at91_set_b_periph(AT91_PIO_PORTC, 22, 0);	/* ERX2 */
+	at91_set_b_periph(AT91_PIO_PORTC, 23, 0);	/* ERX3 */
+	at91_set_b_periph(AT91_PIO_PORTC, 27, 0);	/* ERXCK */
+	at91_set_b_periph(AT91_PIO_PORTC, 20, 0);	/* ETX2 */
+	at91_set_b_periph(AT91_PIO_PORTC, 21, 0);	/* ETX3 */
+	at91_set_b_periph(AT91_PIO_PORTC, 24, 0);	/* ETXER */
+#endif
+}
+#endif
+
+#ifdef CONFIG_USB_OHCI_NEW
+void at91_uhp_hw_init(void)
+{
+	/* Enable VBus on UHP ports */
+	at91_set_pio_output(AT91_PIO_PORTA, 21, 0);
+	at91_set_pio_output(AT91_PIO_PORTA, 24, 0);
+}
+#endif
+
+#ifdef CONFIG_AT91_CAN
+void at91_can_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 13, 0);	/* CAN_TX */
+	at91_set_a_periph(AT91_PIO_PORTA, 14, 1);	/* CAN_RX */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_CAN, &pmc->pcer);
+}
+#endif
diff --git a/arch/arm/mach-at91/arm926ejs/at91sam9m10g45_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9m10g45_devices.c
new file mode 100644
index 0000000..0e6c0da
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/at91sam9m10g45_devices.c
@@ -0,0 +1,184 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/gpio.h>
+#include <asm/io.h>
+
+/*
+ * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all
+ * peripheral pins. Good to have if hardware is soldered optionally
+ * or in case of SPI no slave is selected. Avoid lines to float
+ * needlessly. Use a short local PUP define.
+ *
+ * Due to errata "TXD floats when CTS is inactive" pullups are always
+ * on for TXD pins.
+ */
+#ifdef CONFIG_AT91_GPIO_PULLUP
+# define PUP CONFIG_AT91_GPIO_PULLUP
+#else
+# define PUP 0
+#endif
+
+void at91_serial0_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTB, 19, 1);	/* TXD0 */
+	at91_set_a_periph(AT91_PIO_PORTB, 18, PUP);	/* RXD0 */
+	writel(1 << ATMEL_ID_USART0, &pmc->pcer);
+}
+
+void at91_serial1_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTB, 4, 1);		/* TXD1 */
+	at91_set_a_periph(AT91_PIO_PORTB, 5, PUP);		/* RXD1 */
+	writel(1 << ATMEL_ID_USART1, &pmc->pcer);
+}
+
+void at91_serial2_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTD, 6, 1);		/* TXD2 */
+	at91_set_a_periph(AT91_PIO_PORTD, 7, PUP);		/* RXD2 */
+	writel(1 << ATMEL_ID_USART2, &pmc->pcer);
+}
+
+void at91_seriald_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTB, 12, 0);	/* DRXD */
+	at91_set_a_periph(AT91_PIO_PORTB, 13, 1);	/* DTXD */
+	writel(1 << ATMEL_ID_SYS, &pmc->pcer);
+}
+
+#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI)
+void at91_spi0_hw_init(unsigned long cs_mask)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTB, 0, PUP);	/* SPI0_MISO */
+	at91_set_a_periph(AT91_PIO_PORTB, 1, PUP);	/* SPI0_MOSI */
+	at91_set_a_periph(AT91_PIO_PORTB, 2, PUP);	/* SPI0_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI0, &pmc->pcer);
+
+	if (cs_mask & (1 << 0)) {
+		at91_set_a_periph(AT91_PIO_PORTB, 3, 1);
+	}
+	if (cs_mask & (1 << 1)) {
+		at91_set_b_periph(AT91_PIO_PORTB, 18, 1);
+	}
+	if (cs_mask & (1 << 2)) {
+		at91_set_b_periph(AT91_PIO_PORTB, 19, 1);
+	}
+	if (cs_mask & (1 << 3)) {
+		at91_set_b_periph(AT91_PIO_PORTD, 27, 1);
+	}
+	if (cs_mask & (1 << 4)) {
+		at91_set_pio_output(AT91_PIO_PORTB, 3, 1);
+	}
+	if (cs_mask & (1 << 5)) {
+		at91_set_pio_output(AT91_PIO_PORTB, 18, 1);
+	}
+	if (cs_mask & (1 << 6)) {
+		at91_set_pio_output(AT91_PIO_PORTB, 19, 1);
+	}
+	if (cs_mask & (1 << 7)) {
+		at91_set_pio_output(AT91_PIO_PORTD, 27, 1);
+	}
+}
+
+void at91_spi1_hw_init(unsigned long cs_mask)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTB, 14, PUP);	/* SPI1_MISO */
+	at91_set_a_periph(AT91_PIO_PORTB, 15, PUP);	/* SPI1_MOSI */
+	at91_set_a_periph(AT91_PIO_PORTB, 16, PUP);	/* SPI1_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI1, &pmc->pcer);
+
+	if (cs_mask & (1 << 0)) {
+		at91_set_a_periph(AT91_PIO_PORTB, 17, 1);
+	}
+	if (cs_mask & (1 << 1)) {
+		at91_set_b_periph(AT91_PIO_PORTD, 28, 1);
+	}
+	if (cs_mask & (1 << 2)) {
+		at91_set_a_periph(AT91_PIO_PORTD, 18, 1);
+	}
+	if (cs_mask & (1 << 3)) {
+		at91_set_a_periph(AT91_PIO_PORTD, 19, 1);
+	}
+	if (cs_mask & (1 << 4)) {
+		at91_set_pio_output(AT91_PIO_PORTB, 17, 1);
+	}
+	if (cs_mask & (1 << 5)) {
+		at91_set_pio_output(AT91_PIO_PORTD, 28, 1);
+	}
+	if (cs_mask & (1 << 6)) {
+		at91_set_pio_output(AT91_PIO_PORTD, 18, 1);
+	}
+	if (cs_mask & (1 << 7)) {
+		at91_set_pio_output(AT91_PIO_PORTD, 19, 1);
+	}
+
+}
+#endif
+
+#ifdef CONFIG_MACB
+void at91_macb_hw_init(void)
+{
+	at91_set_a_periph(AT91_PIO_PORTA, 17, 0);	/* ETXCK_EREFCK */
+	at91_set_a_periph(AT91_PIO_PORTA, 15, 0);	/* ERXDV */
+	at91_set_a_periph(AT91_PIO_PORTA, 12, 0);	/* ERX0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 13, 0);	/* ERX1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 16, 0);	/* ERXER */
+	at91_set_a_periph(AT91_PIO_PORTA, 14, 0);	/* ETXEN */
+	at91_set_a_periph(AT91_PIO_PORTA, 10, 0);	/* ETX0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 11, 0);	/* ETX1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 19, 0);	/* EMDIO */
+	at91_set_a_periph(AT91_PIO_PORTA, 18, 0);	/* EMDC */
+#ifndef CONFIG_RMII
+	at91_set_b_periph(AT91_PIO_PORTA, 29, 0);	/* ECRS */
+	at91_set_b_periph(AT91_PIO_PORTA, 30, 0);	/* ECOL */
+	at91_set_b_periph(AT91_PIO_PORTA, 8,  0);	/* ERX2 */
+	at91_set_b_periph(AT91_PIO_PORTA, 9,  0);	/* ERX3 */
+	at91_set_b_periph(AT91_PIO_PORTA, 28, 0);	/* ERXCK */
+	at91_set_b_periph(AT91_PIO_PORTA, 6,  0);	/* ETX2 */
+	at91_set_b_periph(AT91_PIO_PORTA, 7,  0);	/* ETX3 */
+	at91_set_b_periph(AT91_PIO_PORTA, 27, 0);	/* ETXER */
+#endif
+}
+#endif
+
+#ifdef CONFIG_GENERIC_ATMEL_MCI
+void at91_mci_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 0, 0);	/* MCI0 CLK */
+	at91_set_a_periph(AT91_PIO_PORTA, 1, 0);	/* MCI0 CDA */
+	at91_set_a_periph(AT91_PIO_PORTA, 2, 0);	/* MCI0 DA0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 3, 0);	/* MCI0 DA1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 4, 0);	/* MCI0 DA2 */
+	at91_set_a_periph(AT91_PIO_PORTA, 5, 0);	/* MCI0 DA3 */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_MCI0, &pmc->pcer);
+}
+#endif
diff --git a/arch/arm/mach-at91/arm926ejs/at91sam9n12_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9n12_devices.c
new file mode 100644
index 0000000..39f17a1
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/at91sam9n12_devices.c
@@ -0,0 +1,161 @@
+/*
+ * (C) Copyright 2013 Atmel Corporation
+ * Josh Wu <josh.wu@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_pio.h>
+
+unsigned int has_lcdc()
+{
+	return 1;
+}
+
+void at91_serial0_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 0, 1);		/* TXD0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 1, 0);		/* RXD0 */
+	writel(1 << ATMEL_ID_USART0, &pmc->pcer);
+}
+
+void at91_serial1_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 5, 1);		/* TXD1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 6, 0);		/* RXD1 */
+	writel(1 << ATMEL_ID_USART1, &pmc->pcer);
+}
+
+void at91_serial2_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 7, 1);		/* TXD2 */
+	at91_set_a_periph(AT91_PIO_PORTA, 8, 0);		/* RXD2 */
+	writel(1 << ATMEL_ID_USART2, &pmc->pcer);
+}
+
+void at91_serial3_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_b_periph(AT91_PIO_PORTC, 22, 1);		/* TXD3 */
+	at91_set_b_periph(AT91_PIO_PORTC, 23, 0);		/* RXD3 */
+	writel(1 << ATMEL_ID_USART3, &pmc->pcer);
+}
+
+void at91_seriald_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 10, 1);		/* DTXD */
+	at91_set_a_periph(AT91_PIO_PORTA, 9, 0);		/* DRXD */
+	writel(1 << ATMEL_ID_SYS, &pmc->pcer);
+}
+
+#ifdef CONFIG_ATMEL_SPI
+void at91_spi0_hw_init(unsigned long cs_mask)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 11, 0);	/* SPI0_MISO */
+	at91_set_a_periph(AT91_PIO_PORTA, 12, 0);	/* SPI0_MOSI */
+	at91_set_a_periph(AT91_PIO_PORTA, 13, 0);	/* SPI0_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI0, &pmc->pcer);
+
+	if (cs_mask & (1 << 0))
+		at91_set_pio_output(AT91_PIO_PORTA, 14, 1);
+	if (cs_mask & (1 << 1))
+		at91_set_pio_output(AT91_PIO_PORTA, 7, 1);
+	if (cs_mask & (1 << 2))
+		at91_set_pio_output(AT91_PIO_PORTA, 1, 1);
+	if (cs_mask & (1 << 3))
+		at91_set_pio_output(AT91_PIO_PORTB, 3, 1);
+}
+
+void at91_spi1_hw_init(unsigned long cs_mask)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_b_periph(AT91_PIO_PORTA, 21, 0);	/* SPI1_MISO */
+	at91_set_b_periph(AT91_PIO_PORTA, 22, 0);	/* SPI1_MOSI */
+	at91_set_b_periph(AT91_PIO_PORTA, 23, 0);	/* SPI1_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI1, &pmc->pcer);
+
+	if (cs_mask & (1 << 0))
+		at91_set_pio_output(AT91_PIO_PORTA, 8, 1);
+	if (cs_mask & (1 << 1))
+		at91_set_pio_output(AT91_PIO_PORTA, 0, 1);
+	if (cs_mask & (1 << 2))
+		at91_set_pio_output(AT91_PIO_PORTA, 31, 1);
+	if (cs_mask & (1 << 3))
+		at91_set_pio_output(AT91_PIO_PORTA, 30, 1);
+}
+#endif
+
+void at91_mci_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 17, 0);	/* MCCK */
+	at91_set_a_periph(AT91_PIO_PORTA, 16, 0);	/* MCCDA */
+	at91_set_a_periph(AT91_PIO_PORTA, 15, 0);	/* MCDA0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 18, 0);	/* MCDA1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 19, 0);	/* MCDA2 */
+	at91_set_a_periph(AT91_PIO_PORTA, 20, 0);	/* MCDA3 */
+
+	writel(1 << ATMEL_ID_HSMCI0, &pmc->pcer);
+}
+
+#ifdef CONFIG_LCD
+void at91_lcd_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTC, 24, 0);	/* LCDDPWR */
+	at91_set_a_periph(AT91_PIO_PORTC, 26, 0);	/* LCDVSYNC */
+	at91_set_a_periph(AT91_PIO_PORTC, 27, 0);	/* LCDHSYNC */
+	at91_set_a_periph(AT91_PIO_PORTC, 28, 0);	/* LCDDOTCK */
+	at91_set_a_periph(AT91_PIO_PORTC, 29, 0);	/* LCDDEN */
+	at91_set_a_periph(AT91_PIO_PORTC, 30, 0);	/* LCDDOTCK */
+
+	at91_set_a_periph(AT91_PIO_PORTC, 0, 0);	/* LCDD0 */
+	at91_set_a_periph(AT91_PIO_PORTC, 1, 0);	/* LCDD1 */
+	at91_set_a_periph(AT91_PIO_PORTC, 2, 0);	/* LCDD2 */
+	at91_set_a_periph(AT91_PIO_PORTC, 3, 0);	/* LCDD3 */
+	at91_set_a_periph(AT91_PIO_PORTC, 4, 0);	/* LCDD4 */
+	at91_set_a_periph(AT91_PIO_PORTC, 5, 0);	/* LCDD5 */
+	at91_set_a_periph(AT91_PIO_PORTC, 6, 0);	/* LCDD6 */
+	at91_set_a_periph(AT91_PIO_PORTC, 7, 0);	/* LCDD7 */
+	at91_set_a_periph(AT91_PIO_PORTC, 8, 0);	/* LCDD8 */
+	at91_set_a_periph(AT91_PIO_PORTC, 9, 0);	/* LCDD9 */
+	at91_set_a_periph(AT91_PIO_PORTC, 10, 0);	/* LCDD10 */
+	at91_set_a_periph(AT91_PIO_PORTC, 11, 0);	/* LCDD11 */
+	at91_set_a_periph(AT91_PIO_PORTC, 12, 0);	/* LCDD12 */
+	at91_set_a_periph(AT91_PIO_PORTC, 13, 0);	/* LCDD13 */
+	at91_set_a_periph(AT91_PIO_PORTC, 14, 0);	/* LCDD14 */
+	at91_set_a_periph(AT91_PIO_PORTC, 15, 0);	/* LCDD15 */
+	at91_set_a_periph(AT91_PIO_PORTC, 16, 0);	/* LCDD16 */
+	at91_set_a_periph(AT91_PIO_PORTC, 17, 0);	/* LCDD17 */
+	at91_set_a_periph(AT91_PIO_PORTC, 18, 0);	/* LCDD18 */
+	at91_set_a_periph(AT91_PIO_PORTC, 19, 0);	/* LCDD19 */
+	at91_set_a_periph(AT91_PIO_PORTC, 20, 0);	/* LCDD20 */
+	at91_set_a_periph(AT91_PIO_PORTC, 21, 0);	/* LCDD21 */
+	at91_set_a_periph(AT91_PIO_PORTC, 22, 0);	/* LCDD22 */
+	at91_set_a_periph(AT91_PIO_PORTC, 23, 0);	/* LCDD23 */
+
+	writel(1 << ATMEL_ID_LCDC, &pmc->pcer);
+}
+#endif
diff --git a/arch/arm/mach-at91/arm926ejs/at91sam9rl_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9rl_devices.c
new file mode 100644
index 0000000..0ec32c3
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/at91sam9rl_devices.c
@@ -0,0 +1,103 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.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/gpio.h>
+
+/*
+ * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all
+ * peripheral pins. Good to have if hardware is soldered optionally
+ * or in case of SPI no slave is selected. Avoid lines to float
+ * needlessly. Use a short local PUP define.
+ *
+ * Due to errata "TXD floats when CTS is inactive" pullups are always
+ * on for TXD pins.
+ */
+#ifdef CONFIG_AT91_GPIO_PULLUP
+# define PUP CONFIG_AT91_GPIO_PULLUP
+#else
+# define PUP 0
+#endif
+
+void at91_serial0_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 6, 1);		/* TXD0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 7, PUP);		/* RXD0 */
+	writel(1 << ATMEL_ID_USART0, &pmc->pcer);
+}
+
+void at91_serial1_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 11, 1);		/* TXD1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 12, PUP);		/* RXD1 */
+	writel(1 << ATMEL_ID_USART1, &pmc->pcer);
+}
+
+void at91_serial2_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 13, 1);		/* TXD2 */
+	at91_set_a_periph(AT91_PIO_PORTA, 14, PUP);		/* RXD2 */
+	writel(1 << ATMEL_ID_USART2, &pmc->pcer);
+}
+
+void at91_seriald_hw_init(void)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 21, PUP);		/* DRXD */
+	at91_set_a_periph(AT91_PIO_PORTA, 22, 1);		/* DTXD */
+	writel(1 << ATMEL_ID_SYS, &pmc->pcer);
+}
+
+#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI)
+void at91_spi0_hw_init(unsigned long cs_mask)
+{
+	at91_pmc_t	*pmc	= (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 25, PUP);	/* SPI0_MISO */
+	at91_set_a_periph(AT91_PIO_PORTA, 26, PUP);	/* SPI0_MOSI */
+	at91_set_a_periph(AT91_PIO_PORTA, 27, PUP);	/* SPI0_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI, &pmc->pcer);
+
+	if (cs_mask & (1 << 0)) {
+		at91_set_a_periph(AT91_PIO_PORTA, 28, 1);
+	}
+	if (cs_mask & (1 << 1)) {
+		at91_set_b_periph(AT91_PIO_PORTB, 7, 1);
+	}
+	if (cs_mask & (1 << 2)) {
+		at91_set_a_periph(AT91_PIO_PORTD, 8, 1);
+	}
+	if (cs_mask & (1 << 3)) {
+		at91_set_b_periph(AT91_PIO_PORTD, 9, 1);
+	}
+	if (cs_mask & (1 << 4)) {
+		at91_set_pio_output(AT91_PIO_PORTA, 28, 1);
+	}
+	if (cs_mask & (1 << 5)) {
+		at91_set_pio_output(AT91_PIO_PORTB, 7, 1);
+	}
+	if (cs_mask & (1 << 6)) {
+		at91_set_pio_output(AT91_PIO_PORTD, 8, 1);
+	}
+	if (cs_mask & (1 << 7)) {
+		at91_set_pio_output(AT91_PIO_PORTD, 9, 1);
+	}
+}
+#endif
diff --git a/arch/arm/mach-at91/arm926ejs/at91sam9x5_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9x5_devices.c
new file mode 100644
index 0000000..6d94572
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/at91sam9x5_devices.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2012 Atmel Corporation
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/gpio.h>
+#include <asm/io.h>
+
+unsigned int get_chip_id(void)
+{
+	/* The 0x40 is the offset of cidr in DBGU */
+	return readl(ATMEL_BASE_DBGU + 0x40) & ~ARCH_ID_VERSION_MASK;
+}
+
+unsigned int get_extension_chip_id(void)
+{
+	/* The 0x44 is the offset of exid in DBGU */
+	return readl(ATMEL_BASE_DBGU + 0x44);
+}
+
+unsigned int has_emac1()
+{
+	return cpu_is_at91sam9x25();
+}
+
+unsigned int has_emac0()
+{
+	return !(cpu_is_at91sam9g15());
+}
+
+unsigned int has_lcdc()
+{
+	return cpu_is_at91sam9g15() || cpu_is_at91sam9g35()
+		|| cpu_is_at91sam9x35();
+}
+
+char *get_cpu_name()
+{
+	unsigned int extension_id = get_extension_chip_id();
+
+	if (cpu_is_at91sam9x5()) {
+		switch (extension_id) {
+		case ARCH_EXID_AT91SAM9G15:
+			return "AT91SAM9G15";
+		case ARCH_EXID_AT91SAM9G25:
+			return "AT91SAM9G25";
+		case ARCH_EXID_AT91SAM9G35:
+			return "AT91SAM9G35";
+		case ARCH_EXID_AT91SAM9X25:
+			return "AT91SAM9X25";
+		case ARCH_EXID_AT91SAM9X35:
+			return "AT91SAM9X35";
+		default:
+			return "Unknown CPU type";
+		}
+	} else {
+		return "Unknown CPU type";
+	}
+}
+
+void at91_seriald_hw_init(void)
+{
+	at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 9, 0);	/* DRXD */
+	at91_set_a_periph(AT91_PIO_PORTA, 10, 1);	/* DTXD */
+
+	writel(1 << ATMEL_ID_SYS, &pmc->pcer);
+}
+
+void at91_serial0_hw_init(void)
+{
+	at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 0, 1);	/* TXD */
+	at91_set_a_periph(AT91_PIO_PORTA, 1, 0);	/* RXD */
+
+	writel(1 << ATMEL_ID_USART0, &pmc->pcer);
+}
+
+void at91_serial1_hw_init(void)
+{
+	at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 5, 1);	/* TXD */
+	at91_set_a_periph(AT91_PIO_PORTA, 6, 0);	/* RXD */
+
+	writel(1 << ATMEL_ID_USART1, &pmc->pcer);
+}
+
+void at91_serial2_hw_init(void)
+{
+	at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 7, 1);	/* TXD */
+	at91_set_a_periph(AT91_PIO_PORTA, 8, 0);	/* RXD */
+
+	writel(1 << ATMEL_ID_USART2, &pmc->pcer);
+}
+
+void at91_mci_hw_init(void)
+{
+	/* Initialize the MCI0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 17, 1);	/* MCCK */
+	at91_set_a_periph(AT91_PIO_PORTA, 16, 1);	/* MCCDA */
+	at91_set_a_periph(AT91_PIO_PORTA, 15, 1);	/* MCDA0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 18, 1);	/* MCDA1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 19, 1);	/* MCDA2 */
+	at91_set_a_periph(AT91_PIO_PORTA, 20, 1);	/* MCDA3 */
+
+	/* Enable clock for MCI0 */
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	writel(1 << ATMEL_ID_HSMCI0, &pmc->pcer);
+}
+
+#ifdef CONFIG_ATMEL_SPI
+void at91_spi0_hw_init(unsigned long cs_mask)
+{
+	at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 11, 0);	/* SPI0_MISO */
+	at91_set_a_periph(AT91_PIO_PORTA, 12, 0);	/* SPI0_MOSI */
+	at91_set_a_periph(AT91_PIO_PORTA, 13, 0);	/* SPI0_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI0, &pmc->pcer);
+
+	if (cs_mask & (1 << 0))
+		at91_set_a_periph(AT91_PIO_PORTA, 14, 0);
+	if (cs_mask & (1 << 1))
+		at91_set_b_periph(AT91_PIO_PORTA, 7, 0);
+	if (cs_mask & (1 << 2))
+		at91_set_b_periph(AT91_PIO_PORTA, 1, 0);
+	if (cs_mask & (1 << 3))
+		at91_set_b_periph(AT91_PIO_PORTB, 3, 0);
+	if (cs_mask & (1 << 4))
+		at91_set_pio_output(AT91_PIO_PORTA, 14, 0);
+	if (cs_mask & (1 << 5))
+		at91_set_pio_output(AT91_PIO_PORTA, 7, 0);
+	if (cs_mask & (1 << 6))
+		at91_set_pio_output(AT91_PIO_PORTA, 1, 0);
+	if (cs_mask & (1 << 7))
+		at91_set_pio_output(AT91_PIO_PORTB, 3, 0);
+}
+
+void at91_spi1_hw_init(unsigned long cs_mask)
+{
+	at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	at91_set_b_periph(AT91_PIO_PORTA, 21, 0);	/* SPI1_MISO */
+	at91_set_b_periph(AT91_PIO_PORTA, 22, 0);	/* SPI1_MOSI */
+	at91_set_b_periph(AT91_PIO_PORTA, 23, 0);	/* SPI1_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI1, &pmc->pcer);
+
+	if (cs_mask & (1 << 0))
+		at91_set_b_periph(AT91_PIO_PORTA, 8, 0);
+	if (cs_mask & (1 << 1))
+		at91_set_b_periph(AT91_PIO_PORTA, 0, 0);
+	if (cs_mask & (1 << 2))
+		at91_set_b_periph(AT91_PIO_PORTA, 31, 0);
+	if (cs_mask & (1 << 3))
+		at91_set_b_periph(AT91_PIO_PORTA, 30, 0);
+	if (cs_mask & (1 << 4))
+		at91_set_pio_output(AT91_PIO_PORTA, 8, 0);
+	if (cs_mask & (1 << 5))
+		at91_set_pio_output(AT91_PIO_PORTA, 0, 0);
+	if (cs_mask & (1 << 6))
+		at91_set_pio_output(AT91_PIO_PORTA, 31, 0);
+	if (cs_mask & (1 << 7))
+		at91_set_pio_output(AT91_PIO_PORTA, 30, 0);
+}
+#endif
+
+#if defined(CONFIG_USB_OHCI_NEW) || defined(CONFIG_USB_EHCI)
+void at91_uhp_hw_init(void)
+{
+	/* Enable VBus on UHP ports */
+	at91_set_pio_output(AT91_PIO_PORTD, 18, 0); /* port A */
+	at91_set_pio_output(AT91_PIO_PORTD, 19, 0); /* port B */
+#if defined(CONFIG_USB_OHCI_NEW)
+	/* port C is OHCI only */
+	at91_set_pio_output(AT91_PIO_PORTD, 20, 0); /* port C */
+#endif
+}
+#endif
+
+#ifdef CONFIG_MACB
+void at91_macb_hw_init(void)
+{
+	at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
+
+	if (has_emac0()) {
+		/* Enable EMAC0 clock */
+		writel(1 << ATMEL_ID_EMAC0, &pmc->pcer);
+		/* EMAC0 pins setup */
+		at91_set_a_periph(AT91_PIO_PORTB, 4, 0);	/* ETXCK */
+		at91_set_a_periph(AT91_PIO_PORTB, 3, 0);	/* ERXDV */
+		at91_set_a_periph(AT91_PIO_PORTB, 0, 0);	/* ERX0 */
+		at91_set_a_periph(AT91_PIO_PORTB, 1, 0);	/* ERX1 */
+		at91_set_a_periph(AT91_PIO_PORTB, 2, 0);	/* ERXER */
+		at91_set_a_periph(AT91_PIO_PORTB, 7, 0);	/* ETXEN */
+		at91_set_a_periph(AT91_PIO_PORTB, 9, 0);	/* ETX0 */
+		at91_set_a_periph(AT91_PIO_PORTB, 10, 0);	/* ETX1 */
+		at91_set_a_periph(AT91_PIO_PORTB, 5, 0);	/* EMDIO */
+		at91_set_a_periph(AT91_PIO_PORTB, 6, 0);	/* EMDC */
+	}
+
+	if (has_emac1()) {
+		/* Enable EMAC1 clock */
+		writel(1 << ATMEL_ID_EMAC1, &pmc->pcer);
+		/* EMAC1 pins setup */
+		at91_set_b_periph(AT91_PIO_PORTC, 29, 0);	/* ETXCK */
+		at91_set_b_periph(AT91_PIO_PORTC, 28, 0);	/* ECRSDV */
+		at91_set_b_periph(AT91_PIO_PORTC, 20, 0);	/* ERXO */
+		at91_set_b_periph(AT91_PIO_PORTC, 21, 0);	/* ERX1 */
+		at91_set_b_periph(AT91_PIO_PORTC, 16, 0);	/* ERXER */
+		at91_set_b_periph(AT91_PIO_PORTC, 27, 0);	/* ETXEN */
+		at91_set_b_periph(AT91_PIO_PORTC, 18, 0);	/* ETX0 */
+		at91_set_b_periph(AT91_PIO_PORTC, 19, 0);	/* ETX1 */
+		at91_set_b_periph(AT91_PIO_PORTC, 31, 0);	/* EMDIO */
+		at91_set_b_periph(AT91_PIO_PORTC, 30, 0);	/* EMDC */
+	}
+
+#ifndef CONFIG_RMII
+	/* Only emac0 support MII */
+	if (has_emac0()) {
+		at91_set_a_periph(AT91_PIO_PORTB, 16, 0);	/* ECRS */
+		at91_set_a_periph(AT91_PIO_PORTB, 17, 0);	/* ECOL */
+		at91_set_a_periph(AT91_PIO_PORTB, 13, 0);	/* ERX2 */
+		at91_set_a_periph(AT91_PIO_PORTB, 14, 0);	/* ERX3 */
+		at91_set_a_periph(AT91_PIO_PORTB, 15, 0);	/* ERXCK */
+		at91_set_a_periph(AT91_PIO_PORTB, 11, 0);	/* ETX2 */
+		at91_set_a_periph(AT91_PIO_PORTB, 12, 0);	/* ETX3 */
+		at91_set_a_periph(AT91_PIO_PORTB, 8, 0);	/* ETXER */
+	}
+#endif
+}
+#endif
diff --git a/arch/arm/mach-at91/arm926ejs/clock.c b/arch/arm/mach-at91/arm926ejs/clock.c
new file mode 100644
index 0000000..f363982
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/clock.c
@@ -0,0 +1,249 @@
+/*
+ * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c]
+ *
+ * Copyright (C) 2005 David Brownell
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/clk.h>
+
+#if !defined(CONFIG_AT91FAMILY)
+# error You need to define CONFIG_AT91FAMILY in your board config!
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static unsigned long at91_css_to_rate(unsigned long css)
+{
+	switch (css) {
+	case AT91_PMC_MCKR_CSS_SLOW:
+		return CONFIG_SYS_AT91_SLOW_CLOCK;
+	case AT91_PMC_MCKR_CSS_MAIN:
+		return gd->arch.main_clk_rate_hz;
+	case AT91_PMC_MCKR_CSS_PLLA:
+		return gd->arch.plla_rate_hz;
+	case AT91_PMC_MCKR_CSS_PLLB:
+		return gd->arch.pllb_rate_hz;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_USB_ATMEL
+static unsigned at91_pll_calc(unsigned main_freq, unsigned out_freq)
+{
+	unsigned i, div = 0, mul = 0, diff = 1 << 30;
+	unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00;
+
+	/* PLL output max 240 MHz (or 180 MHz per errata) */
+	if (out_freq > 240000000)
+		goto fail;
+
+	for (i = 1; i < 256; i++) {
+		int diff1;
+		unsigned input, mul1;
+
+		/*
+		 * PLL input between 1MHz and 32MHz per spec, but lower
+		 * frequences seem necessary in some cases so allow 100K.
+		 * Warning: some newer products need 2MHz min.
+		 */
+		input = main_freq / i;
+#if defined(CONFIG_AT91SAM9G20)
+		if (input < 2000000)
+			continue;
+#endif
+		if (input < 100000)
+			continue;
+		if (input > 32000000)
+			continue;
+
+		mul1 = out_freq / input;
+#if defined(CONFIG_AT91SAM9G20)
+		if (mul > 63)
+			continue;
+#endif
+		if (mul1 > 2048)
+			continue;
+		if (mul1 < 2)
+			goto fail;
+
+		diff1 = out_freq - input * mul1;
+		if (diff1 < 0)
+			diff1 = -diff1;
+		if (diff > diff1) {
+			diff = diff1;
+			div = i;
+			mul = mul1;
+			if (diff == 0)
+				break;
+		}
+	}
+	if (i == 256 && diff > (out_freq >> 5))
+		goto fail;
+	return ret | ((mul - 1) << 16) | div;
+fail:
+	return 0;
+}
+#endif
+
+static u32 at91_pll_rate(u32 freq, u32 reg)
+{
+	unsigned mul, div;
+
+	div = reg & 0xff;
+	mul = (reg >> 16) & 0x7ff;
+	if (div && mul) {
+		freq /= div;
+		freq *= mul + 1;
+	} else
+		freq = 0;
+
+	return freq;
+}
+
+int at91_clock_init(unsigned long main_clock)
+{
+	unsigned freq, mckr;
+	at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
+#ifndef CONFIG_SYS_AT91_MAIN_CLOCK
+	unsigned tmp;
+	/*
+	 * When the bootloader initialized the main oscillator correctly,
+	 * there's no problem using the cycle counter.  But if it didn't,
+	 * or when using oscillator bypass mode, we must be told the speed
+	 * of the main clock.
+	 */
+	if (!main_clock) {
+		do {
+			tmp = readl(&pmc->mcfr);
+		} while (!(tmp & AT91_PMC_MCFR_MAINRDY));
+		tmp &= AT91_PMC_MCFR_MAINF_MASK;
+		main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16);
+	}
+#endif
+	gd->arch.main_clk_rate_hz = main_clock;
+
+	/* report if PLLA is more than mildly overclocked */
+	gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
+
+#ifdef CONFIG_USB_ATMEL
+	/*
+	 * USB clock init:  choose 48 MHz PLLB value,
+	 * disable 48MHz clock during usb peripheral suspend.
+	 *
+	 * REVISIT:  assumes MCK doesn't derive from PLLB!
+	 */
+	gd->arch.at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
+			     AT91_PMC_PLLBR_USBDIV_2;
+	gd->arch.pllb_rate_hz = at91_pll_rate(main_clock,
+					      gd->arch.at91_pllb_usb_init);
+#endif
+
+	/*
+	 * MCK and CPU derive from one of those primary clocks.
+	 * For now, assume this parentage won't change.
+	 */
+	mckr = readl(&pmc->mckr);
+#if defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \
+		|| defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5)
+	/* plla divisor by 2 */
+	gd->arch.plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12));
+#endif
+	gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
+	freq = gd->arch.mck_rate_hz;
+
+	freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2));	/* prescale */
+#if defined(CONFIG_AT91SAM9G20)
+	/* mdiv ; (x >> 7) = ((x >> 8) * 2) */
+	gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ?
+		freq / ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 7) : freq;
+	if (mckr & AT91_PMC_MCKR_MDIV_MASK)
+		freq /= 2;			/* processor clock division */
+#elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \
+		|| defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5)
+	/* mdiv <==> divisor
+	 *  0   <==>   1
+	 *  1   <==>   2
+	 *  2   <==>   4
+	 *  3   <==>   3
+	 */
+	gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ==
+		(AT91_PMC_MCKR_MDIV_2 | AT91_PMC_MCKR_MDIV_4)
+		? freq / 3
+		: freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
+#else
+	gd->arch.mck_rate_hz = freq /
+			(1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
+#endif
+	gd->arch.cpu_clk_rate_hz = freq;
+
+	return 0;
+}
+
+#if !defined(AT91_PLL_LOCK_TIMEOUT)
+#define AT91_PLL_LOCK_TIMEOUT	1000000
+#endif
+
+void at91_plla_init(u32 pllar)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	int timeout = AT91_PLL_LOCK_TIMEOUT;
+
+	writel(pllar, &pmc->pllar);
+	while (!(readl(&pmc->sr) & (AT91_PMC_LOCKA | AT91_PMC_MCKRDY))) {
+		timeout--;
+		if (timeout == 0)
+			break;
+	}
+}
+void at91_pllb_init(u32 pllbr)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	int timeout = AT91_PLL_LOCK_TIMEOUT;
+
+	writel(pllbr, &pmc->pllbr);
+	while (!(readl(&pmc->sr) & (AT91_PMC_LOCKB | AT91_PMC_MCKRDY))) {
+		timeout--;
+		if (timeout == 0)
+			break;
+	}
+}
+
+void at91_mck_init(u32 mckr)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	int timeout = AT91_PLL_LOCK_TIMEOUT;
+	u32 tmp;
+
+	tmp = readl(&pmc->mckr);
+	tmp &= ~(AT91_PMC_MCKR_PRES_MASK |
+		 AT91_PMC_MCKR_MDIV_MASK |
+		 AT91_PMC_MCKR_PLLADIV_MASK |
+		 AT91_PMC_MCKR_CSS_MASK);
+	tmp |= mckr & (AT91_PMC_MCKR_PRES_MASK |
+		       AT91_PMC_MCKR_MDIV_MASK |
+		       AT91_PMC_MCKR_PLLADIV_MASK |
+		       AT91_PMC_MCKR_CSS_MASK);
+	writel(tmp, &pmc->mckr);
+
+	while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY)) {
+		timeout--;
+		if (timeout == 0)
+			break;
+	}
+}
+
+void at91_periph_clk_enable(int id)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	writel(1 << id, &pmc->pcer);
+}
diff --git a/arch/arm/mach-at91/arm926ejs/cpu.c b/arch/arm/mach-at91/arm926ejs/cpu.c
new file mode 100644
index 0000000..da1d359
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/cpu.c
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2010
+ * Reinhard Meyer, reinhard.meyer@emk-elektronik.de
+ * (C) Copyright 2009
+ * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_pit.h>
+#include <asm/arch/at91_gpbr.h>
+#include <asm/arch/clk.h>
+
+#ifndef CONFIG_SYS_AT91_MAIN_CLOCK
+#define CONFIG_SYS_AT91_MAIN_CLOCK 0
+#endif
+
+int arch_cpu_init(void)
+{
+	return at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK);
+}
+
+void arch_preboot_os(void)
+{
+	ulong cpiv;
+	at91_pit_t *pit = (at91_pit_t *) ATMEL_BASE_PIT;
+
+	cpiv = AT91_PIT_MR_PIV_MASK(readl(&pit->piir));
+
+	/*
+	 * Disable PITC
+	 * Add 0x1000 to current counter to stop it faster
+	 * without waiting for wrapping back to 0
+	 */
+	writel(cpiv + 0x1000, &pit->mr);
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	char buf[32];
+
+	printf("CPU: %s\n", ATMEL_CPU_NAME);
+	printf("Crystal frequency: %8s MHz\n",
+					strmhz(buf, get_main_clk_rate()));
+	printf("CPU clock        : %8s MHz\n",
+					strmhz(buf, get_cpu_clk_rate()));
+	printf("Master clock     : %8s MHz\n",
+					strmhz(buf, get_mck_clk_rate()));
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/mach-at91/arm926ejs/eflash.c b/arch/arm/mach-at91/arm926ejs/eflash.c
new file mode 100644
index 0000000..3f39264
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/eflash.c
@@ -0,0 +1,254 @@
+/*
+ * (C) Copyright 2010
+ * Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.de
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ * this driver supports the enhanced embedded flash in the Atmel
+ * AT91SAM9XE devices with the following geometry:
+ *
+ * AT91SAM9XE128: 1 plane of  8 regions of 32 pages (total  256 pages)
+ * AT91SAM9XE256: 1 plane of 16 regions of 32 pages (total  512 pages)
+ * AT91SAM9XE512: 1 plane of 32 regions of 32 pages (total 1024 pages)
+ * (the exact geometry is read from the flash at runtime, so any
+ *  future devices should already be covered)
+ *
+ * Regions can be write/erase protected.
+ * Whole (!) pages can be individually written with erase on the fly.
+ * Writing partial pages will corrupt the rest of the page.
+ *
+ * The flash is presented to u-boot with each region being a sector,
+ * having the following effects:
+ * Each sector can be hardware protected (protect on/off).
+ * Each page in a sector can be rewritten anytime.
+ * Since pages are erased when written, the "erase" does nothing.
+ * The first "CONFIG_EFLASH_PROTSECTORS" cannot be unprotected
+ * by u-Boot commands.
+ *
+ * Note: Redundant environment will not work in this flash since
+ * it does use partial page writes. Make sure the environment spans
+ * whole pages!
+ */
+
+/*
+ * optional TODOs (nice to have features):
+ *
+ * make the driver coexist with other NOR flash drivers
+ *	(use an index into flash_info[], requires work
+ *	in those other drivers, too)
+ * Make the erase command fill the sectors with 0xff
+ *	(if the flashes grow larger in the future and
+ *	someone puts a jffs2 into them)
+ * do a read-modify-write for partially programmed pages
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_eefc.h>
+#include <asm/arch/at91_dbu.h>
+
+/* checks to detect configuration errors */
+#if CONFIG_SYS_MAX_FLASH_BANKS!=1
+#error eflash: this driver can only handle 1 bank
+#endif
+
+/* global structure */
+flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
+static u32 pagesize;
+
+unsigned long flash_init (void)
+{
+	at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC;
+	at91_dbu_t *dbu = (at91_dbu_t *) ATMEL_BASE_DBGU;
+	u32 id, size, nplanes, planesize, nlocks;
+	u32 addr, i, tmp=0;
+
+	debug("eflash: init\n");
+
+	flash_info[0].flash_id = FLASH_UNKNOWN;
+
+	/* check if its an AT91ARM9XE SoC */
+	if ((readl(&dbu->cidr) & AT91_DBU_CID_ARCH_MASK) != AT91_DBU_CID_ARCH_9XExx) {
+		puts("eflash: not an AT91SAM9XE\n");
+		return 0;
+	}
+
+	/* now query the eflash for its structure */
+	writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GETD, &eefc->fcr);
+	while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
+		;
+	id = readl(&eefc->frr);		/* word 0 */
+	size = readl(&eefc->frr);	/* word 1 */
+	pagesize = readl(&eefc->frr);	/* word 2 */
+	nplanes = readl(&eefc->frr);	/* word 3 */
+	planesize = readl(&eefc->frr);	/* word 4 */
+	debug("id=%08x size=%u pagesize=%u planes=%u planesize=%u\n",
+		id, size, pagesize, nplanes, planesize);
+	for (i=1; i<nplanes; i++) {
+		tmp = readl(&eefc->frr);	/* words 5..4+nplanes-1 */
+	};
+	nlocks = readl(&eefc->frr);	/* word 4+nplanes */
+	debug("nlocks=%u\n", nlocks);
+	/* since we are going to use the lock regions as sectors, check count */
+	if (nlocks > CONFIG_SYS_MAX_FLASH_SECT) {
+		printf("eflash: number of lock regions(%u) "\
+			"> CONFIG_SYS_MAX_FLASH_SECT. reducing...\n",
+			nlocks);
+		nlocks = CONFIG_SYS_MAX_FLASH_SECT;
+	}
+	flash_info[0].size = size;
+	flash_info[0].sector_count = nlocks;
+	flash_info[0].flash_id = id;
+
+	addr = ATMEL_BASE_FLASH;
+	for (i=0; i<nlocks; i++) {
+		tmp = readl(&eefc->frr);	/* words 4+nplanes+1.. */
+		flash_info[0].start[i] = addr;
+		flash_info[0].protect[i] = 0;
+		addr += tmp;
+	};
+
+	/* now read the protection information for all regions */
+	writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr);
+	while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
+		;
+	for (i=0; i<flash_info[0].sector_count; i++) {
+		if (i%32 == 0)
+			tmp = readl(&eefc->frr);
+		flash_info[0].protect[i] = (tmp >> (i%32)) & 1;
+#if defined(CONFIG_EFLASH_PROTSECTORS)
+		if (i < CONFIG_EFLASH_PROTSECTORS)
+			flash_info[0].protect[i] = 1;
+#endif
+	}
+
+	return size;
+}
+
+void flash_print_info (flash_info_t *info)
+{
+	int i;
+
+	puts("AT91SAM9XE embedded flash\n  Size: ");
+	print_size(info->size, " in ");
+	printf("%d Sectors\n", info->sector_count);
+
+	printf("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf("\n   ");
+		printf(" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+int flash_real_protect (flash_info_t *info, long sector, int prot)
+{
+	at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC;
+	u32 pagenum = (info->start[sector]-ATMEL_BASE_FLASH)/pagesize;
+	u32 i, tmp=0;
+
+	debug("protect sector=%ld prot=%d\n", sector, prot);
+
+#if defined(CONFIG_EFLASH_PROTSECTORS)
+	if (sector < CONFIG_EFLASH_PROTSECTORS) {
+		if (!prot) {
+			printf("eflash: sector %lu cannot be unprotected\n",
+				sector);
+		}
+		return 1; /* return anyway, caller does not care for result */
+	}
+#endif
+	if (prot) {
+		writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_SLB |
+			(pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
+	} else {
+		writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_CLB |
+			(pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
+	}
+	while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
+		;
+	/* now re-read the protection information for all regions */
+	writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr);
+	while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
+		;
+	for (i=0; i<info->sector_count; i++) {
+		if (i%32 == 0)
+			tmp = readl(&eefc->frr);
+		info->protect[i] = (tmp >> (i%32)) & 1;
+	}
+	return 0;
+}
+
+static u32 erase_write_page (u32 pagenum)
+{
+	at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC;
+
+	debug("erase+write page=%u\n", pagenum);
+
+	/* give erase and write page command */
+	writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_EWP |
+		(pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
+	while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
+		;
+	/* return status */
+	return readl(&eefc->fsr)
+		& (AT91_EEFC_FSR_FCMDE | AT91_EEFC_FSR_FLOCKE);
+}
+
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	debug("erase first=%d last=%d\n", s_first, s_last);
+	puts("this flash does not need and support erasing!\n");
+	return 0;
+}
+
+/*
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	u32 pagenum;
+	u32 *src32, *dst32;
+	u32 i;
+
+	debug("write src=%08lx addr=%08lx cnt=%lx\n",
+		(ulong)src, addr, cnt);
+
+	/* REQUIRE addr to be on a page start, abort if not */
+	if (addr % pagesize) {
+		printf ("eflash: start %08lx is not on page start\n"\
+			"        write aborted\n", addr);
+		return 1;
+	}
+
+	/* now start copying data */
+	pagenum = (addr-ATMEL_BASE_FLASH)/pagesize;
+	src32 = (u32 *) src;
+	dst32 = (u32 *) addr;
+	while (cnt > 0) {
+		i = pagesize / 4;
+		/* fill page buffer */
+		while (i--)
+			*dst32++ = *src32++;
+		/* write page */
+		if (erase_write_page(pagenum))
+			return 1;
+		pagenum++;
+		if (cnt > pagesize)
+			cnt -= pagesize;
+		else
+			cnt = 0;
+	}
+	return 0;
+}
diff --git a/arch/arm/mach-at91/arm926ejs/led.c b/arch/arm/mach-at91/arm926ejs/led.c
new file mode 100644
index 0000000..b8d5c78
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/led.c
@@ -0,0 +1,48 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/arch/gpio.h>
+#include <status_led.h>
+
+#ifdef CONFIG_RED_LED
+void red_led_on(void)
+{
+	gpio_set_value(CONFIG_RED_LED, 1);
+}
+
+void red_led_off(void)
+{
+	gpio_set_value(CONFIG_RED_LED, 0);
+}
+#endif
+
+#ifdef CONFIG_GREEN_LED
+void green_led_on(void)
+{
+	gpio_set_value(CONFIG_GREEN_LED, 0);
+}
+
+void green_led_off(void)
+{
+	gpio_set_value(CONFIG_GREEN_LED, 1);
+}
+#endif
+
+#ifdef CONFIG_YELLOW_LED
+void yellow_led_on(void)
+{
+	gpio_set_value(CONFIG_YELLOW_LED, 0);
+}
+
+void yellow_led_off(void)
+{
+	gpio_set_value(CONFIG_YELLOW_LED, 1);
+}
+#endif
diff --git a/arch/arm/mach-at91/arm926ejs/lowlevel_init.S b/arch/arm/mach-at91/arm926ejs/lowlevel_init.S
new file mode 100644
index 0000000..a9ec81a
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/lowlevel_init.S
@@ -0,0 +1,246 @@
+/*
+ * Memory Setup stuff - taken from blob memsetup.S
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and
+ *		       Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
+ *
+ * Copyright (C) 2008 Ronetix Ilko Iliev (www.ronetix.at)
+ * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_wdt.h>
+#include <asm/arch/at91_pio.h>
+#include <asm/arch/at91_matrix.h>
+#include <asm/arch/at91sam9_sdramc.h>
+#include <asm/arch/at91sam9_smc.h>
+#include <asm/arch/at91_rstc.h>
+#ifdef CONFIG_ATMEL_LEGACY
+#include <asm/arch/at91sam9_matrix.h>
+#endif
+#ifndef CONFIG_SYS_MATRIX_EBICSA_VAL
+#define CONFIG_SYS_MATRIX_EBICSA_VAL CONFIG_SYS_MATRIX_EBI0CSA_VAL
+#endif
+
+.globl lowlevel_init
+.type lowlevel_init,function
+lowlevel_init:
+
+POS1:
+	adr	r5, POS1	/* r5 = POS1 run time */
+	ldr	r0, =POS1	/* r0 = POS1 compile */
+	sub	r5, r5, r0	/* r0 = CONFIG_SYS_TEXT_BASE-1 */
+
+	/* memory control configuration 1 */
+	ldr	r0, =SMRDATA
+	ldr	r2, =SMRDATA1
+	add	r0, r0, r5
+	add	r2, r2, r5
+0:
+	/* the address */
+	ldr	r1, [r0], #4
+	/* the value */
+	ldr	r3, [r0], #4
+	str	r3, [r1]
+	cmp	r2, r0
+	bne	0b
+
+/* ----------------------------------------------------------------------------
+ * PMC Init Step 1.
+ * ----------------------------------------------------------------------------
+ * - Check if the PLL is already initialized
+ * ----------------------------------------------------------------------------
+ */
+	ldr	r1, =(AT91_ASM_PMC_MCKR)
+	ldr	r0, [r1]
+	and	r0, r0, #3
+	cmp	r0, #0
+	bne	PLL_setup_end
+
+/* ---------------------------------------------------------------------------
+ * - Enable the Main Oscillator
+ * ---------------------------------------------------------------------------
+ */
+	ldr	r1, =(AT91_ASM_PMC_MOR)
+	ldr	r2, =(AT91_ASM_PMC_SR)
+	/* Main oscillator Enable register PMC_MOR: */
+	ldr	r0, =CONFIG_SYS_MOR_VAL
+	str	r0, [r1]
+
+	/* Reading the PMC Status to detect when the Main Oscillator is enabled */
+	mov	r4, #AT91_PMC_IXR_MOSCS
+MOSCS_Loop:
+	ldr	r3, [r2]
+	and	r3, r4, r3
+	cmp	r3, #AT91_PMC_IXR_MOSCS
+	bne	MOSCS_Loop
+
+/* ----------------------------------------------------------------------------
+ * PMC Init Step 2.
+ * ----------------------------------------------------------------------------
+ * Setup PLLA
+ * ----------------------------------------------------------------------------
+ */
+	ldr	r1, =(AT91_ASM_PMC_PLLAR)
+	ldr	r0, =CONFIG_SYS_PLLAR_VAL
+	str	r0, [r1]
+
+	/* Reading the PMC Status register to detect when the PLLA is locked */
+	mov	r4, #AT91_PMC_IXR_LOCKA
+MOSCS_Loop1:
+	ldr	r3, [r2]
+	and	r3, r4, r3
+	cmp	r3, #AT91_PMC_IXR_LOCKA
+	bne	MOSCS_Loop1
+
+/* ----------------------------------------------------------------------------
+ * PMC Init Step 3.
+ * ----------------------------------------------------------------------------
+ * - Switch on the Main Oscillator
+ * ----------------------------------------------------------------------------
+ */
+	ldr	r1, =(AT91_ASM_PMC_MCKR)
+
+	/* -Master Clock Controller register PMC_MCKR */
+	ldr	r0, =CONFIG_SYS_MCKR1_VAL
+	str	r0, [r1]
+
+	/* Reading the PMC Status to detect when the Master clock is ready */
+	mov	r4, #AT91_PMC_IXR_MCKRDY
+MCKRDY_Loop:
+	ldr	r3, [r2]
+	and	r3, r4, r3
+	cmp	r3, #AT91_PMC_IXR_MCKRDY
+	bne	MCKRDY_Loop
+
+	ldr	r0, =CONFIG_SYS_MCKR2_VAL
+	str	r0, [r1]
+
+	/* Reading the PMC Status to detect when the Master clock is ready */
+	mov	r4, #AT91_PMC_IXR_MCKRDY
+MCKRDY_Loop1:
+	ldr	r3, [r2]
+	and	r3, r4, r3
+	cmp	r3, #AT91_PMC_IXR_MCKRDY
+	bne	MCKRDY_Loop1
+PLL_setup_end:
+
+/* ----------------------------------------------------------------------------
+ * - memory control configuration 2
+ * ----------------------------------------------------------------------------
+ */
+	ldr	r0, =(AT91_ASM_SDRAMC_TR)
+	ldr	r1, [r0]
+	cmp	r1, #0
+	bne	SDRAM_setup_end
+
+	ldr	r0, =SMRDATA1
+	ldr	r2, =SMRDATA2
+	add	r0, r0, r5
+	add	r2, r2, r5
+2:
+	/* the address */
+	ldr	r1, [r0], #4
+	/* the value */
+	ldr	r3, [r0], #4
+	str	r3, [r1]
+	cmp	r2, r0
+	bne	2b
+
+SDRAM_setup_end:
+	/* everything is fine now */
+	mov	pc, lr
+
+	.ltorg
+
+SMRDATA:
+	.word AT91_ASM_WDT_MR
+	.word CONFIG_SYS_WDTC_WDMR_VAL
+	/* configure PIOx as EBI0 D[16-31] */
+#if defined(CONFIG_AT91SAM9263)
+	.word AT91_ASM_PIOD_PDR
+	.word CONFIG_SYS_PIOD_PDR_VAL1
+	.word AT91_ASM_PIOD_PUDR
+	.word CONFIG_SYS_PIOD_PPUDR_VAL
+	.word AT91_ASM_PIOD_ASR
+	.word CONFIG_SYS_PIOD_PPUDR_VAL
+#elif defined(CONFIG_AT91SAM9260) || defined(CONFIG_AT91SAM9261) \
+	|| defined(CONFIG_AT91SAM9G20)
+	.word AT91_ASM_PIOC_PDR
+	.word CONFIG_SYS_PIOC_PDR_VAL1
+	.word AT91_ASM_PIOC_PUDR
+	.word CONFIG_SYS_PIOC_PPUDR_VAL
+#endif
+	.word AT91_ASM_MATRIX_CSA0
+	.word CONFIG_SYS_MATRIX_EBICSA_VAL
+
+	/* flash */
+	.word AT91_ASM_SMC_MODE0
+	.word CONFIG_SYS_SMC0_MODE0_VAL
+
+	.word AT91_ASM_SMC_CYCLE0
+	.word CONFIG_SYS_SMC0_CYCLE0_VAL
+
+	.word AT91_ASM_SMC_PULSE0
+	.word CONFIG_SYS_SMC0_PULSE0_VAL
+
+	.word AT91_ASM_SMC_SETUP0
+	.word CONFIG_SYS_SMC0_SETUP0_VAL
+
+SMRDATA1:
+	.word AT91_ASM_SDRAMC_MR
+	.word CONFIG_SYS_SDRC_MR_VAL1
+	.word AT91_ASM_SDRAMC_TR
+	.word CONFIG_SYS_SDRC_TR_VAL1
+	.word AT91_ASM_SDRAMC_CR
+	.word CONFIG_SYS_SDRC_CR_VAL
+	.word AT91_ASM_SDRAMC_MDR
+	.word CONFIG_SYS_SDRC_MDR_VAL
+	.word AT91_ASM_SDRAMC_MR
+	.word CONFIG_SYS_SDRC_MR_VAL2
+	.word CONFIG_SYS_SDRAM_BASE
+	.word CONFIG_SYS_SDRAM_VAL1
+	.word AT91_ASM_SDRAMC_MR
+	.word CONFIG_SYS_SDRC_MR_VAL3
+	.word CONFIG_SYS_SDRAM_BASE
+	.word CONFIG_SYS_SDRAM_VAL2
+	.word CONFIG_SYS_SDRAM_BASE
+	.word CONFIG_SYS_SDRAM_VAL3
+	.word CONFIG_SYS_SDRAM_BASE
+	.word CONFIG_SYS_SDRAM_VAL4
+	.word CONFIG_SYS_SDRAM_BASE
+	.word CONFIG_SYS_SDRAM_VAL5
+	.word CONFIG_SYS_SDRAM_BASE
+	.word CONFIG_SYS_SDRAM_VAL6
+	.word CONFIG_SYS_SDRAM_BASE
+	.word CONFIG_SYS_SDRAM_VAL7
+	.word CONFIG_SYS_SDRAM_BASE
+	.word CONFIG_SYS_SDRAM_VAL8
+	.word CONFIG_SYS_SDRAM_BASE
+	.word CONFIG_SYS_SDRAM_VAL9
+	.word AT91_ASM_SDRAMC_MR
+	.word CONFIG_SYS_SDRC_MR_VAL4
+	.word CONFIG_SYS_SDRAM_BASE
+	.word CONFIG_SYS_SDRAM_VAL10
+	.word AT91_ASM_SDRAMC_MR
+	.word CONFIG_SYS_SDRC_MR_VAL5
+	.word CONFIG_SYS_SDRAM_BASE
+	.word CONFIG_SYS_SDRAM_VAL11
+	.word AT91_ASM_SDRAMC_TR
+	.word CONFIG_SYS_SDRC_TR_VAL2
+	.word CONFIG_SYS_SDRAM_BASE
+	.word CONFIG_SYS_SDRAM_VAL12
+	/* User reset enable*/
+	.word AT91_ASM_RSTC_MR
+	.word CONFIG_SYS_RSTC_RMR_VAL
+#ifdef CONFIG_SYS_MATRIX_MCFG_REMAP
+	/* MATRIX_MCFG - REMAP all masters */
+	.word AT91_ASM_MATRIX_MCFG
+	.word 0x1FF
+#endif
+SMRDATA2:
+	.word 0
diff --git a/arch/arm/mach-at91/arm926ejs/reset.c b/arch/arm/mach-at91/arm926ejs/reset.c
new file mode 100644
index 0000000..e67f47b
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/reset.c
@@ -0,0 +1,29 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_rstc.h>
+
+/* Reset the cpu by telling the reset controller to do so */
+void reset_cpu(ulong ignored)
+{
+	at91_rstc_t *rstc = (at91_rstc_t *) ATMEL_BASE_RSTC;
+
+	writel(AT91_RSTC_KEY
+		| AT91_RSTC_CR_PROCRST	/* Processor Reset */
+		| AT91_RSTC_CR_PERRST	/* Peripheral Reset */
+#ifdef CONFIG_AT91RESET_EXTRST
+		| AT91_RSTC_CR_EXTRST	/* External Reset (assert nRST pin) */
+#endif
+		, &rstc->cr);
+	/* never reached */
+	while (1)
+		;
+}
diff --git a/arch/arm/mach-at91/arm926ejs/timer.c b/arch/arm/mach-at91/arm926ejs/timer.c
new file mode 100644
index 0000000..b0b7fb9
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/timer.c
@@ -0,0 +1,120 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pit.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/clk.h>
+#include <div64.h>
+
+#if !defined(CONFIG_AT91FAMILY)
+# error You need to define CONFIG_AT91FAMILY in your board config!
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * We're using the AT91CAP9/SAM9 PITC in 32 bit mode, by
+ * setting the 20 bit counter period to its maximum (0xfffff).
+ * (See the relevant data sheets to understand that this really works)
+ *
+ * We do also mimic the typical powerpc way of incrementing
+ * two 32 bit registers called tbl and tbu.
+ *
+ * Those registers increment at 1/16 the main clock rate.
+ */
+
+#define TIMER_LOAD_VAL	0xfffff
+
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+	tick *= CONFIG_SYS_HZ;
+	do_div(tick, gd->arch.timer_rate_hz);
+
+	return tick;
+}
+
+static inline unsigned long long usec_to_tick(unsigned long long usec)
+{
+	usec *= gd->arch.timer_rate_hz;
+	do_div(usec, 1000000);
+
+	return usec;
+}
+
+/*
+ * Use the PITC in full 32 bit incrementing mode
+ */
+int timer_init(void)
+{
+	at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
+	at91_pit_t *pit = (at91_pit_t *) ATMEL_BASE_PIT;
+
+	/* Enable PITC Clock */
+	writel(1 << ATMEL_ID_SYS, &pmc->pcer);
+
+	/* 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.tbu = gd->arch.tbl = 0;
+
+	return 0;
+}
+
+/*
+ * Get the current 64 bit timer tick count
+ */
+unsigned long long get_ticks(void)
+{
+	at91_pit_t *pit = (at91_pit_t *) ATMEL_BASE_PIT;
+
+	ulong now = readl(&pit->piir);
+
+	/* increment tbu if tbl has rolled over */
+	if (now < gd->arch.tbl)
+		gd->arch.tbu++;
+	gd->arch.tbl = now;
+	return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl;
+}
+
+void __udelay(unsigned long usec)
+{
+	unsigned long long start;
+	ulong tmo;
+
+	start = get_ticks();		/* get current timestamp */
+	tmo = usec_to_tick(usec);	/* convert usecs to ticks */
+	while ((get_ticks() - start) < tmo)
+		;			/* loop till time has passed */
+}
+
+/*
+ * get_timer(base) can be used to check for timeouts or
+ * to measure elasped time relative to an event:
+ *
+ * ulong start_time = get_timer(0) sets start_time to the current
+ * time value.
+ * get_timer(start_time) returns the time elapsed since then.
+ *
+ * The time is used in CONFIG_SYS_HZ units!
+ */
+ulong get_timer(ulong base)
+{
+	return tick_to_time(get_ticks()) - base;
+}
+
+/*
+ * Return the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	return gd->arch.timer_rate_hz;
+}
diff --git a/arch/arm/mach-at91/armv7/Makefile b/arch/arm/mach-at91/armv7/Makefile
new file mode 100644
index 0000000..f4f35a4
--- /dev/null
+++ b/arch/arm/mach-at91/armv7/Makefile
@@ -0,0 +1,16 @@
+#
+# (C) Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2013
+# Bo Shen <voice.shen@atmel.com>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_SAMA5D3)	+= sama5d3_devices.o
+obj-$(CONFIG_SAMA5D4)	+= sama5d4_devices.o
+obj-y += clock.o
+obj-y += cpu.o
+obj-y += reset.o
+obj-y += timer.o
diff --git a/arch/arm/mach-at91/armv7/clock.c b/arch/arm/mach-at91/armv7/clock.c
new file mode 100644
index 0000000..0bf453e
--- /dev/null
+++ b/arch/arm/mach-at91/armv7/clock.c
@@ -0,0 +1,175 @@
+/*
+ * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c]
+ *
+ * Copyright (C) 2005 David Brownell
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ * Copyright (C) 2013 Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/clk.h>
+
+#if !defined(CONFIG_AT91FAMILY)
+# error You need to define CONFIG_AT91FAMILY in your board config!
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static unsigned long at91_css_to_rate(unsigned long css)
+{
+	switch (css) {
+	case AT91_PMC_MCKR_CSS_SLOW:
+		return CONFIG_SYS_AT91_SLOW_CLOCK;
+	case AT91_PMC_MCKR_CSS_MAIN:
+		return gd->arch.main_clk_rate_hz;
+	case AT91_PMC_MCKR_CSS_PLLA:
+		return gd->arch.plla_rate_hz;
+	}
+
+	return 0;
+}
+
+static u32 at91_pll_rate(u32 freq, u32 reg)
+{
+	unsigned mul, div;
+
+	div = reg & 0xff;
+	mul = (reg >> 18) & 0x7f;
+	if (div && mul) {
+		freq /= div;
+		freq *= mul + 1;
+	} else {
+		freq = 0;
+	}
+
+	return freq;
+}
+
+int at91_clock_init(unsigned long main_clock)
+{
+	unsigned freq, mckr;
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+#ifndef CONFIG_SYS_AT91_MAIN_CLOCK
+	unsigned tmp;
+	/*
+	 * When the bootloader initialized the main oscillator correctly,
+	 * there's no problem using the cycle counter.  But if it didn't,
+	 * or when using oscillator bypass mode, we must be told the speed
+	 * of the main clock.
+	 */
+	if (!main_clock) {
+		do {
+			tmp = readl(&pmc->mcfr);
+		} while (!(tmp & AT91_PMC_MCFR_MAINRDY));
+		tmp &= AT91_PMC_MCFR_MAINF_MASK;
+		main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16);
+	}
+#endif
+	gd->arch.main_clk_rate_hz = main_clock;
+
+	/* report if PLLA is more than mildly overclocked */
+	gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
+
+	/*
+	 * MCK and CPU derive from one of those primary clocks.
+	 * For now, assume this parentage won't change.
+	 */
+	mckr = readl(&pmc->mckr);
+
+	/* plla divisor by 2 */
+	if (mckr & (1 << 12))
+		gd->arch.plla_rate_hz >>= 1;
+
+	gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
+	freq = gd->arch.mck_rate_hz;
+
+	/* prescale */
+	freq >>= mckr & AT91_PMC_MCKR_PRES_MASK;
+
+	switch (mckr & AT91_PMC_MCKR_MDIV_MASK) {
+	case AT91_PMC_MCKR_MDIV_2:
+		gd->arch.mck_rate_hz = freq / 2;
+		break;
+	case AT91_PMC_MCKR_MDIV_3:
+		gd->arch.mck_rate_hz = freq / 3;
+		break;
+	case AT91_PMC_MCKR_MDIV_4:
+		gd->arch.mck_rate_hz = freq / 4;
+		break;
+	default:
+		break;
+	}
+
+	gd->arch.cpu_clk_rate_hz = freq;
+
+	return 0;
+}
+
+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_CSS_MASK  |
+		 AT91_PMC_MCKR_PRES_MASK |
+		 AT91_PMC_MCKR_MDIV_MASK |
+		 AT91_PMC_MCKR_PLLADIV_2);
+#ifdef CPU_HAS_H32MXDIV
+	tmp &= ~AT91_PMC_MCKR_H32MXDIV;
+#endif
+
+	tmp |= mckr & (AT91_PMC_MCKR_CSS_MASK  |
+		       AT91_PMC_MCKR_PRES_MASK |
+		       AT91_PMC_MCKR_MDIV_MASK |
+		       AT91_PMC_MCKR_PLLADIV_2);
+#ifdef CPU_HAS_H32MXDIV
+	tmp |= mckr & AT91_PMC_MCKR_H32MXDIV;
+#endif
+
+	writel(tmp, &pmc->mckr);
+
+	while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
+		;
+}
+
+void at91_periph_clk_enable(int id)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	u32 regval;
+
+	if (id > AT91_PMC_PCR_PID_MASK)
+		return;
+
+	regval = AT91_PMC_PCR_EN | AT91_PMC_PCR_CMD_WRITE | id;
+
+	writel(regval, &pmc->pcr);
+}
+
+void at91_periph_clk_disable(int id)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	u32 regval;
+
+	if (id > AT91_PMC_PCR_PID_MASK)
+		return;
+
+	regval = AT91_PMC_PCR_CMD_WRITE | id;
+
+	writel(regval, &pmc->pcr);
+}
diff --git a/arch/arm/mach-at91/armv7/cpu.c b/arch/arm/mach-at91/armv7/cpu.c
new file mode 100644
index 0000000..8d86f97
--- /dev/null
+++ b/arch/arm/mach-at91/armv7/cpu.c
@@ -0,0 +1,76 @@
+/*
+ * (C) Copyright 2010
+ * Reinhard Meyer, reinhard.meyer@emk-elektronik.de
+ * (C) Copyright 2009
+ * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ * (C) Copyright 2013
+ * Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_dbu.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_pit.h>
+#include <asm/arch/at91_gpbr.h>
+#include <asm/arch/clk.h>
+
+#ifndef CONFIG_SYS_AT91_MAIN_CLOCK
+#define CONFIG_SYS_AT91_MAIN_CLOCK 0
+#endif
+
+int arch_cpu_init(void)
+{
+	return at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK);
+}
+
+void arch_preboot_os(void)
+{
+	ulong cpiv;
+	at91_pit_t *pit = (at91_pit_t *)ATMEL_BASE_PIT;
+
+	cpiv = AT91_PIT_MR_PIV_MASK(readl(&pit->piir));
+
+	/*
+	 * Disable PITC
+	 * Add 0x1000 to current counter to stop it faster
+	 * without waiting for wrapping back to 0
+	 */
+	writel(cpiv + 0x1000, &pit->mr);
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	char buf[32];
+
+	printf("CPU: %s\n", get_cpu_name());
+	printf("Crystal frequency: %8s MHz\n",
+	       strmhz(buf, get_main_clk_rate()));
+	printf("CPU clock        : %8s MHz\n",
+	       strmhz(buf, get_cpu_clk_rate()));
+	printf("Master clock     : %8s MHz\n",
+	       strmhz(buf, get_mck_clk_rate()));
+
+	return 0;
+}
+#endif
+
+void enable_caches(void)
+{
+	icache_enable();
+	dcache_enable();
+}
+
+unsigned int get_chip_id(void)
+{
+	return readl(ATMEL_BASE_DBGU + AT91_DBU_CIDR) & ~AT91_DBU_CIDR_MASK;
+}
+
+unsigned int get_extension_chip_id(void)
+{
+	return readl(ATMEL_BASE_DBGU + AT91_DBU_EXID);
+}
diff --git a/arch/arm/mach-at91/armv7/reset.c b/arch/arm/mach-at91/armv7/reset.c
new file mode 100644
index 0000000..b30e79b
--- /dev/null
+++ b/arch/arm/mach-at91/armv7/reset.c
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.com>
+ *
+ * (C) Copyright 2013
+ * Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_rstc.h>
+
+/* Reset the cpu by telling the reset controller to do so */
+void reset_cpu(ulong ignored)
+{
+	at91_rstc_t *rstc = (at91_rstc_t *)ATMEL_BASE_RSTC;
+
+	writel(AT91_RSTC_KEY
+		| AT91_RSTC_CR_PROCRST	/* Processor Reset */
+		| AT91_RSTC_CR_PERRST	/* Peripheral Reset */
+#ifdef CONFIG_AT91RESET_EXTRST
+		| AT91_RSTC_CR_EXTRST	/* External Reset (assert nRST pin) */
+#endif
+		, &rstc->cr);
+	/* never reached */
+	do { } while (1);
+}
diff --git a/arch/arm/mach-at91/armv7/sama5d3_devices.c b/arch/arm/mach-at91/armv7/sama5d3_devices.c
new file mode 100644
index 0000000..78ecfc8
--- /dev/null
+++ b/arch/arm/mach-at91/armv7/sama5d3_devices.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2012-2013 Atmel Corporation
+ * Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/sama5d3.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/gpio.h>
+#include <asm/io.h>
+
+unsigned int has_emac()
+{
+	return cpu_is_sama5d31() || cpu_is_sama5d35() || cpu_is_sama5d36();
+}
+
+unsigned int has_gmac()
+{
+	return !cpu_is_sama5d31();
+}
+
+unsigned int has_lcdc()
+{
+	return !cpu_is_sama5d35();
+}
+
+char *get_cpu_name()
+{
+	unsigned int extension_id = get_extension_chip_id();
+
+	if (cpu_is_sama5d3())
+		switch (extension_id) {
+		case ARCH_EXID_SAMA5D31:
+			return "SAMA5D31";
+		case ARCH_EXID_SAMA5D33:
+			return "SAMA5D33";
+		case ARCH_EXID_SAMA5D34:
+			return "SAMA5D34";
+		case ARCH_EXID_SAMA5D35:
+			return "SAMA5D35";
+		case ARCH_EXID_SAMA5D36:
+			return "SAMA5D36";
+		default:
+			return "Unknown CPU type";
+		}
+	else
+		return "Unknown CPU type";
+}
+
+void at91_serial0_hw_init(void)
+{
+	at91_set_a_periph(AT91_PIO_PORTD, 18, 1);	/* TXD0 */
+	at91_set_a_periph(AT91_PIO_PORTD, 17, 0);	/* RXD0 */
+
+	/* Enable clock */
+	at91_periph_clk_enable(ATMEL_ID_USART0);
+}
+
+void at91_serial1_hw_init(void)
+{
+	at91_set_a_periph(AT91_PIO_PORTB, 29, 1);	/* TXD1 */
+	at91_set_a_periph(AT91_PIO_PORTB, 28, 0);	/* RXD1 */
+
+	/* Enable clock */
+	at91_periph_clk_enable(ATMEL_ID_USART1);
+}
+
+void at91_serial2_hw_init(void)
+{
+	at91_set_b_periph(AT91_PIO_PORTE, 26, 1);	/* TXD2 */
+	at91_set_b_periph(AT91_PIO_PORTE, 25, 0);	/* RXD2 */
+
+	/* Enable clock */
+	at91_periph_clk_enable(ATMEL_ID_USART2);
+}
+
+void at91_seriald_hw_init(void)
+{
+	at91_set_a_periph(AT91_PIO_PORTB, 31, 1);	/* DTXD */
+	at91_set_a_periph(AT91_PIO_PORTB, 30, 0);	/* DRXD */
+
+	/* Enable clock */
+	at91_periph_clk_enable(ATMEL_ID_DBGU);
+}
+
+#if defined(CONFIG_ATMEL_SPI)
+void at91_spi0_hw_init(unsigned long cs_mask)
+{
+	at91_set_a_periph(AT91_PIO_PORTD, 10, 0);       /* SPI0_MISO */
+	at91_set_a_periph(AT91_PIO_PORTD, 11, 0);       /* SPI0_MOSI */
+	at91_set_a_periph(AT91_PIO_PORTD, 12, 0);       /* SPI0_SPCK */
+
+	if (cs_mask & (1 << 0))
+		at91_set_pio_output(AT91_PIO_PORTD, 13, 1);
+	if (cs_mask & (1 << 1))
+		at91_set_pio_output(AT91_PIO_PORTD, 14, 1);
+	if (cs_mask & (1 << 2))
+		at91_set_pio_output(AT91_PIO_PORTD, 15, 1);
+	if (cs_mask & (1 << 3))
+		at91_set_pio_output(AT91_PIO_PORTD, 16, 1);
+
+	/* Enable clock */
+	at91_periph_clk_enable(ATMEL_ID_SPI0);
+}
+#endif
+
+#ifdef CONFIG_GENERIC_ATMEL_MCI
+void at91_mci_hw_init(void)
+{
+	at91_set_a_periph(AT91_PIO_PORTD, 0, 0);	/* MCI0 CMD */
+	at91_set_a_periph(AT91_PIO_PORTD, 1, 0);	/* MCI0 DA0 */
+	at91_set_a_periph(AT91_PIO_PORTD, 2, 0);	/* MCI0 DA1 */
+	at91_set_a_periph(AT91_PIO_PORTD, 3, 0);        /* MCI0 DA2 */
+	at91_set_a_periph(AT91_PIO_PORTD, 4, 0);        /* MCI0 DA3 */
+#ifdef CONFIG_ATMEL_MCI_8BIT
+	at91_set_a_periph(AT91_PIO_PORTD, 5, 0);        /* MCI0 DA4 */
+	at91_set_a_periph(AT91_PIO_PORTD, 6, 0);        /* MCI0 DA5 */
+	at91_set_a_periph(AT91_PIO_PORTD, 7, 0);        /* MCI0 DA6 */
+	at91_set_a_periph(AT91_PIO_PORTD, 8, 0);        /* MCI0 DA7 */
+#endif
+	at91_set_a_periph(AT91_PIO_PORTD, 9, 0);        /* MCI0 CLK */
+
+	/* Enable clock */
+	at91_periph_clk_enable(ATMEL_ID_MCI0);
+}
+#endif
+
+#ifdef CONFIG_MACB
+void at91_macb_hw_init(void)
+{
+	at91_set_a_periph(AT91_PIO_PORTC, 7, 0);	/* ETXCK_EREFCK */
+	at91_set_a_periph(AT91_PIO_PORTC, 5, 0);	/* ERXDV */
+	at91_set_a_periph(AT91_PIO_PORTC, 2, 0);	/* ERX0 */
+	at91_set_a_periph(AT91_PIO_PORTC, 3, 0);	/* ERX1 */
+	at91_set_a_periph(AT91_PIO_PORTC, 6, 0);	/* ERXER */
+	at91_set_a_periph(AT91_PIO_PORTC, 4, 0);	/* ETXEN */
+	at91_set_a_periph(AT91_PIO_PORTC, 0, 0);	/* ETX0 */
+	at91_set_a_periph(AT91_PIO_PORTC, 1, 0);	/* ETX1 */
+	at91_set_a_periph(AT91_PIO_PORTC, 9, 0);	/* EMDIO */
+	at91_set_a_periph(AT91_PIO_PORTC, 8, 0);	/* EMDC */
+
+	/* Enable clock */
+	at91_periph_clk_enable(ATMEL_ID_EMAC);
+}
+
+void at91_gmac_hw_init(void)
+{
+	at91_set_a_periph(AT91_PIO_PORTB, 0, 0);	/* GTX0 */
+	at91_set_a_periph(AT91_PIO_PORTB, 1, 0);	/* GTX1 */
+	at91_set_a_periph(AT91_PIO_PORTB, 2, 0);	/* GTX2 */
+	at91_set_a_periph(AT91_PIO_PORTB, 3, 0);	/* GTX3 */
+	at91_set_a_periph(AT91_PIO_PORTB, 4, 0);	/* GRX0 */
+	at91_set_a_periph(AT91_PIO_PORTB, 5, 0);	/* GRX1 */
+	at91_set_a_periph(AT91_PIO_PORTB, 6, 0);	/* GRX2 */
+	at91_set_a_periph(AT91_PIO_PORTB, 7, 0);	/* GRX3 */
+	at91_set_a_periph(AT91_PIO_PORTB, 8, 0);	/* GTXCK */
+	at91_set_a_periph(AT91_PIO_PORTB, 9, 0);	/* GTXEN */
+
+	at91_set_a_periph(AT91_PIO_PORTB, 11, 0);	/* GRXCK */
+	at91_set_a_periph(AT91_PIO_PORTB, 13, 0);	/* GRXER */
+
+	at91_set_a_periph(AT91_PIO_PORTB, 16, 0);	/* GMDC */
+	at91_set_a_periph(AT91_PIO_PORTB, 17, 0);	/* GMDIO */
+	at91_set_a_periph(AT91_PIO_PORTB, 18, 0);	/* G125CK */
+
+	/* Enable clock */
+	at91_periph_clk_enable(ATMEL_ID_GMAC);
+}
+#endif
+
+#ifdef CONFIG_LCD
+void at91_lcd_hw_init(void)
+{
+	at91_set_a_periph(AT91_PIO_PORTA, 24, 0);	/* LCDPWM */
+	at91_set_a_periph(AT91_PIO_PORTA, 25, 0);	/* LCDDISP */
+	at91_set_a_periph(AT91_PIO_PORTA, 26, 0);	/* LCDVSYNC */
+	at91_set_a_periph(AT91_PIO_PORTA, 27, 0);	/* LCDHSYNC */
+	at91_set_a_periph(AT91_PIO_PORTA, 28, 0);	/* LCDDOTCK */
+	at91_set_a_periph(AT91_PIO_PORTA, 29, 0);	/* LCDDEN */
+
+	/* The lower 16-bit of LCD only available on Port A */
+	at91_set_a_periph(AT91_PIO_PORTA,  0, 0);	/* LCDD0 */
+	at91_set_a_periph(AT91_PIO_PORTA,  1, 0);	/* LCDD1 */
+	at91_set_a_periph(AT91_PIO_PORTA,  2, 0);	/* LCDD2 */
+	at91_set_a_periph(AT91_PIO_PORTA,  3, 0);	/* LCDD3 */
+	at91_set_a_periph(AT91_PIO_PORTA,  4, 0);	/* LCDD4 */
+	at91_set_a_periph(AT91_PIO_PORTA,  5, 0);	/* LCDD5 */
+	at91_set_a_periph(AT91_PIO_PORTA,  6, 0);	/* LCDD6 */
+	at91_set_a_periph(AT91_PIO_PORTA,  7, 0);	/* LCDD7 */
+	at91_set_a_periph(AT91_PIO_PORTA,  8, 0);	/* LCDD8 */
+	at91_set_a_periph(AT91_PIO_PORTA,  9, 0);	/* LCDD9 */
+	at91_set_a_periph(AT91_PIO_PORTA, 10, 0);	/* LCDD10 */
+	at91_set_a_periph(AT91_PIO_PORTA, 11, 0);	/* LCDD11 */
+	at91_set_a_periph(AT91_PIO_PORTA, 12, 0);	/* LCDD12 */
+	at91_set_a_periph(AT91_PIO_PORTA, 13, 0);	/* LCDD13 */
+	at91_set_a_periph(AT91_PIO_PORTA, 14, 0);	/* LCDD14 */
+	at91_set_a_periph(AT91_PIO_PORTA, 15, 0);	/* LCDD15 */
+
+	/* Enable clock */
+	at91_periph_clk_enable(ATMEL_ID_LCDC);
+}
+#endif
+
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+void at91_udp_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	/* Enable UPLL clock */
+	writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr);
+	/* Enable UDPHS clock */
+	at91_periph_clk_enable(ATMEL_ID_UDPHS);
+}
+#endif
diff --git a/arch/arm/mach-at91/armv7/sama5d4_devices.c b/arch/arm/mach-at91/armv7/sama5d4_devices.c
new file mode 100644
index 0000000..ef39cb7
--- /dev/null
+++ b/arch/arm/mach-at91/armv7/sama5d4_devices.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2014 Atmel
+ *		      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/clk.h>
+#include <asm/arch/sama5_matrix.h>
+#include <asm/arch/sama5_sfr.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";
+}
+
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+void at91_udp_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	/* Enable UPLL clock */
+	writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr);
+	/* Enable UDPHS clock */
+	at91_periph_clk_enable(ATMEL_ID_UDPHS);
+}
+#endif
+
+#ifdef CONFIG_SPL_BUILD
+void matrix_init(void)
+{
+	struct atmel_matrix *h64mx = (struct atmel_matrix *)ATMEL_BASE_MATRIX0;
+	struct atmel_matrix *h32mx = (struct atmel_matrix *)ATMEL_BASE_MATRIX1;
+	int i;
+
+	/* Disable the write protect */
+	writel(ATMEL_MATRIX_WPMR_WPKEY & ~ATMEL_MATRIX_WPMR_WPEN, &h64mx->wpmr);
+	writel(ATMEL_MATRIX_WPMR_WPKEY & ~ATMEL_MATRIX_WPMR_WPEN, &h32mx->wpmr);
+
+	/* DDR port 1 ~ poart 7, slave number is: 4 ~ 10 */
+	for (i = 4; i <= 10; i++) {
+		writel(0x000f0f0f, &h64mx->ssr[i]);
+		writel(0x0000ffff, &h64mx->sassr[i]);
+		writel(0x0000000f, &h64mx->srtsr[i]);
+	}
+
+	/* CS3 */
+	writel(0x00c0c0c0, &h32mx->ssr[3]);
+	writel(0xff000000, &h32mx->sassr[3]);
+	writel(0xff000000, &h32mx->srtsr[3]);
+
+	/* NFC SRAM */
+	writel(0x00010101, &h32mx->ssr[4]);
+	writel(0x00000001, &h32mx->sassr[4]);
+	writel(0x00000001, &h32mx->srtsr[4]);
+
+	/* Enable the write protect */
+	writel(ATMEL_MATRIX_WPMR_WPKEY | ATMEL_MATRIX_WPMR_WPEN, &h64mx->wpmr);
+	writel(ATMEL_MATRIX_WPMR_WPKEY | ATMEL_MATRIX_WPMR_WPEN, &h32mx->wpmr);
+}
+
+void redirect_int_from_saic_to_aic(void)
+{
+	struct atmel_sfr *sfr = (struct atmel_sfr *)ATMEL_BASE_SFR;
+	u32 key32;
+
+	if (!(readl(&sfr->aicredir) & ATMEL_SFR_AICREDIR_NSAIC)) {
+		key32 = readl(&sfr->sn1) ^ ATMEL_SFR_AICREDIR_KEY;
+		writel((key32 | ATMEL_SFR_AICREDIR_NSAIC), &sfr->aicredir);
+	}
+}
+#endif
diff --git a/arch/arm/mach-at91/armv7/timer.c b/arch/arm/mach-at91/armv7/timer.c
new file mode 100644
index 0000000..19bf80b
--- /dev/null
+++ b/arch/arm/mach-at91/armv7/timer.c
@@ -0,0 +1,124 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.com>
+ *
+ * (C) Copyright 2013
+ * Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pit.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/clk.h>
+#include <div64.h>
+
+#if !defined(CONFIG_AT91FAMILY)
+# error You need to define CONFIG_AT91FAMILY in your board config!
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * We're using the SAMA5D3x PITC in 32 bit mode, by
+ * setting the 20 bit counter period to its maximum (0xfffff).
+ * (See the relevant data sheets to understand that this really works)
+ *
+ * We do also mimic the typical powerpc way of incrementing
+ * two 32 bit registers called tbl and tbu.
+ *
+ * Those registers increment at 1/16 the main clock rate.
+ */
+
+#define TIMER_LOAD_VAL	0xfffff
+
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+	tick *= CONFIG_SYS_HZ;
+	do_div(tick, gd->arch.timer_rate_hz);
+
+	return tick;
+}
+
+static inline unsigned long long usec_to_tick(unsigned long long usec)
+{
+	usec *= gd->arch.timer_rate_hz;
+	do_div(usec, 1000000);
+
+	return usec;
+}
+
+/*
+ * Use the PITC in full 32 bit incrementing mode
+ */
+int timer_init(void)
+{
+	at91_pit_t *pit = (at91_pit_t *)ATMEL_BASE_PIT;
+
+	/* Enable PITC Clock */
+	at91_periph_clk_enable(ATMEL_ID_PIT);
+
+	/* Enable PITC */
+	writel(TIMER_LOAD_VAL | AT91_PIT_MR_EN , &pit->mr);
+
+	gd->arch.timer_rate_hz = get_pit_clk_rate() / 16;
+
+	gd->arch.tbu = 0;
+	gd->arch.tbl = 0;
+
+	return 0;
+}
+
+/*
+ * Get the current 64 bit timer tick count
+ */
+unsigned long long get_ticks(void)
+{
+	at91_pit_t *pit = (at91_pit_t *)ATMEL_BASE_PIT;
+
+	ulong now = readl(&pit->piir);
+
+	/* increment tbu if tbl has rolled over */
+	if (now < gd->arch.tbl)
+		gd->arch.tbu++;
+	gd->arch.tbl = now;
+	return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl;
+}
+
+void __udelay(unsigned long usec)
+{
+	unsigned long long start;
+	ulong tmo;
+
+	start = get_ticks();		/* get current timestamp */
+	tmo = usec_to_tick(usec);	/* convert usecs to ticks */
+	while ((get_ticks() - start) < tmo)
+		;			/* loop till time has passed */
+}
+
+/*
+ * get_timer(base) can be used to check for timeouts or
+ * to measure elasped time relative to an event:
+ *
+ * ulong start_time = get_timer(0) sets start_time to the current
+ * time value.
+ * get_timer(start_time) returns the time elapsed since then.
+ *
+ * The time is used in CONFIG_SYS_HZ units!
+ */
+ulong get_timer(ulong base)
+{
+	return tick_to_time(get_ticks()) - base;
+}
+
+/*
+ * Return the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	return gd->arch.timer_rate_hz;
+}
diff --git a/arch/arm/mach-at91/config.mk b/arch/arm/mach-at91/config.mk
new file mode 100644
index 0000000..7168abb
--- /dev/null
+++ b/arch/arm/mach-at91/config.mk
@@ -0,0 +1,9 @@
+ifeq ($(CONFIG_CPU_ARM926EJS),y)
+PLATFORM_CPPFLAGS += $(call cc-option,-mtune=arm926ejs,)
+endif
+
+ifeq ($(CONFIG_CPU_V7),y)
+ifndef CONFIG_SPL_BUILD
+ALL-y	+= u-boot.img
+endif
+endif
diff --git a/arch/arm/mach-at91/mpddrc.c b/arch/arm/mach-at91/mpddrc.c
new file mode 100644
index 0000000..beec13d
--- /dev/null
+++ b/arch/arm/mach-at91/mpddrc.c
@@ -0,0 +1,133 @@
+/*
+ * 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/atmel_mpddrc.h>
+
+static inline void atmel_mpddr_op(int mode, u32 ram_address)
+{
+	struct atmel_mpddr *mpddr = (struct atmel_mpddr *)ATMEL_BASE_MPDDRC;
+
+	writel(mode, &mpddr->mr);
+	writel(0, ram_address);
+}
+
+static int ddr2_decodtype_is_seq(u32 cr)
+{
+#if defined(CONFIG_SAMA5D3) || defined(CONFIG_SAMA5D4)
+	if (cr & ATMEL_MPDDRC_CR_DECOD_INTERLEAVED)
+		return 0;
+#endif
+	return 1;
+}
+
+int ddr2_init(const unsigned int ram_address,
+	      const struct atmel_mpddr *mpddr_value)
+{
+	struct atmel_mpddr *mpddr = (struct atmel_mpddr *)ATMEL_BASE_MPDDRC;
+	u32 ba_off, cr;
+
+	/* Compute bank offset according to NC in configuration register */
+	ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9;
+	if (ddr2_decodtype_is_seq(mpddr_value->cr))
+		ba_off += ((mpddr_value->cr & ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11;
+
+	ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2;
+
+	/* Program the memory device type into the memory device register */
+	writel(mpddr_value->md, &mpddr->md);
+
+	/* Program the configuration register */
+	writel(mpddr_value->cr, &mpddr->cr);
+
+	/* Program the timing register */
+	writel(mpddr_value->tpr0, &mpddr->tpr0);
+	writel(mpddr_value->tpr1, &mpddr->tpr1);
+	writel(mpddr_value->tpr2, &mpddr->tpr2);
+
+	/* Issue a NOP command */
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
+
+	/* A 200 us is provided to precede any signal toggle */
+	udelay(200);
+
+	/* Issue a NOP command */
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
+
+	/* Issue an all banks precharge command */
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address);
+
+	/* Issue an extended mode register set(EMRS2) to choose operation */
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
+		       ram_address + (0x2 << ba_off));
+
+	/* Issue an extended mode register set(EMRS3) to set EMSR to 0 */
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
+		       ram_address + (0x3 << ba_off));
+
+	/*
+	 * Issue an extended mode register set(EMRS1) to enable DLL and
+	 * program D.I.C (output driver impedance control)
+	 */
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
+		       ram_address + (0x1 << ba_off));
+
+	/* Enable DLL reset */
+	cr = readl(&mpddr->cr);
+	writel(cr | ATMEL_MPDDRC_CR_DLL_RESET_ENABLED, &mpddr->cr);
+
+	/* A mode register set(MRS) cycle is issued to reset DLL */
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
+
+	/* Issue an all banks precharge command */
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address);
+
+	/* Two auto-refresh (CBR) cycles are provided */
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address);
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address);
+
+	/* Disable DLL reset */
+	cr = readl(&mpddr->cr);
+	writel(cr & (~ATMEL_MPDDRC_CR_DLL_RESET_ENABLED), &mpddr->cr);
+
+	/* A mode register set (MRS) cycle is issued to disable DLL reset */
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
+
+	/* Set OCD calibration in default state */
+	cr = readl(&mpddr->cr);
+	writel(cr | ATMEL_MPDDRC_CR_OCD_DEFAULT, &mpddr->cr);
+
+	/*
+	 * An extended mode register set (EMRS1) cycle is issued
+	 * to OCD default value
+	 */
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
+		       ram_address + (0x1 << ba_off));
+
+	 /* OCD calibration mode exit */
+	cr = readl(&mpddr->cr);
+	writel(cr & (~ATMEL_MPDDRC_CR_OCD_DEFAULT), &mpddr->cr);
+
+	/*
+	 * An extended mode register set (EMRS1) cycle is issued
+	 * to enable OCD exit
+	 */
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
+		       ram_address + (0x1 << ba_off));
+
+	/* A nornal mode command is provided */
+	atmel_mpddr_op(ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address);
+
+	/* Perform a write access to any DDR2-SDRAM address */
+	writel(0, ram_address);
+
+	/* Write the refresh rate */
+	writel(mpddr_value->rtr, &mpddr->rtr);
+
+	return 0;
+}
diff --git a/arch/arm/mach-at91/phy.c b/arch/arm/mach-at91/phy.c
new file mode 100644
index 0000000..2cba716
--- /dev/null
+++ b/arch/arm/mach-at91/phy.c
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.com>
+ *
+ * (C) Copyright 2012
+ * Markus Hubig <mhubig@imko.de>
+ * IMKO GmbH <www.imko.de>
+ *
+ * Copyright (C) 2013 DENX Software Engineering, hs@denx.de
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/sizes.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+#include <watchdog.h>
+
+void at91_phy_reset(void)
+{
+	unsigned long erstl;
+	unsigned long start = get_timer(0);
+	unsigned long const timeout = 1000; /* 1000ms */
+	at91_rstc_t *rstc = (at91_rstc_t *)ATMEL_BASE_RSTC;
+
+	erstl = readl(&rstc->mr) & AT91_RSTC_MR_ERSTL_MASK;
+
+	/*
+	 * Need to reset PHY -> 500ms reset
+	 * Reset PHY by pulling the NRST line for 500ms to low. To do so
+	 * disable user reset for low level on NRST pin and poll the NRST
+	 * level in reset status register.
+	 */
+	writel(AT91_RSTC_KEY | AT91_RSTC_MR_ERSTL(0x0D) |
+		AT91_RSTC_MR_URSTEN, &rstc->mr);
+
+	writel(AT91_RSTC_KEY | AT91_RSTC_CR_EXTRST, &rstc->cr);
+
+	/* Wait for end of hardware reset */
+	while (!(readl(&rstc->sr) & AT91_RSTC_SR_NRSTL)) {
+		/* avoid shutdown by watchdog */
+		WATCHDOG_RESET();
+		mdelay(10);
+
+		/* timeout for not getting stuck in an endless loop */
+		if (get_timer(start) >= timeout) {
+			puts("*** ERROR: Timeout waiting for PHY reset!\n");
+			break;
+		}
+	};
+
+	/* Restore NRST value */
+	writel(AT91_RSTC_KEY | erstl | AT91_RSTC_MR_URSTEN, &rstc->mr);
+}
diff --git a/arch/arm/mach-at91/sdram.c b/arch/arm/mach-at91/sdram.c
new file mode 100644
index 0000000..5758b06
--- /dev/null
+++ b/arch/arm/mach-at91/sdram.c
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2014
+ * Heiko Schocher, DENX Software Engineering, hs@denx.de.
+ *
+ * Based on:
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.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/at91sam9_sdramc.h>
+#include <asm/arch/gpio.h>
+
+int sdramc_initialize(unsigned int sdram_address, const struct sdramc_reg *p)
+{
+	struct sdramc_reg *reg = (struct sdramc_reg *)ATMEL_BASE_SDRAMC;
+	unsigned int i;
+
+	/* SDRAM feature must be in the configuration register */
+	writel(p->cr, &reg->cr);
+
+	/* The SDRAM memory type must be set in the Memory Device Register */
+	writel(p->mdr, &reg->mdr);
+
+	/*
+	 * The minimum pause of 200 us is provided to precede any single
+	 * toggle
+	 */
+	for (i = 0; i < 1000; i++)
+		;
+
+	/* A NOP command is issued to the SDRAM devices */
+	writel(AT91_SDRAMC_MODE_NOP, &reg->mr);
+	writel(0x00000000, sdram_address);
+
+	/* An All Banks Precharge command is issued to the SDRAM devices */
+	writel(AT91_SDRAMC_MODE_PRECHARGE, &reg->mr);
+	writel(0x00000000, sdram_address);
+
+	for (i = 0; i < 10000; i++)
+		;
+
+	/* Eight auto-refresh cycles are provided */
+	for (i = 0; i < 8; i++) {
+		writel(AT91_SDRAMC_MODE_REFRESH, &reg->mr);
+		writel(0x00000001 + i, sdram_address + 4 + 4 * i);
+	}
+
+	/*
+	 * A Mode Register set (MRS) cyscle is issued to program the
+	 * SDRAM parameters(TCSR, PASR, DS)
+	 */
+	writel(AT91_SDRAMC_MODE_LMR, &reg->mr);
+	writel(0xcafedede, sdram_address + 0x24);
+
+	/*
+	 * The application must go into Normal Mode, setting Mode
+	 * to 0 in the Mode Register and perform a write access at
+	 * any location in the SDRAM.
+	 */
+	writel(AT91_SDRAMC_MODE_NORMAL, &reg->mr);
+	writel(0x00000000, sdram_address);	/* Perform Normal mode */
+
+	/*
+	 * Write the refresh rate into the count field in the SDRAMC
+	 * Refresh Timer Rgister.
+	 */
+	writel(p->tr, &reg->tr);
+
+	return 0;
+}
diff --git a/arch/arm/mach-at91/spl.c b/arch/arm/mach-at91/spl.c
new file mode 100644
index 0000000..aaa5eec
--- /dev/null
+++ b/arch/arm/mach-at91/spl.c
@@ -0,0 +1,50 @@
+/*
+ * 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_wdt.h>
+#include <asm/arch/clk.h>
+#include <spl.h>
+
+#if defined(CONFIG_AT91SAM9_WATCHDOG)
+void at91_disable_wdt(void) { }
+#else
+void at91_disable_wdt(void)
+{
+	struct at91_wdt *wdt = (struct at91_wdt *)ATMEL_BASE_WDT;
+
+	writel(AT91_WDT_MR_WDDIS, &wdt->mr);
+}
+#endif
+
+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
+	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_FS;
+		break;
+#endif
+	case BOOT_DEVICE_NONE:
+	default:
+		hang();
+	}
+}
diff --git a/arch/arm/mach-at91/spl_at91.c b/arch/arm/mach-at91/spl_at91.c
new file mode 100644
index 0000000..89f588b
--- /dev/null
+++ b/arch/arm/mach-at91/spl_at91.c
@@ -0,0 +1,124 @@
+/*
+ * (C) Copyright 2014 DENX Software Engineering
+ *     Heiko Schocher <hs@denx.de>
+ *
+ * Based on:
+ * 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/at91sam9_matrix.h>
+#include <asm/arch/at91_pit.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+#include <asm/arch/at91_wdt.h>
+#include <asm/arch/clk.h>
+#include <spl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void enable_ext_reset(void)
+{
+	struct at91_rstc *rstc = (struct at91_rstc *)ATMEL_BASE_RSTC;
+
+	writel(AT91_RSTC_KEY | AT91_RSTC_MR_URSTEN, &rstc->mr);
+}
+
+void lowlevel_clock_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	if (!(readl(&pmc->sr) & AT91_PMC_MOSCS)) {
+		/* Enable Main Oscillator */
+		writel(AT91_PMC_MOSCS | (0x40 << 8), &pmc->mor);
+
+		/* Wait until Main Oscillator is stable */
+		while (!(readl(&pmc->sr) & AT91_PMC_MOSCS))
+			;
+	}
+
+	/* After stabilization, switch to Main Oscillator */
+	if ((readl(&pmc->mckr) & AT91_PMC_CSS) == AT91_PMC_CSS_SLOW) {
+		unsigned long tmp;
+
+		tmp = readl(&pmc->mckr);
+		tmp &= ~AT91_PMC_CSS;
+		tmp |= AT91_PMC_CSS_MAIN;
+		writel(tmp, &pmc->mckr);
+		while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
+			;
+
+		tmp &= ~AT91_PMC_PRES;
+		tmp |= AT91_PMC_PRES_1;
+		writel(tmp, &pmc->mckr);
+		while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
+			;
+	}
+
+	return;
+}
+
+void __weak matrix_init(void)
+{
+}
+
+void __weak at91_spl_board_init(void)
+{
+}
+
+void spl_board_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	lowlevel_clock_init();
+	at91_disable_wdt();
+
+	/*
+	 * At this stage the main oscillator is supposed to be enabled
+	 * PCK = MCK = MOSC
+	 */
+	writel(0x00, &pmc->pllicpr);
+
+	/* Configure PLLA = MOSC * (PLL_MULA + 1) / PLL_DIVA */
+	at91_plla_init(CONFIG_SYS_AT91_PLLA);
+
+	/* PCK = PLLA = 2 * MCK */
+	at91_mck_init(CONFIG_SYS_MCKR);
+
+	/* Switch MCK on PLLA output */
+	at91_mck_init(CONFIG_SYS_MCKR_CSS);
+
+#if defined(CONFIG_SYS_AT91_PLLB)
+	/* Configure PLLB */
+	at91_pllb_init(CONFIG_SYS_AT91_PLLB);
+#endif
+
+	/* Enable External Reset */
+	enable_ext_reset();
+
+	/* Initialize matrix */
+	matrix_init();
+
+	gd->arch.mck_rate_hz = CONFIG_SYS_MASTER_CLOCK;
+	/*
+	 * init timer long enough for using in spl.
+	 */
+	timer_init();
+
+	/* enable clocks for all PIOs */
+	at91_periph_clk_enable(ATMEL_ID_PIOA);
+	at91_periph_clk_enable(ATMEL_ID_PIOB);
+	at91_periph_clk_enable(ATMEL_ID_PIOC);
+	/* init console */
+	at91_seriald_hw_init();
+	preloader_console_init();
+
+	mem_init();
+
+	at91_spl_board_init();
+}
diff --git a/arch/arm/mach-at91/spl_atmel.c b/arch/arm/mach-at91/spl_atmel.c
new file mode 100644
index 0000000..9cc1111
--- /dev/null
+++ b/arch/arm/mach-at91/spl_atmel.c
@@ -0,0 +1,96 @@
+/*
+ * 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_pit.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+#include <asm/arch/at91_wdt.h>
+#include <asm/arch/clk.h>
+#include <spl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void switch_to_main_crystal_osc(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	u32 tmp;
+
+	tmp = readl(&pmc->mor);
+	tmp &= ~AT91_PMC_MOR_OSCOUNT(0xff);
+	tmp &= ~AT91_PMC_MOR_KEY(0xff);
+	tmp |= AT91_PMC_MOR_MOSCEN;
+	tmp |= AT91_PMC_MOR_OSCOUNT(8);
+	tmp |= AT91_PMC_MOR_KEY(0x37);
+	writel(tmp, &pmc->mor);
+	while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCS))
+		;
+
+	tmp = readl(&pmc->mor);
+	tmp &= ~AT91_PMC_MOR_OSCBYPASS;
+	tmp &= ~AT91_PMC_MOR_KEY(0xff);
+	tmp |= AT91_PMC_MOR_KEY(0x37);
+	writel(tmp, &pmc->mor);
+
+	tmp = readl(&pmc->mor);
+	tmp |= AT91_PMC_MOR_MOSCSEL;
+	tmp &= ~AT91_PMC_MOR_KEY(0xff);
+	tmp |= AT91_PMC_MOR_KEY(0x37);
+	writel(tmp, &pmc->mor);
+
+	while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCSELS))
+		;
+
+	/* Wait until MAINRDY field is set to make sure main clock is stable */
+	while (!(readl(&pmc->mcfr) & AT91_PMC_MAINRDY))
+		;
+
+#ifndef CONFIG_SAMA5D4
+	tmp = readl(&pmc->mor);
+	tmp &= ~AT91_PMC_MOR_MOSCRCEN;
+	tmp &= ~AT91_PMC_MOR_KEY(0xff);
+	tmp |= AT91_PMC_MOR_KEY(0x37);
+	writel(tmp, &pmc->mor);
+#endif
+}
+
+__weak void matrix_init(void)
+{
+	/* This only be used for sama5d4 soc now */
+}
+
+__weak void redirect_int_from_saic_to_aic(void)
+{
+	/* This only be used for sama5d4 soc now */
+}
+
+void s_init(void)
+{
+	switch_to_main_crystal_osc();
+
+	/* disable watchdog */
+	at91_disable_wdt();
+
+	/* PMC configuration */
+	at91_pmc_init();
+
+	at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK);
+
+	matrix_init();
+
+	redirect_int_from_saic_to_aic();
+
+	timer_init();
+
+	board_early_init_f();
+
+	preloader_console_init();
+
+	mem_init();
+}
diff --git a/arch/arm/mach-at91/u-boot-spl.lds b/arch/arm/mach-at91/u-boot-spl.lds
new file mode 100644
index 0000000..eccca43
--- /dev/null
+++ b/arch/arm/mach-at91/u-boot-spl.lds
@@ -0,0 +1,55 @@
+/*
+ * (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 = .;
+		*(.vectors)
+		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 :
+	{
+		*(.__end)
+	} >.sram
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start = .;
+		*(.bss*)
+		. = ALIGN(4);
+		__bss_end = .;
+	} >.sdram
+}