diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index b6722decff9d7c3c08d369175808a50db2a605d7..2dad16c8cf79f952a56f2e86c4f3f5d38db144f8 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -20,6 +20,11 @@ config SOC_EXYNOS4212
 	help
 	  Enable EXYNOS4212 SoC support
 
+config SOC_EXYNOS4412
+	bool
+	help
+	  Enable EXYNOS4412 SoC support
+
 config EXYNOS4_MCT
 	bool
 	default y
@@ -276,6 +281,15 @@ config MACH_SMDK4212
 	help
 	  Machine support for Samsung SMDK4212
 
+comment "EXYNOS4412 Boards"
+
+config MACH_SMDK4412
+	bool "SMDK4412"
+	select SOC_EXYNOS4412
+	select MACH_SMDK4212
+	help
+	  Machine support for Samsung SMDK4412
+
 endmenu
 
 comment "Configuration for HSMMC bus width"
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
index e19cd12d264e11f772316d4e145f9a0289d4b25c..c9b2e1f97e44b4e1852e5159d2d3bc8263b6b4d9 100644
--- a/arch/arm/mach-exynos4/Makefile
+++ b/arch/arm/mach-exynos4/Makefile
@@ -34,7 +34,8 @@ obj-$(CONFIG_MACH_UNIVERSAL_C210)	+= mach-universal_c210.o
 obj-$(CONFIG_MACH_NURI)			+= mach-nuri.o
 obj-$(CONFIG_MACH_ORIGEN)		+= mach-origen.o
 
-obj-$(CONFIG_MACH_SMDK4212)		+= mach-smdk4212.o
+obj-$(CONFIG_MACH_SMDK4212)		+= mach-smdk4x12.o
+obj-$(CONFIG_MACH_SMDK4412)		+= mach-smdk4x12.o
 
 # device support
 
diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index a25c818367590dc7345c655567737f33b624f650..db616916d7a4b012085ef0f46300ad27026ee5f4 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -1283,7 +1283,7 @@ static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
 	if (soc_is_exynos4210())
 		return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0),
 					pll_4508);
-	else if (soc_is_exynos4212())
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
 		return s5p_get_pll35xx(xtal_rate, __raw_readl(S5P_APLL_CON0));
 	else
 		return 0;
@@ -1399,7 +1399,7 @@ void __init_or_cpufreq exynos4_setup_clocks(void)
 		vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
 		vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
 					__raw_readl(S5P_VPLL_CON1), pll_4650c);
-	} else if (soc_is_exynos4212()) {
+	} else if (soc_is_exynos4212() || soc_is_exynos4412()) {
 		apll = s5p_get_pll35xx(xtal, __raw_readl(S5P_APLL_CON0));
 		mpll = s5p_get_pll35xx(xtal, __raw_readl(S5P_MPLL_CON0));
 		epll = s5p_get_pll36xx(xtal, __raw_readl(S5P_EPLL_CON0),
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 2aa3df00368391c1e94c6a114323322539af7bd5..5b1765b37f75bb6c89acd6b121aed27409a204e5 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -33,6 +33,8 @@
 #include <mach/regs-irq.h>
 #include <mach/regs-pmu.h>
 
+unsigned int gic_bank_offset __read_mostly;
+
 extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
 			 unsigned int irq_start);
 extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
@@ -193,27 +195,34 @@ void __init exynos4_init_clocks(int xtal)
 
 	if (soc_is_exynos4210())
 		exynos4210_register_clocks();
-	else if (soc_is_exynos4212())
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
 		exynos4212_register_clocks();
 
 	exynos4_register_clocks();
 	exynos4_setup_clocks();
 }
 
