Browse Source

Merge branch 'next-s5pv310' into for-next

Kukjin Kim 15 years ago
parent
commit
6b8eda04ff
46 changed files with 2611 additions and 18 deletions
  1. 19 5
      arch/arm/Kconfig
  2. 1 0
      arch/arm/Makefile
  3. 45 0
      arch/arm/mach-s5pv310/Kconfig
  4. 30 0
      arch/arm/mach-s5pv310/Makefile
  5. 2 0
      arch/arm/mach-s5pv310/Makefile.boot
  6. 544 0
      arch/arm/mach-s5pv310/clock.c
  7. 122 0
      arch/arm/mach-s5pv310/cpu.c
  8. 41 0
      arch/arm/mach-s5pv310/headsmp.S
  9. 36 0
      arch/arm/mach-s5pv310/include/mach/debug-macro.S
  10. 84 0
      arch/arm/mach-s5pv310/include/mach/entry-macro.S
  11. 135 0
      arch/arm/mach-s5pv310/include/mach/gpio.h
  12. 18 0
      arch/arm/mach-s5pv310/include/mach/hardware.h
  13. 26 0
      arch/arm/mach-s5pv310/include/mach/io.h
  14. 74 0
      arch/arm/mach-s5pv310/include/mach/irqs.h
  15. 69 0
      arch/arm/mach-s5pv310/include/mach/map.h
  16. 22 0
      arch/arm/mach-s5pv310/include/mach/memory.h
  17. 70 0
      arch/arm/mach-s5pv310/include/mach/pwm-clock.h
  18. 62 0
      arch/arm/mach-s5pv310/include/mach/regs-clock.h
  19. 19 0
      arch/arm/mach-s5pv310/include/mach/regs-irq.h
  20. 29 0
      arch/arm/mach-s5pv310/include/mach/smp.h
  21. 22 0
      arch/arm/mach-s5pv310/include/mach/system.h
  22. 29 0
      arch/arm/mach-s5pv310/include/mach/timex.h
  23. 30 0
      arch/arm/mach-s5pv310/include/mach/uncompress.h
  24. 22 0
      arch/arm/mach-s5pv310/include/mach/vmalloc.h
  25. 41 0
      arch/arm/mach-s5pv310/init.c
  26. 125 0
      arch/arm/mach-s5pv310/irq-combiner.c
  27. 25 0
      arch/arm/mach-s5pv310/localtimer.c
  28. 92 0
      arch/arm/mach-s5pv310/mach-smdkv310.c
  29. 86 0
      arch/arm/mach-s5pv310/mach-universal_c210.c
  30. 192 0
      arch/arm/mach-s5pv310/platsmp.c
  31. 28 0
      arch/arm/mach-s5pv310/setup-i2c0.c
  32. 25 0
      arch/arm/mach-s5pv310/setup-i2c1.c
  33. 25 0
      arch/arm/mach-s5pv310/setup-i2c2.c
  34. 287 0
      arch/arm/mach-s5pv310/time.c
  35. 2 1
      arch/arm/mm/Kconfig
  36. 3 2
      arch/arm/plat-s5p/Kconfig
  37. 13 1
      arch/arm/plat-s5p/cpu.c
  38. 19 4
      arch/arm/plat-s5p/include/plat/map-s5p.h
  39. 41 0
      arch/arm/plat-s5p/include/plat/pll.h
  40. 34 0
      arch/arm/plat-s5p/include/plat/s5pv310.h
  41. 2 0
      arch/arm/plat-s5p/irq.c
  42. 1 1
      arch/arm/plat-samsung/Makefile
  43. 2 0
      arch/arm/plat-samsung/include/plat/regs-serial.h
  44. 2 2
      drivers/serial/Kconfig
  45. 8 0
      drivers/serial/s5pv210.c
  46. 7 2
      drivers/serial/samsung.c

+ 19 - 5
arch/arm/Kconfig

@@ -704,6 +704,15 @@ config ARCH_S5PV210
 	help
 	  Samsung S5PV210/S5PC110 series based systems
 
+config ARCH_S5PV310
+	bool "Samsung S5PV310/S5PC210"
+	select CPU_V7
+	select GENERIC_GPIO
+	select HAVE_CLK
+	select GENERIC_CLOCKEVENTS
+	help
+	  Samsung S5PV310 series based systems
+
 config ARCH_SHARK
 	bool "Shark"
 	select CPU_SA110
@@ -904,6 +913,8 @@ source "arch/arm/mach-s5pc100/Kconfig"
 
 source "arch/arm/mach-s5pv210/Kconfig"
 
+source "arch/arm/mach-s5pv310/Kconfig"
+
 source "arch/arm/mach-shmobile/Kconfig"
 
 source "arch/arm/plat-stmp3xxx/Kconfig"
@@ -1100,10 +1111,11 @@ config SMP
 	bool "Symmetric Multi-Processing (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\
 		 MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
-		 ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+		 ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_S5PV310)
 	depends on GENERIC_CLOCKEVENTS
 	select USE_GENERIC_SMP_HELPERS
-	select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+	select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 ||\
+			ARCH_S5PV310)
 	help
 	  This enables support for systems with more than one CPU. If you have
 	  a system with only one CPU, like most personal computers, say N. If
@@ -1172,9 +1184,10 @@ config HOTPLUG_CPU
 config LOCAL_TIMERS
 	bool "Use local timer interrupts"
 	depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \
-		REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || ARCH_U8500)
+		REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
+		ARCH_U8500 || ARCH_S5PV310)
 	default y
-	select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500)
+	select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || ARCH_S5PV310)
 	help
 	  Enable support for local timers on SMP platforms, rather then the
 	  legacy IPI broadcast method.  Local timers allows the system
@@ -1186,7 +1199,8 @@ source kernel/Kconfig.preempt
 config HZ
 	int
 	default 128 if ARCH_L7200
-	default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PV210
+	default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P6440 || ARCH_S5P6442 || \
+		       ARCH_S5PV210 || ARCH_S5PV310
 	default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
 	default AT91_TIMER_HZ if ARCH_AT91
 	default 100

+ 1 - 0
arch/arm/Makefile

@@ -170,6 +170,7 @@ machine-$(CONFIG_ARCH_S5P6440)		:= s5p6440
 machine-$(CONFIG_ARCH_S5P6442)		:= s5p6442
 machine-$(CONFIG_ARCH_S5PC100)		:= s5pc100
 machine-$(CONFIG_ARCH_S5PV210)		:= s5pv210
+machine-$(CONFIG_ARCH_S5PV310)		:= s5pv310
 machine-$(CONFIG_ARCH_SA1100)		:= sa1100
 machine-$(CONFIG_ARCH_SHARK)		:= shark
 machine-$(CONFIG_ARCH_SHMOBILE) 	:= shmobile

+ 45 - 0
arch/arm/mach-s5pv310/Kconfig

@@ -0,0 +1,45 @@
+# arch/arm/mach-s5pv310/Kconfig
+#
+# Copyright (c) 2010 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+# Configuration options for the S5PV310
+
+if ARCH_S5PV310
+
+config CPU_S5PV310
+	bool
+	select PLAT_S5P
+	help
+	  Enable S5PV310 CPU support
+
+config S5PV310_SETUP_I2C1
+	bool
+	help
+	  Common setup code for i2c bus 1.
+
+config S5PV310_SETUP_I2C2
+	bool
+	help
+	  Common setup code for i2c bus 2.
+
+# machine support
+
+config MACH_SMDKV310
+	bool "SMDKV310"
+	select CPU_S5PV310
+	select ARCH_SPARSEMEM_ENABLE
+	help
+	  Machine support for Samsung SMDKV310
+
+config MACH_UNIVERSAL_C210
+	bool "Mobile UNIVERSAL_C210 Board"
+	select CPU_S5PV310
+	select ARCH_SPARSEMEM_ENABLE
+	help
+	  Machine support for Samsung Mobile Universal S5PC210 Reference
+	  Board. S5PC210(MCP) is one of package option of S5PV310
+
+endif

+ 30 - 0
arch/arm/mach-s5pv310/Makefile

@@ -0,0 +1,30 @@
+# arch/arm/mach-s5pv310/Makefile
+#
+# Copyright (c) 2010 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+# Core support for S5PV310 system
+
+obj-$(CONFIG_CPU_S5PV310)	+= cpu.o init.o clock.o irq-combiner.o
+obj-$(CONFIG_CPU_S5PV310)	+= setup-i2c0.o time.o
+
+obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
+obj-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
+obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
+
+# machine support
+
+obj-$(CONFIG_MACH_SMDKV310)	+= mach-smdkv310.o
+obj-$(CONFIG_MACH_UNIVERSAL_C210)	+= mach-universal_c210.o
+
+# device support
+
+obj-$(CONFIG_S5PV310_SETUP_I2C1)	+= setup-i2c1.o
+obj-$(CONFIG_S5PV310_SETUP_I2C2)	+= setup-i2c2.o

+ 2 - 0
arch/arm/mach-s5pv310/Makefile.boot

@@ -0,0 +1,2 @@
+   zreladdr-y	:= 0x40008000
+params_phys-y	:= 0x40000100

+ 544 - 0
arch/arm/mach-s5pv310/clock.c

