linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/8] ARM: S5PV310: Add support for Samsung S5PV310 SoC
@ 2010-07-16  8:58 Kukjin Kim
  2010-07-16  8:58 ` [PATCH v2 1/8] ARM: S5P: Remove fixed uart offset dependent code Kukjin Kim
                   ` (7 more replies)
  0 siblings, 8 replies; 21+ messages in thread
From: Kukjin Kim @ 2010-07-16  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

This patch set adds support for Samsung S5PV310/S5PC210. The S5PV310
integrates a ARM Cortex A9 microprocessor with several other peripherals
to support features such as multimedia, storage, graphics and gaming.
The S5PV310 can be used in products such as Netbooks and Mobile devices.

Changes since v1:

- Address comments from Rabin Vincent
  : removed unnecessary loking in the irq support functions
  : removed unnecessary debug message in the s5pv310_pwm_init()
  : moved pwm_init() and pwm_start()

- Modified FRACVAL support method in serial/samsung.c
  This can be supported S5PV310 serial with serial/s5pv210.c

- Some coding-style fixes

- Added some comments


This patch set consists of the following patches.

[PATCH v2 1/8] ARM: S5P: Remove fixed uart offset dependent code
[PATCH v2 2/8] ARM: S5PV310: Add new CPU initialization support
[PATCH v2 3/8] ARM: S5PV310: Add Clock and PLL support
[PATCH v2 4/8] ARM: S5PV310: Add IRQ support
[PATCH v2 5/8] ARM: S5PV310: Add Timer support
[PATCH v2 6/8] ARM: S5PV310: Add new Kconfig and Makefiles
[PATCH v2 7/8] ARM: S5PV310: Add Board support file
[PATCH v2 8/8] ARM: S5PV310: Add serial port support

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 1/8] ARM: S5P: Remove fixed uart offset dependent code
  2010-07-16  8:58 [PATCH v2 0/8] ARM: S5PV310: Add support for Samsung S5PV310 SoC Kukjin Kim
@ 2010-07-16  8:58 ` Kukjin Kim
  2010-07-16  8:58 ` [PATCH v2 2/8] ARM: S5PV310: Add new CPU initialization support Kukjin Kim
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Kukjin Kim @ 2010-07-16  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Changhwan Youn <chaos.youn@samsung.com>

The uart offset between channels has been 0x400 for all S5P series
and to present virtual and physical offsets, both number 0x400 and
S3C_UART_OFFSET have been used together.
This patch removes the use of the number 0x400 and expands the virtual
mapping size of S3C_VA_UART from 4KB to 512KB to support the CPU with
S3C_UART_OFFSET being 0x10000.

Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/plat-s5p/cpu.c                  |    2 +-
 arch/arm/plat-s5p/include/plat/map-s5p.h |   11 +++++++----
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c
index 75cb8c3..c478441 100644
--- a/arch/arm/plat-s5p/cpu.c
+++ b/arch/arm/plat-s5p/cpu.c
@@ -81,7 +81,7 @@ 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,
 	}, {
 		.virtual	= (unsigned long)VA_VIC0,
diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h
index 1482852..3d815f4 100644
--- a/arch/arm/plat-s5p/include/plat/map-s5p.h
+++ b/arch/arm/plat-s5p/include/plat/map-s5p.h
@@ -18,12 +18,15 @@
 #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_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)
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 2/8] ARM: S5PV310: Add new CPU initialization support
  2010-07-16  8:58 [PATCH v2 0/8] ARM: S5PV310: Add support for Samsung S5PV310 SoC Kukjin Kim
  2010-07-16  8:58 ` [PATCH v2 1/8] ARM: S5P: Remove fixed uart offset dependent code Kukjin Kim
@ 2010-07-16  8:58 ` Kukjin Kim
  2010-07-16 10:58   ` Kyungmin Park
  2010-07-16 11:52   ` Russell King - ARM Linux
  2010-07-16  8:58 ` [PATCH v2 3/8] ARM: S5PV310: Add Clock and PLL support Kukjin Kim
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 21+ messages in thread
From: Kukjin Kim @ 2010-07-16  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Changhwan Youn <chaos.youn@samsung.com>

This patch adds Samsung's S5PV310/S5PC210 CPU support.
The S5PV310/S5PC210 integrates a ARM Cortex A9 multi-core.

Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Jongpill Lee <boyko.lee@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pv310/cpu.c                      |  122 +++++++++++++
 arch/arm/mach-s5pv310/headsmp.S                  |   41 ++++
 arch/arm/mach-s5pv310/include/mach/debug-macro.S |   36 ++++
 arch/arm/mach-s5pv310/include/mach/entry-macro.S |   84 +++++++++
 arch/arm/mach-s5pv310/include/mach/gpio.h        |  135 ++++++++++++++
 arch/arm/mach-s5pv310/include/mach/hardware.h    |   18 ++
 arch/arm/mach-s5pv310/include/mach/io.h          |   26 +++
 arch/arm/mach-s5pv310/include/mach/map.h         |   66 +++++++
 arch/arm/mach-s5pv310/include/mach/memory.h      |   22 +++
 arch/arm/mach-s5pv310/include/mach/smp.h         |   29 +++
 arch/arm/mach-s5pv310/include/mach/system.h      |   22 +++
 arch/arm/mach-s5pv310/include/mach/timex.h       |   29 +++
 arch/arm/mach-s5pv310/include/mach/uncompress.h  |   27 +++
 arch/arm/mach-s5pv310/include/mach/vmalloc.h     |   22 +++
 arch/arm/mach-s5pv310/init.c                     |   41 ++++
 arch/arm/mach-s5pv310/platsmp.c                  |  212 ++++++++++++++++++++++
 arch/arm/mach-s5pv310/setup-i2c0.c               |   20 ++
 arch/arm/plat-s5p/cpu.c                          |   12 ++
 arch/arm/plat-s5p/include/plat/map-s5p.h         |   12 ++
 arch/arm/plat-s5p/include/plat/s5pv310.h         |   33 ++++
 20 files changed, 1009 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-s5pv310/cpu.c
 create mode 100644 arch/arm/mach-s5pv310/headsmp.S
 create mode 100644 arch/arm/mach-s5pv310/include/mach/debug-macro.S
 create mode 100644 arch/arm/mach-s5pv310/include/mach/entry-macro.S
 create mode 100644 arch/arm/mach-s5pv310/include/mach/gpio.h
 create mode 100644 arch/arm/mach-s5pv310/include/mach/hardware.h
 create mode 100644 arch/arm/mach-s5pv310/include/mach/io.h
 create mode 100644 arch/arm/mach-s5pv310/include/mach/map.h
 create mode 100644 arch/arm/mach-s5pv310/include/mach/memory.h
 create mode 100644 arch/arm/mach-s5pv310/include/mach/smp.h
 create mode 100644 arch/arm/mach-s5pv310/include/mach/system.h
 create mode 100644 arch/arm/mach-s5pv310/include/mach/timex.h
 create mode 100644 arch/arm/mach-s5pv310/include/mach/uncompress.h
 create mode 100644 arch/arm/mach-s5pv310/include/mach/vmalloc.h
 create mode 100644 arch/arm/mach-s5pv310/init.c
 create mode 100644 arch/arm/mach-s5pv310/platsmp.c
 create mode 100644 arch/arm/mach-s5pv310/setup-i2c0.c
 create mode 100644 arch/arm/plat-s5p/include/plat/s5pv310.h

diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c
new file mode 100644
index 0000000..196c9f1
--- /dev/null
+++ b/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);
+}
diff --git a/arch/arm/mach-s5pv310/headsmp.S b/arch/arm/mach-s5pv310/headsmp.S
new file mode 100644
index 0000000..164b7b0
--- /dev/null
+++ b/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
diff --git a/arch/arm/mach-s5pv310/include/mach/debug-macro.S b/arch/arm/mach-s5pv310/include/mach/debug-macro.S
new file mode 100644
index 0000000..6fb3893
--- /dev/null
+++ b/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>
diff --git a/arch/arm/mach-s5pv310/include/mach/entry-macro.S b/arch/arm/mach-s5pv310/include/mach/entry-macro.S
new file mode 100644
index 0000000..e600e1d
--- /dev/null
+++ b/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
diff --git a/arch/arm/mach-s5pv310/include/mach/gpio.h b/arch/arm/mach-s5pv310/include/mach/gpio.h
new file mode 100644
index 0000000..20cb80c
--- /dev/null
+++ b/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 */
diff --git a/arch/arm/mach-s5pv310/include/mach/hardware.h b/arch/arm/mach-s5pv310/include/mach/hardware.h
new file mode 100644
index 0000000..28ff988
--- /dev/null
+++ b/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 */
diff --git a/arch/arm/mach-s5pv310/include/mach/io.h b/arch/arm/mach-s5pv310/include/mach/io.h
new file mode 100644
index 0000000..8a7f912
--- /dev/null
+++ b/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 */
diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h
new file mode 100644
index 0000000..50e0901
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/map.h
@@ -0,0 +1,66 @@
+/* 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_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
+
+#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/memory.h b/arch/arm/mach-s5pv310/include/mach/memory.h
new file mode 100644
index 0000000..1dffb48
--- /dev/null
+++ b/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 */
diff --git a/arch/arm/mach-s5pv310/include/mach/smp.h b/arch/arm/mach-s5pv310/include/mach/smp.h
new file mode 100644
index 0000000..990f3ba
--- /dev/null
+++ b/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
diff --git a/arch/arm/mach-s5pv310/include/mach/system.h b/arch/arm/mach-s5pv310/include/mach/system.h
new file mode 100644
index 0000000..d10c009
--- /dev/null
+++ b/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 */
diff --git a/arch/arm/mach-s5pv310/include/mach/timex.h b/arch/arm/mach-s5pv310/include/mach/timex.h
new file mode 100644
index 0000000..bd2359b
--- /dev/null
+++ b/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 */
diff --git a/arch/arm/mach-s5pv310/include/mach/uncompress.h b/arch/arm/mach-s5pv310/include/mach/uncompress.h
new file mode 100644
index 0000000..ad88c24
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/uncompress.h
@@ -0,0 +1,27 @@
+/* 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. */
+
+	fifo_mask = S5PV210_UFSTAT_TXMASK;
+	fifo_max = 63 << S5PV210_UFSTAT_TXSHIFT;
+}
+
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/vmalloc.h b/arch/arm/mach-s5pv310/include/mach/vmalloc.h
new file mode 100644
index 0000000..426d997
--- /dev/null
+++ b/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	  (0xE0000000)
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5pv310/init.c b/arch/arm/mach-s5pv310/init.c
new file mode 100644
index 0000000..182dcf4
--- /dev/null
+++ b/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);
+}
diff --git a/arch/arm/mach-s5pv310/platsmp.c b/arch/arm/mach-s5pv310/platsmp.c
new file mode 100644
index 0000000..9325ac2
--- /dev/null
+++ b/arch/arm/mach-s5pv310/platsmp.c
@@ -0,0 +1,212 @@
+/* linux/arch/arm/mach-s5pv310/platsmp.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Cloned from linux/arch/arm/mach-realview/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 <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/localtimer.h>
+#include <asm/unified.h>
+
+#include <asm/smp_scu.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 inline unsigned int get_core_count(void)
+{
+	void __iomem *scu_base = scu_base_addr();
+	if (scu_base)
+		return scu_get_core_count(scu_base);
+	return 1;
+}
+
+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;
+	flush_cache_all();
+
+	/*
+	 * XXX
+	 *
+	 * This is a later addition to the booting protocol: the
+	 * bootMonitor now puts secondary cores into WFI, so
+	 * poke_milo() no longer gets the cores moving; we need
+	 * to send a soft interrupt to wake the secondary core.
+	 * Use smp_cross_call() for this, since there's little
+	 * point duplicating the code here
+	 */
+	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;
+}
+
+static void __init poke_milo(void)
+{
+	/* nobody is to be released from the pen yet */
+	pen_release = -1;
+
+	/*
+	 * Write the address of secondary startup into the system-wide flags
+	 * register. The BootMonitor waits for this register to become
+	 * non-zero.
+	 */
+	__raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_INFORM0);
+
+	mb();
+}
+
+/*
+ * 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)
+{
+	unsigned int i, ncores = get_core_count();
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	unsigned int ncores = get_core_count();
+	unsigned int cpu = smp_processor_id();
+	int i;
+
+	/* sanity check */
+	if (ncores == 0) {
+		printk(KERN_ERR
+		       "Realview: strange CM count of 0? Default to 1\n");
+
+		ncores = 1;
+	}
+
+	if (ncores > NR_CPUS) {
+		printk(KERN_WARNING
+		       "Realview: no. of cores (%d) greater than configured "
+		       "maximum of %d - clipping\n",
+		       ncores, NR_CPUS);
+		ncores = NR_CPUS;
+	}
+
+	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. Note that, on modern versions of
+	 * MILO, the "poke" doesn't actually do anything until each
+	 * individual core is sent a soft interrupt to get it out of
+	 * WFI
+	 */
+	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());
+		poke_milo();
+	}
+}
diff --git a/arch/arm/mach-s5pv310/setup-i2c0.c b/arch/arm/mach-s5pv310/setup-i2c0.c
new file mode 100644
index 0000000..d4f5a81
--- /dev/null
+++ b/arch/arm/mach-s5pv310/setup-i2c0.c
@@ -0,0 +1,20 @@
+/* linux/arch/arm/mach-s5pv210/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 */
+
+void s3c_i2c0_cfg_gpio(struct platform_device *dev)
+{
+/* will be implemented later */
+}
diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c
index c478441..9261a27 100644
--- a/arch/arm/plat-s5p/cpu.c
+++ b/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,
 	},
 };
 
@@ -83,6 +93,7 @@ static struct map_desc s5p_iodesc[] __initdata = {
 		.pfn		= __phys_to_pfn(S3C_PA_UART),
 		.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),
diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h
index 3d815f4..54e9fb9 100644
--- a/arch/arm/plat-s5p/include/plat/map-s5p.h
+++ b/arch/arm/plat-s5p/include/plat/map-s5p.h
@@ -18,6 +18,18 @@
 #define S5P_VA_SYSTIMER		S3C_ADDR(0x01200000)
 #define S5P_VA_SROMC		S3C_ADDR(0x01100000)
 
+#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)
diff --git a/arch/arm/plat-s5p/include/plat/s5pv310.h b/arch/arm/plat-s5p/include/plat/s5pv310.h
new file mode 100644
index 0000000..d2f05e1
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/s5pv310.h
@@ -0,0 +1,33 @@
+/* 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);
+
+#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
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 3/8] ARM: S5PV310: Add Clock and PLL support
  2010-07-16  8:58 [PATCH v2 0/8] ARM: S5PV310: Add support for Samsung S5PV310 SoC Kukjin Kim
  2010-07-16  8:58 ` [PATCH v2 1/8] ARM: S5P: Remove fixed uart offset dependent code Kukjin Kim
  2010-07-16  8:58 ` [PATCH v2 2/8] ARM: S5PV310: Add new CPU initialization support Kukjin Kim
@ 2010-07-16  8:58 ` Kukjin Kim
  2010-07-27  6:24   ` MyungJoo Ham
  2010-07-16  8:58 ` [PATCH v2 4/8] ARM: S5PV310: Add IRQ support Kukjin Kim
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: Kukjin Kim @ 2010-07-16  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Changhwan Youn <chaos.youn@samsung.com>

