Patchwork [U-Boot,v5,02/11] S3C24XX: Add core support for Samsung's S3C24XX SoCs

login
register
mail settings
Submitter José Miguel Gonçalves
Date Sept. 21, 2012, 6:47 p.m.
Message ID <1348253268-21812-3-git-send-email-jose.goncalves@inov.pt>
Download mbox | patch
Permalink /patch/185884/
State Changes Requested
Delegated to: Minkyu Kang
Headers show

Comments

José Miguel Gonçalves - Sept. 21, 2012, 6:47 p.m.
This patch adds the support for Samsung's S3C24XX SoCs that have an ARM926EJS core.
Currently it supports S3C2412, S3C2413, S3C2416 and S3C2450.
Tested on an S3C2416 platform.

Signed-off-by: José Miguel Gonçalves <jose.goncalves@inov.pt>
---
Changes for v2:
   - Added register bit macros to avoid magic numbers
   - Removed volatile attribute from register structs
   - Added s3c24x0_cpu.h to be able to use drivers from s3c24x0 family
   - Fixed EPLL computation in get_PLLCLK for S3C2416
   - Added display of UCLK in print_cpu_info
   - Use of clrsetbits_le32()

Changes for v3:
   - Add __noreturn attribute to reset_cpu()
   - Removed magic numbers
   - Add arch/arm/include/asm/arch-s3c24xx/spl.h for new SPL framework

Changes for v4:
   - None

Changes for v5:
   - None
---
 arch/arm/cpu/arm926ejs/s3c24xx/Makefile         |   56 +++
 arch/arm/cpu/arm926ejs/s3c24xx/cpu.c            |   57 +++
 arch/arm/cpu/arm926ejs/s3c24xx/cpu_info.c       |   57 +++
 arch/arm/cpu/arm926ejs/s3c24xx/s3c2412_speed.c  |  114 +++++
 arch/arm/cpu/arm926ejs/s3c24xx/s3c2416_speed.c  |  116 +++++
 arch/arm/cpu/arm926ejs/s3c24xx/timer.c          |  152 ++++++
 arch/arm/include/asm/arch-s3c24xx/s3c2412.h     |  130 +++++
 arch/arm/include/asm/arch-s3c24xx/s3c2416.h     |  183 +++++++
 arch/arm/include/asm/arch-s3c24xx/s3c24x0_cpu.h |   41 ++
 arch/arm/include/asm/arch-s3c24xx/s3c24xx.h     |  615 +++++++++++++++++++++++
 arch/arm/include/asm/arch-s3c24xx/s3c24xx_cpu.h |   30 ++
 arch/arm/include/asm/arch-s3c24xx/spl.h         |   29 ++
 include/common.h                                |    1 +
 13 files changed, 1581 insertions(+)
 create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/Makefile
 create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/cpu.c
 create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/cpu_info.c
 create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/s3c2412_speed.c
 create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/s3c2416_speed.c
 create mode 100644 arch/arm/cpu/arm926ejs/s3c24xx/timer.c
 create mode 100644 arch/arm/include/asm/arch-s3c24xx/s3c2412.h
 create mode 100644 arch/arm/include/asm/arch-s3c24xx/s3c2416.h
 create mode 100644 arch/arm/include/asm/arch-s3c24xx/s3c24x0_cpu.h
 create mode 100644 arch/arm/include/asm/arch-s3c24xx/s3c24xx.h
 create mode 100644 arch/arm/include/asm/arch-s3c24xx/s3c24xx_cpu.h
 create mode 100644 arch/arm/include/asm/arch-s3c24xx/spl.h

Patch