@@ -0,0 +1,544 @@
+/* linux/arch/arm/mach-s5pv310/clock.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV310 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+static struct clk clk_sclk_hdmi27m = {
+	.name		= "sclk_hdmi27m",
+	.id		= -1,
+	.rate		= 27000000,
+};
+
+/* Core list of CMU_CPU side */
+
+static struct clksrc_clk clk_mout_apll = {
+	.clk	= {
+		.name		= "mout_apll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_apll,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
+};
+
+static struct clksrc_clk clk_mout_epll = {
+	.clk	= {
+		.name		= "mout_epll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_epll,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk clk_mout_mpll = {
+	.clk = {
+		.name		= "mout_mpll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_mpll,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 },
+};
+
+static struct clk *clkset_moutcore_list[] = {
+	[0] = &clk_mout_apll.clk,
+	[1] = &clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_moutcore = {
+	.sources	= clkset_moutcore_list,
+	.nr_sources	= ARRAY_SIZE(clkset_moutcore_list),
+};
+
+static struct clksrc_clk clk_moutcore = {
+	.clk	= {
+		.name		= "moutcore",
+		.id		= -1,
+	},
+	.sources	= &clkset_moutcore,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
+};
+
+static struct clksrc_clk clk_coreclk = {
+	.clk	= {
+		.name		= "core_clk",
+		.id		= -1,
+		.parent		= &clk_moutcore.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_armclk = {
+	.clk	= {
+		.name		= "armclk",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+};
+
+static struct clksrc_clk clk_aclk_corem0 = {
+	.clk	= {
+		.name		= "aclk_corem0",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_cores = {
+	.clk	= {
+		.name		= "aclk_cores",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_corem1 = {
+	.clk	= {
+		.name		= "aclk_corem1",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
+};
+
+static struct clksrc_clk clk_periphclk = {
+	.clk	= {
+		.name		= "periphclk",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
+};
+
+static struct clksrc_clk clk_atclk = {
+	.clk	= {
+		.name		= "atclk",
+		.id		= -1,
+		.parent		= &clk_moutcore.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 16, .size = 3 },
+};
+
+static struct clksrc_clk clk_pclk_dbg = {
+	.clk	= {
+		.name		= "pclk_dbg",
+		.id		= -1,
+		.parent		= &clk_atclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 20, .size = 3 },
+};
+
+/* Core list of CMU_CORE side */
+
+static struct clk *clkset_corebus_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_mout_apll.clk,
+};
+
+static struct clksrc_sources clkset_mout_corebus = {
+	.sources	= clkset_corebus_list,
+	.nr_sources	= ARRAY_SIZE(clkset_corebus_list),
+};
+
+static struct clksrc_clk clk_mout_corebus = {
+	.clk	= {
+		.name		= "mout_corebus",
+		.id		= -1,
+	},
+	.sources	= &clkset_mout_corebus,
+	.reg_src	= { .reg = S5P_CLKSRC_CORE, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_dmc = {
+	.clk	= {
+		.name		= "sclk_dmc",
+		.id		= -1,
+		.parent		= &clk_mout_corebus.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 12, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_cored = {
+	.clk	= {
+		.name		= "aclk_cored",
+		.id		= -1,
+		.parent		= &clk_sclk_dmc.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 16, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_corep = {
+	.clk	= {
+		.name		= "aclk_corep",
+		.id		= -1,
+		.parent		= &clk_aclk_cored.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 20, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_acp = {
+	.clk	= {
+		.name		= "aclk_acp",
+		.id		= -1,
+		.parent		= &clk_mout_corebus.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_pclk_acp = {
+	.clk	= {
+		.name		= "pclk_acp",
+		.id		= -1,
+		.parent		= &clk_aclk_acp.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 4, .size = 3 },
+};
+
+/* Core list of CMU_TOP side */
+
+static struct clk *clkset_aclk_top_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_mout_apll.clk,
+};
+
+static struct clksrc_sources clkset_aclk_200 = {
+	.sources	= clkset_aclk_top_list,
+	.nr_sources	= ARRAY_SIZE(clkset_aclk_top_list),
+};
+
+static struct clksrc_clk clk_aclk_200 = {
+	.clk	= {
+		.name		= "aclk_200",
+		.id		= -1,
+	},
+	.sources	= &clkset_aclk_200,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_sources clkset_aclk_100 = {
+	.sources	= clkset_aclk_top_list,
+	.nr_sources	= ARRAY_SIZE(clkset_aclk_top_list),
+};
+
+static struct clksrc_clk clk_aclk_100 = {
+	.clk	= {
+		.name		= "aclk_100",
+		.id		= -1,
+	},
+	.sources	= &clkset_aclk_100,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 },
+};
+
+static struct clksrc_sources clkset_aclk_160 = {
+	.sources	= clkset_aclk_top_list,
+	.nr_sources	= ARRAY_SIZE(clkset_aclk_top_list),
+};
+
+static struct clksrc_clk clk_aclk_160 = {
+	.clk	= {
+		.name		= "aclk_160",
+		.id		= -1,
+	},
+	.sources	= &clkset_aclk_160,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
+};
+
+static struct clksrc_sources clkset_aclk_133 = {
+	.sources	= clkset_aclk_top_list,
+	.nr_sources	= ARRAY_SIZE(clkset_aclk_top_list),
+};
+
+static struct clksrc_clk clk_aclk_133 = {
+	.clk	= {
+		.name		= "aclk_133",
+		.id		= -1,
+	},
+	.sources	= &clkset_aclk_133,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 },
+};
+
+static struct clk *clkset_vpllsrc_list[] = {
+	[0] = &clk_fin_vpll,
+	[1] = &clk_sclk_hdmi27m,
+};
+
+static struct clksrc_sources clkset_vpllsrc = {
+	.sources	= clkset_vpllsrc_list,
+	.nr_sources	= ARRAY_SIZE(clkset_vpllsrc_list),
+};
+
+static struct clksrc_clk clk_vpllsrc = {
+	.clk	= {
+		.name		= "vpll_src",
+		.id		= -1,
+	},
+	.sources	= &clkset_vpllsrc,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_sclk_vpll_list[] = {
+	[0] = &clk_vpllsrc.clk,
+	[1] = &clk_fout_vpll,
+};
+
+static struct clksrc_sources clkset_sclk_vpll = {
+	.sources	= clkset_sclk_vpll_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_vpll_list),
+};
+
+static struct clksrc_clk clk_sclk_vpll = {
+	.clk	= {
+		.name		= "sclk_vpll",
+		.id		= -1,
+	},
+	.sources	= &clkset_sclk_vpll,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
+};
+
+static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable);
+}
+
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= s5pv310_clk_ip_peril_ctrl,
+		.ctrlbit	= (1<<24),
+	}
+};
+
+static struct clk init_clocks[] = {
+	/* Nothing here yet */
+};
+
+static struct clk *clkset_group_list[] = {
+	[0] = &clk_ext_xtal_mux,
+	[1] = &clk_xusbxti,
+	[2] = &clk_sclk_hdmi27m,
+	[6] = &clk_mout_mpll.clk,
+	[7] = &clk_mout_epll.clk,
+	[8] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_group = {
+	.sources	= clkset_group_list,
+	.nr_sources	= ARRAY_SIZE(clkset_group_list),
+};
+
+static struct clksrc_clk clksrcs[] = {
+	{
+		.clk	= {
+			.name		= "uclk1",
+			.id		= 0,
+			.ctrlbit	= (1 << 0),
+			.enable		= s5pv310_clk_ip_peril_ctrl,
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.id		= 1,
+			.enable		= s5pv310_clk_ip_peril_ctrl,
+			.ctrlbit	= (1 << 1),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.id		= 2,
+			.enable		= s5pv310_clk_ip_peril_ctrl,
+			.ctrlbit	= (1 << 2),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.id		= 3,
+			.enable		= s5pv310_clk_ip_peril_ctrl,
+			.ctrlbit	= (1 << 3),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_pwm",
+			.id		= -1,
+			.enable		= s5pv310_clk_ip_peril_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 },
+	},
+};
+
+/* Clock initialization code */
+static struct clksrc_clk *sysclks[] = {
+	&clk_mout_apll,
+	&clk_mout_epll,
+	&clk_mout_mpll,
+	&clk_moutcore,
+	&clk_coreclk,
+	&clk_armclk,
+	&clk_aclk_corem0,
+	&clk_aclk_cores,
+	&clk_aclk_corem1,
+	&clk_periphclk,
+	&clk_atclk,
+	&clk_pclk_dbg,
+	&clk_mout_corebus,
+	&clk_sclk_dmc,
+	&clk_aclk_cored,
+	&clk_aclk_corep,
+	&clk_aclk_acp,
+	&clk_pclk_acp,
+	&clk_vpllsrc,
+	&clk_sclk_vpll,
+	&clk_aclk_200,
+	&clk_aclk_100,
+	&clk_aclk_160,
+	&clk_aclk_133,
+};
+
+void __init_or_cpufreq s5pv310_setup_clocks(void)
+{
+	struct clk *xtal_clk;
+	unsigned long apll;
+	unsigned long mpll;
+	unsigned long epll;
+	unsigned long vpll;
+	unsigned long vpllsrc;
+	unsigned long xtal;
+	unsigned long armclk;
+	unsigned long aclk_corem0;
+	unsigned long aclk_cores;
+	unsigned long aclk_corem1;
+	unsigned long periphclk;
+	unsigned long sclk_dmc;
+	unsigned long aclk_cored;
+	unsigned long aclk_corep;
+	unsigned long aclk_acp;
+	unsigned long pclk_acp;
+	unsigned int ptr;
+
+	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
+
+	xtal_clk = clk_get(NULL, "xtal");
+	BUG_ON(IS_ERR(xtal_clk));
+
+	xtal = clk_get_rate(xtal_clk);
+	clk_put(xtal_clk);
+
+	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
+
+	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508);
+	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508);
+	epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
+				__raw_readl(S5P_EPLL_CON1), pll_4500);
+
+	vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
+	vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
+				__raw_readl(S5P_VPLL_CON1), pll_4502);
+
+	clk_fout_apll.rate = apll;
+	clk_fout_mpll.rate = mpll;
+	clk_fout_epll.rate = epll;
+	clk_fout_vpll.rate = vpll;
+
+	printk(KERN_INFO "S5PV310: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
+			apll, mpll, epll, vpll);
+
+	armclk = clk_get_rate(&clk_armclk.clk);
+	aclk_corem0 = clk_get_rate(&clk_aclk_corem0.clk);
+	aclk_cores = clk_get_rate(&clk_aclk_cores.clk);
+	aclk_corem1 = clk_get_rate(&clk_aclk_corem1.clk);
+	periphclk = clk_get_rate(&clk_periphclk.clk);
+	sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk);
+	aclk_cored = clk_get_rate(&clk_aclk_cored.clk);
+	aclk_corep = clk_get_rate(&clk_aclk_corep.clk);
+	aclk_acp = clk_get_rate(&clk_aclk_acp.clk);
+	pclk_acp = clk_get_rate(&clk_pclk_acp.clk);
+
+	printk(KERN_INFO "S5PV310: ARMCLK=%ld, COREM0=%ld, CORES=%ld\n"
+			 "COREM1=%ld, PERI=%ld, DMC=%ld, CORED=%ld\n"
+			 "COREP=%ld, ACLK_ACP=%ld, PCLK_ACP=%ld",
+			armclk, aclk_corem0, aclk_cores, aclk_corem1,
+			periphclk, sclk_dmc, aclk_cored, aclk_corep,
+			aclk_acp, pclk_acp);
+
+	clk_f.rate = armclk;
+	clk_h.rate = sclk_dmc;
+	clk_p.rate = periphclk;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+		s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+static struct clk *clks[] __initdata = {
+	/* Nothing here yet */
+};
+
+void __init s5pv310_register_clocks(void)
+{
+	struct clk *clkp;
+	int ret;
+	int ptr;
+
+	ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+	if (ret > 0)
+		printk(KERN_ERR "Failed to register %u clocks\n", ret);
+
+	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+		s3c_register_clksrc(sysclks[ptr], 1);
+
+	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+		(clkp->enable)(clkp, 0);
+	}
+
+	s3c_pwmclk_init();
+}

+ 122 - 0
arch/arm/mach-s5pv310/cpu.c

@@ -0,0 +1,122 @@
+/* linux/arch/arm/mach-s5pv310/cpu.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/sched.h>
+#include <linux/sysdev.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/proc-fns.h>
+
+#include <plat/cpu.h>
+#include <plat/clock.h>
+#include <plat/s5pv310.h>
+
+#include <mach/regs-irq.h>
+
+void __iomem *gic_cpu_base_addr;
+
+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);
+
+/* Initial IO mappings */
+static struct map_desc s5pv310_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_COREPERI_BASE,
+		.pfn		= __phys_to_pfn(S5PV310_PA_COREPERI),
+		.length		= SZ_8K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_COMBINER_BASE,
+		.pfn		= __phys_to_pfn(S5PV310_PA_COMBINER),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_L2CC,
+		.pfn		= __phys_to_pfn(S5PV310_PA_L2CC),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static void s5pv310_idle(void)
+{
+	if (!need_resched())
+		cpu_do_idle();
+
+	local_irq_enable();
+}
+
+/* s5pv310_map_io
+ *
+ * register the standard cpu IO areas
+*/
+void __init s5pv310_map_io(void)
+{
+	iotable_init(s5pv310_iodesc, ARRAY_SIZE(s5pv310_iodesc));
+}
+
+void __init s5pv310_init_clocks(int xtal)
+{
+	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+	s3c24xx_register_baseclocks(xtal);
+	s5p_register_clocks(xtal);
+	s5pv310_register_clocks();
+	s5pv310_setup_clocks();
+}
+
+void __init s5pv310_init_irq(void)
+{
+	int irq;
+
+	gic_cpu_base_addr = S5P_VA_GIC_CPU;
+	gic_dist_init(0, S5P_VA_GIC_DIST, IRQ_LOCALTIMER);
+	gic_cpu_init(0, S5P_VA_GIC_CPU);
+
+	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
+		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
+				COMBINER_IRQ(irq, 0));
+		combiner_cascade_irq(irq, IRQ_SPI(irq));
+	}
+
+	/* The parameters of s5p_init_irq() are for VIC init.
+	 * Theses parameters should be NULL and 0 because S5PV310
+	 * uses GIC instead of VIC.
+	 */
+	s5p_init_irq(NULL, 0);
+}
+
+struct sysdev_class s5pv310_sysclass = {
+	.name	= "s5pv310-core",
+};
+
+static struct sys_device s5pv310_sysdev = {
+	.cls	= &s5pv310_sysclass,
+};
+
+static int __init s5pv310_core_init(void)
+{
+	return sysdev_class_register(&s5pv310_sysclass);
+}
+
+core_initcall(s5pv310_core_init);
+
+int __init s5pv310_init(void)
+{
+	printk(KERN_INFO "S5PV310: Initializing architecture\n");
+
+	/* set idle function */
+	pm_idle = s5pv310_idle;
+
+	return sysdev_register(&s5pv310_sysdev);
+}

+ 41 - 0
arch/arm/mach-s5pv310/headsmp.S

@@ -0,0 +1,41 @@
+/*
+ *  linux/arch/arm/mach-s5pv310/headsmp.S
+ *
+ *  Cloned from linux/arch/arm/mach-realview/headsmp.S
+ *
+ *  Copyright (c) 2003 ARM Limited
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+	__INIT
+
+/*
+ * s5pv310 specific entry point for secondary CPUs.  This provides
+ * a "holding pen" into which all secondary cores are held until we're
+ * ready for them to initialise.
+ */
+ENTRY(s5pv310_secondary_startup)
+	mrc	p15, 0, r0, c0, c0, 5
+	and	r0, r0, #15
+	adr	r4, 1f
+	ldmia	r4, {r5, r6}
+	sub	r4, r4, r5
+	add	r6, r6, r4
+pen:	ldr	r7, [r6]
+	cmp	r7, r0
+	bne	pen
+
+	/*
+	 * we've been released from the holding pen: secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
+
+1:	.long	.
+	.long	pen_release

+ 36 - 0
arch/arm/mach-s5pv310/include/mach/debug-macro.S

@@ -0,0 +1,36 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* pull in the relevant register and map files. */
+
+#include <mach/map.h>
+
+	/* note, for the boot process to work we have to keep the UART
+	 * virtual address aligned to an 1MiB boundary for the L1
+	 * mapping the head code makes. We keep the UART virtual address
+	 * aligned and add in the offset when we load the value here.
+	 */
+
+	.macro addruart, rx, tmp
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1
+		ldreq	\rx, = S3C_PA_UART
+		ldrne	\rx, = S3C_VA_UART
+#if CONFIG_DEBUG_S3C_UART != 0
+		add	\rx, \rx, #(0x10000 * CONFIG_DEBUG_S3C_UART)
+#endif
+	.endm
+
+#define fifo_full fifo_full_s5pv210
+#define fifo_level fifo_level_s5pv210
+
+#include <plat/debug-macro.S>

+ 84 - 0
arch/arm/mach-s5pv310/include/mach/entry-macro.S

@@ -0,0 +1,84 @@
+/* arch/arm/mach-s5pv310/include/mach/entry-macro.S
+ *
+ * Cloned from arch/arm/mach-realview/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for S5PV310 platforms
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+*/
+
+#include <mach/hardware.h>
+#include <asm/hardware/gic.h>
+
+		.macro	disable_fiq
+		.endm
+
+		.macro  get_irqnr_preamble, base, tmp
+		ldr	\base, =gic_cpu_base_addr
+		ldr	\base, [\base]
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
+		/*
+		 * The interrupt numbering scheme is defined in the
+		 * interrupt controller spec.  To wit:
+		 *
+		 * Interrupts 0-15 are IPI
+		 * 16-28 are reserved
+		 * 29-31 are local.  We allow 30 to be used for the watchdog.
+		 * 32-1020 are global
+		 * 1021-1022 are reserved
+		 * 1023 is "spurious" (no interrupt)
+		 *
+		 * For now, we ignore all local interrupts so only return an interrupt if it's
+		 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
+		 *
+		 * A simple read from the controller will tell us the number of the highest
+                 * priority enabled interrupt.  We then just need to check whether it is in the
+		 * valid range for an IRQ (30-1020 inclusive).
+		 */
+
+		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+		ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
+
+		ldr	\tmp, =1021
+
+		bic     \irqnr, \irqstat, #0x1c00
+
+		cmp     \irqnr, #29
+		cmpcc	\irqnr, \irqnr
+		cmpne	\irqnr, \tmp
+		cmpcs	\irqnr, \irqnr
+		addne	\irqnr, \irqnr, #32
+
+		.endm
+
+		/* We assume that irqstat (the raw value of the IRQ acknowledge
+		 * register) is preserved from the macro above.
+		 * If there is an IPI, we immediately signal end of interrupt on the
+		 * controller, since this requires the original irqstat value which
+		 * we won't easily be able to recreate later.
+		 */
+
+		.macro test_for_ipi, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		cmp	\irqnr, #16
+		strcc	\irqstat, [\base, #GIC_CPU_EOI]
+		cmpcs	\irqnr, \irqnr
+		.endm
+
+		/* 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, #29
+		moveq	\tmp, #1
+		streq	\irqstat, [\base, #GIC_CPU_EOI]
+		cmp	\tmp, #0
+		.endm

+ 135 - 0
arch/arm/mach-s5pv310/include/mach/gpio.h

@@ -0,0 +1,135 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/gpio.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV310 - GPIO lib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H __FILE__
+
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+#define gpio_to_irq	__gpio_to_irq
+
+/* Practically, GPIO banks upto GPZ are the configurable gpio banks */
+
+/* GPIO bank sizes */
+#define S5PV310_GPIO_A0_NR	(8)
+#define S5PV310_GPIO_A1_NR	(6)
+#define S5PV310_GPIO_B_NR	(8)
+#define S5PV310_GPIO_C0_NR	(5)
+#define S5PV310_GPIO_C1_NR	(5)
+#define S5PV310_GPIO_D0_NR	(4)
+#define S5PV310_GPIO_D1_NR	(4)
+#define S5PV310_GPIO_E0_NR	(5)
+#define S5PV310_GPIO_E1_NR	(8)
+#define S5PV310_GPIO_E2_NR	(6)
+#define S5PV310_GPIO_E3_NR	(8)
+#define S5PV310_GPIO_E4_NR	(8)
+#define S5PV310_GPIO_F0_NR	(8)
+#define S5PV310_GPIO_F1_NR	(8)
+#define S5PV310_GPIO_F2_NR	(8)
+#define S5PV310_GPIO_F3_NR	(6)
+#define S5PV310_GPIO_J0_NR	(8)
+#define S5PV310_GPIO_J1_NR	(5)
+#define S5PV310_GPIO_K0_NR	(7)
+#define S5PV310_GPIO_K1_NR	(7)
+#define S5PV310_GPIO_K2_NR	(7)
+#define S5PV310_GPIO_K3_NR	(7)
+#define S5PV310_GPIO_L0_NR	(8)
+#define S5PV310_GPIO_L1_NR	(3)
+#define S5PV310_GPIO_L2_NR	(8)
+#define S5PV310_GPIO_X0_NR	(8)
+#define S5PV310_GPIO_X1_NR	(8)
+#define S5PV310_GPIO_X2_NR	(8)
+#define S5PV310_GPIO_X3_NR	(8)
+#define S5PV310_GPIO_Z_NR	(7)
+
+/* GPIO bank numbers */
+
+#define S5PV310_GPIO_NEXT(__gpio) \
+	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
+
+enum s5p_gpio_number {
+	S5PV310_GPIO_A0_START	= 0,
+	S5PV310_GPIO_A1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_A0),
+	S5PV310_GPIO_B_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_A1),
+	S5PV310_GPIO_C0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_B),
+	S5PV310_GPIO_C1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_C0),
+	S5PV310_GPIO_D0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_C1),
+	S5PV310_GPIO_D1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_D0),
+	S5PV310_GPIO_E0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_D1),
+	S5PV310_GPIO_E1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E0),
+	S5PV310_GPIO_E2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E1),
+	S5PV310_GPIO_E3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E2),
+	S5PV310_GPIO_E4_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E3),
+	S5PV310_GPIO_F0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E4),
+	S5PV310_GPIO_F1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F0),
+	S5PV310_GPIO_F2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F1),
+	S5PV310_GPIO_F3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F2),
+	S5PV310_GPIO_J0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F3),
+	S5PV310_GPIO_J1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_J0),
+	S5PV310_GPIO_K0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_J1),
+	S5PV310_GPIO_K1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K0),
+	S5PV310_GPIO_K2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K1),
+	S5PV310_GPIO_K3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K2),
+	S5PV310_GPIO_L0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K3),
+	S5PV310_GPIO_L1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_L0),
+	S5PV310_GPIO_L2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_L1),
+	S5PV310_GPIO_X0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_L2),
+	S5PV310_GPIO_X1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X0),
+	S5PV310_GPIO_X2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X1),
+	S5PV310_GPIO_X3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X2),
+	S5PV310_GPIO_Z_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X3),
+};
+
+/* S5PV310 GPIO number definitions */
+#define S5PV310_GPA0(_nr)	(S5PV310_GPIO_A0_START + (_nr))
+#define S5PV310_GPA1(_nr)	(S5PV310_GPIO_A1_START + (_nr))
+#define S5PV310_GPB(_nr)	(S5PV310_GPIO_B_START + (_nr))
+#define S5PV310_GPC0(_nr)	(S5PV310_GPIO_C0_START + (_nr))
+#define S5PV310_GPC1(_nr)	(S5PV310_GPIO_C1_START + (_nr))
+#define S5PV310_GPD0(_nr)	(S5PV310_GPIO_D0_START + (_nr))
+#define S5PV310_GPD1(_nr)	(S5PV310_GPIO_D1_START + (_nr))
+#define S5PV310_GPE0(_nr)	(S5PV310_GPIO_E0_START + (_nr))
+#define S5PV310_GPE1(_nr)	(S5PV310_GPIO_E1_START + (_nr))
+#define S5PV310_GPE2(_nr)	(S5PV310_GPIO_E2_START + (_nr))
+#define S5PV310_GPE3(_nr)	(S5PV310_GPIO_E3_START + (_nr))
+#define S5PV310_GPE4(_nr)	(S5PV310_GPIO_E4_START + (_nr))
+#define S5PV310_GPF0(_nr)	(S5PV310_GPIO_F0_START + (_nr))
+#define S5PV310_GPF1(_nr)	(S5PV310_GPIO_F1_START + (_nr))
+#define S5PV310_GPF2(_nr)	(S5PV310_GPIO_F2_START + (_nr))
+#define S5PV310_GPF3(_nr)	(S5PV310_GPIO_F3_START + (_nr))
+#define S5PV310_GPJ0(_nr)	(S5PV310_GPIO_J0_START + (_nr))
+#define S5PV310_GPJ1(_nr)	(S5PV310_GPIO_J1_START + (_nr))
+#define S5PV310_GPK0(_nr)	(S5PV310_GPIO_K0_START + (_nr))
+#define S5PV310_GPK1(_nr)	(S5PV310_GPIO_K1_START + (_nr))
+#define S5PV310_GPK2(_nr)	(S5PV310_GPIO_K2_START + (_nr))
+#define S5PV310_GPK3(_nr)	(S5PV310_GPIO_K3_START + (_nr))
+#define S5PV310_GPL0(_nr)	(S5PV310_GPIO_L0_START + (_nr))
+#define S5PV310_GPL1(_nr)	(S5PV310_GPIO_L1_START + (_nr))
+#define S5PV310_GPL2(_nr)	(S5PV310_GPIO_L2_START + (_nr))
+#define S5PV310_GPX0(_nr)	(S5PV310_GPIO_X0_START + (_nr))
+#define S5PV310_GPX1(_nr)	(S5PV310_GPIO_X1_START + (_nr))
+#define S5PV310_GPX2(_nr)	(S5PV310_GPIO_X2_START + (_nr))
+#define S5PV310_GPX3(_nr)	(S5PV310_GPIO_X3_START + (_nr))
+#define S5PV310_GPZ(_nr)	(S5PV310_GPIO_Z_START + (_nr))
+
+/* the end of the S5PV310 specific gpios */
+#define S5PV310_GPIO_END	(S5PV310_GPZ(S5PV310_GPIO_Z_NR) + 1)
+#define S3C_GPIO_END		S5PV310_GPIO_END
+
+/* define the number of gpios we need to the one after the GPZ() range */
+#define ARCH_NR_GPIOS		(S5PV310_GPZ(S5PV310_GPIO_Z_NR) +	\
+				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
+
+#include <asm-generic/gpio.h>
+
+#endif /* __ASM_ARCH_GPIO_H */