This patch adds clock and pll support for S5PV310.

Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pv310/clock.c                   |  544 +++++++++++++++++++++++
 arch/arm/mach-s5pv310/include/mach/regs-clock.h |   60 +++
 arch/arm/plat-s5p/include/plat/pll.h            |   41 ++
 3 files changed, 645 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-s5pv310/clock.c
 create mode 100644 arch/arm/mach-s5pv310/include/mach/regs-clock.h

diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
new file mode 100644
index 0000000..bb671d5
--- /dev/null
+++ b/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 = 4, .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_periph = {
+	.clk	= {
+		.name		= "periph",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
+};
+
+static struct clksrc_clk clk_atbout = {
+	.clk	= {
+		.name		= "atbout",
+		.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_atbout.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_CPU, .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_TOP0, .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_periph,
+	&clk_atbout,
+	&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 periclk;
+	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);
+	periclk = clk_get_rate(&clk_periph.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,
+			periclk, sclk_dmc, aclk_cored, aclk_corep,
+			aclk_acp, pclk_acp);
+
+	clk_f.rate = armclk;
+	clk_h.rate = sclk_dmc;
+	clk_p.rate = periclk;
+
+	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();
+}
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
new file mode 100644
index 0000000..77f637f
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
@@ -0,0 +1,60 @@
+/* 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_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 */
diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h
index 7db3227..4e8fe08 100644
--- a/arch/arm/plat-s5p/include/plat/pll.h
+++ b/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)
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 4/8] ARM: S5PV310: Add IRQ support
  2010-07-16  8:58 [PATCH v2 0/8] ARM: S5PV310: Add support for Samsung S5PV310 SoC Kukjin Kim
                   ` (2 preceding siblings ...)
  2010-07-16  8:58 ` [PATCH v2 3/8] ARM: S5PV310: Add Clock and PLL support Kukjin Kim
@ 2010-07-16  8:58 ` Kukjin Kim
  2010-07-16  8:58 ` [PATCH v2 5/8] ARM: S5PV310: Add Timer support Kukjin Kim
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Kukjin Kim @ 2010-07-16  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Changhwan Youn <chaos.youn@samsung.com>

This patch adds IRQ support for S5PV310.
ARM GIC is installed in S5PV310 instead of VIC which is in every other CPUs
in S5P series. Several irq combiners are used to resolve the lack of irq
lines in current implementation.

Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Hyuk Lee <hyuk1.lee@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pv310/include/mach/irqs.h     |   74 +++++++++++++++
 arch/arm/mach-s5pv310/include/mach/regs-irq.h |   19 ++++
 arch/arm/mach-s5pv310/irq-combiner.c          |  125 +++++++++++++++++++++++++
 arch/arm/plat-s5p/irq.c                       |    2 +
 4 files changed, 220 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-s5pv310/include/mach/irqs.h
 create mode 100644 arch/arm/mach-s5pv310/include/mach/regs-irq.h
 create mode 100644 arch/arm/mach-s5pv310/irq-combiner.c

diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h
new file mode 100644
index 0000000..56885ca
--- /dev/null
+++ b/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 */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-irq.h b/arch/arm/mach-s5pv310/include/mach/regs-irq.h
new file mode 100644
index 0000000..c6e09c7
--- /dev/null
+++ b/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 */
diff --git a/arch/arm/mach-s5pv310/irq-combiner.c b/arch/arm/mach-s5pv310/irq-combiner.c
new file mode 100644
index 0000000..0f70521
--- /dev/null
+++ b/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);
+	}
+}
diff --git a/arch/arm/plat-s5p/irq.c b/arch/arm/plat-s5p/irq.c
index 25e1eb6..5560b12 100644
--- a/arch/arm/plat-s5p/irq.c
+++ b/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.6.2.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 5/8] ARM: S5PV310: Add Timer support
  2010-07-16  8:58 [PATCH v2 0/8] ARM: S5PV310: Add support for Samsung S5PV310 SoC Kukjin Kim
                   ` (3 preceding siblings ...)
  2010-07-16  8:58 ` [PATCH v2 4/8] ARM: S5PV310: Add IRQ support Kukjin Kim
@ 2010-07-16  8:58 ` Kukjin Kim
  2010-07-16 10:30   ` Kyungmin Park
  2010-07-16  8:58 ` [PATCH v2 6/8] ARM: S5PV310: Add new Kconfig and Makefiles Kukjin Kim
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: Kukjin Kim @ 2010-07-16  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Changhwan Youn <chaos.youn@samsung.com>

This patch adds timer support for S5PV310.
Until now, all S5P SoCs use CONFIG_ARCH_USES_GETTIMEOFFSET macro as a default
configuration. Instead, S5PV310 implements clocksource and clock_event_device
to support the high resolution timer and tickless system.

Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Hyuk Lee <hyuk1.lee@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pv310/include/mach/pwm-clock.h |   70 ++++++
 arch/arm/mach-s5pv310/localtimer.c             |   25 ++
 arch/arm/mach-s5pv310/time.c                   |  287 ++++++++++++++++++++++++
 arch/arm/plat-s5p/include/plat/s5pv310.h       |    1 +
 arch/arm/plat-samsung/Makefile                 |    2 +-
 5 files changed, 384 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-s5pv310/include/mach/pwm-clock.h
 create mode 100644 arch/arm/mach-s5pv310/localtimer.c
 create mode 100644 arch/arm/mach-s5pv310/time.c

diff --git a/arch/arm/mach-s5pv310/include/mach/pwm-clock.h b/arch/arm/mach-s5pv310/include/mach/pwm-clock.h
new file mode 100644
index 0000000..7e6da27
--- /dev/null
+++ b/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 */
diff --git a/arch/arm/mach-s5pv310/localtimer.c b/arch/arm/mach-s5pv310/localtimer.c
new file mode 100644
index 0000000..2784036
--- /dev/null
+++ b/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);
+}
diff --git a/arch/arm/mach-s5pv310/time.c b/arch/arm/mach-s5pv310/time.c
new file mode 100644
index 0000000..64accf8
--- /dev/null
+++ b/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(4, cycles);
+	s5pv310_pwm_start(4, 0);
+	return 0;
+}
+
+static void s5pv310_pwm_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	s5pv310_pwm_stop(4);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		s5pv310_pwm_init(4, clock_count_per_tick);
+		s5pv310_pwm_start(4, 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_timer4",
+	.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_timer4_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(tdiv4);
+
+	clk_set_rate(tscaler, pclk / 2);
+	clk_set_rate(tdiv4, pclk / 2);
+	clk_set_parent(tin4, tdiv4);
+
+	clock_rate = clk_get_rate(tin4);
+
+	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_TIMER4, &s5pv310_clock_event_irq);
+}
+
+static cycle_t s5pv310_pwm2_read(struct clocksource *cs)
+{
+	return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x2c));
+}
+
+struct clocksource pwm_clocksource = {
+	.name		= "pwm_timer2",
+	.rating		= 250,
+	.read		= s5pv310_pwm2_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(tdiv2, pclk / 2);
+	clk_set_parent(tin2, tdiv2);
+
+	clock_rate = clk_get_rate(tin2);
+
+	s5pv310_pwm_init(2, ~0);
+	s5pv310_pwm_start(2, 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,
+};
diff --git a/arch/arm/plat-s5p/include/plat/s5pv310.h b/arch/arm/plat-s5p/include/plat/s5pv310.h
index d2f05e1..769c991 100644
--- a/arch/arm/plat-s5p/include/plat/s5pv310.h
+++ b/arch/arm/plat-s5p/include/plat/s5pv310.h
@@ -22,6 +22,7 @@ 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
 
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index b1d82cc..0d5bf8a 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/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
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 6/8] ARM: S5PV310: Add new Kconfig and Makefiles
  2010-07-16  8:58 [PATCH v2 0/8] ARM: S5PV310: Add support for Samsung S5PV310 SoC Kukjin Kim
                   ` (4 preceding siblings ...)
  2010-07-16  8:58 ` [PATCH v2 5/8] ARM: S5PV310: Add Timer support Kukjin Kim
@ 2010-07-16  8:58 ` Kukjin Kim
  2010-07-16  8:58 ` [PATCH v2 7/8] ARM: S5PV310: Add Board support file Kukjin Kim
  2010-07-16  8:58 ` [PATCH v2 8/8] ARM: S5PV310: Add serial port support Kukjin Kim
  7 siblings, 0 replies; 21+ messages in thread
From: Kukjin Kim @ 2010-07-16  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Changhwan Youn <chaos.youn@samsung.com>