diff --git a/arch/arm/cpu/arm926ejs/s3c24xx/Makefile b/arch/arm/cpu/arm926ejs/s3c24xx/Makefile
new file mode 100644
index 0000000..d7f5e0d
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/s3c24xx/Makefile
@@ -0,0 +1,56 @@ 
+#
+# (C) Copyright 2012 INOV - INESC Inovacao
+# Jose Goncalves <jose.goncalves@inov.pt>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(SOC).o
+
+ifndef CONFIG_SPL_BUILD
+COBJS-$(CONFIG_DISPLAY_CPUINFO)	+= cpu_info.o
+endif
+
+ifeq ($(filter y,$(CONFIG_S3C2412) $(CONFIG_S3C2413)),y)
+COBJS-y	+= s3c2412_speed.o
+else
+COBJS-y	+= s3c2416_speed.o
+endif
+
+COBJS-y	+= cpu.o
+COBJS-y	+= timer.o
+
+SRCS	:= $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/arm926ejs/s3c24xx/cpu.c b/arch/arm/cpu/arm926ejs/s3c24xx/cpu.c
new file mode 100644
index 0000000..a6a90d8
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/s3c24xx/cpu.c
@@ -0,0 +1,57 @@ 
+/*
+ * (C) Copyright 2012 INOV - INESC Inovacao
+ * Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <linux/compiler.h>
+#include <asm/io.h>
+#include <asm/arch/s3c24xx_cpu.h>
+
+void enable_caches(void)
+{
+#ifndef CONFIG_SYS_ICACHE_OFF
+	icache_enable();
+#endif
+#ifndef CONFIG_SYS_DCACHE_OFF
+	dcache_enable();
+#endif
+}
+
+/*
+ * Reset the cpu by setting up the watchdog timer and let him time out.
+ */
+void __noreturn reset_cpu(ulong addr)
+{
+	struct s3c24xx_watchdog *const watchdog = s3c24xx_get_base_watchdog();
+
+	/* Disable watchdog */
+	writel(WTCON_DISABLE_VAL, &watchdog->wtcon);
+
+	/* Initialize watchdog timer count register with the minimum value */
+	writel(0x0001, &watchdog->wtcnt);
+
+	/* Enable watchdog timer; assert reset at timer timeout */
+	writel(WTCON_RSTEN | WTCON_ENABLE, &watchdog->wtcon);
+
+	while (1)
+		/* loop forever and wait for reset to happen */;
+}
diff --git a/arch/arm/cpu/arm926ejs/s3c24xx/cpu_info.c b/arch/arm/cpu/arm926ejs/s3c24xx/cpu_info.c
new file mode 100644
index 0000000..d2a8b95
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/s3c24xx/cpu_info.c
@@ -0,0 +1,57 @@ 
+/*
+ * (C) Copyright 2010
+ * David Mueller <d.mueller@elsoft.ch>
+ *
+ * (C) Copyright 2012 INOV - INESC Inovacao
+ * Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/s3c24xx_cpu.h>
+
+typedef ulong(*getfreq) (void);
+
+static const getfreq freq_f[] = {
+	get_FCLK,
+	get_HCLK,
+	get_PCLK,
+	get_UCLK,
+};
+
+static const char freq_c[] = { 'F', 'H', 'P', 'U' };
+
+int print_cpuinfo(void)
+{
+	int i;
+	char buf[32];
+	ulong cpuid;
+	struct s3c24xx_gpio *const gpio = s3c24xx_get_base_gpio();
+
+	cpuid = readl(&gpio->gstatus[1]);
+	printf("CPU:  %8s (id %08lX) @ %s MHz\n", s3c24xx_get_cpu_name(),
+	       cpuid, strmhz(buf, get_ARMCLK()));
+	for (i = 0; i < ARRAY_SIZE(freq_f); i++)
+		printf("%cCLK: %8s MHz\n", freq_c[i],
+		       strmhz(buf, freq_f[i] ()));
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm926ejs/s3c24xx/s3c2412_speed.c b/arch/arm/cpu/arm926ejs/s3c24xx/s3c2412_speed.c
new file mode 100644
index 0000000..d584cf2
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/s3c24xx/s3c2412_speed.c
@@ -0,0 +1,114 @@ 
+/*
+ * (C) Copyright 2012 INOV - INESC Inovacao
+ * Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * Based on U-Boot 1.3.4 from Samsung.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/s3c2412.h>
+
+#define MPLL 0
+#define UPLL 1
+
+/* ------------------------------------------------------------------------- */
+/*
+ * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL.
+ *
+ * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of
+ * the specified bus in HZ.
+ */
+/* ------------------------------------------------------------------------- */
+
+static ulong get_PLLCLK(int pllreg)
+{
+	struct s3c2412_sysctl *const sysctl = s3c2412_get_base_sysctl();
+	u32 pllcon, f;
+	u16 mdiv, pdiv, sdiv;
+
+	if (pllreg == MPLL)
+		pllcon = readl(&sysctl->mpllcon);
+	else if (pllreg == UPLL)
+		pllcon = readl(&sysctl->upllcon);
+	else
+		hang();
+
+	mdiv = PLLCON_MDIV_GET(pllcon);
+	pdiv = PLLCON_PDIV_GET(pllcon);
+	sdiv = PLLCON_SDIV_GET(pllcon);
+
+	f = (mdiv + 8) * (CONFIG_SYS_CLK_FREQ / ((pdiv + 2) << sdiv));
+	if (pllreg == MPLL)
+		f <<= 1;
+
+	return f;
+}
+
+/* return FCLK frequency */
+ulong get_FCLK(void)
+{
+	return get_PLLCLK(MPLL);
+}
+
+/* return HCLK frequency */
+ulong get_HCLK(void)
+{
+	struct s3c2412_sysctl *const sysctl = s3c2412_get_base_sysctl();
+	u32 clkdivn;
+	u16 hclk_div, arm_div;
+
+	clkdivn = readl(&sysctl->clkdivn);
+	hclk_div = CLKDIVN_HCLKDIV_GET(clkdivn) + 1;
+	arm_div = CLKDIVN_ARMDIV_GET(clkdivn) + 1;
+
+	return get_FCLK() / (hclk_div * arm_div);
+}
+
+/* return PCLK frequency */
+ulong get_PCLK(void)
+{
+	struct s3c2412_sysctl *const sysctl = s3c2412_get_base_sysctl();
+	u32 clkdivn;
+
+	clkdivn = readl(&sysctl->clkdivn);
+
+	return (clkdivn & CLKDIVN_PCLKDIV) ? get_HCLK() / 2 : get_HCLK();
+}
+
+/* return UCLK frequency */
+ulong get_UCLK(void)
+{
+	return get_PLLCLK(UPLL);
+}
+
+/* return ARMCORE frequency */
+ulong get_ARMCLK(void)
+{
+	struct s3c2412_sysctl *const sysctl = s3c2412_get_base_sysctl();
+	u32 clkdivn;
+
+	clkdivn = readl(&sysctl->clkdivn);
+	if (clkdivn & CLKDIVN_DVS)
+		return get_FCLK();
+
+	return (clkdivn & CLKDIVN_ARMDIV) ? get_FCLK() / 2 : get_FCLK();
+}
diff --git a/arch/arm/cpu/arm926ejs/s3c24xx/s3c2416_speed.c b/arch/arm/cpu/arm926ejs/s3c24xx/s3c2416_speed.c
new file mode 100644
index 0000000..625e603
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/s3c24xx/s3c2416_speed.c
@@ -0,0 +1,116 @@ 
+/*
+ * (C) Copyright 2012 INOV - INESC Inovacao
+ * Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * Based on U-Boot 1.3.4 from Samsung.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/s3c2416.h>
+
+#define MPLL 0
+#define EPLL 1
+
+/* ------------------------------------------------------------------------- */
+/*
+ * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL.
+ *
+ * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of
+ * the specified bus in HZ.
+ */
+/* ------------------------------------------------------------------------- */
+
+static ulong get_PLLCLK(int pllreg)
+{
+	struct s3c2416_sysctl *const sysctl = s3c2416_get_base_sysctl();
+	u32 pllcon;
+	u16 mdiv, pdiv, sdiv;
+
+	if (pllreg == MPLL) {
+		pllcon = readl(&sysctl->mpllcon);
+		mdiv = MPLLCON_MDIV_GET(pllcon);
+		pdiv = MPLLCON_PDIV_GET(pllcon);
+	} else if (pllreg == EPLL) {
+		pllcon = readl(&sysctl->epllcon);
+		mdiv = EPLLCON_MDIV_GET(pllcon);
+		pdiv = EPLLCON_PDIV_GET(pllcon);
+	} else {
+		hang();
+	}
+
+	sdiv = PLLCON_SDIV_GET(pllcon);
+
+	return mdiv * (CONFIG_SYS_CLK_FREQ / (pdiv << sdiv));
+}
+
+/* return FCLK frequency */
+ulong get_FCLK(void)
+{
+	return get_PLLCLK(MPLL);
+}
+
+/* return HCLK frequency */
+ulong get_HCLK(void)
+{
+	struct s3c2416_sysctl *const sysctl = s3c2416_get_base_sysctl();
+	u32 clkdiv0;
+	u16 hclk_div, pre_div;
+
+	clkdiv0 = readl(&sysctl->clkdiv0);
+	hclk_div = (CLKDIV0_HCLKDIV_GET(clkdiv0)) + 1;
+	pre_div = (CLKDIV0_PREDIV_GET(clkdiv0)) + 1;
+
+	return get_FCLK() / (hclk_div * pre_div);
+}
+
+/* return PCLK frequency */
+ulong get_PCLK(void)
+{
+	struct s3c2416_sysctl *const sysctl = s3c2416_get_base_sysctl();
+	u32 clkdiv0;
+
+	clkdiv0 = readl(&sysctl->clkdiv0);
+
+	return (clkdiv0 & CLKDIV0_PCLKDIV) ? get_HCLK() / 2 : get_HCLK();
+}
+
+/* return UCLK frequency */
+ulong get_UCLK(void)
+{
+	return get_PLLCLK(EPLL);
+}
+
+/* return ARMCORE frequency */
+ulong get_ARMCLK(void)
+{
+	struct s3c2416_sysctl *const sysctl = s3c2416_get_base_sysctl();
+	u32 clkdiv0;
+	u16 arm_div;
+
+	clkdiv0 = readl(&sysctl->clkdiv0);
+	if (clkdiv0 & CLKDIV0_DVS)
+		return get_FCLK();
+
+	arm_div = CLKDIV0_ARMDIV_GET(clkdiv0) + 1;
+
+	return get_FCLK() / arm_div;
+}
diff --git a/arch/arm/cpu/arm926ejs/s3c24xx/timer.c b/arch/arm/cpu/arm926ejs/s3c24xx/timer.c
new file mode 100644
index 0000000..1a838f8
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/s3c24xx/timer.c
@@ -0,0 +1,152 @@ 
+/*
+ * (C) Copyright 2012 INOV - INESC Inovacao
+ * Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * Based on arch/arm/cpu/armv7/s5p-common/timer.c and U-Boot 1.3.4 from Samsung.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/s3c24xx_cpu.h>
+
+#define PRESCALER 15
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static ulong get_current_tick(void)
+{
+	struct s3c24xx_timers *const timers = s3c24xx_get_base_timers();
+	ulong now = readl(&timers->tcnto4);
+
+	if (gd->lastinc >= now)
+		gd->tbl += gd->lastinc - now;
+	else
+		gd->tbl += gd->lastinc + gd->tbu - now;
+
+	gd->lastinc = now;
+
+	return gd->tbl;
+}
+
+int timer_init(void)
+{
+	struct s3c24xx_timers *const timers = s3c24xx_get_base_timers();
+
+	/* use PWM Timer 4 because it has no output */
+	if (gd->tbu == 0) {
+		/* set divider value for Timer 4 to 2 */
+		clrsetbits_le32(&timers->tcfg1, TCFG1_MUX4_MASK,
+				TCFG1_MUX4_DIV2);
+		/* set prescaler value for Timer 4 to PRESCALER */
+		clrsetbits_le32(&timers->tcfg0, TCFG0_PRESCALER1_MASK,
+				TCFG0_PRESCALER1(PRESCALER));
+		/*
+		 * Timer Freq(HZ) =
+		 *      PCLK / (prescaler_value + 1) / (divider_value)
+		 */
+		gd->timer_rate_hz = get_PCLK() / (PRESCALER + 1) / 2;
+		gd->tbu = gd->timer_rate_hz / CONFIG_SYS_HZ;
+	}
+	/* load value for selected timeout */
+	writel(gd->tbu, &timers->tcntb4);
+	/* auto reload, manual update of timer 4 */
+	clrsetbits_le32(&timers->tcon, TCON_T4START,
+			TCON_T4RELOAD | TCON_T4MANUALUPD);
+	/* auto reload, start timer 4 */
+	clrsetbits_le32(&timers->tcon, TCON_T4MANUALUPD,
+			TCON_T4RELOAD | TCON_T4START);
+	gd->lastinc = 0;
+	gd->tbl = 0;
+
+	return 0;
+}
+
+ulong get_timer(ulong base)
+{
+	return get_timer_masked() - base;
+}
+
+void __udelay(unsigned long usec)
+{
+	ulong tmo, tmp;
+
+	if (usec >= 1000) {
+		/*
+		 * if "big" number, spread normalization
+		 * to seconds
+		 * 1. start to normalize for usec to ticks per sec
+		 * 2. find number of "ticks" to wait to achieve target
+		 * 3. finish normalize.
+		 */
+		tmo = usec / 1000;
+		tmo *= gd->timer_rate_hz;
+		tmo /= 1000;
+	} else {
+		/* else small number, don't kill it prior to HZ multiply */
+		tmo = usec * gd->timer_rate_hz;
+		tmo /= (1000 * 1000);
+	}
+
+	/* get current timestamp */
+	tmp = get_current_tick();
+
+	/* if advancing the timestamp would roll-up the timer, reset it */
+	if ((tmo + tmp + 1) < tmp)
+		reset_timer_masked();
+	else
+		tmo += tmp;
+
+	/* loop till event */
+	while (get_current_tick() < tmo)
+		/* NOP */;
+}
+
+void reset_timer_masked(void)
+{
+	struct s3c24xx_timers *const timers = s3c24xx_get_base_timers();
+
+	/* reset time */
+	gd->lastinc = readl(&timers->tcnto4);
+	gd->tbl = 0;
+}
+
+ulong get_timer_masked(void)
+{
+	return get_current_tick() / gd->tbu;
+}
+
+/*
+ * 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_masked();
+}
+
+/*
+ * 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/include/asm/arch-s3c24xx/s3c2412.h b/arch/arm/include/asm/arch-s3c24xx/s3c2412.h
new file mode 100644
index 0000000..8945308
--- /dev/null
+++ b/arch/arm/include/asm/arch-s3c24xx/s3c2412.h
@@ -0,0 +1,130 @@ 
+/*
+ * (C) Copyright 2012 INOV - INESC Inovacao
+ * Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/************************************************
+ * NAME	    : s3c2412.h
+ *
+ * Based on S3C2412 User's manual Rev 1.06a
+ ************************************************/
+
+#ifndef __S3C2412_H__
+#define __S3C2412_H__
+
+/* Base addresses for S3C2412 specific modules */
+#define S3C2412_INTERRUPT_BASE		0x4A000000
+#define S3C2412_SYSCTL_BASE		0x4C000000
+#define S3C2412_LCD_BASE		0x4D000000
+#define S3C2412_USB_DEVICE_BASE		0x52000000
+#define S3C2412_ADC_BASE		0x58000000
+#define S3C2412_SPI_BASE		0x59000000
+#define S3C2412_SDIO_BASE		0x5A000000
+
+#define S3C24XX_UART_CHANNELS	3
+#define S3C24XX_DMA_CHANNELS	4
+#define S3C24XX_SMC_BANKS	8
+
+#ifdef CONFIG_S3C2412
+#define S3C24XX_CPU_NAME	"S3C2412"
+#else
+#define S3C24XX_CPU_NAME	"S3C2413"
+#endif
+
+enum s3c24xx_uarts {
+	S3C24XX_UART0,
+	S3C24XX_UART1,
+	S3C24XX_UART2
+};
+
+enum s3c24xx_dmas {
+	S3C24XX_DMA0,
+	S3C24XX_DMA1,
+	S3C24XX_DMA2,
+	S3C24XX_DMA3
+};
+
+enum s3c24xx_smcs {
+	S3C24XX_SMC0,
+	S3C24XX_SMC1,
+	S3C24XX_SMC2,
+	S3C24XX_SMC3,
+	S3C24XX_SMC4,
+	S3C24XX_SMC5,
+	S3C24XX_SMC6,
+	S3C24XX_SMC7
+};
+
+/* Interrupt Controller */
+struct s3c2412_interrupt {
+	u32 srcpnd;
+	u32 intmod;
+	u32 intmsk;
+	u32 priority;
+	u32 intpnd;
+	u32 intoffset;
+	u32 subsrcpnd;
+	u32 intsubmsk;
+};
+
+/* System Controller */
+struct s3c2412_sysctl {
+	u32 locktime;
+	u32 mpllcon;
+	u32 upllcon;
+	u32 clkcon;
+	u32 _res1;
+	u32 clkdivn;
+	u32 oscset;
+	u32 clksrc;
+	u32 _res2;
+	u32 pwrcfg;
+	u32 _res3[2];
+	u32 swrstcon;
+	u32 rstcon;
+	u32 _res4[13];
+	u32 inform[4];
+};
+
+#define PLLCON_MDIV_GET(x)	(((x)>>12) & 0xFF)
+#define PLLCON_PDIV_GET(x)	(((x)>>4) & 0x3F)
+#define PLLCON_SDIV_GET(x)	(((x)>>0) & 0x3)
+
+#define CLKDIVN_DVS		(1<<4)
+#define CLKDIVN_ARMDIV_GET(x)	(((x)>>3) & 0x1)
+#define CLKDIVN_ARMDIV		(1<<3)
+#define CLKDIVN_PCLKDIV		(1<<2)
+#define CLKDIVN_HCLKDIV_GET(x)	(((x)>>0) & 0x3)
+
+static inline struct s3c2412_interrupt *s3c2412_get_base_interrupt(void)
+{
+	return (struct s3c2412_interrupt *)S3C2412_INTERRUPT_BASE;
+}
+
+static inline struct s3c2412_sysctl *s3c2412_get_base_sysctl(void)
+{
+	return (struct s3c2412_sysctl *)S3C2412_SYSCTL_BASE;
+}
+
+/* Include common stuff */
+#include <asm/arch/s3c24xx.h>
+
+#endif /*__S3C2412_H__*/
diff --git a/arch/arm/include/asm/arch-s3c24xx/s3c2416.h b/arch/arm/include/asm/arch-s3c24xx/s3c2416.h
new file mode 100644
index 0000000..748e7b8
--- /dev/null
+++ b/arch/arm/include/asm/arch-s3c24xx/s3c2416.h
@@ -0,0 +1,183 @@ 
+/*
+ * (C) Copyright 2012 INOV - INESC Inovacao
+ * Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/************************************************
+ * NAME	    : s3c2416.h
+ *
+ * Based on S3C2416 User's manual Rev 1.40
+ ************************************************/
+
+#ifndef __S3C2416_H__
+#define __S3C2416_H__
+
+/* Base addresses for S3C2416 specific modules */
+#define S3C2416_USB_DEVICE_BASE		0x49800000
+#define S3C2416_INTERRUPT_BASE		0x4A000000
+#define S3C2416_HSMMC_BASE		0x4A800000
+#define S3C2416_SYSCTL_BASE		0x4C000000
+#define S3C2416_LCD_BASE		0x4C800000
+#define S3C2416_HSSPI_BASE		0x52000000
+#define S3C2416_ADC_BASE		0x58000000
+
+#define S3C24XX_UART_CHANNELS	4
+#define S3C24XX_DMA_CHANNELS	6
+#define S3C24XX_SMC_BANKS	6
+
+#ifdef CONFIG_S3C2416
+#define S3C24XX_CPU_NAME	"S3C2416"
+#else
+#define S3C24XX_CPU_NAME	"S3C2450"
+#endif
+
+enum s3c24xx_uarts {
+	S3C24XX_UART0,
+	S3C24XX_UART1,
+	S3C24XX_UART2,
+	S3C24XX_UART3
+};
+
+enum s3c24xx_dmas {
+	S3C24XX_DMA0,
+	S3C24XX_DMA1,
+	S3C24XX_DMA2,
+	S3C24XX_DMA3,
+	S3C24XX_DMA4,
+	S3C24XX_DMA5
+};
+
+enum s3c24xx_smcs {
+	S3C24XX_SMC0,
+	S3C24XX_SMC1,
+	S3C24XX_SMC2,
+	S3C24XX_SMC3,
+	S3C24XX_SMC4,
+	S3C24XX_SMC5
+};
+
+/* Interrupt Controller */
+struct s3c2416_interrupt {
+	u32 srcpnd1;
+	u32 intmod1;
+	u32 intmsk1;
+	u32 _res1;
+	u32 intpnd1;
+	u32 intoffset1;
+	u32 subsrcpnd;
+	u32 intsubmsk;
+	u32 _res2[4];
+	u32 priority_mode1;
+	u32 priority_update1;
+	u32 _res3[2];
+	u32 srcpnd2;
+	u32 intmod2;
+	u32 intmsk2;
+	u32 _res4;
+	u32 intpnd2;
+	u32 intoffset2;
+	u32 _res5[6];
+	u32 priority_mode2;
+	u32 priority_update2;
+};
+
+/* System Controller */
+struct s3c2416_sysctl {
+	u32 lockcon0;
+	u32 lockcon1;
+	u32 oscset;
+	u32 _res1;
+	u32 mpllcon;
+	u32 _res2;
+	u32 epllcon;
+	u32 epllcon_k;
+	u32 clksrc;
+	u32 clkdiv0;
+	u32 clkdiv1;
+	u32 clkdiv2;
+	u32 hclkcon;
+	u32 pclkcon;
+	u32 sclkcon;
+	u32 _res3;
+	u32 pwrmode;
+	u32 swrst;
+	u32 _res4[2];
+	u32 busprio;
+	u32 _res5[3];
+	u32 pwrcfg;
+	u32 rstcon;
+	u32 rststat;
+	u32 wkupstat;
+	u32 inform[4];
+	u32 uphyctrl;
+	u32 uphypwr;
+	u32 urstcon;
+	u32 uclkcon;
+};
+
+#define MPLLCON_MDIV_MASK	(0x3FF<<14)
+#define MPLLCON_MDIV(x)		((x)<<14)
+#define MPLLCON_MDIV_GET(x)	(((x)>>14) & 0x3FF)
+#define MPLLCON_PDIV_MASK	(0x3F<<5)
+#define MPLLCON_PDIV(x)		((x)<<5)
+#define MPLLCON_PDIV_GET(x)	(((x)>>5) & 0x3F)
+
+#define EPLLCON_MDIV_MASK	(0xFF<<16)
+#define EPLLCON_MDIV(x)		((x)<<16)
+#define EPLLCON_MDIV_GET(x)	(((x)>>16) & 0xFF)
+#define EPLLCON_PDIV_MASK	(0x3F<<8)
+#define EPLLCON_PDIV(x)		((x)<<8)
+#define EPLLCON_PDIV_GET(x)	(((x)>>8) & 0x3F)
+
+#define PLLCON_SDIV_MASK	(0x7<<0)
+#define PLLCON_SDIV(x)		((x)<<0)
+#define PLLCON_SDIV_GET(x)	(((x)>>0) & 0x7)
+
+#define CLKSRC_MSYSCLK_MPLL	(1<<4)
+#define CLKSRC_ESYSCLK_EPLL	(1<<6)
+
+#define CLKDIV0_HCLKDIV_MASK	(0x3<<0)
+#define CLKDIV0_HCLKDIV(x)	((x)<<0)
+#define CLKDIV0_HCLKDIV_GET(x)	(((x)>>0) & 0x3)
+#define CLKDIV0_PCLKDIV		(1<<2)
+#define CLKDIV0_HALFHCLK	(1<<3)
+#define CLKDIV0_PREDIV_MASK	(3<<4)
+#define CLKDIV0_PREDIV(x)	((x)<<4)
+#define CLKDIV0_PREDIV_GET(x)	(((x)>>4) & 0x3)
+#define CLKDIV0_ARMDIV_MASK	(7<<9)
+#define CLKDIV0_ARMDIV(x)	((x)<<9)
+#define CLKDIV0_ARMDIV_GET(x)	(((x)>>9) & 0x7)
+#define CLKDIV0_DVS		(1<<13)
+
+static inline struct s3c2416_interrupt *s3c2416_get_base_interrupt(void)
+{
+	return (struct s3c2416_interrupt *)S3C2416_INTERRUPT_BASE;
+}
+
+static inline struct s3c2416_sysctl *s3c2416_get_base_sysctl(void)
+{
+	return (struct s3c2416_sysctl *)S3C2416_SYSCTL_BASE;
+}
+
+/* Include common stuff */
+#include <asm/arch/s3c24xx.h>
+
+#endif /*__S3C2416_H__*/
diff --git a/arch/arm/include/asm/arch-s3c24xx/s3c24x0_cpu.h b/arch/arm/include/asm/arch-s3c24xx/s3c24x0_cpu.h
new file mode 100644
index 0000000..e54a46b
--- /dev/null
+++ b/arch/arm/include/asm/arch-s3c24xx/s3c24x0_cpu.h
@@ -0,0 +1,41 @@ 
+/*
+ * (C) Copyright 2012 INOV - INESC Inovacao
+ * Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* To be able to use s3c24x0 drivers */
+
+#ifndef __S3C24X0_CPU_H__
+#define __S3C24X0_CPU_H__
+
+#include <asm/arch/s3c24xx_cpu.h>
+
+#define s3c24x0_rtc s3c24xx_rtc
+#define s3c24x0_get_base_rtc s3c24xx_get_base_rtc
+
+#define S3C24X0_UART0 S3C24XX_UART0
+#define S3C24X0_UART1 S3C24XX_UART1
+#define S3C24X0_UART2 S3C24XX_UART2
+#define S3C24X0_UART3 S3C24XX_UART3
+#define s3c24x0_uart s3c24xx_uart
+#define s3c24x0_get_base_uart s3c24xx_get_base_uart
+
+#endif
diff --git a/arch/arm/include/asm/arch-s3c24xx/s3c24xx.h b/arch/arm/include/asm/arch-s3c24xx/s3c24xx.h
new file mode 100644
index 0000000..78c6941
--- /dev/null
+++ b/arch/arm/include/asm/arch-s3c24xx/s3c24xx.h
@@ -0,0 +1,615 @@ 
+/*
+ * (C) Copyright 2012 INOV - INESC Inovacao
+ * Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/******************************************************
+ * NAME	    : s3c24xx.h
+ *
+ * Common stuff for SAMSUNG S3C24XX SoC (ARM926EJ core)
+ ******************************************************/
+
+#ifndef __S3C24XX_H__
+#define __S3C24XX_H__
+
+/* Base addresses for S3C24XX common modules */
+#define S3C24XX_DRAMCTL_BASE		0x48000000
+#define S3C24XX_USB_HOST_BASE		0x49000000
+#define S3C24XX_DMA_BASE		0x4B000000
+#define S3C24XX_NAND_BASE		0x4E000000
+#define S3C24XX_SMC_BASE		0x4F000000
+#define S3C24XX_UART_BASE		0x50000000
+#define S3C24XX_TIMER_BASE		0x51000000
+#define S3C24XX_WATCHDOG_BASE		0x53000000
+#define S3C24XX_I2C_BASE		0x54000000
+#define S3C24XX_I2S_BASE		0x55000000
+#define S3C24XX_GPIO_BASE		0x56000000
+#define S3C24XX_RTC_BASE		0x57000000
+#define S3C24XX_ADC_BASE		0x58000000
+
+/* Mobile DRAM Controller */
+struct s3c24xx_dramctl {
+	u32 bankcfg;
+	u32 bankcon1;
+	u32 bankcon2;
+	u32 bankcon3;
+	u32 refresh;
+	u32 timeout;
+};
+
+#define BANKCFG_VAL_DDR2		0x00049253
+
+#define BANKCON1_VAL_DDR2		0x44000040
+#define BANKCON1_INIT_NORMAL		0x0
+#define BANKCON1_INIT_PALL		0x1
+#define BANKCON1_INIT_MRS		0x2
+#define BANKCON1_INIT_EMRS		0x3
+
+#define BANKCON2_VAL_DDR2		0x005D0035
+
+#define BANKCON3_VAL_EMRS1		0x44000000
+#define BANKCON3_EMRS1_CAS3		(3<<4)
+#define BANKCON3_EMRS1_OCD7		(7<<23)
+#define BANKCON3_VAL_EMRS2		0x80000000
+#define BANKCON3_VAL_EMRS3		0xC0000000
+#define BANKCON3_VAL_MRS		0x44000030
+#define BANKCON3_MRS_DLL_RESET		(1<<8)
+
+/* USB Host Controller */
+struct s3c24xx_usb_host {
+	u32 HcRevision;
+	u32 HcControl;
+	u32 HcCommonStatus;
+	u32 HcInterruptStatus;
+	u32 HcInterruptEnable;
+	u32 HcInterruptDisable;
+	u32 HcHCCA;
+	u32 HcPeriodCuttendED;
+	u32 HcControlHeadED;
+	u32 HcControlCurrentED;
+	u32 HcBulkHeadED;
+	u32 HcBuldCurrentED;
+	u32 HcDoneHead;
+	u32 HcRmInterval;
+	u32 HcFmRemaining;
+	u32 HcFmNumber;
+	u32 HcPeriodicStart;
+	u32 HcLSThreshold;
+	u32 HcRhDescriptorA;
+	u32 HcRhDescriptorB;
+	u32 HcRhStatus;
+	u32 HcRhPortStatus1;
+	u32 HcRhPortStatus2;
+};
+
+/* DMA Controller */
+struct s3c24xx_dma {
+	u32 disrc;
+	u32 disrcc;
+	u32 didst;
+	u32 didstc;
+	u32 dcon;
+	u32 dstat;
+	u32 dcsrc;
+	u32 dcdst;
+	u32 dmasktrig;
+	u32 dmareqsel0;
+};
+
+/* NAND Flash Controller */
+struct s3c24xx_nand {
+	u32 nfconf;
+	u32 nfcont;
+	u32 nfcmmd;
+	u32 nfaddr;
+	u32 nfdata;
+	u32 nfmeccd[2];
+	u32 nfseccd;
+	u32 nfsblk;
+	u32 nfeblk;
+	u32 nfstat;
+	u32 nfeccerr[2];
+	u32 nfmecc[2];
+	u32 nfsecc;
+	u32 nfmlcbitpt;
+#if !(defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413))
+	u32 nf8eccerr[3];
+	u32 nfm8ecc[4];
+	u32 nfmlc8bitpt[2];
+#endif
+};
+
+#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413)
+#define NFCONF_ECCTYPE_MASK	(1<<24)
+#define NFCONF_ECCTYPE_1BIT	(0<<24)
+#define NFCONF_ECCTYPE_4BIT	(1<<24)
+#else
+#define NFCONF_ECCTYPE_MASK	(3<<23)
+#define NFCONF_ECCTYPE_1BIT	(0<<23)
+#define NFCONF_ECCTYPE_8BIT	(1<<23)
+#define NFCONF_ECCTYPE_4BIT	(2<<23)
+#endif
+#define NFCONF_TACLS_MASK	(7<<12)
+#define NFCONF_TWRPH0_MASK	(7<<8)
+#define NFCONF_TWRPH1_MASK	(7<<4)
+#define NFCONF_TACLS(x)		((x)<<12)
+#define NFCONF_TWRPH0(x)	((x)<<8)
+#define NFCONF_TWRPH1(x)	((x)<<4)
+
+#define NFCONT_ENABLE		(1<<0)
+#define NFCONT_NCE0		(1<<1)
+#define NFCONT_NCE1		(1<<2)
+#define NFCONT_INITSECC		(1<<4)
+#define NFCONT_INITMECC		(1<<5)
+#define NFCONT_SECCLOCK		(1<<6)
+#define NFCONT_MECCLOCK		(1<<7)
+#define NFCONT_WP		(1<<16)
+#define NFCONT_ECC_ENC		(1<<18)
+
+#define NFSTAT_RNB		(1<<0)
+
+/* SMC */
+struct s3c24xx_smc {
+	u32 smbidcy;
+	u32 smbwstrd;
+	u32 smbwstwr;
+	u32 smbwstoen;
+	u32 smbwstwen;
+	u32 smbc;
+	u32 smbs;
+	u32 smbwstbrd;
+};
+
+#define SMBC_RBLE		(1<<0)
+#define SMBC_WAIT_POL		(1<<1)
+#define SMBC_WAIT_EN		(1<<2)
+#define SMBC_MW_MASK		(0x3<<4)
+#define SMBC_MW_16BIT		(1<<4)
+#define SMBC_MW_8BIT		(0<<4)
+#define SMBC_DRNCS		(1<<7)
+#define SMBC_RSMAVD_RD		(1<<12)
+#define SMBC_DRNOWE		(1<<15)
+#define SMBC_RSMAVD_WR		(1<<20)
+
+/* UART */
+struct s3c24xx_uart {
+	u32 ulcon;
+	u32 ucon;
+	u32 ufcon;
+	u32 umcon;
+	u32 utrstat;
+	u32 uerstat;
+	u32 ufstat;
+	u32 umstat;
+#ifdef __BIG_ENDIAN
+	u8 _res1[3];
+	u8 utxh;
+	u8 _res2[3];
+	u8 urxh;
+#else				/* Little Endian */
+	u8 utxh;
+	u8 _res1[3];
+	u8 urxh;
+	u8 _res2[3];
+#endif
+	u32 ubrdiv;
+	u32 udivslot;
+};
+
+#define ULCON_8N1		0x03
+
+#define UCON_POLL		0x005
+
+#define UMCON_NOAFC		0
+
+#define UFCON_FIFOMODE		(1<<0)
+#define UFCON_RESETRX		(1<<1)
+#define UFCON_RESETTX		(1<<2)
+
+#define UTRSTAT_RXDR		(1<<0)
+#define UTRSTAT_TXFE		(1<<1)
+#define UTRSTAT_TXE		(1<<2)
+
+/* PWM Timer */
+struct s3c24xx_timer {
+	u32 tcntb;
+	u32 tcmpb;
+	u32 tcnto;
+};
+
+struct s3c24xx_timers {
+	u32 tcfg0;
+	u32 tcfg1;
+	u32 tcon;
+	struct s3c24xx_timer ch[4];
+	u32 tcntb4;
+	u32 tcnto4;
+};
+
+#define TCFG0_PRESCALER1_MASK	(0xFF<<8)
+#define TCFG0_PRESCALER1(x)	((x)<<8)
+
+#define TCFG1_MUX4_DIV2		(0<<16)
+#define TCFG1_MUX4_DIV4		(1<<16)
+#define TCFG1_MUX4_DIV8		(2<<16)
+#define TCFG1_MUX4_DIV16	(3<<16)
+#define TCFG1_MUX4_TCLK1	(4<<16)
+#define TCFG1_MUX4_MASK		(0xF<<16)
+
+#define TCON_T4START		(1<<20)
+#define TCON_T4MANUALUPD	(1<<21)
+#define TCON_T4RELOAD		(1<<22)
+
+/* Watchdog Timer */
+struct s3c24xx_watchdog {
+	u32 wtcon;
+	u32 wtdat;
+	u32 wtcnt;
+};
+
+#define WTCON_DISABLE_VAL	0
+#define WTCON_RSTEN		(1<<0)
+#define WTCON_INTEN		(1<<2)
+#define WTCON_ENABLE		(1<<5)
+
+/* IIC-Bus Interface */
+struct s3c24xx_i2c {
+	u32 iiccon;
+	u32 iicstat;
+	u32 iicadd;
+	u32 iicds;
+	u32 iiclc;
+};
+
+/* IIS-Bus Interface */
+struct s3c24xx_i2s {
+	u32 iiscon;
+	u32 iismod;
+	u32 iisfic;
+	u32 iispsr;
+	u32 iistxd;
+	u32 iisrxd;
+};
+
+/* I/O Ports */
+struct s3c24xx_gpio {
+#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413)
+	u32 gpacon;
+	u32 gpadat;
+	u32 _res1[2];
+	u32 gpbcon;
+	u32 gpbdat;
+	u32 gpbdn;
+	u32 gpbslpcon;
+	u32 gpccon;
+	u32 gpcdat;
+	u32 gpcdn;
+	u32 gpcslpcon;
+	u32 gpdcon;
+	u32 gpddat;
+	u32 gpddn;
+	u32 gpdslpcon;
+	u32 gpecon;
+	u32 gpedat;
+	u32 gpedn;
+	u32 gpeslpcon;
+	u32 gpfcon;
+	u32 gpfdat;
+	u32 gpfdn;
+	u32 _res2;
+	u32 gpgcon;
+	u32 gpgdat;
+	u32 gpgdn;
+	u32 gpgslpcon;
+	u32 gphcon;
+	u32 gphdat;
+	u32 gphdn;
+	u32 gphslpcon;
+	u32 gpjcon;
+	u32 gpjdat;
+	u32 gpjdn;
+	u32 gpjslpcon;
+
+	u32 misccr;
+	u32 dclkcon;
+	u32 extint[3];
+	u32 eintflt[4];
+	u32 eintmask;
+	u32 eintpend;
+	u32 gstatus[6];
+	u32 mstcon;
+	u32 mslcon;
+	u32 dsc[2];
+#else
+	u32 gpacon;
+	u32 gpadat;
+	u32 _res1[2];
+	u32 gpbcon;
+	u32 gpbdat;
+	u32 gpbudp;
+	u32 gpbsel;
+	u32 gpccon;
+	u32 gpcdat;
+	u32 gpcudp;
+	u32 _res2;
+	u32 gpdcon;
+	u32 gpddat;
+	u32 gpdudp;
+	u32 _res3;
+	u32 gpecon;
+	u32 gpedat;
+	u32 gpeudp;
+	u32 gpesel;
+	u32 gpfcon;
+	u32 gpfdat;
+	u32 gpfudp;
+	u32 _res4;
+	u32 gpgcon;
+	u32 gpgdat;
+	u32 gpgudp;
+	u32 _res5;
+	u32 gphcon;
+	u32 gphdat;
+	u32 gphudp;
+	u32 _res6;
+
+	u32 misccr;
+	u32 dclkcon;
+	u32 extint[3];
+	u32 _res7[2];
+	u32 eintflt2;
+	u32 eintflt3;
+	u32 eintmask;
+	u32 eintpend;
+	u32 gstatus[2];
+	u32 _res8[3];
+	u32 dsc[4];
+
+	u32 gpjcon;
+	u32 gpjdat;
+	u32 gpjudp;
+	u32 gpjsel;
+	u32 gpkcon;
+	u32 gpkdat;
+	u32 gpkudp;
+	u32 _res9;
+	u32 gplcon;
+	u32 gpldat;
+	u32 gpludp;
+	u32 gplsel;
+	u32 gpmcon;
+	u32 gpmdat;
+	u32 gpmudp;
+	u32 _res10;
+
+	u32 dsc3;
+	u32 pddmcon;
+	u32 pdsmcon;
+#endif
+};
+
+#define GPACON_NRCS1		(1<<12)
+#define GPACON_CLE		(1<<17)
+#define GPACON_ALE		(1<<18)
+#define GPACON_NFWE		(1<<19)
+#define GPACON_NFRE		(1<<20)
+#define GPACON_NRSTOUT		(1<<21)
+#define GPACON_NFCE		(1<<22)
+
+#define GPCCON_MASK(x)		(0x3 << ((x) * 2))
+#define GPCCON_OUTPUT(x)	(0x1 << ((x) * 2))
+#define GPCDAT(x)		(1 << (x))
+
+#define GPHCON_MASK(x)		(0x3 << ((x) * 2))
+#define GPHCON_TXD(x)		(0x2 << ((x) * 4))
+#define GPHCON_RXD(x)		(0x2 << (((x) * 4) + 2))
+
+/* RTC */
+struct s3c24xx_rtc {
+#ifdef __BIG_ENDIAN
+	u8 _res1[67];
+	u8 rtccon;
+	u8 _res2[3];
+	u8 ticnt0;
+#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413)
+	u8 _res3[4];
+#else
+	u8 _res3[3];
+	u8 ticnt2;
+#endif
+	u8 _res4[3];
+	u8 ticnt1;
+	u8 _res5[3];
+	u8 rtcalm;
+	u8 _res6[3];
+	u8 almsec;
+	u8 _res7[3];
+	u8 almmin;
+	u8 _res8[3];
+	u8 almhour;
+	u8 _res9[3];
+	u8 almdate;
+	u8 _res10[3];
+	u8 almmon;
+	u8 _res11[3];
+	u8 almyear;
+	u8 _res12[7];
+	u8 bcdsec;
+	u8 _res13[3];
+	u8 bcdmin;
+	u8 _res14[3];
+	u8 bcdhour;
+	u8 _res15[3];
+	u8 bcddate;
+	u8 _res16[3];
+	u8 bcdday;
+	u8 _res17[3];
+	u8 bcdmon;
+	u8 _res18[3];
+	u8 bcdyear;
+#if !(defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413))
+	u8 _res19[3];
+	u8 tickcnt;
+#endif
+#else				/*  little endian */
+	u8 _res0[64];
+	u8 rtccon;
+	u8 _res1[3];
+	u8 ticnt0;
+	u8 _res2[3];
+#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413)
+	u8 _res3[4];
+#else
+	u8 ticnt2;
+	u8 _res3[3];
+#endif
+	u8 ticnt1;
+	u8 _res4[3];
+	u8 rtcalm;
+	u8 _res5[3];
+	u8 almsec;
+	u8 _res6[3];
+	u8 almmin;
+	u8 _res7[3];
+	u8 almhour;
+	u8 _res8[3];
+	u8 almdate;
+	u8 _res9[3];
+	u8 almmon;
+	u8 _res10[3];
+	u8 almyear;
+	u8 _res11[7];
+	u8 bcdsec;
+	u8 _res12[3];
+	u8 bcdmin;
+	u8 _res13[3];
+	u8 bcdhour;
+	u8 _res14[3];
+	u8 bcddate;
+	u8 _res15[3];
+	u8 bcdday;
+	u8 _res16[3];
+	u8 bcdmon;
+	u8 _res17[3];
+	u8 bcdyear;
+	u8 _res18[3];
+#if !(defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413))
+	u8 tickcnt;
+	u8 _res19[3];
+#endif
+#endif
+};
+
+#define RTCCON_RTCEN	(1<<0)
+#define RTCCON_CNTSEL	(1<<2)
+#define RTCCON_CLKRST	(1<<3)
+#define RTCCON_TICSEL	(1<<4)
+
+/* ADC & Touch Screen Interface */
+struct s3c24xx_adc {
+	u32 adccon;
+	u32 adctsc;
+	u32 adcdly;
+	u32 adcdat0;
+	u32 adcdat1;
+#if !(defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413))
+	u32 adcupdn;
+	u32 adcmux;
+#endif
+};
+
+static inline struct s3c24xx_dramctl *s3c24xx_get_base_dramctl(void)
+{
+	return (struct s3c24xx_dramctl *)S3C24XX_DRAMCTL_BASE;
+}
+
+static inline struct s3c24xx_usb_host *s3c24xx_get_base_usb_host(void)
+{
+	return (struct s3c24xx_usb_host *)S3C24XX_USB_HOST_BASE;
+}
+
+static inline struct s3c24xx_dma *s3c24xx_get_base_dma(enum s3c24xx_dmas n)
+{
+#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413)
+	return (struct s3c24xx_dma *)(S3C24XX_DMA_BASE + (n * 0x40));
+#else
+	return (struct s3c24xx_dma *)(S3C24XX_DMA_BASE + (n * 0x100));
+#endif
+}
+
+static inline struct s3c24xx_nand *s3c24xx_get_base_nand(void)
+{
+	return (struct s3c24xx_nand *)S3C24XX_NAND_BASE;
+}
+
+static inline struct s3c24xx_smc *s3c24xx_get_base_smc(enum s3c24xx_smcs n)
+{
+	return (struct s3c24xx_smc *)(S3C24XX_SMC_BASE + (n * 0x20));
+}
+
+static inline struct s3c24xx_uart *s3c24xx_get_base_uart(enum s3c24xx_uarts n)
+{
+	return (struct s3c24xx_uart *)(S3C24XX_UART_BASE + (n * 0x4000));
+}
+
+static inline struct s3c24xx_timers *s3c24xx_get_base_timers(void)
+{
+	return (struct s3c24xx_timers *)S3C24XX_TIMER_BASE;
+}
+
+static inline struct s3c24xx_watchdog *s3c24xx_get_base_watchdog(void)
+{
+	return (struct s3c24xx_watchdog *)S3C24XX_WATCHDOG_BASE;
+}
+
+static inline struct s3c24xx_i2c *s3c24xx_get_base_i2c(void)
+{
+	return (struct s3c24xx_i2c *)S3C24XX_I2C_BASE;
+}
+
+static inline struct s3c24xx_i2s *s3c24xx_get_base_i2s(void)
+{
+	return (struct s3c24xx_i2s *)S3C24XX_I2S_BASE;
+}
+
+static inline struct s3c24xx_gpio *s3c24xx_get_base_gpio(void)
+{
+	return (struct s3c24xx_gpio *)S3C24XX_GPIO_BASE;
+}
+
+static inline struct s3c24xx_rtc *s3c24xx_get_base_rtc(void)
+{
+	return (struct s3c24xx_rtc *)S3C24XX_RTC_BASE;
+}
+
+static inline struct s3c24xx_adc *s3c24xx_get_base_adc(void)
+{
+	return (struct s3c24xx_adc *)S3C24XX_ADC_BASE;
+}
+
+static inline char *s3c24xx_get_cpu_name(void)
+{
+	return S3C24XX_CPU_NAME;
+}
+
+extern ulong get_ARMCLK(void);
+
+#endif /*__S3C24XX_H__*/
diff --git a/arch/arm/include/asm/arch-s3c24xx/s3c24xx_cpu.h b/arch/arm/include/asm/arch-s3c24xx/s3c24xx_cpu.h
new file mode 100644
index 0000000..59ccfd4
--- /dev/null
+++ b/arch/arm/include/asm/arch-s3c24xx/s3c24xx_cpu.h
@@ -0,0 +1,30 @@ 
+/*
+ * (C) Copyright 2012 INOV - INESC Inovacao
+ * Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2413)
+#include <asm/arch/s3c2412.h>
+#elif defined(CONFIG_S3C2416) || defined(CONFIG_S3C2450)
+#include <asm/arch/s3c2416.h>
+#else
+#error Please define the S3C24XX SoC type
+#endif
diff --git a/arch/arm/include/asm/arch-s3c24xx/spl.h b/arch/arm/include/asm/arch-s3c24xx/spl.h
new file mode 100644
index 0000000..2741fe7
--- /dev/null
+++ b/arch/arm/include/asm/arch-s3c24xx/spl.h
@@ -0,0 +1,29 @@ 
+/*
+ * (C) Copyright 2012 INOV - INESC Inovacao
+ * Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef	_ASM_ARCH_SPL_H_
+#define	_ASM_SPL_H_
+
+#define BOOT_DEVICE_NAND	1
+#define BOOT_DEVICE_MMC1	2
+
+#endif
diff --git a/include/common.h b/include/common.h
index c10d745..b63e814 100644
--- a/include/common.h
+++ b/include/common.h
@@ -628,6 +628,7 @@  ulong	get_OPB_freq (void);
 ulong	get_PCI_freq (void);
 #endif
 #if defined(CONFIG_S3C24X0) || \
+    defined(CONFIG_S3C24XX) || \
     defined(CONFIG_LH7A40X) || \
     defined(CONFIG_S3C6400) || \
     defined(CONFIG_EP93XX)