+ 18 - 0
arch/arm/mach-s5pv310/include/mach/hardware.h

@@ -0,0 +1,18 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/hardware.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV310 - Hardware support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H __FILE__
+
+/* currently nothing here, placeholder */
+
+#endif /* __ASM_ARCH_HARDWARE_H */

+ 26 - 0
arch/arm/mach-s5pv310/include/mach/io.h

@@ -0,0 +1,26 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/io.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Copyright 2008-2010 Ben Dooks <ben-linux@fluff.org>
+ *
+ * Based on arch/arm/mach-s5p6442/include/mach/io.h
+ *
+ * Default IO routines for S5PV310
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H __FILE__
+
+/* No current ISA/PCI bus support. */
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#define IO_SPACE_LIMIT (0xFFFFFFFF)
+
+#endif /* __ASM_ARM_ARCH_IO_H */

+ 74 - 0
arch/arm/mach-s5pv310/include/mach/irqs.h

@@ -0,0 +1,74 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/irqs.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - IRQ definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H __FILE__
+
+#include <plat/irqs.h>
+
+/* Private Peripheral Interrupt */
+#define IRQ_PPI(x)		S5P_IRQ(x+16)
+
+#define IRQ_LOCALTIMER		IRQ_PPI(13)
+
+/* Shared Peripheral Interrupt */
+#define IRQ_SPI(x)		S5P_IRQ(x+32)
+
+#define IRQ_EINT0		IRQ_SPI(40)
+#define IRQ_EINT1		IRQ_SPI(41)
+#define IRQ_EINT2		IRQ_SPI(42)
+#define IRQ_EINT3		IRQ_SPI(43)
+#define IRQ_USB_HSOTG		IRQ_SPI(44)
+#define IRQ_USB_HOST		IRQ_SPI(45)
+#define IRQ_MODEM_IF		IRQ_SPI(46)
+#define IRQ_ROTATOR		IRQ_SPI(47)
+#define IRQ_JPEG		IRQ_SPI(48)
+#define IRQ_2D			IRQ_SPI(49)
+#define IRQ_PCIE		IRQ_SPI(50)
+#define IRQ_SYSTEM_TIMER	IRQ_SPI(51)
+#define IRQ_MFC			IRQ_SPI(52)
+#define IRQ_WTD			IRQ_SPI(53)
+#define IRQ_AUDIO_SS		IRQ_SPI(54)
+#define IRQ_AC97		IRQ_SPI(55)
+#define IRQ_SPDIF		IRQ_SPI(56)
+#define IRQ_KEYPAD		IRQ_SPI(57)
+#define IRQ_INTFEEDCTRL_SSS	IRQ_SPI(58)
+#define IRQ_SLIMBUS		IRQ_SPI(59)
+#define IRQ_PMU			IRQ_SPI(60)
+#define IRQ_TSI			IRQ_SPI(61)
+#define IRQ_SATA		IRQ_SPI(62)
+#define IRQ_GPS			IRQ_SPI(63)
+
+#define MAX_IRQ_IN_COMBINER	8
+#define COMBINER_GROUP(x)	((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
+#define COMBINER_IRQ(x, y)	(COMBINER_GROUP(x) + y)
+
+#define IRQ_TIMER0_VIC		COMBINER_IRQ(22, 0)
+#define IRQ_TIMER1_VIC		COMBINER_IRQ(22, 1)
+#define IRQ_TIMER2_VIC		COMBINER_IRQ(22, 2)
+#define IRQ_TIMER3_VIC		COMBINER_IRQ(22, 3)
+#define IRQ_TIMER4_VIC		COMBINER_IRQ(22, 4)
+
+#define IRQ_UART0		COMBINER_IRQ(26, 0)
+#define IRQ_UART1		COMBINER_IRQ(26, 1)
+#define IRQ_UART2		COMBINER_IRQ(26, 2)
+#define IRQ_UART3		COMBINER_IRQ(26, 3)
+#define IRQ_UART4		COMBINER_IRQ(26, 4)
+
+#define IRQ_IIC			COMBINER_IRQ(27, 0)
+
+/* Set the default NR_IRQS */
+#define NR_IRQS			COMBINER_IRQ(MAX_COMBINER_NR, 0)
+
+#define MAX_COMBINER_NR		39
+
+#endif /* ASM_ARCH_IRQS_H */