This patch adds the Kconfig and Makefile for the new S5PV310 SoC.
It also updates arch/arm Kconfig, Makefile and arch/arm/mm/Kconfig
to include support for the new S5PV310.

Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/Kconfig                    |   24 +++++++++++++++++++-----
 arch/arm/Makefile                   |    1 +
 arch/arm/mach-s5pv310/Kconfig       |   26 ++++++++++++++++++++++++++
 arch/arm/mach-s5pv310/Makefile      |   20 ++++++++++++++++++++
 arch/arm/mach-s5pv310/Makefile.boot |    2 ++
 arch/arm/mm/Kconfig                 |    3 ++-
 arch/arm/plat-s5p/Kconfig           |    5 +++--
 7 files changed, 73 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm/mach-s5pv310/Kconfig
 create mode 100644 arch/arm/mach-s5pv310/Makefile
 create mode 100644 arch/arm/mach-s5pv310/Makefile.boot

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 98922f7..3e68a93 100644
--- a/arch/arm/Kconfig
+++ b/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
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 64ba313..d80c9f9 100644
--- a/arch/arm/Makefile
+++ b/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
diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig
new file mode 100644
index 0000000..24ef3cd
--- /dev/null
+++ b/arch/arm/mach-s5pv310/Kconfig
@@ -0,0 +1,26 @@
+# 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
+
+# machine support
+
+config MACH_SMDKV310
+	bool "SMDKV310"
+	select CPU_S5PV310
+	select ARCH_SPARSEMEM_ENABLE
+	help
+	  Machine support for Samsung SMDKV310
+endif
diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile
new file mode 100644
index 0000000..1b263a5
--- /dev/null
+++ b/arch/arm/mach-s5pv310/Makefile
@@ -0,0 +1,20 @@
+# 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
diff --git a/arch/arm/mach-s5pv310/Makefile.boot b/arch/arm/mach-s5pv310/Makefile.boot
new file mode 100644
index 0000000..d65956f
--- /dev/null
+++ b/arch/arm/mach-s5pv310/Makefile.boot
@@ -0,0 +1,2 @@
+   zreladdr-y	:= 0x40008000
+params_phys-y	:= 0x40000100
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 101105e..9ca76bf 100644
--- a/arch/arm/mm/Kconfig
+++ b/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
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 11d6a1b..907ac63 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/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
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 7/8] ARM: S5PV310: Add Board support file
  2010-07-16  8:58 [PATCH v2 0/8] ARM: S5PV310: Add support for Samsung S5PV310 SoC Kukjin Kim
                   ` (5 preceding siblings ...)
  2010-07-16  8:58 ` [PATCH v2 6/8] ARM: S5PV310: Add new Kconfig and Makefiles Kukjin Kim
@ 2010-07-16  8:58 ` Kukjin Kim
  2010-07-16 10:36   ` Kyungmin Park
  2010-07-16  8:58 ` [PATCH v2 8/8] ARM: S5PV310: Add serial port support Kukjin Kim
  7 siblings, 1 reply; 21+ messages in thread
From: Kukjin Kim @ 2010-07-16  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Changhwan Youn <chaos.youn@samsung.com>

This patch adds Samsung SMDKV310 board support file.

Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pv310/Makefile        |    4 ++
 arch/arm/mach-s5pv310/mach-smdkv310.c |   92 +++++++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-s5pv310/mach-smdkv310.c

diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile
index 1b263a5..56e7693 100644
--- a/arch/arm/mach-s5pv310/Makefile
+++ b/arch/arm/mach-s5pv310/Makefile
@@ -18,3 +18,7 @@ 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
diff --git a/arch/arm/mach-s5pv310/mach-smdkv310.c b/arch/arm/mach-s5pv310/mach-smdkv310.c
new file mode 100644
index 0000000..0d6ab77
--- /dev/null
+++ b/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
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 8/8] ARM: S5PV310: Add serial port support
  2010-07-16  8:58 [PATCH v2 0/8] ARM: S5PV310: Add support for Samsung S5PV310 SoC Kukjin Kim
                   ` (6 preceding siblings ...)
  2010-07-16  8:58 ` [PATCH v2 7/8] ARM: S5PV310: Add Board support file Kukjin Kim
@ 2010-07-16  8:58 ` Kukjin Kim
  7 siblings, 0 replies; 21+ messages in thread
From: Kukjin Kim @ 2010-07-16  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jongpill Lee <boyko.lee@samsung.com>

This patch adds UART serial port support for S5PV310.
In the case of that serial device has just one clock source, driver can not
control clock source. So add check function in get_clksrc and set_clksrc.

Signed-off-by: Jongpill Lee <boyko.lee@samsung.com>
Acked-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 drivers/serial/Kconfig   |    4 ++--
 drivers/serial/s5pv210.c |    8 ++++++++
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 8b23165..aa22010 100644
--- a/drivers/serial/Kconfig
+++ b/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
diff --git a/drivers/serial/s5pv210.c b/drivers/serial/s5pv210.c
index 4a789e5..6ebccd7 100644
--- a/drivers/serial/s5pv210.c
+++ b/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";
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 5/8] ARM: S5PV310: Add Timer support
  2010-07-16  8:58 ` [PATCH v2 5/8] ARM: S5PV310: Add Timer support Kukjin Kim
@ 2010-07-16 10:30   ` Kyungmin Park
  2010-07-20 12:34     ` Kukjin Kim
  2010-07-26  4:07     ` 김상범
  0 siblings, 2 replies; 21+ messages in thread
From: Kyungmin Park @ 2010-07-16 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jul 16, 2010 at 5:58 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> From: Changhwan Youn <chaos.youn@samsung.com>
>
> This patch adds timer support for S5PV310.
> Until now, all S5P SoCs use CONFIG_ARCH_USES_GETTIMEOFFSET macro as a default
> configuration. Instead, S5PV310 implements clocksource and clock_event_device
> to support the high resolution timer and tickless system.
>
> Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
> Signed-off-by: Hyuk Lee <hyuk1.lee@samsung.com>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> ---
> ?arch/arm/mach-s5pv310/include/mach/pwm-clock.h | ? 70 ++++++
> ?arch/arm/mach-s5pv310/localtimer.c ? ? ? ? ? ? | ? 25 ++
> ?arch/arm/mach-s5pv310/time.c ? ? ? ? ? ? ? ? ? | ?287 ++++++++++++++++++++++++
> ?arch/arm/plat-s5p/include/plat/s5pv310.h ? ? ? | ? ?1 +
> ?arch/arm/plat-samsung/Makefile ? ? ? ? ? ? ? ? | ? ?2 +-
> ?5 files changed, 384 insertions(+), 1 deletions(-)
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/pwm-clock.h
> ?create mode 100644 arch/arm/mach-s5pv310/localtimer.c
> ?create mode 100644 arch/arm/mach-s5pv310/time.c
>
> diff --git a/arch/arm/mach-s5pv310/include/mach/pwm-clock.h b/arch/arm/mach-s5pv310/include/mach/pwm-clock.h
> new file mode 100644
> index 0000000..7e6da27
> --- /dev/null
> +++ b/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 */
> diff --git a/arch/arm/mach-s5pv310/localtimer.c b/arch/arm/mach-s5pv310/localtimer.c
> new file mode 100644
> index 0000000..2784036
> --- /dev/null
> +++ b/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);
> +}
> diff --git a/arch/arm/mach-s5pv310/time.c b/arch/arm/mach-s5pv310/time.c
> new file mode 100644
> index 0000000..64accf8
> --- /dev/null
> +++ b/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

Please make it configurable, now PWM 2 is used for I2C pin in mobile hardware.
It seems to smdk specific file.

Why don't use the systimer?

Thank you,
Kyungmin Park

> + *
> + * 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(4, cycles);
> + ? ? ? s5pv310_pwm_start(4, 0);
> + ? ? ? return 0;
> +}
> +
> +static void s5pv310_pwm_set_mode(enum clock_event_mode mode,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct clock_event_device *evt)
> +{
> + ? ? ? s5pv310_pwm_stop(4);
> +
> + ? ? ? switch (mode) {
> + ? ? ? case CLOCK_EVT_MODE_PERIODIC:
> + ? ? ? ? ? ? ? s5pv310_pwm_init(4, clock_count_per_tick);
> + ? ? ? ? ? ? ? s5pv310_pwm_start(4, 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_timer4",
> + ? ? ? .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_timer4_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(tdiv4);
> +
> + ? ? ? clk_set_rate(tscaler, pclk / 2);
> + ? ? ? clk_set_rate(tdiv4, pclk / 2);
> + ? ? ? clk_set_parent(tin4, tdiv4);
> +
> + ? ? ? clock_rate = clk_get_rate(tin4);
> +
> + ? ? ? 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_TIMER4, &s5pv310_clock_event_irq);
> +}
> +
> +static cycle_t s5pv310_pwm2_read(struct clocksource *cs)
> +{
> + ? ? ? return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x2c));
> +}
> +
> +struct clocksource pwm_clocksource = {
> + ? ? ? .name ? ? ? ? ? = "pwm_timer2",
> + ? ? ? .rating ? ? ? ? = 250,
> + ? ? ? .read ? ? ? ? ? = s5pv310_pwm2_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(tdiv2, pclk / 2);
> + ? ? ? clk_set_parent(tin2, tdiv2);
> +
> + ? ? ? clock_rate = clk_get_rate(tin2);
> +
> + ? ? ? s5pv310_pwm_init(2, ~0);
> + ? ? ? s5pv310_pwm_start(2, 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,
> +};
> diff --git a/arch/arm/plat-s5p/include/plat/s5pv310.h b/arch/arm/plat-s5p/include/plat/s5pv310.h
> index d2f05e1..769c991 100644
> --- a/arch/arm/plat-s5p/include/plat/s5pv310.h
> +++ b/arch/arm/plat-s5p/include/plat/s5pv310.h
> @@ -22,6 +22,7 @@ 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
>
> diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
> index b1d82cc..0d5bf8a 100644
> --- a/arch/arm/plat-samsung/Makefile
> +++ b/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
> --
> 1.6.2.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 7/8] ARM: S5PV310: Add Board support file
  2010-07-16  8:58 ` [PATCH v2 7/8] ARM: S5PV310: Add Board support file Kukjin Kim
@ 2010-07-16 10:36   ` Kyungmin Park
  2010-07-21 12:33     ` Kukjin Kim
  0 siblings, 1 reply; 21+ messages in thread
From: Kyungmin Park @ 2010-07-16 10:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jul 16, 2010 at 5:58 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> From: Changhwan Youn <chaos.youn@samsung.com>
>
> This patch adds Samsung SMDKV310 board support file.
>
> Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> ---
> ?arch/arm/mach-s5pv310/Makefile ? ? ? ?| ? ?4 ++
> ?arch/arm/mach-s5pv310/mach-smdkv310.c | ? 92 +++++++++++++++++++++++++++++++++
> ?2 files changed, 96 insertions(+), 0 deletions(-)
> ?create mode 100644 arch/arm/mach-s5pv310/mach-smdkv310.c
>
> diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile
> index 1b263a5..56e7693 100644
> --- a/arch/arm/mach-s5pv310/Makefile
> +++ b/arch/arm/mach-s5pv310/Makefile
> @@ -18,3 +18,7 @@ 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
> diff --git a/arch/arm/mach-s5pv310/mach-smdkv310.c b/arch/arm/mach-s5pv310/mach-smdkv310.c
> new file mode 100644
> index 0000000..0d6ab77
> --- /dev/null
> +++ b/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)

UART supports the 16 triggers at 2/3. No need to setup the lower value.

> +
> +static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = {
> + ? ? ? [0] = {
> + ? ? ? ? ? ? ? .hwport ? ? ? ? = 0,
> + ? ? ? ? ? ? ? .flags ? ? ? ? ?= 0,

Please remove unused flags filed.
Previous time Mr. Shim sent the related patch.

> + ? ? ? ? ? ? ? .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
> --
> 1.6.2.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 2/8] ARM: S5PV310: Add new CPU initialization support
  2010-07-16  8:58 ` [PATCH v2 2/8] ARM: S5PV310: Add new CPU initialization support Kukjin Kim
