aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-prima2
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-01-28 02:03:42 -0500
committerOlof Johansson <olof@lixom.net>2013-01-28 02:03:42 -0500
commitaf70fdc947dbe835acc26c6ee9e8e930f38935f8 (patch)
tree9924e9f2732e3cf3c7a882cb11377247729891ab /arch/arm/mach-prima2
parent66eae035dc59755c51ad3b3c718a5ed7535322e3 (diff)
parent7f46a10724e0d31c83029436e54298be2cc558fa (diff)
Merge branch 'marco-timer-cleanup-rebase' of git://gitorious.org/sirfprima2-kernel/sirfprima2-kernel into next/soc
From Barry Song, this adds support for a new SoC from CSR; marco. It's SMP, uses GIC instead of VIC and in general needs a bit of rework of the platform code for setup, which this branch contains. * 'marco-timer-cleanup-rebase' of git://gitorious.org/sirfprima2-kernel/sirfprima2-kernel: ARM: PRIMA2: provide two DEBUG_LL ports for prima2 and marco ARM: PRIMA2: add new SiRFmarco SMP SoC infrastructures ARM: PRIMA2: irq: make prima2 irq can work even we enable GIC for Marco ARM: PRIMA2: rtciobg: it is also compatible with marco ARM: PRIMA2: rstc: enable the support for Marco ARM: PRIMA2: mv timer to timer-prima2 as we will add timer-marco ARM: PRIMA2: initialize l2x0 according to mach from DT ARM: PRIMA2: enable AUTO_ZRELADDR for SIRF in Kconfig ARM: PRIMA2: add CSR SiRFmarco device tree .dts Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm/mach-prima2')
-rw-r--r--arch/arm/mach-prima2/Kconfig10
-rw-r--r--arch/arm/mach-prima2/Makefile5
-rw-r--r--arch/arm/mach-prima2/common.c45
-rw-r--r--arch/arm/mach-prima2/common.h15
-rw-r--r--arch/arm/mach-prima2/headsmp.S79
-rw-r--r--arch/arm/mach-prima2/hotplug.c41
-rw-r--r--arch/arm/mach-prima2/include/mach/irqs.h4
-rw-r--r--arch/arm/mach-prima2/include/mach/uart.h6
-rw-r--r--arch/arm/mach-prima2/include/mach/uncompress.h3
-rw-r--r--arch/arm/mach-prima2/irq.c16
-rw-r--r--arch/arm/mach-prima2/l2x0.c29
-rw-r--r--arch/arm/mach-prima2/platsmp.c163
-rw-r--r--arch/arm/mach-prima2/rstc.c45
-rw-r--r--arch/arm/mach-prima2/rtciobrg.c1
-rw-r--r--arch/arm/mach-prima2/timer-marco.c316
-rw-r--r--arch/arm/mach-prima2/timer-prima2.c (renamed from arch/arm/mach-prima2/timer.c)6
16 files changed, 751 insertions, 33 deletions
diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig
index 558ccfb8d458..4f7379fe01e2 100644
--- a/arch/arm/mach-prima2/Kconfig
+++ b/arch/arm/mach-prima2/Kconfig
@@ -11,6 +11,16 @@ config ARCH_PRIMA2
11 help 11 help
12 Support for CSR SiRFSoC ARM Cortex A9 Platform 12 Support for CSR SiRFSoC ARM Cortex A9 Platform
13 13
14config ARCH_MARCO
15 bool "CSR SiRFSoC MARCO ARM Cortex A9 Platform"
16 default y
17 select ARM_GIC
18 select CPU_V7
19 select HAVE_SMP
20 select SMP_ON_UP
21 help
22 Support for CSR SiRFSoC ARM Cortex A9 Platform
23
14endmenu 24endmenu
15 25
16config SIRF_IRQ 26config SIRF_IRQ
diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
index fc9ce22e2b5a..bfe360cbd177 100644
--- a/arch/arm/mach-prima2/Makefile
+++ b/arch/arm/mach-prima2/Makefile
@@ -1,4 +1,3 @@
1obj-y := timer.o
2obj-y += rstc.o 1obj-y += rstc.o
3obj-y += common.o 2obj-y += common.o
4obj-y += rtciobrg.o 3obj-y += rtciobrg.o
@@ -6,3 +5,7 @@ obj-$(CONFIG_DEBUG_LL) += lluart.o
6obj-$(CONFIG_CACHE_L2X0) += l2x0.o 5obj-$(CONFIG_CACHE_L2X0) += l2x0.o
7obj-$(CONFIG_SUSPEND) += pm.o sleep.o 6obj-$(CONFIG_SUSPEND) += pm.o sleep.o
8obj-$(CONFIG_SIRF_IRQ) += irq.o 7obj-$(CONFIG_SIRF_IRQ) += irq.o
8obj-$(CONFIG_SMP) += platsmp.o headsmp.o
9obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
10obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o
11obj-$(CONFIG_ARCH_MARCO) += timer-marco.o
diff --git a/arch/arm/mach-prima2/common.c b/arch/arm/mach-prima2/common.c
index ed3570e5eb8f..00a65649a7e2 100644
--- a/arch/arm/mach-prima2/common.c
+++ b/arch/arm/mach-prima2/common.c
@@ -8,9 +8,11 @@
8 8
9#include <linux/init.h> 9#include <linux/init.h>
10#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <linux/of_irq.h>
11#include <asm/sizes.h> 12#include <asm/sizes.h>
12#include <asm/mach-types.h> 13#include <asm/mach-types.h>
13#include <asm/mach/arch.h> 14#include <asm/mach/arch.h>
15#include <asm/hardware/gic.h>
14#include <linux/of.h> 16#include <linux/of.h>
15#include <linux/of_platform.h> 17#include <linux/of_platform.h>
16#include "common.h" 18#include "common.h"
@@ -30,6 +32,12 @@ void __init sirfsoc_init_late(void)
30 sirfsoc_pm_init(); 32 sirfsoc_pm_init();
31} 33}
32 34
35static __init void sirfsoc_map_io(void)
36{
37 sirfsoc_map_lluart();
38 sirfsoc_map_scu();
39}
40
33#ifdef CONFIG_ARCH_PRIMA2 41#ifdef CONFIG_ARCH_PRIMA2
34static const char *prima2_dt_match[] __initdata = { 42static const char *prima2_dt_match[] __initdata = {
35 "sirf,prima2", 43 "sirf,prima2",
@@ -38,9 +46,12 @@ static const char *prima2_dt_match[] __initdata = {
38 46
39DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)") 47DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
40 /* Maintainer: Barry Song <baohua.song@csr.com> */ 48 /* Maintainer: Barry Song <baohua.song@csr.com> */
41 .map_io = sirfsoc_map_lluart, 49 .map_io = sirfsoc_map_io,
42 .init_irq = sirfsoc_of_irq_init, 50 .init_irq = sirfsoc_of_irq_init,
43 .init_time = sirfsoc_timer_init, 51 .init_time = sirfsoc_prima2_timer_init,
52#ifdef CONFIG_MULTI_IRQ_HANDLER
53 .handle_irq = sirfsoc_handle_irq,
54#endif
44 .dma_zone_size = SZ_256M, 55 .dma_zone_size = SZ_256M,
45 .init_machine = sirfsoc_mach_init, 56 .init_machine = sirfsoc_mach_init,
46 .init_late = sirfsoc_init_late, 57 .init_late = sirfsoc_init_late,
@@ -48,3 +59,33 @@ DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
48 .restart = sirfsoc_restart, 59 .restart = sirfsoc_restart,
49MACHINE_END 60MACHINE_END
50#endif 61#endif
62
63#ifdef CONFIG_ARCH_MARCO
64static const struct of_device_id marco_irq_match[] __initconst = {
65 { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
66 { /* sentinel */ }
67};
68
69static void __init marco_init_irq(void)
70{
71 of_irq_init(marco_irq_match);
72}
73
74static const char *marco_dt_match[] __initdata = {
75 "sirf,marco",
76 NULL
77};
78
79DT_MACHINE_START(MARCO_DT, "Generic MARCO (Flattened Device Tree)")
80 /* Maintainer: Barry Song <baohua.song@csr.com> */
81 .smp = smp_ops(sirfsoc_smp_ops),
82 .map_io = sirfsoc_map_io,
83 .init_irq = marco_init_irq,
84 .init_time = sirfsoc_marco_timer_init,
85 .handle_irq = gic_handle_irq,
86 .init_machine = sirfsoc_mach_init,
87 .init_late = sirfsoc_init_late,
88 .dt_compat = marco_dt_match,
89 .restart = sirfsoc_restart,
90MACHINE_END
91#endif
diff --git a/arch/arm/mach-prima2/common.h b/arch/arm/mach-prima2/common.h
index 9c75f124e3cf..b7c26b62e4a7 100644
--- a/arch/arm/mach-prima2/common.h
+++ b/arch/arm/mach-prima2/common.h
@@ -11,12 +11,19 @@
11 11
12#include <linux/init.h> 12#include <linux/init.h>
13#include <asm/mach/time.h> 13#include <asm/mach/time.h>
14#include <asm/exception.h>
14 15
15extern void sirfsoc_timer_init(void); 16extern void sirfsoc_prima2_timer_init(void);
17extern void sirfsoc_marco_timer_init(void);
18
19extern struct smp_operations sirfsoc_smp_ops;
20extern void sirfsoc_secondary_startup(void);
21extern void sirfsoc_cpu_die(unsigned int cpu);
16 22
17extern void __init sirfsoc_of_irq_init(void); 23extern void __init sirfsoc_of_irq_init(void);
18extern void __init sirfsoc_of_clk_init(void); 24extern void __init sirfsoc_of_clk_init(void);
19extern void sirfsoc_restart(char, const char *); 25extern void sirfsoc_restart(char, const char *);
26extern asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs);
20 27
21#ifndef CONFIG_DEBUG_LL 28#ifndef CONFIG_DEBUG_LL
22static inline void sirfsoc_map_lluart(void) {} 29static inline void sirfsoc_map_lluart(void) {}
@@ -24,6 +31,12 @@ static inline void sirfsoc_map_lluart(void) {}
24extern void __init sirfsoc_map_lluart(void); 31extern void __init sirfsoc_map_lluart(void);
25#endif 32#endif
26 33
34#ifndef CONFIG_SMP
35static inline void sirfsoc_map_scu(void) {}
36#else
37extern void sirfsoc_map_scu(void);
38#endif
39
27#ifdef CONFIG_SUSPEND 40#ifdef CONFIG_SUSPEND
28extern int sirfsoc_pm_init(void); 41extern int sirfsoc_pm_init(void);
29#else 42#else
diff --git a/arch/arm/mach-prima2/headsmp.S b/arch/arm/mach-prima2/headsmp.S
new file mode 100644
index 000000000000..6ec19d51a271
--- /dev/null
+++ b/arch/arm/mach-prima2/headsmp.S
@@ -0,0 +1,79 @@
1/*
2 * Entry of the second core for CSR Marco dual-core SMP SoCs
3 *
4 * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
5 *
6 * Licensed under GPLv2 or later.
7 */
8
9#include <linux/linkage.h>
10#include <linux/init.h>
11
12 __INIT
13/*
14 * Cold boot and hardware reset show different behaviour,
15 * system will be always panic if we warm-reset the board
16 * Here we invalidate L1 of CPU1 to make sure there isn't
17 * uninitialized data written into memory later
18 */
19ENTRY(v7_invalidate_l1)
20 mov r0, #0
21 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
22 mcr p15, 2, r0, c0, c0, 0
23 mrc p15, 1, r0, c0, c0, 0
24
25 ldr r1, =0x7fff
26 and r2, r1, r0, lsr #13
27
28 ldr r1, =0x3ff
29
30 and r3, r1, r0, lsr #3 @ NumWays - 1
31 add r2, r2, #1 @ NumSets
32
33 and r0, r0, #0x7
34 add r0, r0, #4 @ SetShift
35
36 clz r1, r3 @ WayShift
37 add r4, r3, #1 @ NumWays
381: sub r2, r2, #1 @ NumSets--
39 mov r3, r4 @ Temp = NumWays
402: subs r3, r3, #1 @ Temp--
41 mov r5, r3, lsl r1
42 mov r6, r2, lsl r0
43 orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
44 mcr p15, 0, r5, c7, c6, 2
45 bgt 2b
46 cmp r2, #0
47 bgt 1b
48 dsb
49 isb
50 mov pc, lr
51ENDPROC(v7_invalidate_l1)
52
53/*
54 * SIRFSOC specific entry point for secondary CPUs. This provides
55 * a "holding pen" into which all secondary cores are held until we're
56 * ready for them to initialise.
57 */
58ENTRY(sirfsoc_secondary_startup)
59 bl v7_invalidate_l1
60 mrc p15, 0, r0, c0, c0, 5
61 and r0, r0, #15
62 adr r4, 1f
63 ldmia r4, {r5, r6}
64 sub r4, r4, r5
65 add r6, r6, r4
66pen: ldr r7, [r6]
67 cmp r7, r0
68 bne pen
69
70 /*
71 * we've been released from the holding pen: secondary_stack
72 * should now contain the SVC stack for this core
73 */
74 b secondary_startup
75ENDPROC(sirfsoc_secondary_startup)
76
77 .align
781: .long .
79 .long pen_release
diff --git a/arch/arm/mach-prima2/hotplug.c b/arch/arm/mach-prima2/hotplug.c
new file mode 100644
index 000000000000..97c1ee586442
--- /dev/null
+++ b/arch/arm/mach-prima2/hotplug.c
@@ -0,0 +1,41 @@
1/*
2 * CPU hotplug support for CSR Marco dual-core SMP SoCs
3 *
4 * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
5 *
6 * Licensed under GPLv2 or later.
7 */
8
9#include <linux/kernel.h>
10#include <linux/errno.h>
11#include <linux/smp.h>
12
13#include <asm/cacheflush.h>
14#include <asm/smp_plat.h>
15
16static inline void platform_do_lowpower(unsigned int cpu)
17{
18 flush_cache_all();
19
20 /* we put the platform to just WFI */
21 for (;;) {
22 __asm__ __volatile__("dsb\n\t" "wfi\n\t"
23 : : : "memory");
24 if (pen_release == cpu_logical_map(cpu)) {
25 /*
26 * OK, proper wakeup, we're done
27 */
28 break;
29 }
30 }
31}
32
33/*
34 * platform-specific code to shutdown a CPU
35 *
36 * Called with IRQs disabled
37 */
38void sirfsoc_cpu_die(unsigned int cpu)
39{
40 platform_do_lowpower(cpu);
41}
diff --git a/arch/arm/mach-prima2/include/mach/irqs.h b/arch/arm/mach-prima2/include/mach/irqs.h
index f6014a07541f..b778a0f248ed 100644
--- a/arch/arm/mach-prima2/include/mach/irqs.h
+++ b/arch/arm/mach-prima2/include/mach/irqs.h
@@ -10,8 +10,8 @@
10#define __ASM_ARCH_IRQS_H 10#define __ASM_ARCH_IRQS_H
11 11
12#define SIRFSOC_INTENAL_IRQ_START 0 12#define SIRFSOC_INTENAL_IRQ_START 0
13#define SIRFSOC_INTENAL_IRQ_END 59 13#define SIRFSOC_INTENAL_IRQ_END 127
14#define SIRFSOC_GPIO_IRQ_START (SIRFSOC_INTENAL_IRQ_END + 1) 14#define SIRFSOC_GPIO_IRQ_START (SIRFSOC_INTENAL_IRQ_END + 1)
15#define NR_IRQS 220 15#define NR_IRQS 288
16 16
17#endif 17#endif
diff --git a/arch/arm/mach-prima2/include/mach/uart.h b/arch/arm/mach-prima2/include/mach/uart.h
index c98b4d5ac24a..c10510d01a44 100644
--- a/arch/arm/mach-prima2/include/mach/uart.h
+++ b/arch/arm/mach-prima2/include/mach/uart.h
@@ -10,7 +10,13 @@
10#define __MACH_PRIMA2_SIRFSOC_UART_H 10#define __MACH_PRIMA2_SIRFSOC_UART_H
11 11
12/* UART-1: used as serial debug port */ 12/* UART-1: used as serial debug port */
13#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1)
13#define SIRFSOC_UART1_PA_BASE 0xb0060000 14#define SIRFSOC_UART1_PA_BASE 0xb0060000
15#elif defined(CONFIG_DEBUG_SIRFMARCO_UART1)
16#define SIRFSOC_UART1_PA_BASE 0xcc060000
17#else
18#define SIRFSOC_UART1_PA_BASE 0
19#endif
14#define SIRFSOC_UART1_VA_BASE SIRFSOC_VA(0x060000) 20#define SIRFSOC_UART1_VA_BASE SIRFSOC_VA(0x060000)
15#define SIRFSOC_UART1_SIZE SZ_4K 21#define SIRFSOC_UART1_SIZE SZ_4K
16 22
diff --git a/arch/arm/mach-prima2/include/mach/uncompress.h b/arch/arm/mach-prima2/include/mach/uncompress.h
index 0c898fcf909c..15f3edcfbb47 100644
--- a/arch/arm/mach-prima2/include/mach/uncompress.h
+++ b/arch/arm/mach-prima2/include/mach/uncompress.h
@@ -25,6 +25,9 @@ static __inline__ void putc(char c)
25 * during kernel decompression, all mappings are flat: 25 * during kernel decompression, all mappings are flat:
26 * virt_addr == phys_addr 26 * virt_addr == phys_addr
27 */ 27 */
28 if (!SIRFSOC_UART1_PA_BASE)
29 return;
30
28 while (__raw_readl((void __iomem *)SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS) 31 while (__raw_readl((void __iomem *)SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS)
29 & SIRFSOC_UART1_TXFIFO_FULL) 32 & SIRFSOC_UART1_TXFIFO_FULL)
30 barrier(); 33 barrier();
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c
index 7dee9176e77a..6c0f3e9c43fb 100644
--- a/arch/arm/mach-prima2/irq.c
+++ b/arch/arm/mach-prima2/irq.c
@@ -9,17 +9,19 @@
9#include <linux/init.h> 9#include <linux/init.h>
10#include <linux/io.h> 10#include <linux/io.h>
11#include <linux/irq.h> 11#include <linux/irq.h>
12#include <mach/hardware.h>
13#include <asm/mach/irq.h>
14#include <linux/of.h> 12#include <linux/of.h>
15#include <linux/of_address.h> 13#include <linux/of_address.h>
16#include <linux/irqdomain.h> 14#include <linux/irqdomain.h>
17#include <linux/syscore_ops.h> 15#include <linux/syscore_ops.h>
16#include <asm/mach/irq.h>
17#include <asm/exception.h>
18#include <mach/hardware.h>
18 19
19#define SIRFSOC_INT_RISC_MASK0 0x0018 20#define SIRFSOC_INT_RISC_MASK0 0x0018
20#define SIRFSOC_INT_RISC_MASK1 0x001C 21#define SIRFSOC_INT_RISC_MASK1 0x001C
21#define SIRFSOC_INT_RISC_LEVEL0 0x0020 22#define SIRFSOC_INT_RISC_LEVEL0 0x0020
22#define SIRFSOC_INT_RISC_LEVEL1 0x0024 23#define SIRFSOC_INT_RISC_LEVEL1 0x0024
24#define SIRFSOC_INIT_IRQ_ID 0x0038
23 25
24void __iomem *sirfsoc_intc_base; 26void __iomem *sirfsoc_intc_base;
25 27
@@ -52,6 +54,16 @@ static __init void sirfsoc_irq_init(void)
52 writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1); 54 writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
53} 55}
54 56
57asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs)
58{
59 u32 irqstat, irqnr;
60
61 irqstat = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INIT_IRQ_ID);
62 irqnr = irqstat & 0xff;
63
64 handle_IRQ(irqnr, regs);
65}
66
55static struct of_device_id intc_ids[] = { 67static struct of_device_id intc_ids[] = {
56 { .compatible = "sirf,prima2-intc" }, 68 { .compatible = "sirf,prima2-intc" },
57 {}, 69 {},
diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c
index c99837797d76..cbcbe9cb094c 100644
--- a/arch/arm/mach-prima2/l2x0.c
+++ b/arch/arm/mach-prima2/l2x0.c
@@ -11,19 +11,38 @@
11#include <linux/of.h> 11#include <linux/of.h>
12#include <asm/hardware/cache-l2x0.h> 12#include <asm/hardware/cache-l2x0.h>
13 13
14static struct of_device_id prima2_l2x0_ids[] = { 14struct l2x0_aux
15 { .compatible = "sirf,prima2-pl310-cache" }, 15{
16 u32 val;
17 u32 mask;
18};
19
20static struct l2x0_aux prima2_l2x0_aux __initconst = {
21 .val = 2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT,
22 .mask = 0,
23};
24
25static struct l2x0_aux marco_l2x0_aux __initconst = {
26 .val = (2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) |
27 (1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT),
28 .mask = L2X0_AUX_CTRL_MASK,
29};
30
31static struct of_device_id sirf_l2x0_ids[] __initconst = {
32 { .compatible = "sirf,prima2-pl310-cache", .data = &prima2_l2x0_aux, },
33 { .compatible = "sirf,marco-pl310-cache", .data = &marco_l2x0_aux, },
16 {}, 34 {},
17}; 35};
18 36
19static int __init sirfsoc_l2x0_init(void) 37static int __init sirfsoc_l2x0_init(void)
20{ 38{
21 struct device_node *np; 39 struct device_node *np;
40 const struct l2x0_aux *aux;
22 41
23 np = of_find_matching_node(NULL, prima2_l2x0_ids); 42 np = of_find_matching_node(NULL, sirf_l2x0_ids);
24 if (np) { 43 if (np) {
25 pr_info("Initializing prima2 L2 cache\n"); 44 aux = of_match_node(sirf_l2x0_ids, np)->data;
26 return l2x0_of_init(0x40000, 0); 45 return l2x0_of_init(aux->val, aux->mask);
27 } 46 }
28 47
29 return 0; 48 return 0;
diff --git a/arch/arm/mach-prima2/platsmp.c b/arch/arm/mach-prima2/platsmp.c
new file mode 100644
index 000000000000..2395022bc733
--- /dev/null
+++ b/arch/arm/mach-prima2/platsmp.c
@@ -0,0 +1,163 @@
1/*
2 * plat smp support for CSR Marco dual-core SMP SoCs
3 *
4 * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
5 *
6 * Licensed under GPLv2 or later.
7 */
8
9#include <linux/init.h>
10#include <linux/smp.h>
11#include <linux/delay.h>
12#include <linux/of.h>
13#include <linux/of_address.h>
14#include <asm/page.h>
15#include <asm/mach/map.h>
16#include <asm/smp_plat.h>
17#include <asm/smp_scu.h>
18#include <asm/cacheflush.h>
19#include <asm/cputype.h>
20#include <asm/hardware/gic.h>
21#include <mach/map.h>
22
23#include "common.h"
24
25static void __iomem *scu_base;
26static void __iomem *rsc_base;
27
28static DEFINE_SPINLOCK(boot_lock);
29
30static struct map_desc scu_io_desc __initdata = {
31 .length = SZ_4K,
32 .type = MT_DEVICE,
33};
34
35void __init sirfsoc_map_scu(void)
36{
37 unsigned long base;
38
39 /* Get SCU base */
40 asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
41
42 scu_io_desc.virtual = SIRFSOC_VA(base);
43 scu_io_desc.pfn = __phys_to_pfn(base);
44 iotable_init(&scu_io_desc, 1);
45
46 scu_base = (void __iomem *)SIRFSOC_VA(base);
47}
48
49static void __cpuinit sirfsoc_secondary_init(unsigned int cpu)
50{
51 /*
52 * if any interrupts are already enabled for the primary
53 * core (e.g. timer irq), then they will not have been enabled
54 * for us: do so
55 */
56 gic_secondary_init(0);
57
58 /*
59 * let the primary processor know we're out of the
60 * pen, then head off into the C entry point
61 */
62 pen_release = -1;
63 smp_wmb();
64
65 /*
66 * Synchronise with the boot thread.
67 */
68 spin_lock(&boot_lock);
69 spin_unlock(&boot_lock);
70}
71
72static struct of_device_id rsc_ids[] = {
73 { .compatible = "sirf,marco-rsc" },
74 {},
75};
76
77static int __cpuinit sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle)
78{
79 unsigned long timeout;
80 struct device_node *np;
81
82 np = of_find_matching_node(NULL, rsc_ids);
83 if (!np)
84 return -ENODEV;
85
86 rsc_base = of_iomap(np, 0);
87 if (!rsc_base)
88 return -ENOMEM;
89
90 /*
91 * write the address of secondary startup into the sram register
92 * at offset 0x2C, then write the magic number 0x3CAF5D62 to the
93 * RSC register at offset 0x28, which is what boot rom code is
94 * waiting for. This would wake up the secondary core from WFE
95 */
96#define SIRFSOC_CPU1_JUMPADDR_OFFSET 0x2C
97 __raw_writel(virt_to_phys(sirfsoc_secondary_startup),
98 rsc_base + SIRFSOC_CPU1_JUMPADDR_OFFSET);
99
100#define SIRFSOC_CPU1_WAKEMAGIC_OFFSET 0x28
101 __raw_writel(0x3CAF5D62,
102 rsc_base + SIRFSOC_CPU1_WAKEMAGIC_OFFSET);
103
104 /* make sure write buffer is drained */
105 mb();
106
107 spin_lock(&boot_lock);
108
109 /*
110 * The secondary processor is waiting to be released from
111 * the holding pen - release it, then wait for it to flag
112 * that it has been released by resetting pen_release.
113 *
114 * Note that "pen_release" is the hardware CPU ID, whereas
115 * "cpu" is Linux's internal ID.
116 */
117 pen_release = cpu_logical_map(cpu);
118 __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
119 outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
120
121 /*
122 * Send the secondary CPU SEV, thereby causing the boot monitor to read
123 * the JUMPADDR and WAKEMAGIC, and branch to the address found there.
124 */
125 dsb_sev();
126
127 timeout = jiffies + (1 * HZ);
128 while (time_before(jiffies, timeout)) {
129 smp_rmb();
130 if (pen_release == -1)
131 break;
132
133 udelay(10);
134 }
135
136 /*
137 * now the secondary core is starting up let it run its
138 * calibrations, then wait for it to finish
139 */
140 spin_unlock(&boot_lock);
141
142 return pen_release != -1 ? -ENOSYS : 0;
143}
144
145static void __init sirfsoc_smp_init_cpus(void)
146{
147 set_smp_cross_call(gic_raise_softirq);
148}
149
150static void __init sirfsoc_smp_prepare_cpus(unsigned int max_cpus)
151{
152 scu_enable(scu_base);
153}
154
155struct smp_operations sirfsoc_smp_ops __initdata = {
156 .smp_init_cpus = sirfsoc_smp_init_cpus,
157 .smp_prepare_cpus = sirfsoc_smp_prepare_cpus,
158 .smp_secondary_init = sirfsoc_secondary_init,
159 .smp_boot_secondary = sirfsoc_boot_secondary,
160#ifdef CONFIG_HOTPLUG_CPU
161 .cpu_die = sirfsoc_cpu_die,
162#endif
163};
diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c
index 762adb73ab7c..435019ca0a48 100644
--- a/arch/arm/mach-prima2/rstc.c
+++ b/arch/arm/mach-prima2/rstc.c
@@ -19,6 +19,7 @@ static DEFINE_MUTEX(rstc_lock);
19 19
20static struct of_device_id rstc_ids[] = { 20static struct of_device_id rstc_ids[] = {
21 { .compatible = "sirf,prima2-rstc" }, 21 { .compatible = "sirf,prima2-rstc" },
22 { .compatible = "sirf,marco-rstc" },
22 {}, 23 {},
23}; 24};
24 25
@@ -42,27 +43,37 @@ early_initcall(sirfsoc_of_rstc_init);
42 43
43int sirfsoc_reset_device(struct device *dev) 44int sirfsoc_reset_device(struct device *dev)
44{ 45{
45 const unsigned int *prop = of_get_property(dev->of_node, "reset-bit", NULL); 46 u32 reset_bit;
46 unsigned int reset_bit;
47 47
48 if (!prop) 48 if (of_property_read_u32(dev->of_node, "reset-bit", &reset_bit))
49 return -ENODEV; 49 return -EINVAL;
50
51 reset_bit = be32_to_cpup(prop);
52 50
53 mutex_lock(&rstc_lock); 51 mutex_lock(&rstc_lock);
54 52
55 /* 53 if (of_device_is_compatible(dev->of_node, "sirf,prima2-rstc")) {
56 * Writing 1 to this bit resets corresponding block. Writing 0 to this 54 /*
57 * bit de-asserts reset signal of the corresponding block. 55 * Writing 1 to this bit resets corresponding block. Writing 0 to this
58 * datasheet doesn't require explicit delay between the set and clear 56 * bit de-asserts reset signal of the corresponding block.
59 * of reset bit. it could be shorter if tests pass. 57 * datasheet doesn't require explicit delay between the set and clear
60 */ 58 * of reset bit. it could be shorter if tests pass.
61 writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit, 59 */
62 sirfsoc_rstc_base + (reset_bit / 32) * 4); 60 writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit,
63 msleep(10); 61 sirfsoc_rstc_base + (reset_bit / 32) * 4);
64 writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit, 62 msleep(10);
65 sirfsoc_rstc_base + (reset_bit / 32) * 4); 63 writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit,
64 sirfsoc_rstc_base + (reset_bit / 32) * 4);
65 } else {
66 /*
67 * For MARCO and POLO
68 * Writing 1 to SET register resets corresponding block. Writing 1 to CLEAR
69 * register de-asserts reset signal of the corresponding block.
70 * datasheet doesn't require explicit delay between the set and clear
71 * of reset bit. it could be shorter if tests pass.
72 */
73 writel(reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8);
74 msleep(10);
75 writel(reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8 + 4);
76 }
66 77
67 mutex_unlock(&rstc_lock); 78 mutex_unlock(&rstc_lock);
68 79
diff --git a/arch/arm/mach-prima2/rtciobrg.c b/arch/arm/mach-prima2/rtciobrg.c
index 557353602130..9f2da2eec4dc 100644
--- a/arch/arm/mach-prima2/rtciobrg.c
+++ b/arch/arm/mach-prima2/rtciobrg.c
@@ -104,6 +104,7 @@ EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel);
104 104
105static const struct of_device_id rtciobrg_ids[] = { 105static const struct of_device_id rtciobrg_ids[] = {
106 { .compatible = "sirf,prima2-rtciobg" }, 106 { .compatible = "sirf,prima2-rtciobg" },
107 { .compatible = "sirf,marco-rtciobg" },
107 {} 108 {}
108}; 109};
109 110
diff --git a/arch/arm/mach-prima2/timer-marco.c b/arch/arm/mach-prima2/timer-marco.c
new file mode 100644
index 000000000000..f4eea2e97eb0
--- /dev/null
+++ b/arch/arm/mach-prima2/timer-marco.c
@@ -0,0 +1,316 @@
1/*
2 * System timer for CSR SiRFprimaII
3 *
4 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5 *
6 * Licensed under GPLv2 or later.
7 */
8
9#include <linux/kernel.h>
10#include <linux/interrupt.h>
11#include <linux/clockchips.h>
12#include <linux/clocksource.h>
13#include <linux/bitops.h>
14#include <linux/irq.h>
15#include <linux/clk.h>
16#include <linux/slab.h>
17#include <linux/of.h>
18#include <linux/of_irq.h>
19#include <linux/of_address.h>
20#include <asm/sched_clock.h>
21#include <asm/localtimer.h>
22#include <asm/mach/time.h>
23
24#include "common.h"
25
26#define SIRFSOC_TIMER_32COUNTER_0_CTRL 0x0000
27#define SIRFSOC_TIMER_32COUNTER_1_CTRL 0x0004
28#define SIRFSOC_TIMER_MATCH_0 0x0018
29#define SIRFSOC_TIMER_MATCH_1 0x001c
30#define SIRFSOC_TIMER_COUNTER_0 0x0048
31#define SIRFSOC_TIMER_COUNTER_1 0x004c
32#define SIRFSOC_TIMER_INTR_STATUS 0x0060
33#define SIRFSOC_TIMER_WATCHDOG_EN 0x0064
34#define SIRFSOC_TIMER_64COUNTER_CTRL 0x0068
35#define SIRFSOC_TIMER_64COUNTER_LO 0x006c
36#define SIRFSOC_TIMER_64COUNTER_HI 0x0070
37#define SIRFSOC_TIMER_64COUNTER_LOAD_LO 0x0074
38#define SIRFSOC_TIMER_64COUNTER_LOAD_HI 0x0078
39#define SIRFSOC_TIMER_64COUNTER_RLATCHED_LO 0x007c
40#define SIRFSOC_TIMER_64COUNTER_RLATCHED_HI 0x0080
41
42#define SIRFSOC_TIMER_REG_CNT 6
43
44static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
45 SIRFSOC_TIMER_WATCHDOG_EN,
46 SIRFSOC_TIMER_32COUNTER_0_CTRL,
47 SIRFSOC_TIMER_32COUNTER_1_CTRL,
48 SIRFSOC_TIMER_64COUNTER_CTRL,
49 SIRFSOC_TIMER_64COUNTER_RLATCHED_LO,
50 SIRFSOC_TIMER_64COUNTER_RLATCHED_HI,
51};
52
53static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
54
55static void __iomem *sirfsoc_timer_base;
56static void __init sirfsoc_of_timer_map(void);
57
58/* disable count and interrupt */
59static inline void sirfsoc_timer_count_disable(int idx)
60{
61 writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) & ~0x7,
62 sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
63}
64
65/* enable count and interrupt */
66static inline void sirfsoc_timer_count_enable(int idx)
67{
68 writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) | 0x7,
69 sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
70}
71
72/* timer interrupt handler */
73static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
74{
75 struct clock_event_device *ce = dev_id;
76 int cpu = smp_processor_id();
77
78 /* clear timer interrupt */
79 writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
80
81 if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
82 sirfsoc_timer_count_disable(cpu);
83
84 ce->event_handler(ce);
85
86 return IRQ_HANDLED;
87}
88
89/* read 64-bit timer counter */
90static cycle_t sirfsoc_timer_read(struct clocksource *cs)
91{
92 u64 cycles;
93
94 writel_relaxed((readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
95 BIT(0)) & ~BIT(1), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
96
97 cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI);
98 cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO);
99
100 return cycles;
101}
102
103static int sirfsoc_timer_set_next_event(unsigned long delta,
104 struct clock_event_device *ce)
105{
106 int cpu = smp_processor_id();
107
108 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0 +
109 4 * cpu);
110 writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0 +
111 4 * cpu);
112
113 /* enable the tick */
114 sirfsoc_timer_count_enable(cpu);
115
116 return 0;
117}
118
119static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
120 struct clock_event_device *ce)
121{
122 switch (mode) {
123 case CLOCK_EVT_MODE_ONESHOT:
124 /* enable in set_next_event */
125 break;
126 default:
127 break;
128 }
129
130 sirfsoc_timer_count_disable(smp_processor_id());
131}
132
133static void sirfsoc_clocksource_suspend(struct clocksource *cs)
134{
135 int i;
136
137 for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
138 sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
139}
140
141static void sirfsoc_clocksource_resume(struct clocksource *cs)
142{
143 int i;
144
145 for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
146 writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
147
148 writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2],
149 sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
150 writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1],
151 sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
152
153 writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
154 BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
155}
156
157static struct clock_event_device sirfsoc_clockevent = {
158 .name = "sirfsoc_clockevent",
159 .rating = 200,
160 .features = CLOCK_EVT_FEAT_ONESHOT,
161 .set_mode = sirfsoc_timer_set_mode,
162 .set_next_event = sirfsoc_timer_set_next_event,
163};
164
165static struct clocksource sirfsoc_clocksource = {
166 .name = "sirfsoc_clocksource",
167 .rating = 200,
168 .mask = CLOCKSOURCE_MASK(64),
169 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
170 .read = sirfsoc_timer_read,
171 .suspend = sirfsoc_clocksource_suspend,
172 .resume = sirfsoc_clocksource_resume,
173};
174
175static struct irqaction sirfsoc_timer_irq = {
176 .name = "sirfsoc_timer0",
177 .flags = IRQF_TIMER | IRQF_NOBALANCING,
178 .handler = sirfsoc_timer_interrupt,
179 .dev_id = &sirfsoc_clockevent,
180};
181
182#ifdef CONFIG_LOCAL_TIMERS
183
184static struct irqaction sirfsoc_timer1_irq = {
185 .name = "sirfsoc_timer1",
186 .flags = IRQF_TIMER | IRQF_NOBALANCING,
187 .handler = sirfsoc_timer_interrupt,
188};
189
190static int __cpuinit sirfsoc_local_timer_setup(struct clock_event_device *ce)
191{
192 /* Use existing clock_event for cpu 0 */
193 if (!smp_processor_id())
194 return 0;
195
196 ce->irq = sirfsoc_timer1_irq.irq;
197 ce->name = "local_timer";
198 ce->features = sirfsoc_clockevent.features;
199 ce->rating = sirfsoc_clockevent.rating;
200 ce->set_mode = sirfsoc_timer_set_mode;
201 ce->set_next_event = sirfsoc_timer_set_next_event;
202 ce->shift = sirfsoc_clockevent.shift;
203 ce->mult = sirfsoc_clockevent.mult;
204 ce->max_delta_ns = sirfsoc_clockevent.max_delta_ns;
205 ce->min_delta_ns = sirfsoc_clockevent.min_delta_ns;
206
207 sirfsoc_timer1_irq.dev_id = ce;
208 BUG_ON(setup_irq(ce->irq, &sirfsoc_timer1_irq));
209 irq_set_affinity(sirfsoc_timer1_irq.irq, cpumask_of(1));
210
211 clockevents_register_device(ce);
212 return 0;
213}
214
215static void sirfsoc_local_timer_stop(struct clock_event_device *ce)
216{
217 sirfsoc_timer_count_disable(1);
218
219 remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq);
220}
221
222static struct local_timer_ops sirfsoc_local_timer_ops __cpuinitdata = {
223 .setup = sirfsoc_local_timer_setup,
224 .stop = sirfsoc_local_timer_stop,
225};
226#endif /* CONFIG_LOCAL_TIMERS */
227
228static void __init sirfsoc_clockevent_init(void)
229{
230 clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
231
232 sirfsoc_clockevent.max_delta_ns =
233 clockevent_delta2ns(-2, &sirfsoc_clockevent);
234 sirfsoc_clockevent.min_delta_ns =
235 clockevent_delta2ns(2, &sirfsoc_clockevent);
236
237 sirfsoc_clockevent.cpumask = cpumask_of(0);
238 clockevents_register_device(&sirfsoc_clockevent);
239#ifdef CONFIG_LOCAL_TIMERS
240 local_timer_register(&sirfsoc_local_timer_ops);
241#endif
242}
243
244/* initialize the kernel jiffy timer source */
245void __init sirfsoc_marco_timer_init(void)
246{
247 unsigned long rate;
248 u32 timer_div;
249 struct clk *clk;
250
251 /* initialize clocking early, we want to set the OS timer */
252 sirfsoc_of_clk_init();
253
254 /* timer's input clock is io clock */
255 clk = clk_get_sys("io", NULL);
256
257 BUG_ON(IS_ERR(clk));
258 rate = clk_get_rate(clk);
259
260 BUG_ON(rate < CLOCK_TICK_RATE);
261 BUG_ON(rate % CLOCK_TICK_RATE);
262
263 sirfsoc_of_timer_map();
264
265 /* Initialize the timer dividers */
266 timer_div = rate / CLOCK_TICK_RATE - 1;
267 writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
268 writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
269 writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
270
271 /* Initialize timer counters to 0 */
272 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
273 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
274 writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
275 BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
276 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0);
277 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_1);
278
279 /* Clear all interrupts */
280 writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
281
282 BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
283
284 BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
285
286 sirfsoc_clockevent_init();
287}
288
289static struct of_device_id timer_ids[] = {
290 { .compatible = "sirf,marco-tick" },
291 {},
292};
293
294static void __init sirfsoc_of_timer_map(void)
295{
296 struct device_node *np;
297
298 np = of_find_matching_node(NULL, timer_ids);
299 if (!np)
300 return;
301 sirfsoc_timer_base = of_iomap(np, 0);
302 if (!sirfsoc_timer_base)
303 panic("unable to map timer cpu registers\n");
304
305 sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0);
306 if (!sirfsoc_timer_irq.irq)
307 panic("No irq passed for timer0 via DT\n");
308
309#ifdef CONFIG_LOCAL_TIMERS
310 sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1);
311 if (!sirfsoc_timer1_irq.irq)
312 panic("No irq passed for timer1 via DT\n");
313#endif
314
315 of_node_put(np);
316}
diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer-prima2.c
index a7a2c199c3ea..6da584f8a949 100644
--- a/arch/arm/mach-prima2/timer.c
+++ b/arch/arm/mach-prima2/timer-prima2.c
@@ -181,7 +181,7 @@ static void __init sirfsoc_clockevent_init(void)
181} 181}
182 182
183/* initialize the kernel jiffy timer source */ 183/* initialize the kernel jiffy timer source */
184void __init sirfsoc_timer_init(void) 184void __init sirfsoc_prima2_timer_init(void)
185{ 185{
186 unsigned long rate; 186 unsigned long rate;
187 struct clk *clk; 187 struct clk *clk;
@@ -220,14 +220,14 @@ static struct of_device_id timer_ids[] = {
220 {}, 220 {},
221}; 221};
222 222
223void __init sirfsoc_of_timer_map(void) 223static void __init sirfsoc_of_timer_map(void)
224{ 224{
225 struct device_node *np; 225 struct device_node *np;
226 const unsigned int *intspec; 226 const unsigned int *intspec;
227 227
228 np = of_find_matching_node(NULL, timer_ids); 228 np = of_find_matching_node(NULL, timer_ids);
229 if (!np) 229 if (!np)
230 panic("unable to find compatible timer node in dtb\n"); 230 return;
231 sirfsoc_timer_base = of_iomap(np, 0); 231 sirfsoc_timer_base = of_iomap(np, 0);
232 if (!sirfsoc_timer_base) 232 if (!sirfsoc_timer_base)
233 panic("unable to map timer cpu registers\n"); 233 panic("unable to map timer cpu registers\n");