+ 69 - 0
arch/arm/mach-s5pv310/include/mach/map.h

@@ -0,0 +1,69 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/map.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV310 - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MAP_H
+#define __ASM_ARCH_MAP_H __FILE__
+
+#include <plat/map-base.h>
+
+/*
+ * S5PV310 UART offset is 0x10000 but the older S5P SoCs are 0x400.
+ * So need to define it, and here is to avoid redefinition warning.
+ */
+#define S3C_UART_OFFSET			(0x10000)
+
+#include <plat/map-s5p.h>
+
+#define S5PV310_PA_CHIPID		(0x10000000)
+#define S5P_PA_CHIPID			S5PV310_PA_CHIPID
+
+#define S5PV310_PA_SYSCON		(0x10020000)
+#define S5P_PA_SYSCON			S5PV310_PA_SYSCON
+
+#define S5PV310_PA_WATCHDOG		(0x10060000)
+
+#define S5PV310_PA_COMBINER		(0x10448000)
+
+#define S5PV310_PA_COREPERI		(0x10500000)
+#define S5PV310_PA_GIC_CPU		(0x10500100)
+#define S5PV310_PA_TWD			(0x10500600)
+#define S5PV310_PA_GIC_DIST		(0x10501000)
+#define S5PV310_PA_L2CC			(0x10502000)
+
+#define S5PV310_PA_GPIO			(0x11000000)
+#define S5P_PA_GPIO			S5PV310_PA_GPIO
+
+#define S5PV310_PA_UART			(0x13800000)
+
+#define S5P_PA_UART(x)			(S5PV310_PA_UART + ((x) * S3C_UART_OFFSET))
+#define S5P_PA_UART0			S5P_PA_UART(0)
+#define S5P_PA_UART1			S5P_PA_UART(1)
+#define S5P_PA_UART2			S5P_PA_UART(2)
+#define S5P_PA_UART3			S5P_PA_UART(3)
+#define S5P_PA_UART4			S5P_PA_UART(4)
+
+#define S5P_SZ_UART			SZ_256
+
+#define S5PV310_PA_IIC0			(0x13860000)
+
+#define S5PV310_PA_TIMER		(0x139D0000)
+#define S5P_PA_TIMER			S5PV310_PA_TIMER
+
+#define S5PV310_PA_SDRAM		(0x40000000)
+#define S5P_PA_SDRAM			S5PV310_PA_SDRAM
+
+/* compatibiltiy defines. */
+#define S3C_PA_UART			S5PV310_PA_UART
+#define S3C_PA_IIC			S5PV310_PA_IIC0
+#define S3C_PA_WDT			S5PV310_PA_WATCHDOG
+
+#endif /* __ASM_ARCH_MAP_H */