@ 2010-07-16 10:58   ` Kyungmin Park
  2010-07-16 11:52   ` Russell King - ARM Linux
  1 sibling, 0 replies; 21+ messages in thread
From: Kyungmin Park @ 2010-07-16 10:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jul 16, 2010 at 5:58 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> From: Changhwan Youn <chaos.youn@samsung.com>
>
> This patch adds Samsung's S5PV310/S5PC210 CPU support.
> The S5PV310/S5PC210 integrates a ARM Cortex A9 multi-core.
>
> Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
> Signed-off-by: Jongpill Lee <boyko.lee@samsung.com>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> ---
> ?arch/arm/mach-s5pv310/cpu.c ? ? ? ? ? ? ? ? ? ? ?| ?122 +++++++++++++
> ?arch/arm/mach-s5pv310/headsmp.S ? ? ? ? ? ? ? ? ?| ? 41 ++++
> ?arch/arm/mach-s5pv310/include/mach/debug-macro.S | ? 36 ++++
> ?arch/arm/mach-s5pv310/include/mach/entry-macro.S | ? 84 +++++++++
> ?arch/arm/mach-s5pv310/include/mach/gpio.h ? ? ? ?| ?135 ++++++++++++++
> ?arch/arm/mach-s5pv310/include/mach/hardware.h ? ?| ? 18 ++
> ?arch/arm/mach-s5pv310/include/mach/io.h ? ? ? ? ?| ? 26 +++
> ?arch/arm/mach-s5pv310/include/mach/map.h ? ? ? ? | ? 66 +++++++
> ?arch/arm/mach-s5pv310/include/mach/memory.h ? ? ?| ? 22 +++
> ?arch/arm/mach-s5pv310/include/mach/smp.h ? ? ? ? | ? 29 +++
> ?arch/arm/mach-s5pv310/include/mach/system.h ? ? ?| ? 22 +++
> ?arch/arm/mach-s5pv310/include/mach/timex.h ? ? ? | ? 29 +++
> ?arch/arm/mach-s5pv310/include/mach/uncompress.h ?| ? 27 +++
> ?arch/arm/mach-s5pv310/include/mach/vmalloc.h ? ? | ? 22 +++
> ?arch/arm/mach-s5pv310/init.c ? ? ? ? ? ? ? ? ? ? | ? 41 ++++
> ?arch/arm/mach-s5pv310/platsmp.c ? ? ? ? ? ? ? ? ?| ?212 ++++++++++++++++++++++
> ?arch/arm/mach-s5pv310/setup-i2c0.c ? ? ? ? ? ? ? | ? 20 ++
> ?arch/arm/plat-s5p/cpu.c ? ? ? ? ? ? ? ? ? ? ? ? ?| ? 12 ++
> ?arch/arm/plat-s5p/include/plat/map-s5p.h ? ? ? ? | ? 12 ++
> ?arch/arm/plat-s5p/include/plat/s5pv310.h ? ? ? ? | ? 33 ++++
> ?20 files changed, 1009 insertions(+), 0 deletions(-)
> ?create mode 100644 arch/arm/mach-s5pv310/cpu.c
> ?create mode 100644 arch/arm/mach-s5pv310/headsmp.S
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/debug-macro.S
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/entry-macro.S
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/gpio.h
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/hardware.h
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/io.h
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/map.h
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/memory.h
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/smp.h
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/system.h
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/timex.h
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/uncompress.h
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/vmalloc.h
> ?create mode 100644 arch/arm/mach-s5pv310/init.c
> ?create mode 100644 arch/arm/mach-s5pv310/platsmp.c
> ?create mode 100644 arch/arm/mach-s5pv310/setup-i2c0.c
> ?create mode 100644 arch/arm/plat-s5p/include/plat/s5pv310.h
>
> diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c
> new file mode 100644
> index 0000000..196c9f1
> --- /dev/null
> +++ b/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);

How about to call core_init at below?
To make a single kernel we need to remove core_initcall before cpu ID detection.

> +
> +int __init s5pv310_init(void)
> +{
> + ? ? ? printk(KERN_INFO "S5PV310: Initializing architecture\n");
> +
> + ? ? ? /* set idle function */
> + ? ? ? pm_idle = s5pv310_idle;
> +
> + ? ? ? return sysdev_register(&s5pv310_sysdev);
> +}
> diff --git a/arch/arm/mach-s5pv310/headsmp.S b/arch/arm/mach-s5pv310/headsmp.S
> new file mode 100644
> index 0000000..164b7b0
> --- /dev/null
> +++ b/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
> diff --git a/arch/arm/mach-s5pv310/include/mach/debug-macro.S b/arch/arm/mach-s5pv310/include/mach/debug-macro.S
> new file mode 100644
> index 0000000..6fb3893
> --- /dev/null
> +++ b/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>
> diff --git a/arch/arm/mach-s5pv310/include/mach/entry-macro.S b/arch/arm/mach-s5pv310/include/mach/entry-macro.S
> new file mode 100644
> index 0000000..e600e1d
> --- /dev/null
> +++ b/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
> diff --git a/arch/arm/mach-s5pv310/include/mach/gpio.h b/arch/arm/mach-s5pv310/include/mach/gpio.h
> new file mode 100644
> index 0000000..20cb80c
> --- /dev/null
> +++ b/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 */
> diff --git a/arch/arm/mach-s5pv310/include/mach/hardware.h b/arch/arm/mach-s5pv310/include/mach/hardware.h
> new file mode 100644
> index 0000000..28ff988
> --- /dev/null
> +++ b/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 */
> diff --git a/arch/arm/mach-s5pv310/include/mach/io.h b/arch/arm/mach-s5pv310/include/mach/io.h
> new file mode 100644
> index 0000000..8a7f912
> --- /dev/null
> +++ b/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 */
> diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h
> new file mode 100644
> index 0000000..50e0901
> --- /dev/null
> +++ b/arch/arm/mach-s5pv310/include/mach/map.h
> @@ -0,0 +1,66 @@
> +/* 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_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
> +
> +#endif /* __ASM_ARCH_MAP_H */
> diff --git a/arch/arm/mach-s5pv310/include/mach/memory.h b/arch/arm/mach-s5pv310/include/mach/memory.h
> new file mode 100644
> index 0000000..1dffb48
> --- /dev/null
> +++ b/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 */
> diff --git a/arch/arm/mach-s5pv310/include/mach/smp.h b/arch/arm/mach-s5pv310/include/mach/smp.h
> new file mode 100644
> index 0000000..990f3ba
> --- /dev/null
> +++ b/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
> diff --git a/arch/arm/mach-s5pv310/include/mach/system.h b/arch/arm/mach-s5pv310/include/mach/system.h
> new file mode 100644
> index 0000000..d10c009
> --- /dev/null
> +++ b/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 */
> diff --git a/arch/arm/mach-s5pv310/include/mach/timex.h b/arch/arm/mach-s5pv310/include/mach/timex.h
> new file mode 100644
> index 0000000..bd2359b
> --- /dev/null
> +++ b/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 */
> diff --git a/arch/arm/mach-s5pv310/include/mach/uncompress.h b/arch/arm/mach-s5pv310/include/mach/uncompress.h
> new file mode 100644
> index 0000000..ad88c24
> --- /dev/null
> +++ b/arch/arm/mach-s5pv310/include/mach/uncompress.h
> @@ -0,0 +1,27 @@
> +/* 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. */
> +
> + ? ? ? fifo_mask = S5PV210_UFSTAT_TXMASK;
> + ? ? ? fifo_max = 63 << S5PV210_UFSTAT_TXSHIFT;
> +}
> +
> +#endif /* __ASM_ARCH_UNCOMPRESS_H */
> diff --git a/arch/arm/mach-s5pv310/include/mach/vmalloc.h b/arch/arm/mach-s5pv310/include/mach/vmalloc.h
> new file mode 100644
> index 0000000..426d997
> --- /dev/null
> +++ b/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 ? ? ?(0xE0000000)

If there's no different reason to use 0xE000'0000, how about to use 0xF000'0000?
I hope to delay using HIGHMEM as possible