-static void exynos4_gic_irq_eoi(struct irq_data *d)
+static void exynos4_gic_irq_fix_base(struct irq_data *d)
 {
 	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
 
 	gic_data->cpu_base = S5P_VA_GIC_CPU +
-			    (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+			    (gic_bank_offset * smp_processor_id());
+
+	gic_data->dist_base = S5P_VA_GIC_DIST +
+			    (gic_bank_offset * smp_processor_id());
 }
 
 void __init exynos4_init_irq(void)
 {
 	int irq;
 
-	gic_init(0, IRQ_SPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
-	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
+	gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
+
+	gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+	gic_arch_extn.irq_eoi = exynos4_gic_irq_fix_base;
+	gic_arch_extn.irq_unmask = exynos4_gic_irq_fix_base;
+	gic_arch_extn.irq_mask = exynos4_gic_irq_fix_base;
 
 	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
 
@@ -252,7 +261,7 @@ static int __init exynos4_l2x0_cache_init(void)
 
 	if (soc_is_exynos4210())
 		__raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
-	else if (soc_is_exynos4212())
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
 		__raw_writel(0x120, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
 
 	/* L2X0 Prefetch Control */
diff --git a/arch/arm/mach-exynos4/include/mach/entry-macro.S b/arch/arm/mach-exynos4/include/mach/entry-macro.S
index d7a1e281ce7a98f437b65da2f33328b1629b5458..4c9adbd87eac864e16fd77b72f9c3b4a9f9c5c45 100644
--- a/arch/arm/mach-exynos4/include/mach/entry-macro.S
+++ b/arch/arm/mach-exynos4/include/mach/entry-macro.S
@@ -17,12 +17,25 @@
 		.endm
 
 		.macro  get_irqnr_preamble, base, tmp
-		ldr	\base, =gic_cpu_base_addr
+		mov	\tmp, #0
+
+		mrc	p15, 0, \base, c0, c0, 5
+		and	\base, \base, #3
+		cmp	\base, #0
+		beq	1f
+
+		ldr	\tmp, =gic_bank_offset
+		ldr	\tmp, [\tmp]
+		cmp	\base, #1
+		beq	1f
+
+		cmp	\base, #2
+		addeq	\tmp, \tmp, \tmp
+		addne	\tmp, \tmp, \tmp, LSL #1
+
+1:		ldr	\base, =gic_cpu_base_addr
 		ldr	\base, [\base]
-		mrc     p15, 0, \tmp, c0, c0, 5
-		and     \tmp, \tmp, #3
-		cmp     \tmp, #1
-		addeq   \base, \base, #EXYNOS4_GIC_BANK_OFFSET
+		add	\base, \base, \tmp
 		.endm
 
 		.macro  arch_ret_to_user, tmp1, tmp2
@@ -80,4 +93,10 @@
 		/* As above, this assumes that irqstat and base are preserved.. */
 
 		.macro test_for_ltirq, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		mov	\tmp, #0
+		cmp	\irqnr, #28
+		moveq	\tmp, #1
+		streq	\irqstat, [\base, #GIC_CPU_EOI]
+		cmp	\tmp, #0
 		.endm
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index 62093b9339db57ef4b980284694b045ba02164b6..dfd4b7eecb9076f8d00716f4a41223acae094b92 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -19,6 +19,8 @@
 
 #define IRQ_PPI(x)		S5P_IRQ(x+16)
 
+#define IRQ_MCT_LOCALTIMER	IRQ_PPI(12)
+
 /* SPI: Shared Peripheral Interrupt */
 
 #define IRQ_SPI(x)		S5P_IRQ(x+32)
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index 1bea7d139bb0f3c0f38981658e78c7ccfdc009f0..918a979181af9a786c439720cc8f970ec651f6eb 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -62,7 +62,6 @@
 
 #define EXYNOS4_PA_GIC_CPU		0x10480000
 #define EXYNOS4_PA_GIC_DIST		0x10490000
-#define EXYNOS4_GIC_BANK_OFFSET		0x8000
 
 #define EXYNOS4_PA_COREPERI		0x10500000
 #define EXYNOS4_PA_TWD			0x10500600
diff --git a/arch/arm/mach-exynos4/include/mach/regs-mct.h b/arch/arm/mach-exynos4/include/mach/regs-mct.h
index ca9c8434b0234a259b8ad4e785f9a4617e7ef5af..80dd02ad6d619072d16a94ca7a3034ff074d7aac 100644
--- a/arch/arm/mach-exynos4/include/mach/regs-mct.h
+++ b/arch/arm/mach-exynos4/include/mach/regs-mct.h
@@ -31,8 +31,9 @@
 #define EXYNOS4_MCT_G_INT_ENB		EXYNOS4_MCTREG(0x248)
 #define EXYNOS4_MCT_G_WSTAT		EXYNOS4_MCTREG(0x24C)
 
-#define EXYNOS4_MCT_L0_BASE		EXYNOS4_MCTREG(0x300)
-#define EXYNOS4_MCT_L1_BASE		EXYNOS4_MCTREG(0x400)
+#define _EXYNOS4_MCT_L_BASE		EXYNOS4_MCTREG(0x300)
+#define EXYNOS4_MCT_L_BASE(x)		(_EXYNOS4_MCT_L_BASE + (0x100 * x))
+#define EXYNOS4_MCT_L_MASK		(0xffffff00)
 
 #define MCT_L_TCNTB_OFFSET		(0x00)
 #define MCT_L_ICNTB_OFFSET		(0x08)
diff --git a/arch/arm/mach-exynos4/mach-origen.c b/arch/arm/mach-exynos4/mach-origen.c
index 18909cf6c07d5b3b59be678d43719e6565819485..71db8480bb5a9261de8c57770efa72c391745bc3 100644
--- a/arch/arm/mach-exynos4/mach-origen.c
+++ b/arch/arm/mach-exynos4/mach-origen.c
@@ -671,7 +671,7 @@ static void __init origen_machine_init(void)
 
 MACHINE_START(ORIGEN, "ORIGEN")
 	/* Maintainer: JeongHyeon Kim <jhkim@insignal.co.kr> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= exynos4_init_irq,
 	.map_io		= origen_map_io,
 	.init_machine	= origen_machine_init,
diff --git a/arch/arm/mach-exynos4/mach-smdk4212.c b/arch/arm/mach-exynos4/mach-smdk4x12.c
similarity index 61%
rename from arch/arm/mach-exynos4/mach-smdk4212.c
rename to arch/arm/mach-exynos4/mach-smdk4x12.c
index 3479a933a6de4079c1953039a27b3225c0f74a17..fcf2e0e23d53f31d98a760e9c11610a62642765e 100644
--- a/arch/arm/mach-exynos4/mach-smdk4212.c
+++ b/arch/arm/mach-exynos4/mach-smdk4x12.c
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-exynos4/mach-smdk4212.c
+ * linux/arch/arm/mach-exynos4/mach-smdk4x12.c
  *
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
@@ -37,51 +37,51 @@
 #include <mach/map.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDK4212_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+#define SMDK4X12_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				 S3C2410_UCON_RXILEVEL |	\
 				 S3C2410_UCON_TXIRQMODE |	\
 				 S3C2410_UCON_RXIRQMODE |	\
 				 S3C2410_UCON_RXFIFO_TOI |	\
 				 S3C2443_UCON_RXERR_IRQEN)
 
-#define SMDK4212_ULCON_DEFAULT	S3C2410_LCON_CS8
+#define SMDK4X12_ULCON_DEFAULT	S3C2410_LCON_CS8
 
-#define SMDK4212_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+#define SMDK4X12_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
 				 S5PV210_UFCON_TXTRIG4 |	\
 				 S5PV210_UFCON_RXTRIG4)
 
-static struct s3c2410_uartcfg smdk4212_uartcfgs[] __initdata = {
+static struct s3c2410_uartcfg smdk4x12_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport		= 0,
 		.flags		= 0,
-		.ucon		= SMDK4212_UCON_DEFAULT,
-		.ulcon		= SMDK4212_ULCON_DEFAULT,
-		.ufcon		= SMDK4212_UFCON_DEFAULT,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
 	},
 	[1] = {
 		.hwport		= 1,
 		.flags		= 0,
-		.ucon		= SMDK4212_UCON_DEFAULT,
-		.ulcon		= SMDK4212_ULCON_DEFAULT,
-		.ufcon		= SMDK4212_UFCON_DEFAULT,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
 	},
 	[2] = {
 		.hwport		= 2,
 		.flags		= 0,
-		.ucon		= SMDK4212_UCON_DEFAULT,
-		.ulcon		= SMDK4212_ULCON_DEFAULT,
-		.ufcon		= SMDK4212_UFCON_DEFAULT,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
 	},
 	[3] = {
 		.hwport		= 3,
 		.flags		= 0,
-		.ucon		= SMDK4212_UCON_DEFAULT,
-		.ulcon		= SMDK4212_ULCON_DEFAULT,
-		.ufcon		= SMDK4212_UFCON_DEFAULT,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
 	},
 };
 
-static struct s3c_sdhci_platdata smdk4212_hsmmc2_pdata __initdata = {
+static struct s3c_sdhci_platdata smdk4x12_hsmmc2_pdata __initdata = {
 	.cd_type		= S3C_SDHCI_CD_INTERNAL,
 	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 #ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
@@ -90,7 +90,7 @@ static struct s3c_sdhci_platdata smdk4212_hsmmc2_pdata __initdata = {
 #endif
 };
 
-static struct s3c_sdhci_platdata smdk4212_hsmmc3_pdata __initdata = {
+static struct s3c_sdhci_platdata smdk4x12_hsmmc3_pdata __initdata = {
 	.cd_type		= S3C_SDHCI_CD_INTERNAL,
 	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
@@ -106,7 +106,7 @@ static struct regulator_consumer_supply max8997_buck3 =
 
 static struct regulator_init_data max8997_buck1_data = {
 	.constraints	= {
-		.name		= "VDD_ARM_SMDK4212",
+		.name		= "VDD_ARM_SMDK4X12",
 		.min_uV		= 925000,
 		.max_uV		= 1350000,
 		.always_on	= 1,
@@ -121,7 +121,7 @@ static struct regulator_init_data max8997_buck1_data = {
 
 static struct regulator_init_data max8997_buck2_data = {
 	.constraints	= {
-		.name		= "VDD_INT_SMDK4212",
+		.name		= "VDD_INT_SMDK4X12",
 		.min_uV		= 950000,
 		.max_uV		= 1150000,
 		.always_on	= 1,
@@ -136,7 +136,7 @@ static struct regulator_init_data max8997_buck2_data = {
 
 static struct regulator_init_data max8997_buck3_data = {
 	.constraints	= {
-		.name		= "VDD_G3D_SMDK4212",
+		.name		= "VDD_G3D_SMDK4X12",
 		.min_uV		= 950000,
 		.max_uV		= 1150000,
 		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
@@ -149,15 +149,15 @@ static struct regulator_init_data max8997_buck3_data = {
 	.consumer_supplies	= &max8997_buck3,
 };
 
-static struct max8997_regulator_data smdk4212_max8997_regulators[] = {
+static struct max8997_regulator_data smdk4x12_max8997_regulators[] = {
 	{ MAX8997_BUCK1, &max8997_buck1_data },
 	{ MAX8997_BUCK2, &max8997_buck2_data },
 	{ MAX8997_BUCK3, &max8997_buck3_data },
 };
 
-static struct max8997_platform_data smdk4212_max8997_pdata = {
-	.num_regulators	= ARRAY_SIZE(smdk4212_max8997_regulators),
-	.regulators	= smdk4212_max8997_regulators,
+static struct max8997_platform_data smdk4x12_max8997_pdata = {
+	.num_regulators	= ARRAY_SIZE(smdk4x12_max8997_regulators),
+	.regulators	= smdk4x12_max8997_regulators,
 
 	.buck1_voltage[0] = 1100000,	/* 1.1V */
 	.buck1_voltage[1] = 1100000,	/* 1.1V */
@@ -187,53 +187,53 @@ static struct max8997_platform_data smdk4212_max8997_pdata = {
 	.buck5_voltage[7] = 1100000,	/* 1.1V */
 };
 
-static struct i2c_board_info smdk4212_i2c_devs0[] __initdata = {
+static struct i2c_board_info smdk4x12_i2c_devs0[] __initdata = {
 	{
 		I2C_BOARD_INFO("max8997", 0x66),
-		.platform_data	= &smdk4212_max8997_pdata,
+		.platform_data	= &smdk4x12_max8997_pdata,
 	}
 };
 
-static struct i2c_board_info smdk4212_i2c_devs1[] __initdata = {
+static struct i2c_board_info smdk4x12_i2c_devs1[] __initdata = {
 	{ I2C_BOARD_INFO("wm8994", 0x1a), }
 };
 
-static struct i2c_board_info smdk4212_i2c_devs3[] __initdata = {
+static struct i2c_board_info smdk4x12_i2c_devs3[] __initdata = {
 	/* nothing here yet */
 };
 
-static struct i2c_board_info smdk4212_i2c_devs7[] __initdata = {
+static struct i2c_board_info smdk4x12_i2c_devs7[] __initdata = {
 	/* nothing here yet */
 };
 
-static struct samsung_bl_gpio_info smdk4212_bl_gpio_info = {
+static struct samsung_bl_gpio_info smdk4x12_bl_gpio_info = {
 	.no = EXYNOS4_GPD0(1),
 	.func = S3C_GPIO_SFN(2),
 };
 
-static struct platform_pwm_backlight_data smdk4212_bl_data = {
+static struct platform_pwm_backlight_data smdk4x12_bl_data = {
 	.pwm_id = 1,
 	.pwm_period_ns  = 1000,
 };
 
-static uint32_t smdk4212_keymap[] __initdata = {
+static uint32_t smdk4x12_keymap[] __initdata = {
 	/* KEY(row, col, keycode) */
 	KEY(1, 0, KEY_D), KEY(1, 1, KEY_A), KEY(1, 2, KEY_B),
 	KEY(1, 3, KEY_E), KEY(1, 4, KEY_C)
 };
 
-static struct matrix_keymap_data smdk4212_keymap_data __initdata = {
-	.keymap		= smdk4212_keymap,
-	.keymap_size	= ARRAY_SIZE(smdk4212_keymap),
+static struct matrix_keymap_data smdk4x12_keymap_data __initdata = {
+	.keymap		= smdk4x12_keymap,
+	.keymap_size	= ARRAY_SIZE(smdk4x12_keymap),
 };
 
-static struct samsung_keypad_platdata smdk4212_keypad_data __initdata = {
-	.keymap_data	= &smdk4212_keymap_data,
+static struct samsung_keypad_platdata smdk4x12_keypad_data __initdata = {
+	.keymap_data	= &smdk4x12_keymap_data,
 	.rows		= 2,
 	.cols		= 5,
 };
 
-static struct platform_device *smdk4212_devices[] __initdata = {
+static struct platform_device *smdk4x12_devices[] __initdata = {
 	&s3c_device_hsmmc2,
 	&s3c_device_hsmmc3,
 	&s3c_device_i2c0,
@@ -245,48 +245,58 @@ static struct platform_device *smdk4212_devices[] __initdata = {
 	&samsung_device_keypad,
 };
 
-static void __init smdk4212_map_io(void)
+static void __init smdk4x12_map_io(void)
 {
 	clk_xusbxti.rate = 24000000;
 
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
 	s3c24xx_init_clocks(clk_xusbxti.rate);
-	s3c24xx_init_uarts(smdk4212_uartcfgs, ARRAY_SIZE(smdk4212_uartcfgs));
+	s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
 }
 
-static void __init smdk4212_machine_init(void)
+static void __init smdk4x12_machine_init(void)
 {
 	s3c_i2c0_set_platdata(NULL);
-	i2c_register_board_info(0, smdk4212_i2c_devs0,
-				ARRAY_SIZE(smdk4212_i2c_devs0));
+	i2c_register_board_info(0, smdk4x12_i2c_devs0,
+				ARRAY_SIZE(smdk4x12_i2c_devs0));
 
 	s3c_i2c1_set_platdata(NULL);
-	i2c_register_board_info(1, smdk4212_i2c_devs1,
-				ARRAY_SIZE(smdk4212_i2c_devs1));
+	i2c_register_board_info(1, smdk4x12_i2c_devs1,
+				ARRAY_SIZE(smdk4x12_i2c_devs1));
 
 	s3c_i2c3_set_platdata(NULL);
-	i2c_register_board_info(3, smdk4212_i2c_devs3,
-				ARRAY_SIZE(smdk4212_i2c_devs3));
+	i2c_register_board_info(3, smdk4x12_i2c_devs3,
+				ARRAY_SIZE(smdk4x12_i2c_devs3));
 
 	s3c_i2c7_set_platdata(NULL);
-	i2c_register_board_info(7, smdk4212_i2c_devs7,
-				ARRAY_SIZE(smdk4212_i2c_devs7));
+	i2c_register_board_info(7, smdk4x12_i2c_devs7,
+				ARRAY_SIZE(smdk4x12_i2c_devs7));
 
-	samsung_bl_set(&smdk4212_bl_gpio_info, &smdk4212_bl_data);
+	samsung_bl_set(&smdk4x12_bl_gpio_info, &smdk4x12_bl_data);
 
-	samsung_keypad_set_platdata(&smdk4212_keypad_data);
+	samsung_keypad_set_platdata(&smdk4x12_keypad_data);
 
-	s3c_sdhci2_set_platdata(&smdk4212_hsmmc2_pdata);
-	s3c_sdhci3_set_platdata(&smdk4212_hsmmc3_pdata);
+	s3c_sdhci2_set_platdata(&smdk4x12_hsmmc2_pdata);
+	s3c_sdhci3_set_platdata(&smdk4x12_hsmmc3_pdata);
 
-	platform_add_devices(smdk4212_devices, ARRAY_SIZE(smdk4212_devices));
+	platform_add_devices(smdk4x12_devices, ARRAY_SIZE(smdk4x12_devices));
 }
 
 MACHINE_START(SMDK4212, "SMDK4212")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= exynos4_init_irq,
-	.map_io		= smdk4212_map_io,
-	.init_machine	= smdk4212_machine_init,
+	.map_io		= smdk4x12_map_io,
+	.init_machine	= smdk4x12_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
+
+MACHINE_START(SMDK4412, "SMDK4412")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdk4x12_map_io,
+	.init_machine	= smdk4x12_machine_init,
 	.timer		= &exynos4_timer,
 MACHINE_END
diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-exynos4/mach-smdkv310.c
index 35a763e9a659b98c764dc2c6adfe2a4be0774349..cec2afabe7b42475e2d1f8585642b048ea7ee34b 100644
--- a/arch/arm/mach-exynos4/mach-smdkv310.c
+++ b/arch/arm/mach-exynos4/mach-smdkv310.c
@@ -372,7 +372,7 @@ static void __init smdkv310_machine_init(void)
 MACHINE_START(SMDKV310, "SMDKV310")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
 	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= exynos4_init_irq,
 	.map_io		= smdkv310_map_io,
 	.init_machine	= smdkv310_machine_init,
@@ -382,7 +382,7 @@ MACHINE_END
 
 MACHINE_START(SMDKC210, "SMDKC210")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= exynos4_init_irq,
 	.map_io		= smdkv310_map_io,
 	.init_machine	= smdkv310_machine_init,
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c
index ddd86864fb8313846428ba75c3ef523ce0508f56..eb182f29f48f8fadf9f0c165c23aaaf422d83305 100644
--- a/arch/arm/mach-exynos4/mct.c
+++ b/arch/arm/mach-exynos4/mct.c
@@ -20,19 +20,31 @@
 #include <linux/delay.h>
 #include <linux/percpu.h>
 
+#include <asm/hardware/gic.h>
+
+#include <plat/cpu.h>
+
 #include <mach/map.h>
+#include <mach/irqs.h>
 #include <mach/regs-mct.h>
 #include <asm/mach/time.h>
 
+enum {
+	MCT_INT_SPI,
+	MCT_INT_PPI
+};
+
 static unsigned long clk_cnt_per_tick;
 static unsigned long clk_rate;
+static unsigned int mct_int_type;
 
 struct mct_clock_event_device {
 	struct clock_event_device *evt;
 	void __iomem *base;
+	char name[10];
 };
 
-struct mct_clock_event_device mct_tick[2];
+struct mct_clock_event_device mct_tick[NR_CPUS];
 
 static void exynos4_mct_write(unsigned int value, void *addr)
 {
@@ -42,57 +54,53 @@ static void exynos4_mct_write(unsigned int value, void *addr)
 
 	__raw_writel(value, addr);
 
-	switch ((u32) addr) {
-	case (u32) EXYNOS4_MCT_G_TCON:
-		stat_addr = EXYNOS4_MCT_G_WSTAT;
-		mask = 1 << 16;		/* G_TCON write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_COMP0_L:
-		stat_addr = EXYNOS4_MCT_G_WSTAT;
-		mask = 1 << 0;		/* G_COMP0_L write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_COMP0_U:
-		stat_addr = EXYNOS4_MCT_G_WSTAT;
-		mask = 1 << 1;		/* G_COMP0_U write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
-		stat_addr = EXYNOS4_MCT_G_WSTAT;
-		mask = 1 << 2;		/* G_COMP0_ADD_INCR write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_CNT_L:
-		stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
-		mask = 1 << 0;		/* G_CNT_L write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_CNT_U:
-		stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
-		mask = 1 << 1;		/* G_CNT_U write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCON_OFFSET):
-		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 3;		/* L0_TCON write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCON_OFFSET):
-		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 3;		/* L1_TCON write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCNTB_OFFSET):
-		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 0;		/* L0_TCNTB write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCNTB_OFFSET):
-		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 0;		/* L1_TCNTB write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_ICNTB_OFFSET):
-		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 1;		/* L0_ICNTB write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_ICNTB_OFFSET):
-		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 1;		/* L1_ICNTB write status */
-		break;
-	default:
-		return;
+	if (likely(addr >= EXYNOS4_MCT_L_BASE(0))) {
+		u32 base = (u32) addr & EXYNOS4_MCT_L_MASK;
+		switch ((u32) addr & ~EXYNOS4_MCT_L_MASK) {
+		case (u32) MCT_L_TCON_OFFSET:
+			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+			mask = 1 << 3;		/* L_TCON write status */
+			break;
+		case (u32) MCT_L_ICNTB_OFFSET:
+			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+			mask = 1 << 1;		/* L_ICNTB write status */
+			break;
+		case (u32) MCT_L_TCNTB_OFFSET:
+			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+			mask = 1 << 0;		/* L_TCNTB write status */
+			break;
+		default:
+			return;
+		}
+	} else {
+		switch ((u32) addr) {
+		case (u32) EXYNOS4_MCT_G_TCON:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 16;		/* G_TCON write status */
+			break;
+		case (u32) EXYNOS4_MCT_G_COMP0_L:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 0;		/* G_COMP0_L write status */
+			break;
+		case (u32) EXYNOS4_MCT_G_COMP0_U:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 1;		/* G_COMP0_U write status */
+			break;
+		case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 2;		/* G_COMP0_ADD_INCR w status */
+			break;
+		case (u32) EXYNOS4_MCT_G_CNT_L:
+			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+			mask = 1 << 0;		/* G_CNT_L write status */
+			break;
+		case (u32) EXYNOS4_MCT_G_CNT_U:
+			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+			mask = 1 << 1;		/* G_CNT_U write status */
+			break;
+		default:
+			return;
+		}
 	}
 
 	/* Wait maximum 1 ms until written values are applied */
@@ -321,9 +329,8 @@ static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
 	}
 }
 
-static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
+static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
 {
-	struct mct_clock_event_device *mevt = dev_id;
 	struct clock_event_device *evt = mevt->evt;
 
 	/*
@@ -335,7 +342,20 @@ static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
 		exynos4_mct_tick_stop(mevt);
 
 	/* Clear the MCT tick interrupt */
-	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+	if (__raw_readl(mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
+		exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
+{
+	struct mct_clock_event_device *mevt = dev_id;
+	struct clock_event_device *evt = mevt->evt;
+
+	exynos4_mct_tick_clear(mevt);
 
 	evt->event_handler(evt);
 
@@ -360,14 +380,10 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
 
 	mct_tick[cpu].evt = evt;
 
-	if (cpu == 0) {
-		mct_tick[cpu].base = EXYNOS4_MCT_L0_BASE;
-		evt->name = "mct_tick0";
-	} else {
-		mct_tick[cpu].base = EXYNOS4_MCT_L1_BASE;
-		evt->name = "mct_tick1";
-	}
+	mct_tick[cpu].base = EXYNOS4_MCT_L_BASE(cpu);
+	sprintf(mct_tick[cpu].name, "mct_tick%d", cpu);
 
+	evt->name = mct_tick[cpu].name;
 	evt->cpumask = cpumask_of(cpu);
 	evt->set_next_event = exynos4_tick_set_next_event;
 	evt->set_mode = exynos4_tick_set_mode;
@@ -384,13 +400,17 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
 
 	exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET);
 
-	if (cpu == 0) {
-		mct_tick0_event_irq.dev_id = &mct_tick[cpu];
-		setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
+	if (mct_int_type == MCT_INT_SPI) {
+		if (cpu == 0) {
+			mct_tick0_event_irq.dev_id = &mct_tick[cpu];
+			setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
+		} else {
+			mct_tick1_event_irq.dev_id = &mct_tick[cpu];
+			setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
+			irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
+		}
 	} else {
-		mct_tick1_event_irq.dev_id = &mct_tick[cpu];
-		setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
-		irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
+		gic_enable_ppi(IRQ_MCT_LOCALTIMER);
 	}
 }
 
@@ -404,7 +424,10 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)
 
 int local_timer_ack(void)
 {
-	return 0;
+	unsigned int cpu = smp_processor_id();
+	struct mct_clock_event_device *mevt = &mct_tick[cpu];
+
+	return exynos4_mct_tick_clear(mevt);
 }
 
 #endif /* CONFIG_LOCAL_TIMERS */
@@ -419,6 +442,11 @@ static void __init exynos4_timer_resources(void)
 
 static void __init exynos4_timer_init(void)
 {
+	if (soc_is_exynos4210())
+		mct_int_type = MCT_INT_SPI;
+	else
+		mct_int_type = MCT_INT_PPI;
+
 	exynos4_timer_resources();
 	exynos4_clocksource_init();
 	exynos4_clockevent_init();
diff --git a/arch/arm/mach-exynos4/platsmp.c b/arch/arm/mach-exynos4/platsmp.c
index a3346e36d0aeb84061ff3a41f596e51dfb93bf14..d5f0f299ba0d6ae608c9d4ee87082c8fa50b7688 100644
--- a/arch/arm/mach-exynos4/platsmp.c
+++ b/arch/arm/mach-exynos4/platsmp.c
@@ -32,6 +32,7 @@
 
 #include <plat/cpu.h>
 
+extern unsigned int gic_bank_offset;
 extern void exynos4_secondary_startup(void);
 
 #define CPU1_BOOT_REG		(samsung_rev() == EXYNOS4210_REV_1_1 ? \
@@ -67,9 +68,9 @@ static DEFINE_SPINLOCK(boot_lock);
 static void __cpuinit exynos4_gic_secondary_init(void)
 {
 	void __iomem *dist_base = S5P_VA_GIC_DIST +
-				 (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+				(gic_bank_offset * smp_processor_id());
 	void __iomem *cpu_base = S5P_VA_GIC_CPU +
-				(EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+				(gic_bank_offset * smp_processor_id());
 	int i;
 
 	/*
diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c
index 909507bae2fab89990abd8a5ffd183625cb3a87b..7b0a28f73a68a2f47601d6ece39edac6547827b6 100644
--- a/arch/arm/plat-s5p/cpu.c
+++ b/arch/arm/plat-s5p/cpu.c
@@ -34,6 +34,7 @@ static const char name_s5pc100[] = "S5PC100";
 static const char name_s5pv210[] = "S5PV210/S5PC110";
 static const char name_exynos4210[] = "EXYNOS4210";
 static const char name_exynos4212[] = "EXYNOS4212";
+static const char name_exynos4412[] = "EXYNOS4412";
 
 static struct cpu_table cpu_ids[] __initdata = {
 	{
@@ -84,6 +85,14 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.init_uarts	= exynos4_init_uarts,
 		.init		= exynos4_init,
 		.name		= name_exynos4212,
+	}, {
+		.idcode		= EXYNOS4412_CPU_ID,
+		.idmask		= EXYNOS4_CPU_MASK,
+		.map_io		= exynos4_map_io,
+		.init_clocks	= exynos4_init_clocks,
+		.init_uarts	= exynos4_init_uarts,
+		.init		= exynos4_init,
+		.name		= name_exynos4412,
 	},
 };
 
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index 1bbbbb420be77e38d39be116f69bc2318cc8ef24..54f370f0fc07f000b89681c92c3dec20ec48edad 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -40,6 +40,7 @@ extern unsigned long samsung_cpu_id;
 
 #define EXYNOS4210_CPU_ID	0x43210000
 #define EXYNOS4212_CPU_ID	0x43220000
+#define EXYNOS4412_CPU_ID	0xE4412200
 #define EXYNOS4_CPU_MASK	0xFFFE0000
 
 #define IS_SAMSUNG_CPU(name, id, mask)		\
@@ -56,6 +57,7 @@ IS_SAMSUNG_CPU(s5pc100, S5PC100_CPU_ID, S5PC100_CPU_MASK)
 IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK)
 IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK)
 IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK)
+IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
 
 #if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
     defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \
@@ -108,6 +110,12 @@ IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK)
 # define soc_is_exynos4212()	0
 #endif
 
+#if defined(CONFIG_SOC_EXYNOS4412)
+# define soc_is_exynos4412()	is_samsung_exynos4412()
+#else
+# define soc_is_exynos4412()	0
+#endif
+
 #define EXYNOS4210_REV_0	(0x0)
 #define EXYNOS4210_REV_1_0	(0x10)
 #define EXYNOS4210_REV_1_1	(0x11)