aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s5pv310
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-08-09 09:09:29 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-08-09 09:09:29 -0400
commit054d5c9238f3c577ad51195c3ee7803613f322cc (patch)
treeff7d9f5c0e0ddf14230ba28f28ef69a2c0a0debf /arch/arm/mach-s5pv310
parent11e4afb49b7fa1fc8e1ffd850c1806dd86a08204 (diff)
parent2192482ee5ce5d5d4a6cec0c351b2d3a744606eb (diff)
Merge branch 'devel-stable' into devel
Diffstat (limited to 'arch/arm/mach-s5pv310')
-rw-r--r--arch/arm/mach-s5pv310/Kconfig45
-rw-r--r--arch/arm/mach-s5pv310/Makefile30
-rw-r--r--arch/arm/mach-s5pv310/Makefile.boot2
-rw-r--r--arch/arm/mach-s5pv310/clock.c544
-rw-r--r--arch/arm/mach-s5pv310/cpu.c122
-rw-r--r--arch/arm/mach-s5pv310/headsmp.S41
-rw-r--r--arch/arm/mach-s5pv310/include/mach/debug-macro.S36
-rw-r--r--arch/arm/mach-s5pv310/include/mach/entry-macro.S84
-rw-r--r--arch/arm/mach-s5pv310/include/mach/gpio.h135
-rw-r--r--arch/arm/mach-s5pv310/include/mach/hardware.h18
-rw-r--r--arch/arm/mach-s5pv310/include/mach/io.h26
-rw-r--r--arch/arm/mach-s5pv310/include/mach/irqs.h74
-rw-r--r--arch/arm/mach-s5pv310/include/mach/map.h69
-rw-r--r--arch/arm/mach-s5pv310/include/mach/memory.h22
-rw-r--r--arch/arm/mach-s5pv310/include/mach/pwm-clock.h70
-rw-r--r--arch/arm/mach-s5pv310/include/mach/regs-clock.h62
-rw-r--r--arch/arm/mach-s5pv310/include/mach/regs-irq.h19
-rw-r--r--arch/arm/mach-s5pv310/include/mach/smp.h29
-rw-r--r--arch/arm/mach-s5pv310/include/mach/system.h22
-rw-r--r--arch/arm/mach-s5pv310/include/mach/timex.h29
-rw-r--r--arch/arm/mach-s5pv310/include/mach/uncompress.h30
-rw-r--r--arch/arm/mach-s5pv310/include/mach/vmalloc.h22
-rw-r--r--arch/arm/mach-s5pv310/init.c41
-rw-r--r--arch/arm/mach-s5pv310/irq-combiner.c125
-rw-r--r--arch/arm/mach-s5pv310/localtimer.c25
-rw-r--r--arch/arm/mach-s5pv310/mach-smdkv310.c92
-rw-r--r--arch/arm/mach-s5pv310/mach-universal_c210.c86
-rw-r--r--arch/arm/mach-s5pv310/platsmp.c192
-rw-r--r--arch/arm/mach-s5pv310/setup-i2c0.c28
-rw-r--r--arch/arm/mach-s5pv310/setup-i2c1.c25
-rw-r--r--arch/arm/mach-s5pv310/setup-i2c2.c25
-rw-r--r--arch/arm/mach-s5pv310/time.c287
32 files changed, 2457 insertions, 0 deletions
diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig
new file mode 100644
index 000000000000..331b5bd97aba
--- /dev/null
+++ b/arch/arm/mach-s5pv310/Kconfig
@@ -0,0 +1,45 @@
1# arch/arm/mach-s5pv310/Kconfig
2#
3# Copyright (c) 2010 Samsung Electronics Co., Ltd.
4# http://www.samsung.com/
5#
6# Licensed under GPLv2
7
8# Configuration options for the S5PV310
9
10if ARCH_S5PV310
11
12config CPU_S5PV310
13 bool
14 select PLAT_S5P
15 help
16 Enable S5PV310 CPU support
17
18config S5PV310_SETUP_I2C1
19 bool
20 help
21 Common setup code for i2c bus 1.
22
23config S5PV310_SETUP_I2C2
24 bool
25 help
26 Common setup code for i2c bus 2.
27
28# machine support
29
30config MACH_SMDKV310
31 bool "SMDKV310"
32 select CPU_S5PV310
33 select ARCH_SPARSEMEM_ENABLE
34 help
35 Machine support for Samsung SMDKV310
36
37config MACH_UNIVERSAL_C210
38 bool "Mobile UNIVERSAL_C210 Board"
39 select CPU_S5PV310
40 select ARCH_SPARSEMEM_ENABLE
41 help
42 Machine support for Samsung Mobile Universal S5PC210 Reference
43 Board. S5PC210(MCP) is one of package option of S5PV310
44
45endif
diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile
new file mode 100644
index 000000000000..d5b51c72340f
--- /dev/null
+++ b/arch/arm/mach-s5pv310/Makefile
@@ -0,0 +1,30 @@
1# arch/arm/mach-s5pv310/Makefile
2#
3# Copyright (c) 2010 Samsung Electronics Co., Ltd.
4# http://www.samsung.com/
5#
6# Licensed under GPLv2
7
8obj-y :=
9obj-m :=
10obj-n :=
11obj- :=
12
13# Core support for S5PV310 system
14
15obj-$(CONFIG_CPU_S5PV310) += cpu.o init.o clock.o irq-combiner.o
16obj-$(CONFIG_CPU_S5PV310) += setup-i2c0.o time.o
17
18obj-$(CONFIG_SMP) += platsmp.o headsmp.o
19obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
20obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
21
22# machine support
23
24obj-$(CONFIG_MACH_SMDKV310) += mach-smdkv310.o
25obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o
26
27# device support
28
29obj-$(CONFIG_S5PV310_SETUP_I2C1) += setup-i2c1.o
30obj-$(CONFIG_S5PV310_SETUP_I2C2) += setup-i2c2.o
diff --git a/arch/arm/mach-s5pv310/Makefile.boot b/arch/arm/mach-s5pv310/Makefile.boot
new file mode 100644
index 000000000000..d65956ffb43d
--- /dev/null
+++ b/arch/arm/mach-s5pv310/Makefile.boot
@@ -0,0 +1,2 @@
1 zreladdr-y := 0x40008000
2params_phys-y := 0x40000100
diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
new file mode 100644
index 000000000000..77f2b4d85e6b
--- /dev/null
+++ b/arch/arm/mach-s5pv310/clock.c
@@ -0,0 +1,544 @@
1/* linux/arch/arm/mach-s5pv310/clock.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5PV310 - Clock support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/kernel.h>
14#include <linux/err.h>
15#include <linux/io.h>
16
17#include <plat/cpu-freq.h>
18#include <plat/clock.h>
19#include <plat/cpu.h>
20#include <plat/pll.h>
21#include <plat/s5p-clock.h>
22#include <plat/clock-clksrc.h>
23
24#include <mach/map.h>
25#include <mach/regs-clock.h>
26
27static struct clk clk_sclk_hdmi27m = {
28 .name = "sclk_hdmi27m",
29 .id = -1,
30 .rate = 27000000,
31};
32
33/* Core list of CMU_CPU side */
34
35static struct clksrc_clk clk_mout_apll = {
36 .clk = {
37 .name = "mout_apll",
38 .id = -1,
39 },
40 .sources = &clk_src_apll,
41 .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
42 .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
43};
44
45static struct clksrc_clk clk_mout_epll = {
46 .clk = {
47 .name = "mout_epll",
48 .id = -1,
49 },
50 .sources = &clk_src_epll,
51 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
52};
53
54static struct clksrc_clk clk_mout_mpll = {
55 .clk = {
56 .name = "mout_mpll",
57 .id = -1,
58 },
59 .sources = &clk_src_mpll,
60 .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 },
61};
62
63static struct clk *clkset_moutcore_list[] = {
64 [0] = &clk_mout_apll.clk,
65 [1] = &clk_mout_mpll.clk,
66};
67
68static struct clksrc_sources clkset_moutcore = {
69 .sources = clkset_moutcore_list,
70 .nr_sources = ARRAY_SIZE(clkset_moutcore_list),
71};
72
73static struct clksrc_clk clk_moutcore = {
74 .clk = {
75 .name = "moutcore",
76 .id = -1,
77 },
78 .sources = &clkset_moutcore,
79 .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
80};
81
82static struct clksrc_clk clk_coreclk = {
83 .clk = {
84 .name = "core_clk",
85 .id = -1,
86 .parent = &clk_moutcore.clk,
87 },
88 .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
89};
90
91static struct clksrc_clk clk_armclk = {
92 .clk = {
93 .name = "armclk",
94 .id = -1,
95 .parent = &clk_coreclk.clk,
96 },
97};
98
99static struct clksrc_clk clk_aclk_corem0 = {
100 .clk = {
101 .name = "aclk_corem0",
102 .id = -1,
103 .parent = &clk_coreclk.clk,
104 },
105 .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
106};
107
108static struct clksrc_clk clk_aclk_cores = {
109 .clk = {
110 .name = "aclk_cores",
111 .id = -1,
112 .parent = &clk_coreclk.clk,
113 },
114 .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
115};
116
117static struct clksrc_clk clk_aclk_corem1 = {
118 .clk = {
119 .name = "aclk_corem1",
120 .id = -1,
121 .parent = &clk_coreclk.clk,
122 },
123 .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
124};
125
126static struct clksrc_clk clk_periphclk = {
127 .clk = {
128 .name = "periphclk",
129 .id = -1,
130 .parent = &clk_coreclk.clk,
131 },
132 .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
133};
134
135static struct clksrc_clk clk_atclk = {
136 .clk = {
137 .name = "atclk",
138 .id = -1,
139 .parent = &clk_moutcore.clk,
140 },
141 .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 16, .size = 3 },
142};
143
144static struct clksrc_clk clk_pclk_dbg = {
145 .clk = {
146 .name = "pclk_dbg",
147 .id = -1,
148 .parent = &clk_atclk.clk,
149 },
150 .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 20, .size = 3 },
151};
152
153/* Core list of CMU_CORE side */
154
155static struct clk *clkset_corebus_list[] = {
156 [0] = &clk_mout_mpll.clk,
157 [1] = &clk_mout_apll.clk,
158};
159
160static struct clksrc_sources clkset_mout_corebus = {
161 .sources = clkset_corebus_list,
162 .nr_sources = ARRAY_SIZE(clkset_corebus_list),
163};
164
165static struct clksrc_clk clk_mout_corebus = {
166 .clk = {
167 .name = "mout_corebus",
168 .id = -1,
169 },
170 .sources = &clkset_mout_corebus,
171 .reg_src = { .reg = S5P_CLKSRC_CORE, .shift = 4, .size = 1 },
172};
173
174static struct clksrc_clk clk_sclk_dmc = {
175 .clk = {
176 .name = "sclk_dmc",
177 .id = -1,
178 .parent = &clk_mout_corebus.clk,
179 },
180 .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 12, .size = 3 },
181};
182
183static struct clksrc_clk clk_aclk_cored = {
184 .clk = {
185 .name = "aclk_cored",
186 .id = -1,
187 .parent = &clk_sclk_dmc.clk,
188 },
189 .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 16, .size = 3 },
190};
191
192static struct clksrc_clk clk_aclk_corep = {
193 .clk = {
194 .name = "aclk_corep",
195 .id = -1,
196 .parent = &clk_aclk_cored.clk,
197 },
198 .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 20, .size = 3 },
199};
200
201static struct clksrc_clk clk_aclk_acp = {
202 .clk = {
203 .name = "aclk_acp",
204 .id = -1,
205 .parent = &clk_mout_corebus.clk,
206 },
207 .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 0, .size = 3 },
208};
209
210static struct clksrc_clk clk_pclk_acp = {
211 .clk = {
212 .name = "pclk_acp",
213 .id = -1,
214 .parent = &clk_aclk_acp.clk,
215 },
216 .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 4, .size = 3 },
217};
218
219/* Core list of CMU_TOP side */
220
221static struct clk *clkset_aclk_top_list[] = {
222 [0] = &clk_mout_mpll.clk,
223 [1] = &clk_mout_apll.clk,
224};
225
226static struct clksrc_sources clkset_aclk_200 = {
227 .sources = clkset_aclk_top_list,
228 .nr_sources = ARRAY_SIZE(clkset_aclk_top_list),
229};
230
231static struct clksrc_clk clk_aclk_200 = {
232 .clk = {
233 .name = "aclk_200",
234 .id = -1,
235 },
236 .sources = &clkset_aclk_200,
237 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
238 .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 },
239};
240
241static struct clksrc_sources clkset_aclk_100 = {
242 .sources = clkset_aclk_top_list,
243 .nr_sources = ARRAY_SIZE(clkset_aclk_top_list),
244};
245
246static struct clksrc_clk clk_aclk_100 = {
247 .clk = {
248 .name = "aclk_100",
249 .id = -1,
250 },
251 .sources = &clkset_aclk_100,
252 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
253 .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 },
254};
255
256static struct clksrc_sources clkset_aclk_160 = {
257 .sources = clkset_aclk_top_list,
258 .nr_sources = ARRAY_SIZE(clkset_aclk_top_list),
259};
260
261static struct clksrc_clk clk_aclk_160 = {
262 .clk = {
263 .name = "aclk_160",
264 .id = -1,
265 },
266 .sources = &clkset_aclk_160,
267 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
268 .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
269};
270
271static struct clksrc_sources clkset_aclk_133 = {
272 .sources = clkset_aclk_top_list,
273 .nr_sources = ARRAY_SIZE(clkset_aclk_top_list),
274};
275
276static struct clksrc_clk clk_aclk_133 = {
277 .clk = {
278 .name = "aclk_133",
279 .id = -1,
280 },
281 .sources = &clkset_aclk_133,
282 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
283 .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 },
284};
285
286static struct clk *clkset_vpllsrc_list[] = {
287 [0] = &clk_fin_vpll,
288 [1] = &clk_sclk_hdmi27m,
289};
290
291static struct clksrc_sources clkset_vpllsrc = {
292 .sources = clkset_vpllsrc_list,
293 .nr_sources = ARRAY_SIZE(clkset_vpllsrc_list),
294};
295
296static struct clksrc_clk clk_vpllsrc = {
297 .clk = {
298 .name = "vpll_src",
299 .id = -1,
300 },
301 .sources = &clkset_vpllsrc,
302 .reg_src = { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 },
303};
304
305static struct clk *clkset_sclk_vpll_list[] = {
306 [0] = &clk_vpllsrc.clk,
307 [1] = &clk_fout_vpll,
308};
309
310static struct clksrc_sources clkset_sclk_vpll = {
311 .sources = clkset_sclk_vpll_list,
312 .nr_sources = ARRAY_SIZE(clkset_sclk_vpll_list),
313};
314
315static struct clksrc_clk clk_sclk_vpll = {
316 .clk = {
317 .name = "sclk_vpll",
318 .id = -1,
319 },
320 .sources = &clkset_sclk_vpll,
321 .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
322};
323
324static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable)
325{
326 return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable);
327}
328
329static struct clk init_clocks_disable[] = {
330 {
331 .name = "timers",
332 .id = -1,
333 .parent = &clk_aclk_100.clk,
334 .enable = s5pv310_clk_ip_peril_ctrl,
335 .ctrlbit = (1<<24),
336 }
337};
338
339static struct clk init_clocks[] = {
340 /* Nothing here yet */
341};
342
343static struct clk *clkset_group_list[] = {
344 [0] = &clk_ext_xtal_mux,
345 [1] = &clk_xusbxti,
346 [2] = &clk_sclk_hdmi27m,
347 [6] = &clk_mout_mpll.clk,
348 [7] = &clk_mout_epll.clk,
349 [8] = &clk_sclk_vpll.clk,
350};
351
352static struct clksrc_sources clkset_group = {
353 .sources = clkset_group_list,
354 .nr_sources = ARRAY_SIZE(clkset_group_list),
355};
356
357static struct clksrc_clk clksrcs[] = {
358 {
359 .clk = {
360 .name = "uclk1",
361 .id = 0,
362 .ctrlbit = (1 << 0),
363 .enable = s5pv310_clk_ip_peril_ctrl,
364 },
365 .sources = &clkset_group,
366 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
367 .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 },
368 }, {
369 .clk = {
370 .name = "uclk1",
371 .id = 1,
372 .enable = s5pv310_clk_ip_peril_ctrl,
373 .ctrlbit = (1 << 1),
374 },
375 .sources = &clkset_group,
376 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
377 .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 },
378 }, {
379 .clk = {
380 .name = "uclk1",
381 .id = 2,
382 .enable = s5pv310_clk_ip_peril_ctrl,
383 .ctrlbit = (1 << 2),
384 },
385 .sources = &clkset_group,
386 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
387 .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 },
388 }, {
389 .clk = {
390 .name = "uclk1",
391 .id = 3,
392 .enable = s5pv310_clk_ip_peril_ctrl,
393 .ctrlbit = (1 << 3),
394 },
395 .sources = &clkset_group,
396 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
397 .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 },
398 }, {
399 .clk = {
400 .name = "sclk_pwm",
401 .id = -1,
402 .enable = s5pv310_clk_ip_peril_ctrl,
403 .ctrlbit = (1 << 24),
404 },
405 .sources = &clkset_group,
406 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 },
407 .reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 },
408 },
409};
410
411/* Clock initialization code */
412static struct clksrc_clk *sysclks[] = {
413 &clk_mout_apll,
414 &clk_mout_epll,
415 &clk_mout_mpll,
416 &clk_moutcore,
417 &clk_coreclk,
418 &clk_armclk,
419 &clk_aclk_corem0,
420 &clk_aclk_cores,
421 &clk_aclk_corem1,
422 &clk_periphclk,
423 &clk_atclk,
424 &clk_pclk_dbg,
425 &clk_mout_corebus,
426 &clk_sclk_dmc,
427 &clk_aclk_cored,
428 &clk_aclk_corep,
429 &clk_aclk_acp,
430 &clk_pclk_acp,
431 &clk_vpllsrc,
432 &clk_sclk_vpll,
433 &clk_aclk_200,
434 &clk_aclk_100,
435 &clk_aclk_160,
436 &clk_aclk_133,
437};
438
439void __init_or_cpufreq s5pv310_setup_clocks(void)
440{
441 struct clk *xtal_clk;
442 unsigned long apll;
443 unsigned long mpll;
444 unsigned long epll;
445 unsigned long vpll;
446 unsigned long vpllsrc;
447 unsigned long xtal;
448 unsigned long armclk;
449 unsigned long aclk_corem0;
450 unsigned long aclk_cores;
451 unsigned long aclk_corem1;
452 unsigned long periphclk;
453 unsigned long sclk_dmc;
454 unsigned long aclk_cored;
455 unsigned long aclk_corep;
456 unsigned long aclk_acp;
457 unsigned long pclk_acp;
458 unsigned int ptr;
459
460 printk(KERN_DEBUG "%s: registering clocks\n", __func__);
461
462 xtal_clk = clk_get(NULL, "xtal");
463 BUG_ON(IS_ERR(xtal_clk));
464
465 xtal = clk_get_rate(xtal_clk);
466 clk_put(xtal_clk);
467
468 printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
469
470 apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508);
471 mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508);
472 epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
473 __raw_readl(S5P_EPLL_CON1), pll_4500);
474
475 vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
476 vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
477 __raw_readl(S5P_VPLL_CON1), pll_4502);
478
479 clk_fout_apll.rate = apll;
480 clk_fout_mpll.rate = mpll;
481 clk_fout_epll.rate = epll;
482 clk_fout_vpll.rate = vpll;
483
484 printk(KERN_INFO "S5PV310: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
485 apll, mpll, epll, vpll);
486
487 armclk = clk_get_rate(&clk_armclk.clk);
488 aclk_corem0 = clk_get_rate(&clk_aclk_corem0.clk);
489 aclk_cores = clk_get_rate(&clk_aclk_cores.clk);
490 aclk_corem1 = clk_get_rate(&clk_aclk_corem1.clk);
491 periphclk = clk_get_rate(&clk_periphclk.clk);
492 sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk);
493 aclk_cored = clk_get_rate(&clk_aclk_cored.clk);
494 aclk_corep = clk_get_rate(&clk_aclk_corep.clk);
495 aclk_acp = clk_get_rate(&clk_aclk_acp.clk);
496 pclk_acp = clk_get_rate(&clk_pclk_acp.clk);
497
498 printk(KERN_INFO "S5PV310: ARMCLK=%ld, COREM0=%ld, CORES=%ld\n"
499 "COREM1=%ld, PERI=%ld, DMC=%ld, CORED=%ld\n"
500 "COREP=%ld, ACLK_ACP=%ld, PCLK_ACP=%ld",
501 armclk, aclk_corem0, aclk_cores, aclk_corem1,
502 periphclk, sclk_dmc, aclk_cored, aclk_corep,
503 aclk_acp, pclk_acp);
504
505 clk_f.rate = armclk;
506 clk_h.rate = sclk_dmc;
507 clk_p.rate = periphclk;
508
509 for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
510 s3c_set_clksrc(&clksrcs[ptr], true);
511}
512
513static struct clk *clks[] __initdata = {
514 /* Nothing here yet */
515};
516
517void __init s5pv310_register_clocks(void)
518{
519 struct clk *clkp;
520 int ret;
521 int ptr;
522
523 ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
524 if (ret > 0)
525 printk(KERN_ERR "Failed to register %u clocks\n", ret);
526
527 for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
528 s3c_register_clksrc(sysclks[ptr], 1);
529
530 s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
531 s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
532
533 clkp = init_clocks_disable;
534 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
535 ret = s3c24xx_register_clock(clkp);
536 if (ret < 0) {
537 printk(KERN_ERR "Failed to register clock %s (%d)\n",
538 clkp->name, ret);
539 }
540 (clkp->enable)(clkp, 0);
541 }
542
543 s3c_pwmclk_init();
544}
diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c
new file mode 100644
index 000000000000..196c9f12ed85
--- /dev/null
+++ b/arch/arm/mach-s5pv310/cpu.c
@@ -0,0 +1,122 @@
1/* linux/arch/arm/mach-s5pv310/cpu.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9*/
10
11#include <linux/sched.h>
12#include <linux/sysdev.h>
13
14#include <asm/mach/map.h>
15#include <asm/mach/irq.h>
16
17#include <asm/proc-fns.h>
18
19#include <plat/cpu.h>
20#include <plat/clock.h>
21#include <plat/s5pv310.h>
22
23#include <mach/regs-irq.h>
24
25void __iomem *gic_cpu_base_addr;
26
27extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
28 unsigned int irq_start);
29extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
30
31/* Initial IO mappings */
32static struct map_desc s5pv310_iodesc[] __initdata = {
33 {
34 .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
35 .pfn = __phys_to_pfn(S5PV310_PA_COREPERI),
36 .length = SZ_8K,
37 .type = MT_DEVICE,
38 }, {
39 .virtual = (unsigned long)S5P_VA_COMBINER_BASE,
40 .pfn = __phys_to_pfn(S5PV310_PA_COMBINER),
41 .length = SZ_4K,
42 .type = MT_DEVICE,
43 }, {
44 .virtual = (unsigned long)S5P_VA_L2CC,
45 .pfn = __phys_to_pfn(S5PV310_PA_L2CC),
46 .length = SZ_4K,
47 .type = MT_DEVICE,
48 },
49};
50
51static void s5pv310_idle(void)
52{
53 if (!need_resched())
54 cpu_do_idle();
55
56 local_irq_enable();
57}
58
59/* s5pv310_map_io
60 *
61 * register the standard cpu IO areas
62*/
63void __init s5pv310_map_io(void)
64{
65 iotable_init(s5pv310_iodesc, ARRAY_SIZE(s5pv310_iodesc));
66}
67
68void __init s5pv310_init_clocks(int xtal)
69{
70 printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
71
72 s3c24xx_register_baseclocks(xtal);
73 s5p_register_clocks(xtal);
74 s5pv310_register_clocks();
75 s5pv310_setup_clocks();
76}
77
78void __init s5pv310_init_irq(void)
79{
80 int irq;
81
82 gic_cpu_base_addr = S5P_VA_GIC_CPU;
83 gic_dist_init(0, S5P_VA_GIC_DIST, IRQ_LOCALTIMER);
84 gic_cpu_init(0, S5P_VA_GIC_CPU);
85
86 for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
87 combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
88 COMBINER_IRQ(irq, 0));
89 combiner_cascade_irq(irq, IRQ_SPI(irq));
90 }
91
92 /* The parameters of s5p_init_irq() are for VIC init.
93 * Theses parameters should be NULL and 0 because S5PV310
94 * uses GIC instead of VIC.
95 */
96 s5p_init_irq(NULL, 0);
97}
98
99struct sysdev_class s5pv310_sysclass = {
100 .name = "s5pv310-core",
101};
102
103static struct sys_device s5pv310_sysdev = {
104 .cls = &s5pv310_sysclass,
105};
106
107static int __init s5pv310_core_init(void)
108{
109 return sysdev_class_register(&s5pv310_sysclass);
110}
111
112core_initcall(s5pv310_core_init);
113
114int __init s5pv310_init(void)
115{
116 printk(KERN_INFO "S5PV310: Initializing architecture\n");
117
118 /* set idle function */
119 pm_idle = s5pv310_idle;
120
121 return sysdev_register(&s5pv310_sysdev);
122}
diff --git a/arch/arm/mach-s5pv310/headsmp.S b/arch/arm/mach-s5pv310/headsmp.S
new file mode 100644
index 000000000000..164b7b045713
--- /dev/null
+++ b/arch/arm/mach-s5pv310/headsmp.S
@@ -0,0 +1,41 @@
1/*
2 * linux/arch/arm/mach-s5pv310/headsmp.S
3 *
4 * Cloned from linux/arch/arm/mach-realview/headsmp.S
5 *
6 * Copyright (c) 2003 ARM Limited
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#include <linux/linkage.h>
14#include <linux/init.h>
15
16 __INIT
17
18/*
19 * s5pv310 specific entry point for secondary CPUs. This provides
20 * a "holding pen" into which all secondary cores are held until we're
21 * ready for them to initialise.
22 */
23ENTRY(s5pv310_secondary_startup)
24 mrc p15, 0, r0, c0, c0, 5
25 and r0, r0, #15
26 adr r4, 1f
27 ldmia r4, {r5, r6}
28 sub r4, r4, r5
29 add r6, r6, r4
30pen: ldr r7, [r6]
31 cmp r7, r0
32 bne pen
33
34 /*
35 * we've been released from the holding pen: secondary_stack
36 * should now contain the SVC stack for this core
37 */
38 b secondary_startup
39
401: .long .
41 .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 000000000000..6fb3893486be
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/debug-macro.S
@@ -0,0 +1,36 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/debug-macro.S
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13/* pull in the relevant register and map files. */
14
15#include <mach/map.h>
16
17 /* note, for the boot process to work we have to keep the UART
18 * virtual address aligned to an 1MiB boundary for the L1
19 * mapping the head code makes. We keep the UART virtual address
20 * aligned and add in the offset when we load the value here.
21 */
22
23 .macro addruart, rx, tmp
24 mrc p15, 0, \rx, c1, c0
25 tst \rx, #1
26 ldreq \rx, = S3C_PA_UART
27 ldrne \rx, = S3C_VA_UART
28#if CONFIG_DEBUG_S3C_UART != 0
29 add \rx, \rx, #(0x10000 * CONFIG_DEBUG_S3C_UART)
30#endif
31 .endm
32
33#define fifo_full fifo_full_s5pv210
34#define fifo_level fifo_level_s5pv210
35
36#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 000000000000..e600e1d522df
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/entry-macro.S
@@ -0,0 +1,84 @@
1/* arch/arm/mach-s5pv310/include/mach/entry-macro.S
2 *
3 * Cloned from arch/arm/mach-realview/include/mach/entry-macro.S
4 *
5 * Low-level IRQ helper macros for S5PV310 platforms
6 *
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
10*/
11
12#include <mach/hardware.h>
13#include <asm/hardware/gic.h>
14
15 .macro disable_fiq
16 .endm
17
18 .macro get_irqnr_preamble, base, tmp
19 ldr \base, =gic_cpu_base_addr
20 ldr \base, [\base]
21 .endm
22
23 .macro arch_ret_to_user, tmp1, tmp2
24 .endm
25
26 /*
27 * The interrupt numbering scheme is defined in the
28 * interrupt controller spec. To wit:
29 *
30 * Interrupts 0-15 are IPI
31 * 16-28 are reserved
32 * 29-31 are local. We allow 30 to be used for the watchdog.
33 * 32-1020 are global
34 * 1021-1022 are reserved
35 * 1023 is "spurious" (no interrupt)
36 *
37 * For now, we ignore all local interrupts so only return an interrupt if it's
38 * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
39 *
40 * A simple read from the controller will tell us the number of the highest
41 * priority enabled interrupt. We then just need to check whether it is in the
42 * valid range for an IRQ (30-1020 inclusive).
43 */
44
45 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
46
47 ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
48
49 ldr \tmp, =1021
50
51 bic \irqnr, \irqstat, #0x1c00
52
53 cmp \irqnr, #29
54 cmpcc \irqnr, \irqnr
55 cmpne \irqnr, \tmp
56 cmpcs \irqnr, \irqnr
57 addne \irqnr, \irqnr, #32
58
59 .endm
60
61 /* We assume that irqstat (the raw value of the IRQ acknowledge
62 * register) is preserved from the macro above.
63 * If there is an IPI, we immediately signal end of interrupt on the
64 * controller, since this requires the original irqstat value which
65 * we won't easily be able to recreate later.
66 */
67
68 .macro test_for_ipi, irqnr, irqstat, base, tmp
69 bic \irqnr, \irqstat, #0x1c00
70 cmp \irqnr, #16
71 strcc \irqstat, [\base, #GIC_CPU_EOI]
72 cmpcs \irqnr, \irqnr
73 .endm
74
75 /* As above, this assumes that irqstat and base are preserved.. */
76
77 .macro test_for_ltirq, irqnr, irqstat, base, tmp
78 bic \irqnr, \irqstat, #0x1c00
79 mov \tmp, #0
80 cmp \irqnr, #29
81 moveq \tmp, #1
82 streq \irqstat, [\base, #GIC_CPU_EOI]
83 cmp \tmp, #0
84 .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 000000000000..20cb80c23466
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/gpio.h
@@ -0,0 +1,135 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/gpio.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5PV310 - GPIO lib support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __ASM_ARCH_GPIO_H
14#define __ASM_ARCH_GPIO_H __FILE__
15
16#define gpio_get_value __gpio_get_value
17#define gpio_set_value __gpio_set_value
18#define gpio_cansleep __gpio_cansleep
19#define gpio_to_irq __gpio_to_irq
20
21/* Practically, GPIO banks upto GPZ are the configurable gpio banks */
22
23/* GPIO bank sizes */
24#define S5PV310_GPIO_A0_NR (8)
25#define S5PV310_GPIO_A1_NR (6)
26#define S5PV310_GPIO_B_NR (8)
27#define S5PV310_GPIO_C0_NR (5)
28#define S5PV310_GPIO_C1_NR (5)
29#define S5PV310_GPIO_D0_NR (4)
30#define S5PV310_GPIO_D1_NR (4)
31#define S5PV310_GPIO_E0_NR (5)
32#define S5PV310_GPIO_E1_NR (8)
33#define S5PV310_GPIO_E2_NR (6)
34#define S5PV310_GPIO_E3_NR (8)
35#define S5PV310_GPIO_E4_NR (8)
36#define S5PV310_GPIO_F0_NR (8)
37#define S5PV310_GPIO_F1_NR (8)
38#define S5PV310_GPIO_F2_NR (8)
39#define S5PV310_GPIO_F3_NR (6)
40#define S5PV310_GPIO_J0_NR (8)
41#define S5PV310_GPIO_J1_NR (5)
42#define S5PV310_GPIO_K0_NR (7)
43#define S5PV310_GPIO_K1_NR (7)
44#define S5PV310_GPIO_K2_NR (7)
45#define S5PV310_GPIO_K3_NR (7)
46#define S5PV310_GPIO_L0_NR (8)
47#define S5PV310_GPIO_L1_NR (3)
48#define S5PV310_GPIO_L2_NR (8)
49#define S5PV310_GPIO_X0_NR (8)
50#define S5PV310_GPIO_X1_NR (8)
51#define S5PV310_GPIO_X2_NR (8)
52#define S5PV310_GPIO_X3_NR (8)
53#define S5PV310_GPIO_Z_NR (7)
54
55/* GPIO bank numbers */
56
57#define S5PV310_GPIO_NEXT(__gpio) \
58 ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
59
60enum s5p_gpio_number {
61 S5PV310_GPIO_A0_START = 0,
62 S5PV310_GPIO_A1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_A0),
63 S5PV310_GPIO_B_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_A1),
64 S5PV310_GPIO_C0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_B),
65 S5PV310_GPIO_C1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_C0),
66 S5PV310_GPIO_D0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_C1),
67 S5PV310_GPIO_D1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_D0),
68 S5PV310_GPIO_E0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_D1),
69 S5PV310_GPIO_E1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_E0),
70 S5PV310_GPIO_E2_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_E1),
71 S5PV310_GPIO_E3_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_E2),
72 S5PV310_GPIO_E4_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_E3),
73 S5PV310_GPIO_F0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_E4),
74 S5PV310_GPIO_F1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_F0),
75 S5PV310_GPIO_F2_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_F1),
76 S5PV310_GPIO_F3_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_F2),
77 S5PV310_GPIO_J0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_F3),
78 S5PV310_GPIO_J1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_J0),
79 S5PV310_GPIO_K0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_J1),
80 S5PV310_GPIO_K1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_K0),
81 S5PV310_GPIO_K2_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_K1),
82 S5PV310_GPIO_K3_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_K2),
83 S5PV310_GPIO_L0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_K3),
84 S5PV310_GPIO_L1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_L0),
85 S5PV310_GPIO_L2_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_L1),
86 S5PV310_GPIO_X0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_L2),
87 S5PV310_GPIO_X1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_X0),
88 S5PV310_GPIO_X2_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_X1),
89 S5PV310_GPIO_X3_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_X2),
90 S5PV310_GPIO_Z_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_X3),
91};
92
93/* S5PV310 GPIO number definitions */
94#define S5PV310_GPA0(_nr) (S5PV310_GPIO_A0_START + (_nr))
95#define S5PV310_GPA1(_nr) (S5PV310_GPIO_A1_START + (_nr))
96#define S5PV310_GPB(_nr) (S5PV310_GPIO_B_START + (_nr))
97#define S5PV310_GPC0(_nr) (S5PV310_GPIO_C0_START + (_nr))
98#define S5PV310_GPC1(_nr) (S5PV310_GPIO_C1_START + (_nr))
99#define S5PV310_GPD0(_nr) (S5PV310_GPIO_D0_START + (_nr))
100#define S5PV310_GPD1(_nr) (S5PV310_GPIO_D1_START + (_nr))
101#define S5PV310_GPE0(_nr) (S5PV310_GPIO_E0_START + (_nr))
102#define S5PV310_GPE1(_nr) (S5PV310_GPIO_E1_START + (_nr))
103#define S5PV310_GPE2(_nr) (S5PV310_GPIO_E2_START + (_nr))
104#define S5PV310_GPE3(_nr) (S5PV310_GPIO_E3_START + (_nr))
105#define S5PV310_GPE4(_nr) (S5PV310_GPIO_E4_START + (_nr))
106#define S5PV310_GPF0(_nr) (S5PV310_GPIO_F0_START + (_nr))
107#define S5PV310_GPF1(_nr) (S5PV310_GPIO_F1_START + (_nr))
108#define S5PV310_GPF2(_nr) (S5PV310_GPIO_F2_START + (_nr))
109#define S5PV310_GPF3(_nr) (S5PV310_GPIO_F3_START + (_nr))
110#define S5PV310_GPJ0(_nr) (S5PV310_GPIO_J0_START + (_nr))
111#define S5PV310_GPJ1(_nr) (S5PV310_GPIO_J1_START + (_nr))
112#define S5PV310_GPK0(_nr) (S5PV310_GPIO_K0_START + (_nr))
113#define S5PV310_GPK1(_nr) (S5PV310_GPIO_K1_START + (_nr))
114#define S5PV310_GPK2(_nr) (S5PV310_GPIO_K2_START + (_nr))
115#define S5PV310_GPK3(_nr) (S5PV310_GPIO_K3_START + (_nr))
116#define S5PV310_GPL0(_nr) (S5PV310_GPIO_L0_START + (_nr))
117#define S5PV310_GPL1(_nr) (S5PV310_GPIO_L1_START + (_nr))
118#define S5PV310_GPL2(_nr) (S5PV310_GPIO_L2_START + (_nr))
119#define S5PV310_GPX0(_nr) (S5PV310_GPIO_X0_START + (_nr))
120#define S5PV310_GPX1(_nr) (S5PV310_GPIO_X1_START + (_nr))
121#define S5PV310_GPX2(_nr) (S5PV310_GPIO_X2_START + (_nr))
122#define S5PV310_GPX3(_nr) (S5PV310_GPIO_X3_START + (_nr))
123#define S5PV310_GPZ(_nr) (S5PV310_GPIO_Z_START + (_nr))
124
125/* the end of the S5PV310 specific gpios */
126#define S5PV310_GPIO_END (S5PV310_GPZ(S5PV310_GPIO_Z_NR) + 1)
127#define S3C_GPIO_END S5PV310_GPIO_END
128
129/* define the number of gpios we need to the one after the GPZ() range */
130#define ARCH_NR_GPIOS (S5PV310_GPZ(S5PV310_GPIO_Z_NR) + \
131 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
132
133#include <asm-generic/gpio.h>
134
135#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 000000000000..28ff9881f1a6
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/hardware.h
@@ -0,0 +1,18 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/hardware.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5PV310 - Hardware support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __ASM_ARCH_HARDWARE_H
14#define __ASM_ARCH_HARDWARE_H __FILE__
15
16/* currently nothing here, placeholder */
17
18#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 000000000000..8a7f9128391f
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/io.h
@@ -0,0 +1,26 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/io.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * Copyright 2008-2010 Ben Dooks <ben-linux@fluff.org>
7 *
8 * Based on arch/arm/mach-s5p6442/include/mach/io.h
9 *
10 * Default IO routines for S5PV310
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15*/
16
17#ifndef __ASM_ARM_ARCH_IO_H
18#define __ASM_ARM_ARCH_IO_H __FILE__
19
20/* No current ISA/PCI bus support. */
21#define __io(a) __typesafe_io(a)
22#define __mem_pci(a) (a)
23
24#define IO_SPACE_LIMIT (0xFFFFFFFF)
25
26#endif /* __ASM_ARM_ARCH_IO_H */
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 000000000000..56885ca3773c
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
@@ -0,0 +1,74 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/irqs.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5PV210 - IRQ definitions
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __ASM_ARCH_IRQS_H
14#define __ASM_ARCH_IRQS_H __FILE__
15
16#include <plat/irqs.h>
17
18/* Private Peripheral Interrupt */
19#define IRQ_PPI(x) S5P_IRQ(x+16)
20
21#define IRQ_LOCALTIMER IRQ_PPI(13)
22
23/* Shared Peripheral Interrupt */
24#define IRQ_SPI(x) S5P_IRQ(x+32)
25
26#define IRQ_EINT0 IRQ_SPI(40)
27#define IRQ_EINT1 IRQ_SPI(41)
28#define IRQ_EINT2 IRQ_SPI(42)
29#define IRQ_EINT3 IRQ_SPI(43)
30#define IRQ_USB_HSOTG IRQ_SPI(44)
31#define IRQ_USB_HOST IRQ_SPI(45)
32#define IRQ_MODEM_IF IRQ_SPI(46)
33#define IRQ_ROTATOR IRQ_SPI(47)
34#define IRQ_JPEG IRQ_SPI(48)
35#define IRQ_2D IRQ_SPI(49)
36#define IRQ_PCIE IRQ_SPI(50)
37#define IRQ_SYSTEM_TIMER IRQ_SPI(51)
38#define IRQ_MFC IRQ_SPI(52)
39#define IRQ_WTD IRQ_SPI(53)
40#define IRQ_AUDIO_SS IRQ_SPI(54)
41#define IRQ_AC97 IRQ_SPI(55)
42#define IRQ_SPDIF IRQ_SPI(56)
43#define IRQ_KEYPAD IRQ_SPI(57)
44#define IRQ_INTFEEDCTRL_SSS IRQ_SPI(58)
45#define IRQ_SLIMBUS IRQ_SPI(59)
46#define IRQ_PMU IRQ_SPI(60)
47#define IRQ_TSI IRQ_SPI(61)
48#define IRQ_SATA IRQ_SPI(62)
49#define IRQ_GPS IRQ_SPI(63)
50
51#define MAX_IRQ_IN_COMBINER 8
52#define COMBINER_GROUP(x) ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
53#define COMBINER_IRQ(x, y) (COMBINER_GROUP(x) + y)
54
55#define IRQ_TIMER0_VIC COMBINER_IRQ(22, 0)
56#define IRQ_TIMER1_VIC COMBINER_IRQ(22, 1)
57#define IRQ_TIMER2_VIC COMBINER_IRQ(22, 2)
58#define IRQ_TIMER3_VIC COMBINER_IRQ(22, 3)
59#define IRQ_TIMER4_VIC COMBINER_IRQ(22, 4)
60
61#define IRQ_UART0 COMBINER_IRQ(26, 0)
62#define IRQ_UART1 COMBINER_IRQ(26, 1)
63#define IRQ_UART2 COMBINER_IRQ(26, 2)
64#define IRQ_UART3 COMBINER_IRQ(26, 3)
65#define IRQ_UART4 COMBINER_IRQ(26, 4)
66
67#define IRQ_IIC COMBINER_IRQ(27, 0)
68
69/* Set the default NR_IRQS */
70#define NR_IRQS COMBINER_IRQ(MAX_COMBINER_NR, 0)
71
72#define MAX_COMBINER_NR 39
73
74#endif /* ASM_ARCH_IRQS_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 000000000000..87697c9fca5b
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/map.h
@@ -0,0 +1,69 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/map.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5PV310 - Memory map definitions
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __ASM_ARCH_MAP_H
14#define __ASM_ARCH_MAP_H __FILE__
15
16#include <plat/map-base.h>
17
18/*
19 * S5PV310 UART offset is 0x10000 but the older S5P SoCs are 0x400.
20 * So need to define it, and here is to avoid redefinition warning.
21 */
22#define S3C_UART_OFFSET (0x10000)
23
24#include <plat/map-s5p.h>
25
26#define S5PV310_PA_CHIPID (0x10000000)
27#define S5P_PA_CHIPID S5PV310_PA_CHIPID
28
29#define S5PV310_PA_SYSCON (0x10020000)
30#define S5P_PA_SYSCON S5PV310_PA_SYSCON
31
32#define S5PV310_PA_WATCHDOG (0x10060000)
33
34#define S5PV310_PA_COMBINER (0x10448000)
35
36#define S5PV310_PA_COREPERI (0x10500000)
37#define S5PV310_PA_GIC_CPU (0x10500100)
38#define S5PV310_PA_TWD (0x10500600)
39#define S5PV310_PA_GIC_DIST (0x10501000)
40#define S5PV310_PA_L2CC (0x10502000)
41
42#define S5PV310_PA_GPIO (0x11000000)
43#define S5P_PA_GPIO S5PV310_PA_GPIO
44
45#define S5PV310_PA_UART (0x13800000)
46
47#define S5P_PA_UART(x) (S5PV310_PA_UART + ((x) * S3C_UART_OFFSET))
48#define S5P_PA_UART0 S5P_PA_UART(0)
49#define S5P_PA_UART1 S5P_PA_UART(1)
50#define S5P_PA_UART2 S5P_PA_UART(2)
51#define S5P_PA_UART3 S5P_PA_UART(3)
52#define S5P_PA_UART4 S5P_PA_UART(4)
53
54#define S5P_SZ_UART SZ_256
55
56#define S5PV310_PA_IIC0 (0x13860000)
57
58#define S5PV310_PA_TIMER (0x139D0000)
59#define S5P_PA_TIMER S5PV310_PA_TIMER
60
61#define S5PV310_PA_SDRAM (0x40000000)
62#define S5P_PA_SDRAM S5PV310_PA_SDRAM
63
64/* compatibiltiy defines. */
65#define S3C_PA_UART S5PV310_PA_UART
66#define S3C_PA_IIC S5PV310_PA_IIC0
67#define S3C_PA_WDT S5PV310_PA_WATCHDOG
68
69#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 000000000000..1dffb4823245
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/memory.h
@@ -0,0 +1,22 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/memory.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5PV310 - Memory definitions
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __ASM_ARCH_MEMORY_H
14#define __ASM_ARCH_MEMORY_H __FILE__
15
16#define PHYS_OFFSET UL(0x40000000)
17
18/* Maximum of 256MiB in one bank */
19#define MAX_PHYSMEM_BITS 32
20#define SECTION_SIZE_BITS 28
21
22#endif /* __ASM_ARCH_MEMORY_H */
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 000000000000..7e6da2701088
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/pwm-clock.h
@@ -0,0 +1,70 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/pwm-clock.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * Copyright 2008 Openmoko, Inc.
7 * Copyright 2008 Simtec Electronics
8 * Ben Dooks <ben@simtec.co.uk>
9 * http://armlinux.simtec.co.uk/
10 *
11 * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
12 *
13 * S5PV310 - pwm clock and timer support
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2 as
17 * published by the Free Software Foundation.
18*/
19
20#ifndef __ASM_ARCH_PWMCLK_H
21#define __ASM_ARCH_PWMCLK_H __FILE__
22
23/**
24 * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
25 * @tcfg: The timer TCFG1 register bits shifted down to 0.
26 *
27 * Return true if the given configuration from TCFG1 is a TCLK instead
28 * any of the TDIV clocks.
29 */
30static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
31{
32 return tcfg == S3C64XX_TCFG1_MUX_TCLK;
33}
34
35/**
36 * tcfg_to_divisor() - convert tcfg1 setting to a divisor
37 * @tcfg1: The tcfg1 setting, shifted down.
38 *
39 * Get the divisor value for the given tcfg1 setting. We assume the
40 * caller has already checked to see if this is not a TCLK source.
41 */
42static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
43{
44 return 1 << tcfg1;
45}
46
47/**
48 * pwm_tdiv_has_div1() - does the tdiv setting have a /1
49 *
50 * Return true if we have a /1 in the tdiv setting.
51 */
52static inline unsigned int pwm_tdiv_has_div1(void)
53{
54 return 1;
55}
56
57/**
58 * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
59 * @div: The divisor to calculate the bit information for.
60 *
61 * Turn a divisor into the necessary bit field for TCFG1.
62 */
63static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
64{
65 return ilog2(div);
66}
67
68#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
69
70#endif /* __ASM_ARCH_PWMCLK_H */
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 000000000000..59e3a7e94d80
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
@@ -0,0 +1,62 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/regs-clock.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5PV310 - Clock register definitions
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __ASM_ARCH_REGS_CLOCK_H
14#define __ASM_ARCH_REGS_CLOCK_H __FILE__
15
16#include <mach/map.h>
17
18#define S5P_CLKREG(x) (S3C_VA_SYS + (x))
19
20#define S5P_INFORM0 S5P_CLKREG(0x800)
21
22#define S5P_EPLL_CON0 S5P_CLKREG(0x1C110)
23#define S5P_EPLL_CON1 S5P_CLKREG(0x1C114)
24#define S5P_VPLL_CON0 S5P_CLKREG(0x1C120)
25#define S5P_VPLL_CON1 S5P_CLKREG(0x1C124)
26
27#define S5P_CLKSRC_TOP0 S5P_CLKREG(0x1C210)
28#define S5P_CLKSRC_TOP1 S5P_CLKREG(0x1C214)
29
30#define S5P_CLKSRC_PERIL0 S5P_CLKREG(0x1C250)
31
32#define S5P_CLKDIV_TOP S5P_CLKREG(0x1C510)
33
34#define S5P_CLKDIV_PERIL0 S5P_CLKREG(0x1C550)
35#define S5P_CLKDIV_PERIL1 S5P_CLKREG(0x1C554)
36#define S5P_CLKDIV_PERIL2 S5P_CLKREG(0x1C558)
37#define S5P_CLKDIV_PERIL3 S5P_CLKREG(0x1C55C)
38#define S5P_CLKDIV_PERIL4 S5P_CLKREG(0x1C560)
39#define S5P_CLKDIV_PERIL5 S5P_CLKREG(0x1C564)
40
41#define S5P_CLKGATE_IP_PERIL S5P_CLKREG(0x1C950)
42
43#define S5P_CLKSRC_CORE S5P_CLKREG(0x20200)
44
45#define S5P_CLKDIV_CORE0 S5P_CLKREG(0x20500)
46
47#define S5P_APLL_LOCK S5P_CLKREG(0x24000)
48#define S5P_MPLL_LOCK S5P_CLKREG(0x24004)
49#define S5P_APLL_CON0 S5P_CLKREG(0x24100)
50#define S5P_APLL_CON1 S5P_CLKREG(0x24104)
51#define S5P_MPLL_CON0 S5P_CLKREG(0x24108)
52#define S5P_MPLL_CON1 S5P_CLKREG(0x2410C)
53
54#define S5P_CLKSRC_CPU S5P_CLKREG(0x24200)
55#define S5P_CLKMUX_STATCPU S5P_CLKREG(0x24400)
56
57#define S5P_CLKDIV_CPU S5P_CLKREG(0x24500)
58#define S5P_CLKDIV_STATCPU S5P_CLKREG(0x24600)
59
60#define S5P_CLKGATE_SCLKCPU S5P_CLKREG(0x24800)
61
62#endif /* __ASM_ARCH_REGS_CLOCK_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 000000000000..c6e09c7f9161
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/regs-irq.h
@@ -0,0 +1,19 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/regs-irq.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5PV310 - IRQ register definitions
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __ASM_ARCH_REGS_IRQ_H
14#define __ASM_ARCH_REGS_IRQ_H __FILE__
15
16#include <asm/hardware/gic.h>
17#include <mach/map.h>
18
19#endif /* __ASM_ARCH_REGS_IRQ_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 000000000000..990f3ba88a1f
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/smp.h
@@ -0,0 +1,29 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/smp.h
2 *
3 * Cloned from arch/arm/mach-realview/include/mach/smp.h
4*/
5
6#ifndef ASM_ARCH_SMP_H
7#define ASM_ARCH_SMP_H __FILE__
8
9#include <asm/hardware/gic.h>
10
11extern void __iomem *gic_cpu_base_addr;
12
13#define hard_smp_processor_id() \
14 ({ \
15 unsigned int cpunum; \
16 __asm__("mrc p15, 0, %0, c0, c0, 5" \
17 : "=r" (cpunum)); \
18 cpunum &= 0x03; \
19 })
20
21/*
22 * We use IRQ1 as the IPI
23 */
24static inline void smp_cross_call(const struct cpumask *mask)
25{
26 gic_raise_softirq(mask, 1);
27}
28
29#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 000000000000..d10c009cf0f1
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/system.h
@@ -0,0 +1,22 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/system.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5PV310 - system support header
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __ASM_ARCH_SYSTEM_H
14#define __ASM_ARCH_SYSTEM_H __FILE__
15
16#include <plat/system-reset.h>
17
18static void arch_idle(void)
19{
20 /* nothing here yet */
21}
22#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 000000000000..bd2359b952b4
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/timex.h
@@ -0,0 +1,29 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/timex.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * Copyright (c) 2003-2010 Simtec Electronics
7 * Ben Dooks <ben@simtec.co.uk>
8 *
9 * Based on arch/arm/mach-s5p6442/include/mach/timex.h
10 *
11 * S5PV310 - time parameters
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16*/
17
18#ifndef __ASM_ARCH_TIMEX_H
19#define __ASM_ARCH_TIMEX_H __FILE__
20
21/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
22 * a variable is useless. It seems as long as we make our timers an
23 * exact multiple of HZ, any value that makes a 1->1 correspondence
24 * for the time conversion functions to/from jiffies is acceptable.
25*/
26
27#define CLOCK_TICK_RATE 12000000
28
29#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 000000000000..59593c1e2416
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/uncompress.h
@@ -0,0 +1,30 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/uncompress.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * S5PV310 - uncompress code
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __ASM_ARCH_UNCOMPRESS_H
14#define __ASM_ARCH_UNCOMPRESS_H __FILE__
15
16#include <mach/map.h>
17#include <plat/uncompress.h>
18
19static void arch_detect_cpu(void)
20{
21 /* we do not need to do any cpu detection here at the moment. */
22
23 /*
24 * For preventing FIFO overrun or infinite loop of UART console,
25 * fifo_max should be the minimum fifo size of all of the UART channels
26 */
27 fifo_mask = S5PV210_UFSTAT_TXMASK;
28 fifo_max = 15 << S5PV210_UFSTAT_TXSHIFT;
29}
30#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 000000000000..3f565ebb7daa
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/vmalloc.h
@@ -0,0 +1,22 @@
1/* linux/arch/arm/mach-s5pv310/include/mach/vmalloc.h
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
7 *
8 * Based on arch/arm/mach-s5p6440/include/mach/vmalloc.h
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * S5PV310 vmalloc definition
15*/
16
17#ifndef __ASM_ARCH_VMALLOC_H
18#define __ASM_ARCH_VMALLOC_H __FILE__
19
20#define VMALLOC_END (0xF0000000)
21
22#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 000000000000..182dcf42cfb4
--- /dev/null
+++ b/arch/arm/mach-s5pv310/init.c
@@ -0,0 +1,41 @@
1/* linux/arch/arm/mach-s5pv310/init.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9*/
10
11#include <linux/serial_core.h>
12
13#include <plat/cpu.h>
14#include <plat/devs.h>
15#include <plat/regs-serial.h>
16
17static struct s3c24xx_uart_clksrc s5pv310_serial_clocks[] = {
18 [0] = {
19 .name = "uclk1",
20 .divisor = 1,
21 .min_baud = 0,
22 .max_baud = 0,
23 },
24};
25
26/* uart registration process */
27void __init s5pv310_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
28{
29 struct s3c2410_uartcfg *tcfg = cfg;
30 u32 ucnt;
31
32 for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
33 if (!tcfg->clocks) {
34 tcfg->has_fracval = 1;
35 tcfg->clocks = s5pv310_serial_clocks;
36 tcfg->clocks_size = ARRAY_SIZE(s5pv310_serial_clocks);
37 }
38 }
39
40 s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
41}
diff --git a/arch/arm/mach-s5pv310/irq-combiner.c b/arch/arm/mach-s5pv310/irq-combiner.c
new file mode 100644
index 000000000000..0f7052164f23
--- /dev/null
+++ b/arch/arm/mach-s5pv310/irq-combiner.c
@@ -0,0 +1,125 @@
1/* linux/arch/arm/mach-s5pv310/irq-combiner.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * Based on arch/arm/common/gic.c
7 *
8 * IRQ COMBINER support
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/io.h>
16
17#include <asm/mach/irq.h>
18
19#define COMBINER_ENABLE_SET 0x0
20#define COMBINER_ENABLE_CLEAR 0x4
21#define COMBINER_INT_STATUS 0xC
22
23static DEFINE_SPINLOCK(irq_controller_lock);
24
25struct combiner_chip_data {
26 unsigned int irq_offset;
27 void __iomem *base;
28};
29
30static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
31
32static inline void __iomem *combiner_base(unsigned int irq)
33{
34 struct combiner_chip_data *combiner_data = get_irq_chip_data(irq);
35 return combiner_data->base;
36}
37
38static void combiner_mask_irq(unsigned int irq)
39{
40 u32 mask = 1 << (irq % 32);
41
42 __raw_writel(mask, combiner_base(irq) + COMBINER_ENABLE_CLEAR);
43}
44
45static void combiner_unmask_irq(unsigned int irq)
46{
47 u32 mask = 1 << (irq % 32);
48
49 __raw_writel(mask, combiner_base(irq) + COMBINER_ENABLE_SET);
50}
51
52static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
53{
54 struct combiner_chip_data *chip_data = get_irq_data(irq);
55 struct irq_chip *chip = get_irq_chip(irq);
56 unsigned int cascade_irq, combiner_irq;
57 unsigned long status;
58
59 /* primary controller ack'ing */
60 chip->ack(irq);
61
62 spin_lock(&irq_controller_lock);
63 status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
64 spin_unlock(&irq_controller_lock);
65
66 if (status == 0)
67 goto out;
68
69 for (combiner_irq = 0; combiner_irq < 32; combiner_irq++) {
70 if (status & 0x1)
71 break;
72 status >>= 1;
73 }
74
75 cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
76 if (unlikely(cascade_irq >= NR_IRQS))
77 do_bad_IRQ(cascade_irq, desc);
78 else
79 generic_handle_irq(cascade_irq);
80
81 out:
82 /* primary controller unmasking */
83 chip->unmask(irq);
84}
85
86static struct irq_chip combiner_chip = {
87 .name = "COMBINER",
88 .mask = combiner_mask_irq,
89 .unmask = combiner_unmask_irq,
90};
91
92void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
93{
94 if (combiner_nr >= MAX_COMBINER_NR)
95 BUG();
96 if (set_irq_data(irq, &combiner_data[combiner_nr]) != 0)
97 BUG();
98 set_irq_chained_handler(irq, combiner_handle_cascade_irq);
99}
100
101void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
102 unsigned int irq_start)
103{
104 unsigned int i;
105
106 if (combiner_nr >= MAX_COMBINER_NR)
107 BUG();
108
109 combiner_data[combiner_nr].base = base;
110 combiner_data[combiner_nr].irq_offset = irq_start;
111
112 /* Disable all interrupts */
113
114 __raw_writel(0xffffffff, base + COMBINER_ENABLE_CLEAR);
115
116 /* Setup the Linux IRQ subsystem */
117
118 for (i = irq_start; i < combiner_data[combiner_nr].irq_offset
119 + MAX_IRQ_IN_COMBINER; i++) {
120 set_irq_chip(i, &combiner_chip);
121 set_irq_chip_data(i, &combiner_data[combiner_nr]);
122 set_irq_handler(i, handle_level_irq);
123 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
124 }
125}
diff --git a/arch/arm/mach-s5pv310/localtimer.c b/arch/arm/mach-s5pv310/localtimer.c
new file mode 100644
index 000000000000..2784036cd8b1
--- /dev/null
+++ b/arch/arm/mach-s5pv310/localtimer.c
@@ -0,0 +1,25 @@
1/* linux/arch/arm/mach-s5pv310/localtimer.c
2 *
3 * Cloned from linux/arch/arm/mach-realview/localtimer.c
4 *
5 * Copyright (C) 2002 ARM Ltd.
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/clockchips.h>
14
15#include <asm/irq.h>
16#include <asm/localtimer.h>
17
18/*
19 * Setup the local clock events for a CPU.
20 */
21void __cpuinit local_timer_setup(struct clock_event_device *evt)
22{
23 evt->irq = IRQ_LOCALTIMER;
24 twd_timer_setup(evt);
25}
diff --git a/arch/arm/mach-s5pv310/mach-smdkv310.c b/arch/arm/mach-s5pv310/mach-smdkv310.c
new file mode 100644
index 000000000000..0d6ab77709d2
--- /dev/null
+++ b/arch/arm/mach-s5pv310/mach-smdkv310.c
@@ -0,0 +1,92 @@
1/* linux/arch/arm/mach-s5pv310/mach-smdkv310.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9*/
10
11#include <linux/serial_core.h>
12
13#include <asm/mach/arch.h>
14#include <asm/mach-types.h>
15#include <asm/hardware/cache-l2x0.h>
16
17#include <plat/regs-serial.h>
18#include <plat/s5pv310.h>
19#include <plat/cpu.h>
20
21#include <mach/map.h>
22
23/* Following are default values for UCON, ULCON and UFCON UART registers */
24#define SMDKV310_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
25 S3C2410_UCON_RXILEVEL | \
26 S3C2410_UCON_TXIRQMODE | \
27 S3C2410_UCON_RXIRQMODE | \
28 S3C2410_UCON_RXFIFO_TOI | \
29 S3C2443_UCON_RXERR_IRQEN)
30
31#define SMDKV310_ULCON_DEFAULT S3C2410_LCON_CS8
32
33#define SMDKV310_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
34 S5PV210_UFCON_TXTRIG4 | \
35 S5PV210_UFCON_RXTRIG4)
36
37static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = {
38 [0] = {
39 .hwport = 0,
40 .flags = 0,
41 .ucon = SMDKV310_UCON_DEFAULT,
42 .ulcon = SMDKV310_ULCON_DEFAULT,
43 .ufcon = SMDKV310_UFCON_DEFAULT,
44 },
45 [1] = {
46 .hwport = 1,
47 .flags = 0,
48 .ucon = SMDKV310_UCON_DEFAULT,
49 .ulcon = SMDKV310_ULCON_DEFAULT,
50 .ufcon = SMDKV310_UFCON_DEFAULT,
51 },
52 [2] = {
53 .hwport = 2,
54 .flags = 0,
55 .ucon = SMDKV310_UCON_DEFAULT,
56 .ulcon = SMDKV310_ULCON_DEFAULT,
57 .ufcon = SMDKV310_UFCON_DEFAULT,
58 },
59 [3] = {
60 .hwport = 3,
61 .flags = 0,
62 .ucon = SMDKV310_UCON_DEFAULT,
63 .ulcon = SMDKV310_ULCON_DEFAULT,
64 .ufcon = SMDKV310_UFCON_DEFAULT,
65 },
66};
67
68static void __init smdkv310_map_io(void)
69{
70 s5p_init_io(NULL, 0, S5P_VA_CHIPID);
71 s3c24xx_init_clocks(24000000);
72 s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
73}
74
75static void __init smdkv310_machine_init(void)
76{
77#ifdef CONFIG_CACHE_L2X0
78 l2x0_init(S5P_VA_L2CC, 1 << 28, 0xffffffff);
79#endif
80}
81
82MACHINE_START(SMDKV310, "SMDKV310")
83 /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
84 /* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
85 .phys_io = S3C_PA_UART & 0xfff00000,
86 .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
87 .boot_params = S5P_PA_SDRAM + 0x100,
88 .init_irq = s5pv310_init_irq,
89 .map_io = smdkv310_map_io,
90 .init_machine = smdkv310_machine_init,
91 .timer = &s5pv310_timer,
92MACHINE_END
diff --git a/arch/arm/mach-s5pv310/mach-universal_c210.c b/arch/arm/mach-s5pv310/mach-universal_c210.c
new file mode 100644
index 000000000000..2388cb947936
--- /dev/null
+++ b/arch/arm/mach-s5pv310/mach-universal_c210.c
@@ -0,0 +1,86 @@
1/* linux/arch/arm/mach-s5pv310/mach-universal_c210.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8*/
9
10#include <linux/serial_core.h>
11
12#include <asm/mach/arch.h>
13#include <asm/mach-types.h>
14#include <asm/hardware/cache-l2x0.h>
15
16#include <plat/regs-serial.h>
17#include <plat/s5pv310.h>
18#include <plat/cpu.h>
19
20#include <mach/map.h>
21
22/* Following are default values for UCON, ULCON and UFCON UART registers */
23#define UNIVERSAL_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
24 S3C2410_UCON_RXILEVEL | \
25 S3C2410_UCON_TXIRQMODE | \
26 S3C2410_UCON_RXIRQMODE | \
27 S3C2410_UCON_RXFIFO_TOI | \
28 S3C2443_UCON_RXERR_IRQEN)
29
30#define UNIVERSAL_ULCON_DEFAULT S3C2410_LCON_CS8
31
32#define UNIVERSAL_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
33 S5PV210_UFCON_TXTRIG256 | \
34 S5PV210_UFCON_RXTRIG256)
35
36static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = {
37 [0] = {
38 .hwport = 0,
39 .ucon = UNIVERSAL_UCON_DEFAULT,
40 .ulcon = UNIVERSAL_ULCON_DEFAULT,
41 .ufcon = UNIVERSAL_UFCON_DEFAULT,
42 },
43 [1] = {
44 .hwport = 1,
45 .ucon = UNIVERSAL_UCON_DEFAULT,
46 .ulcon = UNIVERSAL_ULCON_DEFAULT,
47 .ufcon = UNIVERSAL_UFCON_DEFAULT,
48 },
49 [2] = {
50 .hwport = 2,
51 .ucon = UNIVERSAL_UCON_DEFAULT,
52 .ulcon = UNIVERSAL_ULCON_DEFAULT,
53 .ufcon = UNIVERSAL_UFCON_DEFAULT,
54 },
55 [3] = {
56 .hwport = 3,
57 .ucon = UNIVERSAL_UCON_DEFAULT,
58 .ulcon = UNIVERSAL_ULCON_DEFAULT,
59 .ufcon = UNIVERSAL_UFCON_DEFAULT,
60 },
61};
62
63static void __init universal_map_io(void)
64{
65 s5p_init_io(NULL, 0, S5P_VA_CHIPID);
66 s3c24xx_init_clocks(24000000);
67 s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
68}
69
70static void __init universal_machine_init(void)
71{
72#ifdef CONFIG_CACHE_L2X0
73 l2x0_init(S5P_VA_L2CC, 1 << 28, 0xffffffff);
74#endif
75}
76
77MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
78 /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
79 .phys_io = S3C_PA_UART & 0xfff00000,
80 .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
81 .boot_params = S5P_PA_SDRAM + 0x100,
82 .init_irq = s5pv310_init_irq,
83 .map_io = universal_map_io,
84 .init_machine = universal_machine_init,
85 .timer = &s5pv310_timer,
86MACHINE_END
diff --git a/arch/arm/mach-s5pv310/platsmp.c b/arch/arm/mach-s5pv310/platsmp.c
new file mode 100644
index 000000000000..fe9469abd006
--- /dev/null
+++ b/arch/arm/mach-s5pv310/platsmp.c
@@ -0,0 +1,192 @@
1/* linux/arch/arm/mach-s5pv310/platsmp.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * Cloned from linux/arch/arm/mach-vexpress/platsmp.c
7 *
8 * Copyright (C) 2002 ARM Ltd.
9 * All Rights Reserved
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14*/
15
16#include <linux/init.h>
17#include <linux/errno.h>
18#include <linux/delay.h>
19#include <linux/device.h>
20#include <linux/jiffies.h>
21#include <linux/smp.h>
22#include <linux/io.h>
23
24#include <asm/cacheflush.h>
25#include <asm/localtimer.h>
26#include <asm/smp_scu.h>
27#include <asm/unified.h>
28
29#include <mach/hardware.h>
30#include <mach/regs-clock.h>
31
32extern void s5pv310_secondary_startup(void);
33
34/*
35 * control for which core is the next to come out of the secondary
36 * boot "holding pen"
37 */
38
39volatile int __cpuinitdata pen_release = -1;
40
41static void __iomem *scu_base_addr(void)
42{
43 return (void __iomem *)(S5P_VA_SCU);
44}
45
46static DEFINE_SPINLOCK(boot_lock);
47
48void __cpuinit platform_secondary_init(unsigned int cpu)
49{
50 trace_hardirqs_off();
51
52 /*
53 * if any interrupts are already enabled for the primary
54 * core (e.g. timer irq), then they will not have been enabled
55 * for us: do so
56 */
57 gic_cpu_init(0, gic_cpu_base_addr);
58
59 /*
60 * let the primary processor know we're out of the
61 * pen, then head off into the C entry point
62 */
63 pen_release = -1;
64 smp_wmb();
65
66 /*
67 * Synchronise with the boot thread.
68 */
69 spin_lock(&boot_lock);
70 spin_unlock(&boot_lock);
71}
72
73int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
74{
75 unsigned long timeout;
76
77 /*
78 * Set synchronisation state between this boot processor
79 * and the secondary one
80 */
81 spin_lock(&boot_lock);
82
83 /*
84 * The secondary processor is waiting to be released from
85 * the holding pen - release it, then wait for it to flag
86 * that it has been released by resetting pen_release.
87 *
88 * Note that "pen_release" is the hardware CPU ID, whereas
89 * "cpu" is Linux's internal ID.
90 */
91 pen_release = cpu;
92 __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
93 outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
94
95 /*
96 * Send the secondary CPU a soft interrupt, thereby causing
97 * the boot monitor to read the system wide flags register,
98 * and branch to the address found there.
99 */
100 smp_cross_call(cpumask_of(cpu));
101
102 timeout = jiffies + (1 * HZ);
103 while (time_before(jiffies, timeout)) {
104 smp_rmb();
105 if (pen_release == -1)
106 break;
107
108 udelay(10);
109 }
110
111 /*
112 * now the secondary core is starting up let it run its
113 * calibrations, then wait for it to finish
114 */
115 spin_unlock(&boot_lock);
116
117 return pen_release != -1 ? -ENOSYS : 0;
118}
119
120/*
121 * Initialise the CPU possible map early - this describes the CPUs
122 * which may be present or become present in the system.
123 */
124
125void __init smp_init_cpus(void)
126{
127 void __iomem *scu_base = scu_base_addr();
128 unsigned int i, ncores;
129
130 ncores = scu_base ? scu_get_core_count(scu_base) : 1;
131
132 /* sanity check */
133 if (ncores == 0) {
134 printk(KERN_ERR
135 "S5PV310: strange CM count of 0? Default to 1\n");
136
137 ncores = 1;
138 }
139
140 if (ncores > NR_CPUS) {
141 printk(KERN_WARNING
142 "S5PV310: no. of cores (%d) greater than configured "
143 "maximum of %d - clipping\n",
144 ncores, NR_CPUS);
145 ncores = NR_CPUS;
146 }
147
148 for (i = 0; i < ncores; i++)
149 set_cpu_possible(i, true);
150}
151
152void __init smp_prepare_cpus(unsigned int max_cpus)
153{
154 unsigned int ncores = num_possible_cpus();
155 unsigned int cpu = smp_processor_id();
156 int i;
157
158 smp_store_cpu_info(cpu);
159
160 /* are we trying to boot more cores than exist? */
161 if (max_cpus > ncores)
162 max_cpus = ncores;
163
164 /*
165 * Initialise the present map, which describes the set of CPUs
166 * actually populated at the present time.
167 */
168 for (i = 0; i < max_cpus; i++)
169 set_cpu_present(i, true);
170
171 /*
172 * Initialise the SCU if there are more than one CPU and let
173 * them know where to start.
174 */
175 if (max_cpus > 1) {
176 /*
177 * Enable the local timer or broadcast device for the
178 * boot CPU, but only if we have more than one CPU.
179 */
180 percpu_timer_setup();
181
182 scu_enable(scu_base_addr());
183
184 /*
185 * Write the address of secondary startup into the
186 * system-wide flags register. The boot monitor waits
187 * until it receives a soft interrupt, and then the
188 * secondary CPU branches to this address.
189 */
190 __raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_INFORM0);
191 }
192}
diff --git a/arch/arm/mach-s5pv310/setup-i2c0.c b/arch/arm/mach-s5pv310/setup-i2c0.c
new file mode 100644
index 000000000000..436712807383
--- /dev/null
+++ b/arch/arm/mach-s5pv310/setup-i2c0.c
@@ -0,0 +1,28 @@
1/*
2 * linux/arch/arm/mach-s5pv310/setup-i2c0.c
3 *
4 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * I2C0 GPIO configuration.
8 *
9 * Based on plat-s3c64xx/setup-i2c0.c
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14*/
15
16struct platform_device; /* don't need the contents */
17
18#include <linux/gpio.h>
19#include <plat/iic.h>
20#include <plat/gpio-cfg.h>
21
22void s3c_i2c0_cfg_gpio(struct platform_device *dev)
23{
24 s3c_gpio_cfgpin(S5PV310_GPD1(0), S3C_GPIO_SFN(2));
25 s3c_gpio_setpull(S5PV310_GPD1(0), S3C_GPIO_PULL_UP);
26 s3c_gpio_cfgpin(S5PV310_GPD1(1), S3C_GPIO_SFN(2));
27 s3c_gpio_setpull(S5PV310_GPD1(1), S3C_GPIO_PULL_UP);
28}
diff --git a/arch/arm/mach-s5pv310/setup-i2c1.c b/arch/arm/mach-s5pv310/setup-i2c1.c
new file mode 100644
index 000000000000..1ecd5bc35b5a
--- /dev/null
+++ b/arch/arm/mach-s5pv310/setup-i2c1.c
@@ -0,0 +1,25 @@
1/*
2 * linux/arch/arm/mach-s5pv310/setup-i2c1.c
3 *
4 * Copyright (C) 2010 Samsung Electronics Co., Ltd.
5 *
6 * I2C1 GPIO configuration.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13struct platform_device; /* don't need the contents */
14
15#include <linux/gpio.h>
16#include <plat/iic.h>
17#include <plat/gpio-cfg.h>
18
19void s3c_i2c1_cfg_gpio(struct platform_device *dev)
20{
21 s3c_gpio_cfgpin(S5PV310_GPD1(2), S3C_GPIO_SFN(2));
22 s3c_gpio_setpull(S5PV310_GPD1(2), S3C_GPIO_PULL_UP);
23 s3c_gpio_cfgpin(S5PV310_GPD1(3), S3C_GPIO_SFN(2));
24 s3c_gpio_setpull(S5PV310_GPD1(3), S3C_GPIO_PULL_UP);
25}
diff --git a/arch/arm/mach-s5pv310/setup-i2c2.c b/arch/arm/mach-s5pv310/setup-i2c2.c
new file mode 100644
index 000000000000..4c0d8def660a
--- /dev/null
+++ b/arch/arm/mach-s5pv310/setup-i2c2.c
@@ -0,0 +1,25 @@
1/*
2 * linux/arch/arm/mach-s5pv310/setup-i2c2.c
3 *
4 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
5 *
6 * I2C2 GPIO configuration.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13struct platform_device; /* don't need the contents */
14
15#include <linux/gpio.h>
16#include <plat/iic.h>
17#include <plat/gpio-cfg.h>
18
19void s3c_i2c2_cfg_gpio(struct platform_device *dev)
20{
21 s3c_gpio_cfgpin(S5PV310_GPA0(6), S3C_GPIO_SFN(3));
22 s3c_gpio_setpull(S5PV310_GPA0(6), S3C_GPIO_PULL_UP);
23 s3c_gpio_cfgpin(S5PV310_GPA0(7), S3C_GPIO_SFN(3));
24 s3c_gpio_setpull(S5PV310_GPA0(7), S3C_GPIO_PULL_UP);
25}
diff --git a/arch/arm/mach-s5pv310/time.c b/arch/arm/mach-s5pv310/time.c
new file mode 100644
index 000000000000..01b012ad1bfd
--- /dev/null
+++ b/arch/arm/mach-s5pv310/time.c
@@ -0,0 +1,287 @@
1/* linux/arch/arm/mach-s5pv310/time.c
2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * S5PV310 (and compatible) HRT support
7 * PWM 2/4 is used for this feature
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14#include <linux/sched.h>
15#include <linux/interrupt.h>
16#include <linux/irq.h>
17#include <linux/err.h>
18#include <linux/clk.h>
19#include <linux/clockchips.h>
20#include <linux/platform_device.h>
21
22#include <asm/smp_twd.h>
23
24#include <mach/map.h>
25#include <plat/regs-timer.h>
26#include <asm/mach/time.h>
27
28static unsigned long clock_count_per_tick;
29
30static struct clk *tin2;
31static struct clk *tin4;
32static struct clk *tdiv2;
33static struct clk *tdiv4;
34static struct clk *timerclk;
35
36static void s5pv310_pwm_stop(unsigned int pwm_id)
37{
38 unsigned long tcon;
39
40 tcon = __raw_readl(S3C2410_TCON);
41
42 switch (pwm_id) {
43 case 2:
44 tcon &= ~S3C2410_TCON_T2START;
45 break;
46 case 4:
47 tcon &= ~S3C2410_TCON_T4START;
48 break;
49 default:
50 break;
51 }
52 __raw_writel(tcon, S3C2410_TCON);
53}
54
55static void s5pv310_pwm_init(unsigned int pwm_id, unsigned long tcnt)
56{
57 unsigned long tcon;
58
59 tcon = __raw_readl(S3C2410_TCON);
60
61 /* timers reload after counting zero, so reduce the count by 1 */
62 tcnt--;
63
64 /* ensure timer is stopped... */
65 switch (pwm_id) {
66 case 2:
67 tcon &= ~(0xf<<12);
68 tcon |= S3C2410_TCON_T2MANUALUPD;
69
70 __raw_writel(tcnt, S3C2410_TCNTB(2));
71 __raw_writel(tcnt, S3C2410_TCMPB(2));
72 __raw_writel(tcon, S3C2410_TCON);
73
74 break;
75 case 4:
76 tcon &= ~(7<<20);
77 tcon |= S3C2410_TCON_T4MANUALUPD;
78
79 __raw_writel(tcnt, S3C2410_TCNTB(4));
80 __raw_writel(tcnt, S3C2410_TCMPB(4));
81 __raw_writel(tcon, S3C2410_TCON);
82
83 break;
84 default:
85 break;
86 }
87}
88
89static inline void s5pv310_pwm_start(unsigned int pwm_id, bool periodic)
90{
91 unsigned long tcon;
92
93 tcon = __raw_readl(S3C2410_TCON);
94
95 switch (pwm_id) {
96 case 2:
97 tcon |= S3C2410_TCON_T2START;
98 tcon &= ~S3C2410_TCON_T2MANUALUPD;
99
100 if (periodic)
101 tcon |= S3C2410_TCON_T2RELOAD;
102 else
103 tcon &= ~S3C2410_TCON_T2RELOAD;
104 break;
105 case 4:
106 tcon |= S3C2410_TCON_T4START;
107 tcon &= ~S3C2410_TCON_T4MANUALUPD;
108
109 if (periodic)
110 tcon |= S3C2410_TCON_T4RELOAD;
111 else
112 tcon &= ~S3C2410_TCON_T4RELOAD;
113 break;
114 default:
115 break;
116 }
117 __raw_writel(tcon, S3C2410_TCON);
118}
119
120static int s5pv310_pwm_set_next_event(unsigned long cycles,
121 struct clock_event_device *evt)
122{
123 s5pv310_pwm_init(2, cycles);
124 s5pv310_pwm_start(2, 0);
125 return 0;
126}
127
128static void s5pv310_pwm_set_mode(enum clock_event_mode mode,
129 struct clock_event_device *evt)
130{
131 s5pv310_pwm_stop(2);
132
133 switch (mode) {
134 case CLOCK_EVT_MODE_PERIODIC:
135 s5pv310_pwm_init(2, clock_count_per_tick);
136 s5pv310_pwm_start(2, 1);
137 break;
138 case CLOCK_EVT_MODE_ONESHOT:
139 break;
140 case CLOCK_EVT_MODE_UNUSED:
141 case CLOCK_EVT_MODE_SHUTDOWN:
142 case CLOCK_EVT_MODE_RESUME:
143 break;
144 }
145}
146
147static struct clock_event_device pwm_event_device = {
148 .name = "pwm_timer2",
149 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
150 .rating = 200,
151 .shift = 32,
152 .set_next_event = s5pv310_pwm_set_next_event,
153 .set_mode = s5pv310_pwm_set_mode,
154};
155
156irqreturn_t s5pv310_clock_event_isr(int irq, void *dev_id)
157{
158 struct clock_event_device *evt = &pwm_event_device;
159
160 evt->event_handler(evt);
161
162 return IRQ_HANDLED;
163}
164
165static struct irqaction s5pv310_clock_event_irq = {
166 .name = "pwm_timer2_irq",
167 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
168 .handler = s5pv310_clock_event_isr,
169};
170
171static void __init s5pv310_clockevent_init(void)
172{
173 unsigned long pclk;
174 unsigned long clock_rate;
175 struct clk *tscaler;
176
177 pclk = clk_get_rate(timerclk);
178
179 /* configure clock tick */
180
181 tscaler = clk_get_parent(tdiv2);
182
183 clk_set_rate(tscaler, pclk / 2);
184 clk_set_rate(tdiv2, pclk / 2);
185 clk_set_parent(tin2, tdiv2);
186
187 clock_rate = clk_get_rate(tin2);
188
189 clock_count_per_tick = clock_rate / HZ;
190
191 pwm_event_device.mult =
192 div_sc(clock_rate, NSEC_PER_SEC, pwm_event_device.shift);
193 pwm_event_device.max_delta_ns =
194 clockevent_delta2ns(-1, &pwm_event_device);
195 pwm_event_device.min_delta_ns =
196 clockevent_delta2ns(1, &pwm_event_device);
197
198 pwm_event_device.cpumask = cpumask_of(0);
199 clockevents_register_device(&pwm_event_device);
200
201 setup_irq(IRQ_TIMER2, &s5pv310_clock_event_irq);
202}
203
204static cycle_t s5pv310_pwm4_read(struct clocksource *cs)
205{
206 return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40));
207}
208
209struct clocksource pwm_clocksource = {
210 .name = "pwm_timer4",
211 .rating = 250,
212 .read = s5pv310_pwm4_read,
213 .mask = CLOCKSOURCE_MASK(32),
214 .shift = 20,
215 .flags = CLOCK_SOURCE_IS_CONTINUOUS ,
216};
217
218static void __init s5pv310_clocksource_init(void)
219{
220 unsigned long pclk;
221 unsigned long clock_rate;
222
223 pclk = clk_get_rate(timerclk);
224
225 clk_set_rate(tdiv4, pclk / 2);
226 clk_set_parent(tin4, tdiv4);
227
228 clock_rate = clk_get_rate(tin4);
229
230 s5pv310_pwm_init(4, ~0);
231 s5pv310_pwm_start(4, 1);
232
233 pwm_clocksource.mult =
234 clocksource_khz2mult(clock_rate/1000, pwm_clocksource.shift);
235
236 if (clocksource_register(&pwm_clocksource))
237 panic("%s: can't register clocksource\n", pwm_clocksource.name);
238}
239
240static void __init s5pv310_timer_resources(void)
241{
242 struct platform_device tmpdev;
243
244 tmpdev.dev.bus = &platform_bus_type;
245
246 timerclk = clk_get(NULL, "timers");
247 if (IS_ERR(timerclk))
248 panic("failed to get timers clock for system timer");
249
250 clk_enable(timerclk);
251
252 tmpdev.id = 2;
253 tin2 = clk_get(&tmpdev.dev, "pwm-tin");
254 if (IS_ERR(tin2))
255 panic("failed to get pwm-tin2 clock for system timer");
256
257 tdiv2 = clk_get(&tmpdev.dev, "pwm-tdiv");
258 if (IS_ERR(tdiv2))
259 panic("failed to get pwm-tdiv2 clock for system timer");
260 clk_enable(tin2);
261
262 tmpdev.id = 4;
263 tin4 = clk_get(&tmpdev.dev, "pwm-tin");
264 if (IS_ERR(tin4))
265 panic("failed to get pwm-tin4 clock for system timer");
266
267 tdiv4 = clk_get(&tmpdev.dev, "pwm-tdiv");
268 if (IS_ERR(tdiv4))
269 panic("failed to get pwm-tdiv4 clock for system timer");
270
271 clk_enable(tin4);
272}
273
274static void __init s5pv310_timer_init(void)
275{
276#ifdef CONFIG_LOCAL_TIMERS
277 twd_base = S5P_VA_TWD;
278#endif
279
280 s5pv310_timer_resources();
281 s5pv310_clockevent_init();
282 s5pv310_clocksource_init();
283}
284
285struct sys_timer s5pv310_timer = {
286 .init = s5pv310_timer_init,
287};