> +
> +#endif /* __ASM_ARCH_VMALLOC_H */
> diff --git a/arch/arm/mach-s5pv310/init.c b/arch/arm/mach-s5pv310/init.c
> new file mode 100644
> index 0000000..182dcf4
> --- /dev/null
> +++ b/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);
> +}
> diff --git a/arch/arm/mach-s5pv310/platsmp.c b/arch/arm/mach-s5pv310/platsmp.c
> new file mode 100644
> index 0000000..9325ac2
> --- /dev/null
> +++ b/arch/arm/mach-s5pv310/platsmp.c
> @@ -0,0 +1,212 @@
> +/* linux/arch/arm/mach-s5pv310/platsmp.c
> + *
> + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> + * ? ? ? ? ? ? http://www.samsung.com/
> + *
> + * Cloned from linux/arch/arm/mach-realview/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 <mach/hardware.h>
> +#include <asm/mach-types.h>
> +#include <asm/localtimer.h>
> +#include <asm/unified.h>
> +
> +#include <asm/smp_scu.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 inline unsigned int get_core_count(void)
> +{
> + ? ? ? void __iomem *scu_base = scu_base_addr();
> + ? ? ? if (scu_base)
> + ? ? ? ? ? ? ? return scu_get_core_count(scu_base);
> + ? ? ? return 1;
> +}
> +
> +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;
> + ? ? ? flush_cache_all();
> +
> + ? ? ? /*
> + ? ? ? ?* XXX
> + ? ? ? ?*
> + ? ? ? ?* This is a later addition to the booting protocol: the
> + ? ? ? ?* bootMonitor now puts secondary cores into WFI, so
> + ? ? ? ?* poke_milo() no longer gets the cores moving; we need
> + ? ? ? ?* to send a soft interrupt to wake the secondary core.
> + ? ? ? ?* Use smp_cross_call() for this, since there's little
> + ? ? ? ?* point duplicating the code here
> + ? ? ? ?*/
> + ? ? ? 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;
> +}
> +
> +static void __init poke_milo(void)
> +{
> + ? ? ? /* nobody is to be released from the pen yet */
> + ? ? ? pen_release = -1;
> +
> + ? ? ? /*
> + ? ? ? ?* Write the address of secondary startup into the system-wide flags
> + ? ? ? ?* register. The BootMonitor waits for this register to become
> + ? ? ? ?* non-zero.
> + ? ? ? ?*/
> + ? ? ? __raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_INFORM0);
> +
> + ? ? ? mb();
> +}
> +
> +/*
> + * 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)
> +{
> + ? ? ? unsigned int i, ncores = get_core_count();
> +
> + ? ? ? for (i = 0; i < ncores; i++)
> + ? ? ? ? ? ? ? set_cpu_possible(i, true);
> +}
> +
> +void __init smp_prepare_cpus(unsigned int max_cpus)
> +{
> + ? ? ? unsigned int ncores = get_core_count();
> + ? ? ? unsigned int cpu = smp_processor_id();
> + ? ? ? int i;
> +
> + ? ? ? /* sanity check */
> + ? ? ? if (ncores == 0) {
> + ? ? ? ? ? ? ? printk(KERN_ERR
> + ? ? ? ? ? ? ? ? ? ? ?"Realview: strange CM count of 0? Default to 1\n");
> +
> + ? ? ? ? ? ? ? ncores = 1;
> + ? ? ? }
> +
> + ? ? ? if (ncores > NR_CPUS) {
> + ? ? ? ? ? ? ? printk(KERN_WARNING
> + ? ? ? ? ? ? ? ? ? ? ?"Realview: no. of cores (%d) greater than configured "
> + ? ? ? ? ? ? ? ? ? ? ?"maximum of %d - clipping\n",
> + ? ? ? ? ? ? ? ? ? ? ?ncores, NR_CPUS);
> + ? ? ? ? ? ? ? ncores = NR_CPUS;
> + ? ? ? }
> +
> + ? ? ? 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. Note that, on modern versions of
> + ? ? ? ?* MILO, the "poke" doesn't actually do anything until each
> + ? ? ? ?* individual core is sent a soft interrupt to get it out of
> + ? ? ? ?* WFI
> + ? ? ? ?*/
> + ? ? ? 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());
> + ? ? ? ? ? ? ? poke_milo();
> + ? ? ? }
> +}
> diff --git a/arch/arm/mach-s5pv310/setup-i2c0.c b/arch/arm/mach-s5pv310/setup-i2c0.c
> new file mode 100644
> index 0000000..d4f5a81
> --- /dev/null
> +++ b/arch/arm/mach-s5pv310/setup-i2c0.c
> @@ -0,0 +1,20 @@
> +/* linux/arch/arm/mach-s5pv210/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 */
> +
> +void s3c_i2c0_cfg_gpio(struct platform_device *dev)
> +{
> +/* will be implemented later */
> +}
> diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c
> index c478441..9261a27 100644
> --- a/arch/arm/plat-s5p/cpu.c
> +++ b/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,
> ? ? ? ?},
> ?};
>
> @@ -83,6 +93,7 @@ static struct map_desc s5p_iodesc[] __initdata = {
> ? ? ? ? ? ? ? ?.pfn ? ? ? ? ? ?= __phys_to_pfn(S3C_PA_UART),
> ? ? ? ? ? ? ? ?.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),
> diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h
> index 3d815f4..54e9fb9 100644
> --- a/arch/arm/plat-s5p/include/plat/map-s5p.h
> +++ b/arch/arm/plat-s5p/include/plat/map-s5p.h
> @@ -18,6 +18,18 @@
> ?#define S5P_VA_SYSTIMER ? ? ? ? ? ? ? ?S3C_ADDR(0x01200000)
> ?#define S5P_VA_SROMC ? ? ? ? ? S3C_ADDR(0x01100000)
>
> +#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)
> diff --git a/arch/arm/plat-s5p/include/plat/s5pv310.h b/arch/arm/plat-s5p/include/plat/s5pv310.h
> new file mode 100644
> index 0000000..d2f05e1
> --- /dev/null
> +++ b/arch/arm/plat-s5p/include/plat/s5pv310.h
> @@ -0,0 +1,33 @@
> +/* 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);
> +
> +#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
> --
> 1.6.2.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 2/8] ARM: S5PV310: Add new CPU initialization support
  2010-07-16  8:58 ` [PATCH v2 2/8] ARM: S5PV310: Add new CPU initialization support Kukjin Kim
  2010-07-16 10:58   ` Kyungmin Park
@ 2010-07-16 11:52   ` Russell King - ARM Linux
  2010-07-17  3:52     ` Kyungmin Park
  2010-07-19  0:09     ` Kukjin Kim
  1 sibling, 2 replies; 21+ messages in thread
From: Russell King - ARM Linux @ 2010-07-16 11:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jul 16, 2010 at 05:58:28PM +0900, Kukjin Kim wrote:
> diff --git a/arch/arm/mach-s5pv310/platsmp.c b/arch/arm/mach-s5pv310/platsmp.c
> new file mode 100644
> index 0000000..9325ac2
> --- /dev/null
> +++ b/arch/arm/mach-s5pv310/platsmp.c
> @@ -0,0 +1,212 @@
> +/* linux/arch/arm/mach-s5pv310/platsmp.c
> + *
> + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> + *		http://www.samsung.com/
> + *
> + * Cloned from linux/arch/arm/mach-realview/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 <mach/hardware.h>
> +#include <asm/mach-types.h>
> +#include <asm/localtimer.h>
> +#include <asm/unified.h>
> +
> +#include <asm/smp_scu.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 inline unsigned int get_core_count(void)
> +{
> +	void __iomem *scu_base = scu_base_addr();
> +	if (scu_base)
> +		return scu_get_core_count(scu_base);
> +	return 1;
> +}
> +
> +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;
> +	flush_cache_all();
> +
> +	/*
> +	 * XXX
> +	 *
> +	 * This is a later addition to the booting protocol: the
> +	 * bootMonitor now puts secondary cores into WFI, so
> +	 * poke_milo() no longer gets the cores moving; we need
> +	 * to send a soft interrupt to wake the secondary core.
> +	 * Use smp_cross_call() for this, since there's little
> +	 * point duplicating the code here
> +	 */
> +	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;
> +}
> +
> +static void __init poke_milo(void)
> +{
> +	/* nobody is to be released from the pen yet */
> +	pen_release = -1;
> +
> +	/*
> +	 * Write the address of secondary startup into the system-wide flags
> +	 * register. The BootMonitor waits for this register to become
> +	 * non-zero.
> +	 */
> +	__raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_INFORM0);
> +
> +	mb();
> +}
> +
> +/*
> + * 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)
> +{
> +	unsigned int i, ncores = get_core_count();
> +
> +	for (i = 0; i < ncores; i++)
> +		set_cpu_possible(i, true);
> +}
> +
> +void __init smp_prepare_cpus(unsigned int max_cpus)
> +{
> +	unsigned int ncores = get_core_count();
> +	unsigned int cpu = smp_processor_id();
> +	int i;
> +
> +	/* sanity check */
> +	if (ncores == 0) {
> +		printk(KERN_ERR
> +		       "Realview: strange CM count of 0? Default to 1\n");
> +
> +		ncores = 1;
> +	}
> +
> +	if (ncores > NR_CPUS) {
> +		printk(KERN_WARNING
> +		       "Realview: no. of cores (%d) greater than configured "
> +		       "maximum of %d - clipping\n",
> +		       ncores, NR_CPUS);
> +		ncores = NR_CPUS;
> +	}
> +
> +	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. Note that, on modern versions of
> +	 * MILO, the "poke" doesn't actually do anything until each
> +	 * individual core is sent a soft interrupt to get it out of
> +	 * WFI
> +	 */
> +	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());
> +		poke_milo();
> +	}
> +}

Please can you model this on the Versatile Express platsmp.c rather than
the Realview platsmp.c ?

The Realview platsmp.c implementation contains a lot of left-overs from
the initial Integrator-based SMP implementation which we really shouldn't
be carrying endlessly forward.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 2/8] ARM: S5PV310: Add new CPU initialization support
  2010-07-16 11:52   ` Russell King - ARM Linux
@ 2010-07-17  3:52     ` Kyungmin Park
  2010-07-19  0:09     ` Kukjin Kim
  1 sibling, 0 replies; 21+ messages in thread
From: Kyungmin Park @ 2010-07-17  3:52 UTC (permalink / raw)
  To: linux-arm-kernel

To Ben,

Now you are working on make a single kernel for s5p series at your git.
The v310 or c210 chip also included in these works.

Previous time Marek sent the mail if you are busy with other works, he
can help it.

Give your opinions.

TO Changhwan or Kukjin

Did you see the ben's work? If yes, can you make it similar way?

Thank you,
Kyungmin Park


On Fri, Jul 16, 2010 at 8:52 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Fri, Jul 16, 2010 at 05:58:28PM +0900, Kukjin Kim wrote:
>> diff --git a/arch/arm/mach-s5pv310/platsmp.c b/arch/arm/mach-s5pv310/platsmp.c
>> new file mode 100644
>> index 0000000..9325ac2
>> --- /dev/null
>> +++ b/arch/arm/mach-s5pv310/platsmp.c
>> @@ -0,0 +1,212 @@
>> +/* linux/arch/arm/mach-s5pv310/platsmp.c
>> + *
>> + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
>> + * ? ? ? ? ? http://www.samsung.com/
>> + *
>> + * Cloned from linux/arch/arm/mach-realview/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 <mach/hardware.h>
>> +#include <asm/mach-types.h>
>> +#include <asm/localtimer.h>
>> +#include <asm/unified.h>
>> +
>> +#include <asm/smp_scu.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 inline unsigned int get_core_count(void)
>> +{
>> + ? ? void __iomem *scu_base = scu_base_addr();
>> + ? ? if (scu_base)
>> + ? ? ? ? ? ? return scu_get_core_count(scu_base);
>> + ? ? return 1;
>> +}
>> +
>> +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;
>> + ? ? flush_cache_all();
>> +
>> + ? ? /*
>> + ? ? ?* XXX
>> + ? ? ?*
>> + ? ? ?* This is a later addition to the booting protocol: the
>> + ? ? ?* bootMonitor now puts secondary cores into WFI, so
>> + ? ? ?* poke_milo() no longer gets the cores moving; we need
>> + ? ? ?* to send a soft interrupt to wake the secondary core.
>> + ? ? ?* Use smp_cross_call() for this, since there's little
>> + ? ? ?* point duplicating the code here
>> + ? ? ?*/
>> + ? ? 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;
>> +}
>> +
>> +static void __init poke_milo(void)
>> +{
>> + ? ? /* nobody is to be released from the pen yet */
>> + ? ? pen_release = -1;
>> +
>> + ? ? /*
>> + ? ? ?* Write the address of secondary startup into the system-wide flags
>> + ? ? ?* register. The BootMonitor waits for this register to become
>> + ? ? ?* non-zero.
>> + ? ? ?*/
>> + ? ? __raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_INFORM0);
>> +
>> + ? ? mb();
>> +}
>> +
>> +/*
>> + * 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)
>> +{
>> + ? ? unsigned int i, ncores = get_core_count();
>> +
>> + ? ? for (i = 0; i < ncores; i++)
>> + ? ? ? ? ? ? set_cpu_possible(i, true);
>> +}
>> +
>> +void __init smp_prepare_cpus(unsigned int max_cpus)
>> +{
>> + ? ? unsigned int ncores = get_core_count();
>> + ? ? unsigned int cpu = smp_processor_id();
>> + ? ? int i;
>> +
>> + ? ? /* sanity check */
>> + ? ? if (ncores == 0) {
>> + ? ? ? ? ? ? printk(KERN_ERR
>> + ? ? ? ? ? ? ? ? ? ?"Realview: strange CM count of 0? Default to 1\n");
>> +
>> + ? ? ? ? ? ? ncores = 1;
>> + ? ? }
>> +
>> + ? ? if (ncores > NR_CPUS) {
>> + ? ? ? ? ? ? printk(KERN_WARNING
>> + ? ? ? ? ? ? ? ? ? ?"Realview: no. of cores (%d) greater than configured "
>> + ? ? ? ? ? ? ? ? ? ?"maximum of %d - clipping\n",
>> + ? ? ? ? ? ? ? ? ? ?ncores, NR_CPUS);
>> + ? ? ? ? ? ? ncores = NR_CPUS;
>> + ? ? }
>> +
>> + ? ? 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. Note that, on modern versions of
>> + ? ? ?* MILO, the "poke" doesn't actually do anything until each
>> + ? ? ?* individual core is sent a soft interrupt to get it out of
>> + ? ? ?* WFI
>> + ? ? ?*/
>> + ? ? 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());
>> + ? ? ? ? ? ? poke_milo();
>> + ? ? }
>> +}
>
> Please can you model this on the Versatile Express platsmp.c rather than
> the Realview platsmp.c ?
>
> The Realview platsmp.c implementation contains a lot of left-overs from
> the initial Integrator-based SMP implementation which we really shouldn't
> be carrying endlessly forward.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 2/8] ARM: S5PV310: Add new CPU initialization support
  2010-07-16 11:52   ` Russell King - ARM Linux
  2010-07-17  3:52     ` Kyungmin Park
@ 2010-07-19  0:09     ` Kukjin Kim
  1 sibling, 0 replies; 21+ messages in thread
From: Kukjin Kim @ 2010-07-19  0:09 UTC (permalink / raw)
  To: linux-arm-kernel