+ 22 - 0
arch/arm/mach-s5pv310/include/mach/memory.h

@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/memory.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV310 - Memory definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H __FILE__
+
+#define PHYS_OFFSET		UL(0x40000000)
+
+/* Maximum of 256MiB in one bank */
+#define MAX_PHYSMEM_BITS	32
+#define SECTION_SIZE_BITS	28
+
+#endif /* __ASM_ARCH_MEMORY_H */

+ 70 - 0
arch/arm/mach-s5pv310/include/mach/pwm-clock.h

@@ -0,0 +1,70 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/pwm-clock.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
+ *
+ * S5PV310 - pwm clock and timer support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_PWMCLK_H
+#define __ASM_ARCH_PWMCLK_H __FILE__
+
+/**
+ * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
+ * @tcfg: The timer TCFG1 register bits shifted down to 0.
+ *
+ * Return true if the given configuration from TCFG1 is a TCLK instead
+ * any of the TDIV clocks.
+ */
+static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
+{
+	return tcfg == S3C64XX_TCFG1_MUX_TCLK;
+}
+
+/**
+ * tcfg_to_divisor() - convert tcfg1 setting to a divisor
+ * @tcfg1: The tcfg1 setting, shifted down.
+ *
+ * Get the divisor value for the given tcfg1 setting. We assume the
+ * caller has already checked to see if this is not a TCLK source.
+ */
+static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
+{
+	return 1 << tcfg1;
+}
+
+/**
+ * pwm_tdiv_has_div1() - does the tdiv setting have a /1
+ *
+ * Return true if we have a /1 in the tdiv setting.
+ */
+static inline unsigned int pwm_tdiv_has_div1(void)
+{
+	return 1;
+}
+
+/**
+ * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
+ * @div: The divisor to calculate the bit information for.
+ *
+ * Turn a divisor into the necessary bit field for TCFG1.
+ */
+static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
+{
+	return ilog2(div);
+}
+
+#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
+
+#endif /* __ASM_ARCH_PWMCLK_H */

+ 62 - 0
arch/arm/mach-s5pv310/include/mach/regs-clock.h

@@ -0,0 +1,62 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/regs-clock.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV310 - Clock register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_CLOCK_H
+#define __ASM_ARCH_REGS_CLOCK_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_CLKREG(x)			(S3C_VA_SYS + (x))
+
+#define S5P_INFORM0			S5P_CLKREG(0x800)
+
+#define S5P_EPLL_CON0			S5P_CLKREG(0x1C110)
+#define S5P_EPLL_CON1			S5P_CLKREG(0x1C114)
+#define S5P_VPLL_CON0			S5P_CLKREG(0x1C120)
+#define S5P_VPLL_CON1			S5P_CLKREG(0x1C124)
+
+#define S5P_CLKSRC_TOP0			S5P_CLKREG(0x1C210)
+#define S5P_CLKSRC_TOP1			S5P_CLKREG(0x1C214)
+
+#define S5P_CLKSRC_PERIL0		S5P_CLKREG(0x1C250)
+
+#define S5P_CLKDIV_TOP			S5P_CLKREG(0x1C510)
+
+#define S5P_CLKDIV_PERIL0		S5P_CLKREG(0x1C550)
+#define S5P_CLKDIV_PERIL1		S5P_CLKREG(0x1C554)
+#define S5P_CLKDIV_PERIL2		S5P_CLKREG(0x1C558)
+#define S5P_CLKDIV_PERIL3		S5P_CLKREG(0x1C55C)
+#define S5P_CLKDIV_PERIL4		S5P_CLKREG(0x1C560)
+#define S5P_CLKDIV_PERIL5		S5P_CLKREG(0x1C564)
+
+#define S5P_CLKGATE_IP_PERIL		S5P_CLKREG(0x1C950)
+
+#define S5P_CLKSRC_CORE			S5P_CLKREG(0x20200)
+
+#define S5P_CLKDIV_CORE0		S5P_CLKREG(0x20500)
+
+#define S5P_APLL_LOCK			S5P_CLKREG(0x24000)
+#define S5P_MPLL_LOCK			S5P_CLKREG(0x24004)
+#define S5P_APLL_CON0			S5P_CLKREG(0x24100)
+#define S5P_APLL_CON1			S5P_CLKREG(0x24104)
+#define S5P_MPLL_CON0			S5P_CLKREG(0x24108)
+#define S5P_MPLL_CON1			S5P_CLKREG(0x2410C)
+
+#define S5P_CLKSRC_CPU			S5P_CLKREG(0x24200)
+#define S5P_CLKMUX_STATCPU		S5P_CLKREG(0x24400)
+
+#define S5P_CLKDIV_CPU			S5P_CLKREG(0x24500)
+#define S5P_CLKDIV_STATCPU		S5P_CLKREG(0x24600)
+
+#define S5P_CLKGATE_SCLKCPU		S5P_CLKREG(0x24800)
+
+#endif /* __ASM_ARCH_REGS_CLOCK_H */

+ 19 - 0
arch/arm/mach-s5pv310/include/mach/regs-irq.h

@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/regs-irq.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV310 - IRQ register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_IRQ_H
+#define __ASM_ARCH_REGS_IRQ_H __FILE__
+
+#include <asm/hardware/gic.h>
+#include <mach/map.h>
+
+#endif /* __ASM_ARCH_REGS_IRQ_H */

+ 29 - 0
arch/arm/mach-s5pv310/include/mach/smp.h

@@ -0,0 +1,29 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/smp.h
+ *
+ * Cloned from arch/arm/mach-realview/include/mach/smp.h
+*/
+
+#ifndef ASM_ARCH_SMP_H
+#define ASM_ARCH_SMP_H __FILE__
+
+#include <asm/hardware/gic.h>
+
+extern void __iomem *gic_cpu_base_addr;
+
+#define hard_smp_processor_id()			\
+	({						\
+		unsigned int cpunum;			\
+		__asm__("mrc p15, 0, %0, c0, c0, 5"	\
+			: "=r" (cpunum));		\
+		cpunum &= 0x03;				\
+	})
+
+/*
+ * We use IRQ1 as the IPI
+ */
+static inline void smp_cross_call(const struct cpumask *mask)
+{
+	gic_raise_softirq(mask, 1);
+}
+
+#endif

+ 22 - 0
arch/arm/mach-s5pv310/include/mach/system.h

@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/system.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV310 - system support header
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H __FILE__
+
+#include <plat/system-reset.h>
+
+static void arch_idle(void)
+{
+	/* nothing here yet */
+}
+#endif /* __ASM_ARCH_SYSTEM_H */

+ 29 - 0
arch/arm/mach-s5pv310/include/mach/timex.h

@@ -0,0 +1,29 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/timex.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Copyright (c) 2003-2010 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Based on arch/arm/mach-s5p6442/include/mach/timex.h
+ *
+ * S5PV310 - time parameters
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H __FILE__
+
+/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
+ * a variable is useless. It seems as long as we make our timers an
+ * exact multiple of HZ, any value that makes a 1->1 correspondence
+ * for the time conversion functions to/from jiffies is acceptable.
+*/
+
+#define CLOCK_TICK_RATE 12000000
+
+#endif /* __ASM_ARCH_TIMEX_H */

+ 30 - 0
arch/arm/mach-s5pv310/include/mach/uncompress.h

@@ -0,0 +1,30 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/uncompress.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV310 - uncompress code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H __FILE__
+
+#include <mach/map.h>
+#include <plat/uncompress.h>
+
+static void arch_detect_cpu(void)
+{
+	/* we do not need to do any cpu detection here at the moment. */
+
+	/*
+	 * For preventing FIFO overrun or infinite loop of UART console,
+	 * fifo_max should be the minimum fifo size of all of the UART channels
+	 */
+	fifo_mask = S5PV210_UFSTAT_TXMASK;
+	fifo_max = 15 << S5PV210_UFSTAT_TXSHIFT;
+}
+#endif /* __ASM_ARCH_UNCOMPRESS_H */

+ 22 - 0
arch/arm/mach-s5pv310/include/mach/vmalloc.h

@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/vmalloc.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
+ *
+ * Based on arch/arm/mach-s5p6440/include/mach/vmalloc.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * S5PV310 vmalloc definition
+*/
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H __FILE__
+
+#define VMALLOC_END	  (0xF0000000)
+
+#endif /* __ASM_ARCH_VMALLOC_H */

+ 41 - 0
arch/arm/mach-s5pv310/init.c