Russell King wrote:
> 
> On Fri, Jul 16, 2010 at 05:58:28PM +0900, Kukjin Kim wrote:
> > diff --git a/arch/arm/mach-s5pv310/platsmp.c b/arch/arm/mach-
> s5pv310/platsmp.c
> > new file mode 100644
> > index 0000000..9325ac2
> > --- /dev/null
> > +++ b/arch/arm/mach-s5pv310/platsmp.c
> > @@ -0,0 +1,212 @@
> > +/* linux/arch/arm/mach-s5pv310/platsmp.c
> > + *
> > + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> > + *		http://www.samsung.com/
> > + *
> > + * Cloned from linux/arch/arm/mach-realview/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 <mach/hardware.h>
> > +#include <asm/mach-types.h>
> > +#include <asm/localtimer.h>
> > +#include <asm/unified.h>
> > +
> > +#include <asm/smp_scu.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 inline unsigned int get_core_count(void)
> > +{
> > +	void __iomem *scu_base = scu_base_addr();
> > +	if (scu_base)
> > +		return scu_get_core_count(scu_base);
> > +	return 1;
> > +}
> > +
> > +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;
> > +	flush_cache_all();
> > +
> > +	/*
> > +	 * XXX
> > +	 *
> > +	 * This is a later addition to the booting protocol: the
> > +	 * bootMonitor now puts secondary cores into WFI, so
> > +	 * poke_milo() no longer gets the cores moving; we need
> > +	 * to send a soft interrupt to wake the secondary core.
> > +	 * Use smp_cross_call() for this, since there's little
> > +	 * point duplicating the code here
> > +	 */
> > +	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;
> > +}
> > +
> > +static void __init poke_milo(void)
> > +{
> > +	/* nobody is to be released from the pen yet */
> > +	pen_release = -1;
> > +
> > +	/*
> > +	 * Write the address of secondary startup into the system-wide flags
> > +	 * register. The BootMonitor waits for this register to become
> > +	 * non-zero.
> > +	 */
> > +	__raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)),
> S5P_INFORM0);
> > +
> > +	mb();
> > +}
> > +
> > +/*
> > + * 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)
> > +{
> > +	unsigned int i, ncores = get_core_count();
> > +
> > +	for (i = 0; i < ncores; i++)
> > +		set_cpu_possible(i, true);
> > +}
> > +
> > +void __init smp_prepare_cpus(unsigned int max_cpus)
> > +{
> > +	unsigned int ncores = get_core_count();
> > +	unsigned int cpu = smp_processor_id();
> > +	int i;
> > +
> > +	/* sanity check */
> > +	if (ncores == 0) {
> > +		printk(KERN_ERR
> > +		       "Realview: strange CM count of 0? Default to 1\n");
> > +
> > +		ncores = 1;
> > +	}
> > +
> > +	if (ncores > NR_CPUS) {
> > +		printk(KERN_WARNING
> > +		       "Realview: no. of cores (%d) greater than configured
"
> > +		       "maximum of %d - clipping\n",
> > +		       ncores, NR_CPUS);
> > +		ncores = NR_CPUS;
> > +	}
> > +
> > +	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. Note that, on modern versions of
> > +	 * MILO, the "poke" doesn't actually do anything until each
> > +	 * individual core is sent a soft interrupt to get it out of
> > +	 * WFI
> > +	 */
> > +	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());
> > +		poke_milo();
> > +	}
> > +}
> 
> Please can you model this on the Versatile Express platsmp.c rather than
> the Realview platsmp.c ?
> 
Sure, will do it.

> The Realview platsmp.c implementation contains a lot of left-overs from
> the initial Integrator-based SMP implementation which we really shouldn't
> be carrying endlessly forward.

Oh, I didn't know/check about that.
Thanks for your information and inputs.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 5/8] ARM: S5PV310: Add Timer support
  2010-07-16 10:30   ` Kyungmin Park
@ 2010-07-20 12:34     ` Kukjin Kim
  2010-07-26  4:07     ` 김상범
  1 sibling, 0 replies; 21+ messages in thread
From: Kukjin Kim @ 2010-07-20 12:34 UTC (permalink / raw)
  To: linux-arm-kernel

Kyungmin Park wrote:
> 
> On Fri, Jul 16, 2010 at 5:58 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> > From: Changhwan Youn <chaos.youn@samsung.com>
> >
> > This patch adds timer support for S5PV310.
> > Until now, all S5P SoCs use CONFIG_ARCH_USES_GETTIMEOFFSET macro as
> a default
> > configuration. Instead, S5PV310 implements clocksource and
> clock_event_device
> > to support the high resolution timer and tickless system.
> >
> > Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
> > Signed-off-by: Hyuk Lee <hyuk1.lee@samsung.com>
> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > ---

(snip)

> > diff --git a/arch/arm/mach-s5pv310/time.c b/arch/arm/mach-s5pv310/time.c
> > new file mode 100644
> > index 0000000..64accf8
> > --- /dev/null
> > +++ b/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
> 
> Please make it configurable, now PWM 2 is used for I2C pin in mobile
hardware.
> It seems to smdk specific file.
> 
> Why don't use the systimer?
> 
Your suggestion looks reasonable, so will support HRT with System Timer.

(snip)

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 7/8] ARM: S5PV310: Add Board support file
  2010-07-16 10:36   ` Kyungmin Park
@ 2010-07-21 12:33     ` Kukjin Kim
  0 siblings, 0 replies; 21+ messages in thread
From: Kukjin Kim @ 2010-07-21 12:33 UTC (permalink / raw)
  To: linux-arm-kernel

Kyungmin Park wrote:
> 
> On Fri, Jul 16, 2010 at 5:58 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> > From: Changhwan Youn <chaos.youn@samsung.com>
> >
> > This patch adds Samsung SMDKV310 board support file.
> >
> > Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > ---
> > ?arch/arm/mach-s5pv310/Makefile ? ? ? ?| ? ?4 ++
> > ?arch/arm/mach-s5pv310/mach-smdkv310.c | ? 92
> +++++++++++++++++++++++++++++++++
> > ?2 files changed, 96 insertions(+), 0 deletions(-)
> > ?create mode 100644 arch/arm/mach-s5pv310/mach-smdkv310.c
> >
> > diff --git a/arch/arm/mach-s5pv310/Makefile
b/arch/arm/mach-s5pv310/Makefile
> > index 1b263a5..56e7693 100644
> > --- a/arch/arm/mach-s5pv310/Makefile
> > +++ b/arch/arm/mach-s5pv310/Makefile
> > @@ -18,3 +18,7 @@ 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
> > diff --git a/arch/arm/mach-s5pv310/mach-smdkv310.c b/arch/arm/mach-
> s5pv310/mach-smdkv310.c
> > new file mode 100644
> > index 0000000..0d6ab77
> > --- /dev/null
> > +++ b/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)
> 
> UART supports the 16 triggers at 2/3. No need to setup the lower value.
> 
UFCON_DEFAULT is board specific UART configuration. Usually, we set the Tx
and Rx FIFO trigger level at 4. It does not matter. It mainly depends on the
final use of UART. If required, it can be changed later.

> > +
> > +static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = {
> > + ? ? ? [0] = {
> > + ? ? ? ? ? ? ? .hwport ? ? ? ? = 0,
> > + ? ? ? ? ? ? ? .flags ? ? ? ? ?= 0,
> 
> Please remove unused flags filed.
> Previous time Mr. Shim sent the related patch.
> 
As far as I know, not applied yet.

> > + ? ? ? ? ? ? ? .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
> > --

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 5/8] ARM: S5PV310: Add Timer support
  2010-07-16 10:30   ` Kyungmin Park
  2010-07-20 12:34     ` Kukjin Kim
@ 2010-07-26  4:07     ` 김상범
  1 sibling, 0 replies; 21+ messages in thread
From: 김상범 @ 2010-07-26  4:07 UTC (permalink / raw)
  To: linux-arm-kernel


Hi Kyungmin,

>On Fri, Jul 16, 2010 at 5:58 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
>> From: Changhwan Youn <chaos.youn@samsung.com>
>>
>> This patch adds timer support for S5PV310.
>> Until now, all S5P SoCs use CONFIG_ARCH_USES_GETTIMEOFFSET macro as a
>default
>> configuration. Instead, S5PV310 implements clocksource and
>clock_event_device
>> to support the high resolution timer and tickless system.
>>
>> Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
>> Signed-off-by: Hyuk Lee <hyuk1.lee@samsung.com>
>> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
>> ---
>>  arch/arm/mach-s5pv310/include/mach/pwm-clock.h |   70 ++++++
>>  arch/arm/mach-s5pv310/localtimer.c             |   25 ++
>>  arch/arm/mach-s5pv310/time.c                   |  287
>++++++++++++++++++++++++
>>  arch/arm/plat-s5p/include/plat/s5pv310.h       |    1 +
>>  arch/arm/plat-samsung/Makefile                 |    2 +-
>>  5 files changed, 384 insertions(+), 1 deletions(-)
>>  create mode 100644 arch/arm/mach-s5pv310/include/mach/pwm-clock.h
>>  create mode 100644 arch/arm/mach-s5pv310/localtimer.c
>>  create mode 100644 arch/arm/mach-s5pv310/time.c
>>
>> diff --git a/arch/arm/mach-s5pv310/include/mach/pwm-clock.h
>b/arch/arm/mach-s5pv310/include/mach/pwm-clock.h
>> new file mode 100644
>> index 0000000..7e6da27
>> --- /dev/null
>> +++ b/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 */
>> diff --git a/arch/arm/mach-s5pv310/localtimer.c b/arch/arm/mach-
>s5pv310/localtimer.c
>> new file mode 100644
>> index 0000000..2784036
>> --- /dev/null
>> +++ b/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);
>> +}
>> diff --git a/arch/arm/mach-s5pv310/time.c b/arch/arm/mach-s5pv310/time.c
>> new file mode 100644
>> index 0000000..64accf8
>> --- /dev/null
>> +++ b/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
>
>Please make it configurable, now PWM 2 is used for I2C pin in mobile
>hardware.
>It seems to smdk specific file.
>
>Why don't use the systimer?
>
>Thank you,
>Kyungmin Park
>

In current implementation, pwm 2 is for clock source and 
arm private timers are used for clock event device.
Pwm 4 is used only for calibrating arm private timers.
because arm private timers are calibrated using Jiffies and that means 
we need other timer for clock event before the arm private timers are registered to the kernel.

According to your comment, it seems that pwm 4 is more appropriate for clock source 
because pwm 4 doesn't have external output function through GPIO port.
With this modification, pwm 2 will be used for clock event device during early boot time 
and can be used for other purpose after system boot time.

regards,
Sangbeom Kim

>> + *
>> + * 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(4, cycles);
>> +       s5pv310_pwm_start(4, 0);
>> +       return 0;
>> +}
>> +
>> +static void s5pv310_pwm_set_mode(enum clock_event_mode mode,
>> +                               struct clock_event_device *evt)
>> +{
>> +       s5pv310_pwm_stop(4);
>> +
>> +       switch (mode) {
>> +       case CLOCK_EVT_MODE_PERIODIC:
>> +               s5pv310_pwm_init(4, clock_count_per_tick);
>> +               s5pv310_pwm_start(4, 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_timer4",
>> +       .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_timer4_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(tdiv4);
>> +
>> +       clk_set_rate(tscaler, pclk / 2);
>> +       clk_set_rate(tdiv4, pclk / 2);
>> +       clk_set_parent(tin4, tdiv4);
>> +
>> +       clock_rate = clk_get_rate(tin4);
>> +
>> +       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_TIMER4, &s5pv310_clock_event_irq);
>> +}
>> +
>> +static cycle_t s5pv310_pwm2_read(struct clocksource *cs)
>> +{
>> +       return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x2c));
>> +}
>> +
>> +struct clocksource pwm_clocksource = {
>> +       .name           = "pwm_timer2",
>> +       .rating         = 250,
>> +       .read           = s5pv310_pwm2_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(tdiv2, pclk / 2);
>> +       clk_set_parent(tin2, tdiv2);
>> +
>> +       clock_rate = clk_get_rate(tin2);
>> +
>> +       s5pv310_pwm_init(2, ~0);
>> +       s5pv310_pwm_start(2, 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,
>> +};
>> diff --git a/arch/arm/plat-s5p/include/plat/s5pv310.h b/arch/arm/plat-
>s5p/include/plat/s5pv310.h
>> index d2f05e1..769c991 100644
>> --- a/arch/arm/plat-s5p/include/plat/s5pv310.h
>> +++ b/arch/arm/plat-s5p/include/plat/s5pv310.h
>> @@ -22,6 +22,7 @@ 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
>>
>> diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-
>samsung/Makefile
>> index b1d82cc..0d5bf8a 100644
>> --- a/arch/arm/plat-samsung/Makefile
>> +++ b/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
>> --
>> 1.6.2.5
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-samsung-
>soc" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>--
>To unsubscribe from this list: send the line "unsubscribe linux-samsung-
>soc" in
>the body of a message to majordomo at vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 3/8] ARM: S5PV310: Add Clock and PLL support
  2010-07-16  8:58 ` [PATCH v2 3/8] ARM: S5PV310: Add Clock and PLL support Kukjin Kim
@ 2010-07-27  6:24   ` MyungJoo Ham
  2010-07-27  9:06     ` Kukjin Kim
  0 siblings, 1 reply; 21+ messages in thread
From: MyungJoo Ham @ 2010-07-27  6:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Fri, Jul 16, 2010 at 5:58 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> From: Changhwan Youn <chaos.youn@samsung.com>
>
> This patch adds clock and pll support for S5PV310.
>
> Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> ---
> ?arch/arm/mach-s5pv310/clock.c ? ? ? ? ? ? ? ? ? | ?544 +++++++++++++++++++++++
> ?arch/arm/mach-s5pv310/include/mach/regs-clock.h | ? 60 +++
> ?arch/arm/plat-s5p/include/plat/pll.h ? ? ? ? ? ?| ? 41 ++
> ?3 files changed, 645 insertions(+), 0 deletions(-)
> ?create mode 100644 arch/arm/mach-s5pv310/clock.c
> ?create mode 100644 arch/arm/mach-s5pv310/include/mach/regs-clock.h
>
> diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
> new file mode 100644
> index 0000000..bb671d5
> --- /dev/null
> +++ b/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 = 4, .size = 1 },
> +};

S5P_CLKSRC_CPU[4] is not described in the user manual (it's
"Reserved"). Is it "undocumented", "typographical error" in manual, or
"typographical error" in the source code? If the user manual is
correct, it appears to have the shift value of 8.

> +
> +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 },
> +};

We have two clock definitions that are identical, "aclk_corem0" and
"aclk_cores". Is there any reason to define the same clock source
twice? Although this is not going to make lockup/deadlock issues due
to duplicated clocks as long as there are no enable/disable functions
attached, these two may still suffer from inconsistency due to the
updates (on DIV) from each other.

In the clock diagram, ACLK_COREM0 and ACLK_CORES are getting the same
clock from DIV_COREM0. In such a case, it'd be better let
clk_aclk_corem0 and clk_aclk_cores be children of a source clock of
DIV_corem0 or aclk_cores be a child of aclk_corem0 unless we can
guarantee that at least one of corem0 and cores will _never_ write to
S5P_CLKDIV_CPU.

Please note that with the common struct clk that provides one lock per
clock combined with SMP support of S5PV310, we can suffer from
inconsistency due to parallelism in clock related values. For example,
updating DIV value of corem0 may happen in the middle of
reading/updating cores's DIV value. We can prevent such actions by
locking more widely (the whole section of clk_get_rate and
clk_set_rate with a global lock); however, this may affect the
efficiency greatly especially in SMP machines.

> +
> +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_periph = {
> + ? ? ? .clk ? ?= {
> + ? ? ? ? ? ? ? .name ? ? ? ? ? = "periph",
> + ? ? ? ? ? ? ? .id ? ? ? ? ? ? = -1,
> + ? ? ? ? ? ? ? .parent ? ? ? ? = &clk_coreclk.clk,
> + ? ? ? },
> + ? ? ? .reg_div ? ? ? ?= { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
> +};
> +
> +static struct clksrc_clk clk_atbout = {
> + ? ? ? .clk ? ?= {
> + ? ? ? ? ? ? ? .name ? ? ? ? ? = "atbout",
> + ? ? ? ? ? ? ? .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_atbout.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_CPU, .shift = 4, .size = 1 },
> +};

The clock, "mout_corebus", appears to be either duplicated (another
instance of S5P_CLKSRC_CPU[4]) or mistyped. Besides, "moutcore" is
already defined with a shift value of 16 and sources with
clkset_moutcore. Did you intend to define
MUX_HPM_SEL(CLK_SRC_CPU[20]), which is the only bit that is not
defined yet with CLK_SRC_CPU.

> +
> +static struct clksrc_clk clk_sclk_dmc = {
> + ? ? ? .clk ? ?= {
> + ? ? ? ? ? ? ? .name ? ? ? ? ? = "sclk_dmc",
> + ? ? ? ? ? ? ? .id ? ? ? ? ? ? = -1,
> + ? ? ? ? ? ? ? .parent ? ? ? ? = &clk_mout_corebus.clk,

==> clk_moutcore.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,

==> clk_moutcore.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),
> +};

clkset_aclk_200 and clkset_aclk_100 are the same.

> +
> +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),
> +};

clkset_aclk_160 is also same with _200 and _100.

> +
> +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),
> +};

clkset_aclk_133 is also same with _200, _100, and _160.

> +
> +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_TOP0, .shift = 0, .size = 1 },
> +};

In the user manual, CLKSRC_TOP0[0] is "Reserved". It appears that the
.reg field should be "S5P_CLKSRC_TOP1", not "TOP0".

> +
> +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_periph,
> + ? ? ? &clk_atbout,
> + ? ? ? &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 periclk;
> + ? ? ? 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);
> + ? ? ? periclk = clk_get_rate(&clk_periph.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,
> + ? ? ? ? ? ? ? ? ? ? ? periclk, sclk_dmc, aclk_cored, aclk_corep,
> + ? ? ? ? ? ? ? ? ? ? ? aclk_acp, pclk_acp);
> +
> + ? ? ? clk_f.rate = armclk;
> + ? ? ? clk_h.rate = sclk_dmc;
> + ? ? ? clk_p.rate = periclk;
> +
> + ? ? ? 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();
> +}
> diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
> new file mode 100644
> index 0000000..77f637f
> --- /dev/null
> +++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
> @@ -0,0 +1,60 @@
> +/* 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_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 */
> diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h
> index 7db3227..4e8fe08 100644
> --- a/arch/arm/plat-s5p/include/plat/pll.h
> +++ b/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)
> --
> 1.6.2.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>



-- 
MyungJoo Ham, Ph.D.
Mobile Software Platform Lab,
Digital Media and Communications (DMC) Business
Samsung Electronics
cell: 82-10-6714-2858

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 3/8] ARM: S5PV310: Add Clock and PLL support
  2010-07-27  6:24   ` MyungJoo Ham
@ 2010-07-27  9:06     ` Kukjin Kim
  2010-07-27 10:43       ` MyungJoo Ham
  0 siblings, 1 reply; 21+ messages in thread
From: Kukjin Kim @ 2010-07-27  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

MyungJoo Ham wrote:
> 
> Hello,

Hello,

> 
> On Fri, Jul 16, 2010 at 5:58 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> > From: Changhwan Youn <chaos.youn@samsung.com>
> >
> > This patch adds clock and pll support for S5PV310.
> >
> > Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > ---
> >  arch/arm/mach-s5pv310/clock.c                   |  544
> +++++++++++++++++++++++
> >  arch/arm/mach-s5pv310/include/mach/regs-clock.h |   60 +++
> >  arch/arm/plat-s5p/include/plat/pll.h            |   41 ++
> >  3 files changed, 645 insertions(+), 0 deletions(-)
> >  create mode 100644 arch/arm/mach-s5pv310/clock.c
> >  create mode 100644 arch/arm/mach-s5pv310/include/mach/regs-clock.h
> >
> > diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
> > new file mode 100644
> > index 0000000..bb671d5
> > --- /dev/null
> > +++ b/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 = 4, .size = 1 },
> > +};
> 
> S5P_CLKSRC_CPU[4] is not described in the user manual (it's
> "Reserved"). Is it "undocumented", "typographical error" in manual, or
> "typographical error" in the source code? If the user manual is
> correct, it appears to have the shift value of 8.
> 
Yeah, you're right....typo...will fix it.

> > +
> > +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 },
> > +};
> 
> We have two clock definitions that are identical, "aclk_corem0" and
> "aclk_cores". Is there any reason to define the same clock source
> twice? Although this is not going to make lockup/deadlock issues due
> to duplicated clocks as long as there are no enable/disable functions
> attached, these two may still suffer from inconsistency due to the
> updates (on DIV) from each other.
> 
> In the clock diagram, ACLK_COREM0 and ACLK_CORES are getting the same
> clock from DIV_COREM0. In such a case, it'd be better let
> clk_aclk_corem0 and clk_aclk_cores be children of a source clock of
> DIV_corem0 or aclk_cores be a child of aclk_corem0 unless we can
> guarantee that at least one of corem0 and cores will _never_ write to
> S5P_CLKDIV_CPU.
> 
> Please note that with the common struct clk that provides one lock per
> clock combined with SMP support of S5PV310, we can suffer from
> inconsistency due to parallelism in clock related values. For example,
> updating DIV value of corem0 may happen in the middle of
> reading/updating cores's DIV value. We can prevent such actions by
> locking more widely (the whole section of clk_get_rate and
> clk_set_rate with a global lock); however, this may affect the
> efficiency greatly especially in SMP machines.
> 
Actually, there are own purpose...so we need to separate them.
But used same divider because there is no case that need to set up different each clock rate.

> > +
> > +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_periph = {
> > +       .clk    = {
> > +               .name           = "periph",
> > +               .id             = -1,
> > +               .parent         = &clk_coreclk.clk,
> > +       },
> > +       .reg_div        = { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
> > +};
> > +
> > +static struct clksrc_clk clk_atbout = {
> > +       .clk    = {
> > +               .name           = "atbout",
> > +               .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_atbout.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_CPU, .shift = 4, .size = 1 },
> > +};
> 
> The clock, "mout_corebus", appears to be either duplicated (another
> instance of S5P_CLKSRC_CPU[4]) or mistyped. Besides, "moutcore" is
> already defined with a shift value of 16 and sources with
> clkset_moutcore. Did you intend to define
> MUX_HPM_SEL(CLK_SRC_CPU[20]), which is the only bit that is not
> defined yet with CLK_SRC_CPU.
> 
yeah, should be 16...will fix it.

> > +
> > +static struct clksrc_clk clk_sclk_dmc = {
> > +       .clk    = {
> > +               .name           = "sclk_dmc",
> > +               .id             = -1,
> > +               .parent         = &clk_mout_corebus.clk,
> 
> ==> clk_moutcore.clk?
> 
Please refer to below explain.

> > +       },
> > +       .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,
> 
> ==> clk_moutcore.clk?

The parent of clock 'clk_aclk_acp' is clk_mout_corebus.
The clock 'clk_moutcore' is in ohter domain, CMU_CPU.

> 
> > +       },
> > +       .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),
> > +};
> 
> clkset_aclk_200 and clkset_aclk_100 are the same.
> 
Each clock 'aclk_xxx' has own clock rate for supporting bus clock.
So...it differs.

> > +
> > +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),
> > +};
> 
> clkset_aclk_160 is also same with _200 and _100.
> 
already explained.

> > +
> > +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),
> > +};
> 
> clkset_aclk_133 is also same with _200, _100, and _160.
> 
already explained.

> > +
> > +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_TOP0, .shift = 0, .size = 1 },
> > +};
> 
> In the user manual, CLKSRC_TOP0[0] is "Reserved". It appears that the
> .reg field should be "S5P_CLKSRC_TOP1", not "TOP0".

will fix it.

> 
> > +
> > +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_periph,
> > +       &clk_atbout,
> > +       &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 periclk;
> > +       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);
> > +       periclk = clk_get_rate(&clk_periph.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,
> > +                       periclk, sclk_dmc, aclk_cored, aclk_corep,
> > +                       aclk_acp, pclk_acp);
> > +
> > +       clk_f.rate = armclk;
> > +       clk_h.rate = sclk_dmc;
> > +       clk_p.rate = periclk;
> > +
> > +       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();
> > +}
> > diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-
> s5pv310/include/mach/regs-clock.h
> > new file mode 100644
> > index 0000000..77f637f
> > --- /dev/null
> > +++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
> > @@ -0,0 +1,60 @@
> > +/* 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_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 */
> > diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-
> s5p/include/plat/pll.h
> > index 7db3227..4e8fe08 100644
> > --- a/arch/arm/plat-s5p/include/plat/pll.h
> > +++ b/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)
> > --