@@ -0,0 +1,41 @@
+/* linux/arch/arm/mach-s5pv310/init.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/serial_core.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/regs-serial.h>
+
+static struct s3c24xx_uart_clksrc s5pv310_serial_clocks[] = {
+	[0] = {
+		.name		= "uclk1",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	},
+};
+
+/* uart registration process */
+void __init s5pv310_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	struct s3c2410_uartcfg *tcfg = cfg;
+	u32 ucnt;
+
+	for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
+		if (!tcfg->clocks) {
+			tcfg->has_fracval = 1;
+			tcfg->clocks = s5pv310_serial_clocks;
+			tcfg->clocks_size = ARRAY_SIZE(s5pv310_serial_clocks);
+		}
+	}
+
+	s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
+}

+ 125 - 0
arch/arm/mach-s5pv310/irq-combiner.c

@@ -0,0 +1,125 @@
+/* linux/arch/arm/mach-s5pv310/irq-combiner.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Based on arch/arm/common/gic.c
+ *
+ * IRQ COMBINER support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/io.h>
+
+#include <asm/mach/irq.h>
+
+#define COMBINER_ENABLE_SET	0x0
+#define COMBINER_ENABLE_CLEAR	0x4
+#define COMBINER_INT_STATUS	0xC
+
+static DEFINE_SPINLOCK(irq_controller_lock);
+
+struct combiner_chip_data {
+	unsigned int irq_offset;
+	void __iomem *base;
+};
+
+static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
+
+static inline void __iomem *combiner_base(unsigned int irq)
+{
+	struct combiner_chip_data *combiner_data = get_irq_chip_data(irq);
+	return combiner_data->base;
+}
+
+static void combiner_mask_irq(unsigned int irq)
+{
+	u32 mask = 1 << (irq % 32);
+
+	__raw_writel(mask, combiner_base(irq) + COMBINER_ENABLE_CLEAR);
+}
+
+static void combiner_unmask_irq(unsigned int irq)
+{
+	u32 mask = 1 << (irq % 32);
+
+	__raw_writel(mask, combiner_base(irq) + COMBINER_ENABLE_SET);
+}
+
+static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct combiner_chip_data *chip_data = get_irq_data(irq);
+	struct irq_chip *chip = get_irq_chip(irq);
+	unsigned int cascade_irq, combiner_irq;
+	unsigned long status;
+
+	/* primary controller ack'ing */
+	chip->ack(irq);
+
+	spin_lock(&irq_controller_lock);
+	status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
+	spin_unlock(&irq_controller_lock);
+
+	if (status == 0)
+		goto out;
+
+	for (combiner_irq = 0; combiner_irq < 32; combiner_irq++) {
+		if (status & 0x1)
+			break;
+		status >>= 1;
+	}
+
+	cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
+	if (unlikely(cascade_irq >= NR_IRQS))
+		do_bad_IRQ(cascade_irq, desc);
+	else
+		generic_handle_irq(cascade_irq);
+
+ out:
+	/* primary controller unmasking */
+	chip->unmask(irq);
+}
+
+static struct irq_chip combiner_chip = {
+	.name		= "COMBINER",
+	.mask		= combiner_mask_irq,
+	.unmask		= combiner_unmask_irq,
+};
+
+void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
+{
+	if (combiner_nr >= MAX_COMBINER_NR)
+		BUG();
+	if (set_irq_data(irq, &combiner_data[combiner_nr]) != 0)
+		BUG();
+	set_irq_chained_handler(irq, combiner_handle_cascade_irq);
+}
+
+void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
+			  unsigned int irq_start)
+{
+	unsigned int i;
+
+	if (combiner_nr >= MAX_COMBINER_NR)
+		BUG();
+
+	combiner_data[combiner_nr].base = base;
+	combiner_data[combiner_nr].irq_offset = irq_start;
+
+	/* Disable all interrupts */
+
+	__raw_writel(0xffffffff, base + COMBINER_ENABLE_CLEAR);
+
+	/* Setup the Linux IRQ subsystem */
+
+	for (i = irq_start; i < combiner_data[combiner_nr].irq_offset
+				+ MAX_IRQ_IN_COMBINER; i++) {
+		set_irq_chip(i, &combiner_chip);
+		set_irq_chip_data(i, &combiner_data[combiner_nr]);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	}
+}

+ 25 - 0
arch/arm/mach-s5pv310/localtimer.c

@@ -0,0 +1,25 @@
+/* linux/arch/arm/mach-s5pv310/localtimer.c
+ *
+ * Cloned from linux/arch/arm/mach-realview/localtimer.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/clockchips.h>
+
+#include <asm/irq.h>
+#include <asm/localtimer.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+void __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	evt->irq = IRQ_LOCALTIMER;
+	twd_timer_setup(evt);
+}

+ 92 - 0
arch/arm/mach-s5pv310/mach-smdkv310.c

@@ -0,0 +1,92 @@
+/* linux/arch/arm/mach-s5pv310/mach-smdkv310.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/serial_core.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <plat/regs-serial.h>
+#include <plat/s5pv310.h>
+#include <plat/cpu.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define SMDKV310_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDKV310_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define SMDKV310_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+};
+
+static void __init smdkv310_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
+}
+
+static void __init smdkv310_machine_init(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+	l2x0_init(S5P_VA_L2CC, 1 << 28, 0xffffffff);
+#endif
+}
+
+MACHINE_START(SMDKV310, "SMDKV310")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= s5pv310_init_irq,
+	.map_io		= smdkv310_map_io,
+	.init_machine	= smdkv310_machine_init,
+	.timer		= &s5pv310_timer,
+MACHINE_END

+ 86 - 0
arch/arm/mach-s5pv310/mach-universal_c210.c

@@ -0,0 +1,86 @@
+/* linux/arch/arm/mach-s5pv310/mach-universal_c210.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/serial_core.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <plat/regs-serial.h>
+#include <plat/s5pv310.h>
+#include <plat/cpu.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define UNIVERSAL_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define UNIVERSAL_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define UNIVERSAL_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG256 |	\
+				 S5PV210_UFCON_RXTRIG256)
+
+static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+};
+
+static void __init universal_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
+}
+
+static void __init universal_machine_init(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+	l2x0_init(S5P_VA_L2CC, 1 << 28, 0xffffffff);
+#endif
+}
+
+MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
+	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= s5pv310_init_irq,
+	.map_io		= universal_map_io,
+	.init_machine	= universal_machine_init,
+	.timer		= &s5pv310_timer,
+MACHINE_END

+ 192 - 0
arch/arm/mach-s5pv310/platsmp.c

@@ -0,0 +1,192 @@
+/* linux/arch/arm/mach-s5pv310/platsmp.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Cloned from linux/arch/arm/mach-vexpress/platsmp.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <asm/localtimer.h>
+#include <asm/smp_scu.h>
+#include <asm/unified.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-clock.h>
+
+extern void s5pv310_secondary_startup(void);
+
+/*
+ * control for which core is the next to come out of the secondary
+ * boot "holding pen"
+ */
+
+volatile int __cpuinitdata pen_release = -1;
+
+static void __iomem *scu_base_addr(void)
+{
+	return (void __iomem *)(S5P_VA_SCU);
+}
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	trace_hardirqs_off();
+
+	/*
+	 * if any interrupts are already enabled for the primary
+	 * core (e.g. timer irq), then they will not have been enabled
+	 * for us: do so
+	 */
+	gic_cpu_init(0, gic_cpu_base_addr);
+
+	/*
+	 * let the primary processor know we're out of the
+	 * pen, then head off into the C entry point
+	 */
+	pen_release = -1;
+	smp_wmb();
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	unsigned long timeout;
+
+	/*
+	 * Set synchronisation state between this boot processor
+	 * and the secondary one
+	 */
+	spin_lock(&boot_lock);
+
+	/*
+	 * The secondary processor is waiting to be released from
+	 * the holding pen - release it, then wait for it to flag
+	 * that it has been released by resetting pen_release.
+	 *
+	 * Note that "pen_release" is the hardware CPU ID, whereas
+	 * "cpu" is Linux's internal ID.
+	 */
+	pen_release = cpu;
+	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+
+	/*
+	 * Send the secondary CPU a soft interrupt, thereby causing
+	 * the boot monitor to read the system wide flags register,
+	 * and branch to the address found there.
+	 */
+	smp_cross_call(cpumask_of(cpu));
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		smp_rmb();
+		if (pen_release == -1)
+			break;
+
+		udelay(10);
+	}
+
+	/*
+	 * now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return pen_release != -1 ? -ENOSYS : 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+
+void __init smp_init_cpus(void)
+{
+	void __iomem *scu_base = scu_base_addr();
+	unsigned int i, ncores;
+
+	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
+
+	/* sanity check */
+	if (ncores == 0) {
+		printk(KERN_ERR
+		       "S5PV310: strange CM count of 0? Default to 1\n");
+
+		ncores = 1;
+	}
+
+	if (ncores > NR_CPUS) {
+		printk(KERN_WARNING
+		       "S5PV310: no. of cores (%d) greater than configured "
+		       "maximum of %d - clipping\n",
+		       ncores, NR_CPUS);
+		ncores = NR_CPUS;
+	}
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	unsigned int ncores = num_possible_cpus();
+	unsigned int cpu = smp_processor_id();
+	int i;
+
+	smp_store_cpu_info(cpu);
+
+	/* are we trying to boot more cores than exist? */
+	if (max_cpus > ncores)
+		max_cpus = ncores;
+
+	/*
+	 * Initialise the present map, which describes the set of CPUs
+	 * actually populated at the present time.
+	 */
+	for (i = 0; i < max_cpus; i++)
+		set_cpu_present(i, true);
+
+	/*
+	 * Initialise the SCU if there are more than one CPU and let
+	 * them know where to start.
+	 */
+	if (max_cpus > 1) {
+		/*
+		 * Enable the local timer or broadcast device for the
+		 * boot CPU, but only if we have more than one CPU.
+		 */
+		percpu_timer_setup();
+
+		scu_enable(scu_base_addr());
+
+		/*
+		 * Write the address of secondary startup into the
+		 * system-wide flags register. The boot monitor waits
+		 * until it receives a soft interrupt, and then the
+		 * secondary CPU branches to this address.
+		 */
+	__raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_INFORM0);
+	}
+}

+ 28 - 0
arch/arm/mach-s5pv310/setup-i2c0.c

@@ -0,0 +1,28 @@
+/*
+ * linux/arch/arm/mach-s5pv310/setup-i2c0.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * I2C0 GPIO configuration.
+ *
+ * Based on plat-s3c64xx/setup-i2c0.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c0_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgpin(S5PV310_GPD1(0), S3C_GPIO_SFN(2));
+	s3c_gpio_setpull(S5PV310_GPD1(0), S3C_GPIO_PULL_UP);
+	s3c_gpio_cfgpin(S5PV310_GPD1(1), S3C_GPIO_SFN(2));
+	s3c_gpio_setpull(S5PV310_GPD1(1), S3C_GPIO_PULL_UP);
+}

+ 25 - 0
arch/arm/mach-s5pv310/setup-i2c1.c

@@ -0,0 +1,25 @@
+/*
+ * linux/arch/arm/mach-s5pv310/setup-i2c1.c
+ *
+ * Copyright (C) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C1 GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c1_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgpin(S5PV310_GPD1(2), S3C_GPIO_SFN(2));
+	s3c_gpio_setpull(S5PV310_GPD1(2), S3C_GPIO_PULL_UP);
+	s3c_gpio_cfgpin(S5PV310_GPD1(3), S3C_GPIO_SFN(2));
+	s3c_gpio_setpull(S5PV310_GPD1(3), S3C_GPIO_PULL_UP);
+}

+ 25 - 0
arch/arm/mach-s5pv310/setup-i2c2.c

@@ -0,0 +1,25 @@
+/*
+ * linux/arch/arm/mach-s5pv310/setup-i2c2.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C2 GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c2_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgpin(S5PV310_GPA0(6), S3C_GPIO_SFN(3));
+	s3c_gpio_setpull(S5PV310_GPA0(6), S3C_GPIO_PULL_UP);
+	s3c_gpio_cfgpin(S5PV310_GPA0(7), S3C_GPIO_SFN(3));
+	s3c_gpio_setpull(S5PV310_GPA0(7), S3C_GPIO_PULL_UP);
+}

+ 287 - 0
arch/arm/mach-s5pv310/time.c

@@ -0,0 +1,287 @@
+/* linux/arch/arm/mach-s5pv310/time.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5PV310 (and compatible) HRT support
+ * PWM 2/4 is used for this feature
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+
+#include <asm/smp_twd.h>
+
+#include <mach/map.h>
+#include <plat/regs-timer.h>
+#include <asm/mach/time.h>
+
+static unsigned long clock_count_per_tick;
+
+static struct clk *tin2;
+static struct clk *tin4;
+static struct clk *tdiv2;
+static struct clk *tdiv4;
+static struct clk *timerclk;
+
+static void s5pv310_pwm_stop(unsigned int pwm_id)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	switch (pwm_id) {
+	case 2:
+		tcon &= ~S3C2410_TCON_T2START;
+		break;
+	case 4:
+		tcon &= ~S3C2410_TCON_T4START;
+		break;
+	default:
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static void s5pv310_pwm_init(unsigned int pwm_id, unsigned long tcnt)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	/* timers reload after counting zero, so reduce the count by 1 */
+	tcnt--;
+
+	/* ensure timer is stopped... */
+	switch (pwm_id) {
+	case 2:
+		tcon &= ~(0xf<<12);
+		tcon |= S3C2410_TCON_T2MANUALUPD;
+
+		__raw_writel(tcnt, S3C2410_TCNTB(2));
+		__raw_writel(tcnt, S3C2410_TCMPB(2));
+		__raw_writel(tcon, S3C2410_TCON);
+
+		break;
+	case 4:
+		tcon &= ~(7<<20);
+		tcon |= S3C2410_TCON_T4MANUALUPD;
+
+		__raw_writel(tcnt, S3C2410_TCNTB(4));
+		__raw_writel(tcnt, S3C2410_TCMPB(4));
+		__raw_writel(tcon, S3C2410_TCON);
+
+		break;
+	default:
+		break;
+	}
+}
+
+static inline void s5pv310_pwm_start(unsigned int pwm_id, bool periodic)
+{
+	unsigned long tcon;
+
+	tcon  = __raw_readl(S3C2410_TCON);
+
+	switch (pwm_id) {
+	case 2:
+		tcon |= S3C2410_TCON_T2START;
+		tcon &= ~S3C2410_TCON_T2MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T2RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T2RELOAD;
+		break;
+	case 4:
+		tcon |= S3C2410_TCON_T4START;
+		tcon &= ~S3C2410_TCON_T4MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T4RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T4RELOAD;
+		break;
+	default:
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static int s5pv310_pwm_set_next_event(unsigned long cycles,
+					struct clock_event_device *evt)
+{
+	s5pv310_pwm_init(2, cycles);
+	s5pv310_pwm_start(2, 0);
+	return 0;
+}
+
+static void s5pv310_pwm_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	s5pv310_pwm_stop(2);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		s5pv310_pwm_init(2, clock_count_per_tick);
+		s5pv310_pwm_start(2, 1);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static struct clock_event_device pwm_event_device = {
+	.name		= "pwm_timer2",
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 200,
+	.shift		= 32,
+	.set_next_event	= s5pv310_pwm_set_next_event,
+	.set_mode	= s5pv310_pwm_set_mode,
+};
+
+irqreturn_t s5pv310_clock_event_isr(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &pwm_event_device;
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction s5pv310_clock_event_irq = {
+	.name		= "pwm_timer2_irq",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= s5pv310_clock_event_isr,
+};
+
+static void __init s5pv310_clockevent_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+	struct clk *tscaler;
+
+	pclk = clk_get_rate(timerclk);
+
+	/* configure clock tick */
+
+	tscaler = clk_get_parent(tdiv2);
+
+	clk_set_rate(tscaler, pclk / 2);
+	clk_set_rate(tdiv2, pclk / 2);
+	clk_set_parent(tin2, tdiv2);
+
+	clock_rate = clk_get_rate(tin2);
+
+	clock_count_per_tick = clock_rate / HZ;
+
+	pwm_event_device.mult =
+		div_sc(clock_rate, NSEC_PER_SEC, pwm_event_device.shift);
+	pwm_event_device.max_delta_ns =
+		clockevent_delta2ns(-1, &pwm_event_device);
+	pwm_event_device.min_delta_ns =
+		clockevent_delta2ns(1, &pwm_event_device);
+
+	pwm_event_device.cpumask = cpumask_of(0);
+	clockevents_register_device(&pwm_event_device);
+
+	setup_irq(IRQ_TIMER2, &s5pv310_clock_event_irq);
+}
+
+static cycle_t s5pv310_pwm4_read(struct clocksource *cs)
+{
+	return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40));
+}
+
+struct clocksource pwm_clocksource = {
+	.name		= "pwm_timer4",
+	.rating		= 250,
+	.read		= s5pv310_pwm4_read,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.shift		= 20,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS ,
+};
+
+static void __init s5pv310_clocksource_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+
+	pclk = clk_get_rate(timerclk);
+
+	clk_set_rate(tdiv4, pclk / 2);
+	clk_set_parent(tin4, tdiv4);
+
+	clock_rate = clk_get_rate(tin4);
+
+	s5pv310_pwm_init(4, ~0);
+	s5pv310_pwm_start(4, 1);
+
+	pwm_clocksource.mult =
+		clocksource_khz2mult(clock_rate/1000, pwm_clocksource.shift);
+
+	if (clocksource_register(&pwm_clocksource))
+		panic("%s: can't register clocksource\n", pwm_clocksource.name);
+}
+
+static void __init s5pv310_timer_resources(void)
+{
+	struct platform_device tmpdev;
+
+	tmpdev.dev.bus = &platform_bus_type;
+
+	timerclk = clk_get(NULL, "timers");
+	if (IS_ERR(timerclk))
+		panic("failed to get timers clock for system timer");
+
+	clk_enable(timerclk);
+
+	tmpdev.id = 2;
+	tin2 = clk_get(&tmpdev.dev, "pwm-tin");
+	if (IS_ERR(tin2))
+		panic("failed to get pwm-tin2 clock for system timer");
+
+	tdiv2 = clk_get(&tmpdev.dev, "pwm-tdiv");
+	if (IS_ERR(tdiv2))
+		panic("failed to get pwm-tdiv2 clock for system timer");
+	clk_enable(tin2);
+
+	tmpdev.id = 4;
+	tin4 = clk_get(&tmpdev.dev, "pwm-tin");
+	if (IS_ERR(tin4))
+		panic("failed to get pwm-tin4 clock for system timer");
+
+	tdiv4 = clk_get(&tmpdev.dev, "pwm-tdiv");
+	if (IS_ERR(tdiv4))
+		panic("failed to get pwm-tdiv4 clock for system timer");
+
+	clk_enable(tin4);
+}
+
+static void __init s5pv310_timer_init(void)
+{
+#ifdef CONFIG_LOCAL_TIMERS
+	twd_base = S5P_VA_TWD;
+#endif
+
+	s5pv310_timer_resources();
+	s5pv310_clockevent_init();
+	s5pv310_clocksource_init();
+}
+
+struct sys_timer s5pv310_timer = {
+	.init		= s5pv310_timer_init,
+};

+ 2 - 1
arch/arm/mm/Kconfig

@@ -782,7 +782,8 @@ config CACHE_L2X0
 	bool "Enable the L2x0 outer cache controller"
 	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
 		   REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \
-		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
+		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
+		   ARCH_S5PV310
 	default y
 	select OUTER_CACHE
 	select OUTER_CACHE_SYNC

+ 3 - 2
arch/arm/plat-s5p/Kconfig

@@ -7,9 +7,10 @@
 
 config PLAT_S5P
 	bool
-	depends on (ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210)
+	depends on (ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310)
 	default y
-	select ARM_VIC
+	select ARM_VIC if !ARCH_S5PV310
+	select ARM_GIC if ARCH_S5PV310
 	select NO_IOPORT
 	select ARCH_REQUIRE_GPIOLIB
 	select S3C_GPIO_TRACK

+ 13 - 1
arch/arm/plat-s5p/cpu.c

@@ -21,6 +21,7 @@
 #include <plat/s5p6442.h>
 #include <plat/s5pc100.h>
 #include <plat/s5pv210.h>
+#include <plat/s5pv310.h>
 
 /* table of supported CPUs */
 