Thanks for pointing it out.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 3/8] ARM: S5PV310: Add Clock and PLL support
  2010-07-27  9:06     ` Kukjin Kim
@ 2010-07-27 10:43       ` MyungJoo Ham
  0 siblings, 0 replies; 21+ messages in thread
From: MyungJoo Ham @ 2010-07-27 10:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, again.

On Tue, Jul 27, 2010 at 6:06 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> MyungJoo Ham wrote:
>>
>> Hello,
>
> Hello,
>
>>
>> On Fri, Jul 16, 2010 at 5:58 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
>> > From: Changhwan Youn <chaos.youn@samsung.com>
>> >
>> > This patch adds clock and pll support for S5PV310.
>> >
>> > Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
>> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
>> > ---
>> > ?arch/arm/mach-s5pv310/clock.c ? ? ? ? ? ? ? ? ? | ?544
>> +++++++++++++++++++++++
>> > ?arch/arm/mach-s5pv310/include/mach/regs-clock.h | ? 60 +++
>> > ?arch/arm/plat-s5p/include/plat/pll.h ? ? ? ? ? ?| ? 41 ++
>> > ?3 files changed, 645 insertions(+), 0 deletions(-)
>> > ?create mode 100644 arch/arm/mach-s5pv310/clock.c
>> > ?create mode 100644 arch/arm/mach-s5pv310/include/mach/regs-clock.h
>> >
>> > diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
>> > new file mode 100644
>> > index 0000000..bb671d5
>> > --- /dev/null
>> > +++ b/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 = 4, .size = 1 },
>> > +};
>>
>> S5P_CLKSRC_CPU[4] is not described in the user manual (it's
>> "Reserved"). Is it "undocumented", "typographical error" in manual, or
>> "typographical error" in the source code? If the user manual is
>> correct, it appears to have the shift value of 8.
>>
> Yeah, you're right....typo...will fix it.
>
>> > +
>> > +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 },
>> > +};
>>
>> We have two clock definitions that are identical, "aclk_corem0" and
>> "aclk_cores". Is there any reason to define the same clock source
>> twice? Although this is not going to make lockup/deadlock issues due
>> to duplicated clocks as long as there are no enable/disable functions
>> attached, these two may still suffer from inconsistency due to the
>> updates (on DIV) from each other.
>>
>> In the clock diagram, ACLK_COREM0 and ACLK_CORES are getting the same
>> clock from DIV_COREM0. In such a case, it'd be better let
>> clk_aclk_corem0 and clk_aclk_cores be children of a source clock of
>> DIV_corem0 or aclk_cores be a child of aclk_corem0 unless we can
>> guarantee that at least one of corem0 and cores will _never_ write to
>> S5P_CLKDIV_CPU.
>>
>> Please note that with the common struct clk that provides one lock per
>> clock combined with SMP support of S5PV310, we can suffer from
>> inconsistency due to parallelism in clock related values. For example,
>> updating DIV value of corem0 may happen in the middle of
>> reading/updating cores's DIV value. We can prevent such actions by
>> locking more widely (the whole section of clk_get_rate and
>> clk_set_rate with a global lock); however, this may affect the
>> efficiency greatly especially in SMP machines.
>>
> Actually, there are own purpose...so we need to separate them.
> But used same divider because there is no case that need to set up different each clock rate.

I understand that ACLK_COREM0 and ACLK_CORES are separated after
DIV_corem0 and each clock rate would not be different.

And, if you can guarantee that nobody is going to update DIV value
without notifying the another (COREM0 vs CORES), it's fine.

However, if it's not (the DIV value may be updated at run-time), we
should let only one of them have the DIV. e.g.,


I suggest the following:

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_aclk_corem0.clk,
 ? ? ? },
};

== OR ==

static struct clksrc_clk clk_div_corem0 = {
 ? ? ? .clk ? ?= {
 ? ? ? ? ? ? ? .name ? ? ? ? ? = "div_corem0",
 ? ? ? ? ? ? ? .id ? ? ? ? ? ? = -1,
 ? ? ? ? ? ? ? .parent ? ? ? ? = &clk_coreclk.clk,
 ? ? ? },
 ? ? ? .reg_div ? ? ? ?= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
};

static struct clksrc_clk clk_aclk_corem0 = {
 ? ? ? .clk ? ?= {
 ? ? ? ? ? ? ? .name ? ? ? ? ? = "aclk_corem0",
 ? ? ? ? ? ? ? .id ? ? ? ? ? ? = -1,
 ? ? ? ? ? ? ? .parent ? ? ? ? = &clk_div_corem0.clk,
 ? ? ? },
};

static struct clksrc_clk clk_aclk_cores = {
 ? ? ? .clk ? ?= {
 ? ? ? ? ? ? ? .name ? ? ? ? ? = "aclk_cores",
 ? ? ? ? ? ? ? .id ? ? ? ? ? ? = -1,
 ? ? ? ? ? ? ? .parent ? ? ? ? = &clk_div_corem0.clk,
 ? ? ? },
};




>
>> > +
>> > +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_periph = {
>> > + ? ? ? .clk ? ?= {
>> > + ? ? ? ? ? ? ? .name ? ? ? ? ? = "periph",
>> > + ? ? ? ? ? ? ? .id ? ? ? ? ? ? = -1,
>> > + ? ? ? ? ? ? ? .parent ? ? ? ? = &clk_coreclk.clk,
>> > + ? ? ? },
>> > + ? ? ? .reg_div ? ? ? ?= { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
>> > +};
>> > +
>> > +static struct clksrc_clk clk_atbout = {
>> > + ? ? ? .clk ? ?= {
>> > + ? ? ? ? ? ? ? .name ? ? ? ? ? = "atbout",
>> > + ? ? ? ? ? ? ? .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_atbout.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_CPU, .shift = 4, .size = 1 },
>> > +};
>>
>> The clock, "mout_corebus", appears to be either duplicated (another
>> instance of S5P_CLKSRC_CPU[4]) or mistyped. Besides, "moutcore" is
>> already defined with a shift value of 16 and sources with
>> clkset_moutcore. Did you intend to define
>> MUX_HPM_SEL(CLK_SRC_CPU[20]), which is the only bit that is not
>> defined yet with CLK_SRC_CPU.
>>
> yeah, should be 16...will fix it.

If this "mout_corebus" is meant to address the MUX_CORE_BUS in CORE
domain as you've mentioned below, it should be CLK_SRC_CORE with shift
= 4.

>
>> > +
>> > +static struct clksrc_clk clk_sclk_dmc = {
>> > + ? ? ? .clk ? ?= {
>> > + ? ? ? ? ? ? ? .name ? ? ? ? ? = "sclk_dmc",
>> > + ? ? ? ? ? ? ? .id ? ? ? ? ? ? = -1,
>> > + ? ? ? ? ? ? ? .parent ? ? ? ? = &clk_mout_corebus.clk,
>>
>> ==> clk_moutcore.clk?
>>
> Please refer to below explain.

If this corebus.clk is to access CLK_SRC_CORE, using clk_mout_corebus
seems correct.

>
>> > + ? ? ? },
>> > + ? ? ? .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,
>>
>> ==> clk_moutcore.clk?
>
> The parent of clock 'clk_aclk_acp' is clk_mout_corebus.
> The clock 'clk_moutcore' is in ohter domain, CMU_CPU.
>
>>
>> > + ? ? ? },
>> > + ? ? ? .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),
>> > +};
>>
>> clkset_aclk_200 and clkset_aclk_100 are the same.
>>
> Each clock 'aclk_xxx' has own clock rate for supporting bus clock.
> So...it differs.

You can still set the SRC differently even if clkset_aclk_* is reused;
i.e., clkset_aclk_* only lists possible clock sources.

>
>> > +
>> > +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),
>> > +};
>>
>> clkset_aclk_160 is also same with _200 and _100.
>>
> already explained.
>
>> > +
>> > +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),
>> > +};
>>
>> clkset_aclk_133 is also same with _200, _100, and _160.
>>
> already explained.
>
>> > +
>> > +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_TOP0, .shift = 0, .size = 1 },
>> > +};
>>
>> In the user manual, CLKSRC_TOP0[0] is "Reserved". It appears that the
>> .reg field should be "S5P_CLKSRC_TOP1", not "TOP0".
>
> will fix it.
>
>>
>> > +
>> > +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_periph,
>> > + ? ? ? &clk_atbout,
>> > + ? ? ? &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 periclk;
>> > + ? ? ? 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);
>> > + ? ? ? periclk = clk_get_rate(&clk_periph.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,
>> > + ? ? ? ? ? ? ? ? ? ? ? periclk, sclk_dmc, aclk_cored, aclk_corep,
>> > + ? ? ? ? ? ? ? ? ? ? ? aclk_acp, pclk_acp);
>> > +
>> > + ? ? ? clk_f.rate = armclk;
>> > + ? ? ? clk_h.rate = sclk_dmc;
>> > + ? ? ? clk_p.rate = periclk;
>> > +
>> > + ? ? ? 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();
>> > +}
>> > diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-
>> s5pv310/include/mach/regs-clock.h
>> > new file mode 100644
>> > index 0000000..77f637f
>> > --- /dev/null
>> > +++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
>> > @@ -0,0 +1,60 @@
>> > +/* 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_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 */
>> > diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-
>> s5p/include/plat/pll.h
>> > index 7db3227..4e8fe08 100644
>> > --- a/arch/arm/plat-s5p/include/plat/pll.h
>> > +++ b/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)
>> > --
>
> Thanks for pointing it out.
>
> Best regards,
> Kgene.
> --
> Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
> SW Solution Development Team, Samsung Electronics Co., Ltd.
>
>



-- 
MyungJoo Ham, Ph.D.
Mobile Software Platform Lab,
Digital Media and Communications (DMC) Business
Samsung Electronics
cell: 82-10-6714-2858

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2010-07-27 10:43 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-16  8:58 [PATCH v2 0/8] ARM: S5PV310: Add support for Samsung S5PV310 SoC Kukjin Kim
2010-07-16  8:58 ` [PATCH v2 1/8] ARM: S5P: Remove fixed uart offset dependent code Kukjin Kim
2010-07-16  8:58 ` [PATCH v2 2/8] ARM: S5PV310: Add new CPU initialization support Kukjin Kim
2010-07-16 10:58   ` Kyungmin Park
2010-07-16 11:52   ` Russell King - ARM Linux
2010-07-17  3:52     ` Kyungmin Park
2010-07-19  0:09     ` Kukjin Kim
2010-07-16  8:58 ` [PATCH v2 3/8] ARM: S5PV310: Add Clock and PLL support Kukjin Kim
2010-07-27  6:24   ` MyungJoo Ham
2010-07-27  9:06     ` Kukjin Kim
2010-07-27 10:43       ` MyungJoo Ham
2010-07-16  8:58 ` [PATCH v2 4/8] ARM: S5PV310: Add IRQ support Kukjin Kim
2010-07-16  8:58 ` [PATCH v2 5/8] ARM: S5PV310: Add Timer support Kukjin Kim
2010-07-16 10:30   ` Kyungmin Park
2010-07-20 12:34     ` Kukjin Kim
2010-07-26  4:07     ` 김상범
2010-07-16  8:58 ` [PATCH v2 6/8] ARM: S5PV310: Add new Kconfig and Makefiles Kukjin Kim
2010-07-16  8:58 ` [PATCH v2 7/8] ARM: S5PV310: Add Board support file Kukjin Kim
2010-07-16 10:36   ` Kyungmin Park
2010-07-21 12:33     ` Kukjin Kim
2010-07-16  8:58 ` [PATCH v2 8/8] ARM: S5PV310: Add serial port support Kukjin Kim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).