@@ -28,6 +29,7 @@ static const char name_s5p6440[] = "S5P6440";
 static const char name_s5p6442[] = "S5P6442";
 static const char name_s5pc100[] = "S5PC100";
 static const char name_s5pv210[] = "S5PV210/S5PC110";
+static const char name_s5pv310[] = "S5PV310";
 
 static struct cpu_table cpu_ids[] __initdata = {
 	{
@@ -62,6 +64,14 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.init_uarts	= s5pv210_init_uarts,
 		.init		= s5pv210_init,
 		.name		= name_s5pv210,
+	}, {
+		.idcode		= 0x43200000,
+		.idmask		= 0xfffff000,
+		.map_io		= s5pv310_map_io,
+		.init_clocks	= s5pv310_init_clocks,
+		.init_uarts	= s5pv310_init_uarts,
+		.init		= s5pv310_init,
+		.name		= name_s5pv310,
 	},
 };
 
@@ -81,8 +91,9 @@ static struct map_desc s5p_iodesc[] __initdata = {
 	}, {
 		.virtual	= (unsigned long)S3C_VA_UART,
 		.pfn		= __phys_to_pfn(S3C_PA_UART),
-		.length		= SZ_4K,
+		.length		= SZ_512K,
 		.type		= MT_DEVICE,
+#ifdef CONFIG_ARM_VIC
 	}, {
 		.virtual	= (unsigned long)VA_VIC0,
 		.pfn		= __phys_to_pfn(S5P_PA_VIC0),
@@ -93,6 +104,7 @@ static struct map_desc s5p_iodesc[] __initdata = {
 		.pfn		= __phys_to_pfn(S5P_PA_VIC1),
 		.length		= SZ_16K,
 		.type		= MT_DEVICE,
+#endif
 	}, {
 		.virtual	= (unsigned long)S3C_VA_TIMER,
 		.pfn		= __phys_to_pfn(S5P_PA_TIMER),

+ 19 - 4
arch/arm/plat-s5p/include/plat/map-s5p.h

@@ -18,12 +18,27 @@
 #define S5P_VA_SYSTIMER		S3C_ADDR(0x01200000)
 #define S5P_VA_SROMC		S3C_ADDR(0x01100000)
 
-#define S5P_VA_UART0		(S3C_VA_UART + 0x0)
-#define S5P_VA_UART1		(S3C_VA_UART + 0x400)
-#define S5P_VA_UART2		(S3C_VA_UART + 0x800)
-#define S5P_VA_UART3		(S3C_VA_UART + 0xC00)
+#define S5P_VA_COMBINER_BASE	S3C_ADDR(0x00600000)
+#define S5P_VA_COMBINER(x)	(S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10)
 
+#define S5P_VA_COREPERI_BASE	S3C_ADDR(0x00800000)
+#define S5P_VA_COREPERI(x)	(S5P_VA_COREPERI_BASE + (x))
+#define S5P_VA_SCU		S5P_VA_COREPERI(0x0)
+#define S5P_VA_GIC_CPU		S5P_VA_COREPERI(0x100)
+#define S5P_VA_TWD		S5P_VA_COREPERI(0x600)
+#define S5P_VA_GIC_DIST		S5P_VA_COREPERI(0x1000)
+
+#define S5P_VA_L2CC		S3C_ADDR(0x00900000)
+
+#define S5P_VA_UART(x)		(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
+#define S5P_VA_UART0		S5P_VA_UART(0)
+#define S5P_VA_UART1		S5P_VA_UART(1)
+#define S5P_VA_UART2		S5P_VA_UART(2)
+#define S5P_VA_UART3		S5P_VA_UART(3)
+
+#ifndef S3C_UART_OFFSET
 #define S3C_UART_OFFSET		(0x400)
+#endif
 
 #define VA_VIC(x)		(S3C_VA_IRQ + ((x) * 0x10000))
 #define VA_VIC0			VA_VIC(0)

+ 41 - 0
arch/arm/plat-s5p/include/plat/pll.h

@@ -46,6 +46,47 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
 	return (unsigned long)fvco;
 }
 
+#define PLL46XX_KDIV_MASK	(0xFFFF)
+#define PLL46XX_MDIV_MASK	(0x1FF)
+#define PLL46XX_PDIV_MASK	(0x3F)
+#define PLL46XX_SDIV_MASK	(0x7)
+#define PLL46XX_MDIV_SHIFT	(16)
+#define PLL46XX_PDIV_SHIFT	(8)
+#define PLL46XX_SDIV_SHIFT	(0)
+
+enum pll46xx_type_t {
+	pll_4600,
+	pll_4650,
+};
+
+static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
+					    u32 pll_con0, u32 pll_con1,
+					    enum pll46xx_type_t pll_type)
+{
+	unsigned long result;
+	u32 mdiv, pdiv, sdiv, kdiv;
+	u64 tmp;
+
+	mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
+	pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
+	sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
+	kdiv = pll_con1 & PLL46XX_KDIV_MASK;
+
+	tmp = baseclk;
+
+	if (pll_type == pll_4600) {
+		tmp *= (mdiv << 16) + kdiv;
+		do_div(tmp, (pdiv << sdiv));
+		result = tmp >> 16;
+	} else {
+		tmp *= (mdiv << 10) + kdiv;
+		do_div(tmp, (pdiv << sdiv));
+		result = tmp >> 10;
+	}
+
+	return result;
+}
+
 #define PLL90XX_MDIV_MASK	(0xFF)
 #define PLL90XX_PDIV_MASK	(0x3F)
 #define PLL90XX_SDIV_MASK	(0x7)

+ 34 - 0
arch/arm/plat-s5p/include/plat/s5pv310.h

@@ -0,0 +1,34 @@
+/* linux/arch/arm/plat-s5p/include/plat/s5pv310.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for s5pv310 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Common init code for S5PV310 related SoCs */
+
+extern void s5pv310_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s5pv310_register_clocks(void);
+extern void s5pv310_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5PV310
+
+extern  int s5pv310_init(void);
+extern void s5pv310_init_irq(void);
+extern void s5pv310_map_io(void);
+extern void s5pv310_init_clocks(int xtal);
+extern struct sys_timer s5pv310_timer;
+
+#define s5pv310_init_uarts s5pv310_common_init_uarts
+
+#else
+#define s5pv310_init_clocks NULL
+#define s5pv310_init_uarts NULL
+#define s5pv310_map_io NULL
+#define s5pv310_init NULL
+#endif

+ 2 - 0
arch/arm/plat-s5p/irq.c

@@ -56,11 +56,13 @@ static struct s3c_uart_irq uart_irqs[] = {
 
 void __init s5p_init_irq(u32 *vic, u32 num_vic)
 {
+#ifdef CONFIG_ARM_VIC
 	int irq;
 
 	/* initialize the VICs */
 	for (irq = 0; irq < num_vic; irq++)
 		vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0);
+#endif
 
 	s3c_init_vic_timer_irq(IRQ_TIMER0_VIC, IRQ_TIMER0);
 	s3c_init_vic_timer_irq(IRQ_TIMER1_VIC, IRQ_TIMER1);

+ 1 - 1
arch/arm/plat-samsung/Makefile

@@ -12,7 +12,7 @@ obj-				:=
 # Objects we always build independent of SoC choice
 
 obj-y				+= init.o
-obj-y				+= time.o
+obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET)   += time.o
 obj-y				+= clock.o
 obj-y				+= pwm-clock.o
 obj-y				+= gpio.o

+ 2 - 0
arch/arm/plat-samsung/include/plat/regs-serial.h

@@ -259,6 +259,8 @@ struct s3c2410_uartcfg {
 	unsigned short	   flags;
 	upf_t		   uart_flags;	 /* default uart flags */
 
+	unsigned int	   has_fracval;
+
 	unsigned long	   ucon;	 /* value of ucon for port */
 	unsigned long	   ulcon;	 /* value of ulcon for port */
 	unsigned long	   ufcon;	 /* value of ufcon for port */

+ 2 - 2
drivers/serial/Kconfig

@@ -544,8 +544,8 @@ config SERIAL_S3C6400
 
 config SERIAL_S5PV210
 	tristate "Samsung S5PV210 Serial port support"
-	depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442)
-	select SERIAL_SAMSUNG_UARTS_4 if CPU_S5PV210
+	depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442 || CPU_S5PV310)
+	select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_S5PV310)
 	default y
 	help
 	  Serial port support for Samsung's S5P Family of SoC's

+ 8 - 0
drivers/serial/s5pv210.c

@@ -28,8 +28,12 @@
 static int s5pv210_serial_setsource(struct uart_port *port,
 					struct s3c24xx_uart_clksrc *clk)
 {
+	struct s3c2410_uartcfg *cfg = port->dev->platform_data;
 	unsigned long ucon = rd_regl(port, S3C2410_UCON);
 
+	if ((cfg->clocks_size) == 1)
+		return 0;
+
 	if (strcmp(clk->name, "pclk") == 0)
 		ucon &= ~S5PV210_UCON_CLKMASK;
 	else if (strcmp(clk->name, "uclk1") == 0)
@@ -47,10 +51,14 @@ static int s5pv210_serial_setsource(struct uart_port *port,
 static int s5pv210_serial_getsource(struct uart_port *port,
 					struct s3c24xx_uart_clksrc *clk)
 {
+	struct s3c2410_uartcfg *cfg = port->dev->platform_data;
 	u32 ucon = rd_regl(port, S3C2410_UCON);
 
 	clk->divisor = 1;
 
+	if ((cfg->clocks_size) == 1)
+		return 0;
+
 	switch (ucon & S5PV210_UCON_CLKMASK) {
 	case S5PV210_UCON_PCLK:
 		clk->name = "pclk";

+ 7 - 2
drivers/serial/samsung.c

@@ -705,8 +705,13 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
 	if (ourport->info->has_divslot) {
 		unsigned int div = ourport->baudclk_rate / baud;
 
-		udivslot = udivslot_table[div & 15];
-		dbg("udivslot = %04x (div %d)\n", udivslot, div & 15);
+		if (cfg->has_fracval) {
+			udivslot = (div & 15);
+			dbg("fracval = %04x\n", udivslot);
+		} else {
+			udivslot = udivslot_table[div & 15];
+			dbg("udivslot = %04x (div %d)\n", udivslot, div & 15);
+		}
 	}
 
 	switch (termios->c_cflag & CSIZE) {