aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-prima2
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-prima2')
-rw-r--r--arch/arm/mach-prima2/Kconfig13
-rw-r--r--arch/arm/mach-prima2/Makefile5
-rw-r--r--arch/arm/mach-prima2/common.c26
-rw-r--r--arch/arm/mach-prima2/common.h4
-rw-r--r--arch/arm/mach-prima2/include/mach/clkdev.h15
-rw-r--r--arch/arm/mach-prima2/include/mach/debug-macro.S29
-rw-r--r--arch/arm/mach-prima2/include/mach/entry-macro.S22
-rw-r--r--arch/arm/mach-prima2/include/mach/hardware.h15
-rw-r--r--arch/arm/mach-prima2/include/mach/irqs.h17
-rw-r--r--arch/arm/mach-prima2/include/mach/map.h18
-rw-r--r--arch/arm/mach-prima2/include/mach/timex.h14
-rw-r--r--arch/arm/mach-prima2/include/mach/uart.h29
-rw-r--r--arch/arm/mach-prima2/include/mach/uncompress.h41
-rw-r--r--arch/arm/mach-prima2/irq.c129
-rw-r--r--arch/arm/mach-prima2/lluart.c14
-rw-r--r--arch/arm/mach-prima2/platsmp.c1
-rw-r--r--arch/arm/mach-prima2/timer-marco.c316
-rw-r--r--arch/arm/mach-prima2/timer-prima2.c241
18 files changed, 44 insertions, 905 deletions
diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig
index b3be7994a2b1..80ca974b2f82 100644
--- a/arch/arm/mach-prima2/Kconfig
+++ b/arch/arm/mach-prima2/Kconfig
@@ -1,3 +1,15 @@
1config ARCH_SIRF
2 bool "CSR SiRF" if ARCH_MULTI_V7
3 select ARCH_REQUIRE_GPIOLIB
4 select GENERIC_CLOCKEVENTS
5 select GENERIC_IRQ_CHIP
6 select MIGHT_HAVE_CACHE_L2X0
7 select NO_IOPORT
8 select PINCTRL
9 select PINCTRL_SIRF
10 help
11 Support for CSR SiRFprimaII/Marco/Polo platforms
12
1if ARCH_SIRF 13if ARCH_SIRF
2 14
3menu "CSR SiRF atlas6/primaII/Marco/Polo Specific Features" 15menu "CSR SiRF atlas6/primaII/Marco/Polo Specific Features"
@@ -24,6 +36,7 @@ config ARCH_MARCO
24 default y 36 default y
25 select ARM_GIC 37 select ARM_GIC
26 select CPU_V7 38 select CPU_V7
39 select HAVE_ARM_SCU if SMP
27 select HAVE_SMP 40 select HAVE_SMP
28 select SMP_ON_UP 41 select SMP_ON_UP
29 help 42 help
diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
index bfe360cbd177..7a6b4a323125 100644
--- a/arch/arm/mach-prima2/Makefile
+++ b/arch/arm/mach-prima2/Makefile
@@ -4,8 +4,7 @@ obj-y += rtciobrg.o
4obj-$(CONFIG_DEBUG_LL) += lluart.o 4obj-$(CONFIG_DEBUG_LL) += lluart.o
5obj-$(CONFIG_CACHE_L2X0) += l2x0.o 5obj-$(CONFIG_CACHE_L2X0) += l2x0.o
6obj-$(CONFIG_SUSPEND) += pm.o sleep.o 6obj-$(CONFIG_SUSPEND) += pm.o sleep.o
7obj-$(CONFIG_SIRF_IRQ) += irq.o
8obj-$(CONFIG_SMP) += platsmp.o headsmp.o 7obj-$(CONFIG_SMP) += platsmp.o headsmp.o
9obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 8obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
10obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o 9
11obj-$(CONFIG_ARCH_MARCO) += timer-marco.o 10CFLAGS_hotplug.o += -march=armv7-a
diff --git a/arch/arm/mach-prima2/common.c b/arch/arm/mach-prima2/common.c
index 72efb4ff2803..4f94cd87972a 100644
--- a/arch/arm/mach-prima2/common.c
+++ b/arch/arm/mach-prima2/common.c
@@ -6,6 +6,7 @@
6 * Licensed under GPLv2 or later. 6 * Licensed under GPLv2 or later.
7 */ 7 */
8 8
9#include <linux/clocksource.h>
9#include <linux/init.h> 10#include <linux/init.h>
10#include <linux/kernel.h> 11#include <linux/kernel.h>
11#include <linux/irqchip.h> 12#include <linux/irqchip.h>
@@ -31,6 +32,13 @@ void __init sirfsoc_init_late(void)
31 sirfsoc_pm_init(); 32 sirfsoc_pm_init();
32} 33}
33 34
35static __init void sirfsoc_init_time(void)
36{
37 /* initialize clocking early, we want to set the OS timer */
38 sirfsoc_of_clk_init();
39 clocksource_of_init();
40}
41
34static __init void sirfsoc_map_io(void) 42static __init void sirfsoc_map_io(void)
35{ 43{
36 sirfsoc_map_lluart(); 44 sirfsoc_map_lluart();
@@ -45,12 +53,10 @@ static const char *atlas6_dt_match[] __initdata = {
45 53
46DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)") 54DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)")
47 /* Maintainer: Barry Song <baohua.song@csr.com> */ 55 /* Maintainer: Barry Song <baohua.song@csr.com> */
56 .nr_irqs = 128,
48 .map_io = sirfsoc_map_io, 57 .map_io = sirfsoc_map_io,
49 .init_irq = sirfsoc_of_irq_init, 58 .init_irq = irqchip_init,
50 .init_time = sirfsoc_prima2_timer_init, 59 .init_time = sirfsoc_init_time,
51#ifdef CONFIG_MULTI_IRQ_HANDLER
52 .handle_irq = sirfsoc_handle_irq,
53#endif
54 .init_machine = sirfsoc_mach_init, 60 .init_machine = sirfsoc_mach_init,
55 .init_late = sirfsoc_init_late, 61 .init_late = sirfsoc_init_late,
56 .dt_compat = atlas6_dt_match, 62 .dt_compat = atlas6_dt_match,
@@ -66,12 +72,10 @@ static const char *prima2_dt_match[] __initdata = {
66 72
67DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)") 73DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
68 /* Maintainer: Barry Song <baohua.song@csr.com> */ 74 /* Maintainer: Barry Song <baohua.song@csr.com> */
75 .nr_irqs = 128,
69 .map_io = sirfsoc_map_io, 76 .map_io = sirfsoc_map_io,
70 .init_irq = sirfsoc_of_irq_init, 77 .init_irq = irqchip_init,
71 .init_time = sirfsoc_prima2_timer_init, 78 .init_time = sirfsoc_init_time,
72#ifdef CONFIG_MULTI_IRQ_HANDLER
73 .handle_irq = sirfsoc_handle_irq,
74#endif
75 .dma_zone_size = SZ_256M, 79 .dma_zone_size = SZ_256M,
76 .init_machine = sirfsoc_mach_init, 80 .init_machine = sirfsoc_mach_init,
77 .init_late = sirfsoc_init_late, 81 .init_late = sirfsoc_init_late,
@@ -91,7 +95,7 @@ DT_MACHINE_START(MARCO_DT, "Generic MARCO (Flattened Device Tree)")
91 .smp = smp_ops(sirfsoc_smp_ops), 95 .smp = smp_ops(sirfsoc_smp_ops),
92 .map_io = sirfsoc_map_io, 96 .map_io = sirfsoc_map_io,
93 .init_irq = irqchip_init, 97 .init_irq = irqchip_init,
94 .init_time = sirfsoc_marco_timer_init, 98 .init_time = sirfsoc_init_time,
95 .init_machine = sirfsoc_mach_init, 99 .init_machine = sirfsoc_mach_init,
96 .init_late = sirfsoc_init_late, 100 .init_late = sirfsoc_init_late,
97 .dt_compat = marco_dt_match, 101 .dt_compat = marco_dt_match,
diff --git a/arch/arm/mach-prima2/common.h b/arch/arm/mach-prima2/common.h
index b7c26b62e4a7..81135cd88e54 100644
--- a/arch/arm/mach-prima2/common.h
+++ b/arch/arm/mach-prima2/common.h
@@ -13,8 +13,8 @@
13#include <asm/mach/time.h> 13#include <asm/mach/time.h>
14#include <asm/exception.h> 14#include <asm/exception.h>
15 15
16extern void sirfsoc_prima2_timer_init(void); 16#define SIRFSOC_VA_BASE _AC(0xFEC00000, UL)
17extern void sirfsoc_marco_timer_init(void); 17#define SIRFSOC_VA(x) (SIRFSOC_VA_BASE + ((x) & 0x00FFF000))
18 18
19extern struct smp_operations sirfsoc_smp_ops; 19extern struct smp_operations sirfsoc_smp_ops;
20extern void sirfsoc_secondary_startup(void); 20extern void sirfsoc_secondary_startup(void);
diff --git a/arch/arm/mach-prima2/include/mach/clkdev.h b/arch/arm/mach-prima2/include/mach/clkdev.h
deleted file mode 100644
index 66932518b1b7..000000000000
--- a/arch/arm/mach-prima2/include/mach/clkdev.h
+++ /dev/null
@@ -1,15 +0,0 @@
1/*
2 * arch/arm/mach-prima2/include/mach/clkdev.h
3 *
4 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5 *
6 * Licensed under GPLv2 or later.
7 */
8
9#ifndef __MACH_CLKDEV_H
10#define __MACH_CLKDEV_H
11
12#define __clk_get(clk) ({ 1; })
13#define __clk_put(clk) do { } while (0)
14
15#endif
diff --git a/arch/arm/mach-prima2/include/mach/debug-macro.S b/arch/arm/mach-prima2/include/mach/debug-macro.S
deleted file mode 100644
index cd97492bb075..000000000000
--- a/arch/arm/mach-prima2/include/mach/debug-macro.S
+++ /dev/null
@@ -1,29 +0,0 @@
1/*
2 * arch/arm/mach-prima2/include/mach/debug-macro.S
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 <mach/hardware.h>
10#include <mach/uart.h>
11
12 .macro addruart, rp, rv, tmp
13 ldr \rp, =SIRFSOC_UART1_PA_BASE @ physical
14 ldr \rv, =SIRFSOC_UART1_VA_BASE @ virtual
15 .endm
16
17 .macro senduart,rd,rx
18 str \rd, [\rx, #SIRFSOC_UART_TXFIFO_DATA]
19 .endm
20
21 .macro busyuart,rd,rx
22 .endm
23
24 .macro waituart,rd,rx
251001: ldr \rd, [\rx, #SIRFSOC_UART_TXFIFO_STATUS]
26 tst \rd, #SIRFSOC_UART1_TXFIFO_EMPTY
27 beq 1001b
28 .endm
29
diff --git a/arch/arm/mach-prima2/include/mach/entry-macro.S b/arch/arm/mach-prima2/include/mach/entry-macro.S
deleted file mode 100644
index 86434e7a5be9..000000000000
--- a/arch/arm/mach-prima2/include/mach/entry-macro.S
+++ /dev/null
@@ -1,22 +0,0 @@
1/*
2 * arch/arm/mach-prima2/include/mach/entry-macro.S
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 <mach/hardware.h>
10
11#define SIRFSOC_INT_ID 0x38
12
13 .macro get_irqnr_preamble, base, tmp
14 ldr \base, =sirfsoc_intc_base
15 ldr \base, [\base]
16 .endm
17
18 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
19 ldr \irqnr, [\base, #SIRFSOC_INT_ID] @ Get the highest priority irq
20 cmp \irqnr, #0x40 @ the irq num can't be larger than 0x3f
21 movges \irqnr, #0
22 .endm
diff --git a/arch/arm/mach-prima2/include/mach/hardware.h b/arch/arm/mach-prima2/include/mach/hardware.h
deleted file mode 100644
index 105b96964f25..000000000000
--- a/arch/arm/mach-prima2/include/mach/hardware.h
+++ /dev/null
@@ -1,15 +0,0 @@
1/*
2 * arch/arm/mach-prima2/include/mach/hardware.h
3 *
4 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5 *
6 * Licensed under GPLv2 or later.
7 */
8
9#ifndef __MACH_HARDWARE_H__
10#define __MACH_HARDWARE_H__
11
12#include <asm/sizes.h>
13#include <mach/map.h>
14
15#endif
diff --git a/arch/arm/mach-prima2/include/mach/irqs.h b/arch/arm/mach-prima2/include/mach/irqs.h
deleted file mode 100644
index b778a0f248ed..000000000000
--- a/arch/arm/mach-prima2/include/mach/irqs.h
+++ /dev/null
@@ -1,17 +0,0 @@
1/*
2 * arch/arm/mach-prima2/include/mach/irqs.h
3 *
4 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5 *
6 * Licensed under GPLv2 or later.
7 */
8
9#ifndef __ASM_ARCH_IRQS_H
10#define __ASM_ARCH_IRQS_H
11
12#define SIRFSOC_INTENAL_IRQ_START 0
13#define SIRFSOC_INTENAL_IRQ_END 127
14#define SIRFSOC_GPIO_IRQ_START (SIRFSOC_INTENAL_IRQ_END + 1)
15#define NR_IRQS 288
16
17#endif
diff --git a/arch/arm/mach-prima2/include/mach/map.h b/arch/arm/mach-prima2/include/mach/map.h
deleted file mode 100644
index 6f243532570c..000000000000
--- a/arch/arm/mach-prima2/include/mach/map.h
+++ /dev/null
@@ -1,18 +0,0 @@
1/*
2 * memory & I/O static mapping definitions 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#ifndef __MACH_PRIMA2_MAP_H__
10#define __MACH_PRIMA2_MAP_H__
11
12#include <linux/const.h>
13
14#define SIRFSOC_VA_BASE _AC(0xFEC00000, UL)
15
16#define SIRFSOC_VA(x) (SIRFSOC_VA_BASE + ((x) & 0x00FFF000))
17
18#endif
diff --git a/arch/arm/mach-prima2/include/mach/timex.h b/arch/arm/mach-prima2/include/mach/timex.h
deleted file mode 100644
index d6f98a75e562..000000000000
--- a/arch/arm/mach-prima2/include/mach/timex.h
+++ /dev/null
@@ -1,14 +0,0 @@
1/*
2 * arch/arm/mach-prima2/include/mach/timex.h
3 *
4 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5 *
6 * Licensed under GPLv2 or later.
7 */
8
9#ifndef __MACH_TIMEX_H__
10#define __MACH_TIMEX_H__
11
12#define CLOCK_TICK_RATE 1000000
13
14#endif
diff --git a/arch/arm/mach-prima2/include/mach/uart.h b/arch/arm/mach-prima2/include/mach/uart.h
deleted file mode 100644
index c10510d01a44..000000000000
--- a/arch/arm/mach-prima2/include/mach/uart.h
+++ /dev/null
@@ -1,29 +0,0 @@
1/*
2 * arch/arm/mach-prima2/include/mach/uart.h
3 *
4 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5 *
6 * Licensed under GPLv2 or later.
7 */
8
9#ifndef __MACH_PRIMA2_SIRFSOC_UART_H
10#define __MACH_PRIMA2_SIRFSOC_UART_H
11
12/* UART-1: used as serial debug port */
13#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1)
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
20#define SIRFSOC_UART1_VA_BASE SIRFSOC_VA(0x060000)
21#define SIRFSOC_UART1_SIZE SZ_4K
22
23#define SIRFSOC_UART_TXFIFO_STATUS 0x0114
24#define SIRFSOC_UART_TXFIFO_DATA 0x0118
25
26#define SIRFSOC_UART1_TXFIFO_FULL (1 << 5)
27#define SIRFSOC_UART1_TXFIFO_EMPTY (1 << 6)
28
29#endif
diff --git a/arch/arm/mach-prima2/include/mach/uncompress.h b/arch/arm/mach-prima2/include/mach/uncompress.h
deleted file mode 100644
index d1513a33709a..000000000000
--- a/arch/arm/mach-prima2/include/mach/uncompress.h
+++ /dev/null
@@ -1,41 +0,0 @@
1/*
2 * arch/arm/mach-prima2/include/mach/uncompress.h
3 *
4 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5 *
6 * Licensed under GPLv2 or later.
7 */
8
9#ifndef __ASM_ARCH_UNCOMPRESS_H
10#define __ASM_ARCH_UNCOMPRESS_H
11
12#include <linux/io.h>
13#include <mach/hardware.h>
14#include <mach/uart.h>
15
16void arch_decomp_setup(void)
17{
18}
19
20static __inline__ void putc(char c)
21{
22 /*
23 * during kernel decompression, all mappings are flat:
24 * virt_addr == phys_addr
25 */
26 if (!SIRFSOC_UART1_PA_BASE)
27 return;
28
29 while (__raw_readl((void __iomem *)SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS)
30 & SIRFSOC_UART1_TXFIFO_FULL)
31 barrier();
32
33 __raw_writel(c, (void __iomem *)SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_DATA);
34}
35
36static inline void flush(void)
37{
38}
39
40#endif
41
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c
deleted file mode 100644
index 6c0f3e9c43fb..000000000000
--- a/arch/arm/mach-prima2/irq.c
+++ /dev/null
@@ -1,129 +0,0 @@
1/*
2 * interrupt controller support 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/init.h>
10#include <linux/io.h>
11#include <linux/irq.h>
12#include <linux/of.h>
13#include <linux/of_address.h>
14#include <linux/irqdomain.h>
15#include <linux/syscore_ops.h>
16#include <asm/mach/irq.h>
17#include <asm/exception.h>
18#include <mach/hardware.h>
19
20#define SIRFSOC_INT_RISC_MASK0 0x0018
21#define SIRFSOC_INT_RISC_MASK1 0x001C
22#define SIRFSOC_INT_RISC_LEVEL0 0x0020
23#define SIRFSOC_INT_RISC_LEVEL1 0x0024
24#define SIRFSOC_INIT_IRQ_ID 0x0038
25
26void __iomem *sirfsoc_intc_base;
27
28static __init void
29sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
30{
31 struct irq_chip_generic *gc;
32 struct irq_chip_type *ct;
33
34 gc = irq_alloc_generic_chip("SIRFINTC", 1, irq_start, base, handle_level_irq);
35 ct = gc->chip_types;
36
37 ct->chip.irq_mask = irq_gc_mask_clr_bit;
38 ct->chip.irq_unmask = irq_gc_mask_set_bit;
39 ct->regs.mask = SIRFSOC_INT_RISC_MASK0;
40
41 irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0);
42}
43
44static __init void sirfsoc_irq_init(void)
45{
46 sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32);
47 sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32,
48 SIRFSOC_INTENAL_IRQ_END + 1 - 32);
49
50 writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
51 writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
52
53 writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
54 writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
55}
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
67static struct of_device_id intc_ids[] = {
68 { .compatible = "sirf,prima2-intc" },
69 {},
70};
71
72void __init sirfsoc_of_irq_init(void)
73{
74 struct device_node *np;
75
76 np = of_find_matching_node(NULL, intc_ids);
77 if (!np)
78 return;
79
80 sirfsoc_intc_base = of_iomap(np, 0);
81 if (!sirfsoc_intc_base)
82 panic("unable to map intc cpu registers\n");
83
84 irq_domain_add_legacy(np, SIRFSOC_INTENAL_IRQ_END + 1, 0, 0,
85 &irq_domain_simple_ops, NULL);
86
87 of_node_put(np);
88
89 sirfsoc_irq_init();
90}
91
92struct sirfsoc_irq_status {
93 u32 mask0;
94 u32 mask1;
95 u32 level0;
96 u32 level1;
97};
98
99static struct sirfsoc_irq_status sirfsoc_irq_st;
100
101static int sirfsoc_irq_suspend(void)
102{
103 sirfsoc_irq_st.mask0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
104 sirfsoc_irq_st.mask1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
105 sirfsoc_irq_st.level0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
106 sirfsoc_irq_st.level1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
107
108 return 0;
109}
110
111static void sirfsoc_irq_resume(void)
112{
113 writel_relaxed(sirfsoc_irq_st.mask0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
114 writel_relaxed(sirfsoc_irq_st.mask1, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
115 writel_relaxed(sirfsoc_irq_st.level0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
116 writel_relaxed(sirfsoc_irq_st.level1, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
117}
118
119static struct syscore_ops sirfsoc_irq_syscore_ops = {
120 .suspend = sirfsoc_irq_suspend,
121 .resume = sirfsoc_irq_resume,
122};
123
124static int __init sirfsoc_irq_pm_init(void)
125{
126 register_syscore_ops(&sirfsoc_irq_syscore_ops);
127 return 0;
128}
129device_initcall(sirfsoc_irq_pm_init);
diff --git a/arch/arm/mach-prima2/lluart.c b/arch/arm/mach-prima2/lluart.c
index a89f9b3c8cc5..99c0c927ca4a 100644
--- a/arch/arm/mach-prima2/lluart.c
+++ b/arch/arm/mach-prima2/lluart.c
@@ -9,8 +9,18 @@
9#include <linux/kernel.h> 9#include <linux/kernel.h>
10#include <asm/page.h> 10#include <asm/page.h>
11#include <asm/mach/map.h> 11#include <asm/mach/map.h>
12#include <mach/map.h> 12#include "common.h"
13#include <mach/uart.h> 13
14#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1)
15#define SIRFSOC_UART1_PA_BASE 0xb0060000
16#elif defined(CONFIG_DEBUG_SIRFMARCO_UART1)
17#define SIRFSOC_UART1_PA_BASE 0xcc060000
18#else
19#define SIRFSOC_UART1_PA_BASE 0
20#endif
21
22#define SIRFSOC_UART1_VA_BASE SIRFSOC_VA(0x060000)
23#define SIRFSOC_UART1_SIZE SZ_4K
14 24
15void __init sirfsoc_map_lluart(void) 25void __init sirfsoc_map_lluart(void)
16{ 26{
diff --git a/arch/arm/mach-prima2/platsmp.c b/arch/arm/mach-prima2/platsmp.c
index c7c92e78f0cf..1c3de7bed841 100644
--- a/arch/arm/mach-prima2/platsmp.c
+++ b/arch/arm/mach-prima2/platsmp.c
@@ -17,7 +17,6 @@
17#include <asm/smp_scu.h> 17#include <asm/smp_scu.h>
18#include <asm/cacheflush.h> 18#include <asm/cacheflush.h>
19#include <asm/cputype.h> 19#include <asm/cputype.h>
20#include <mach/map.h>
21 20
22#include "common.h" 21#include "common.h"
23 22
diff --git a/arch/arm/mach-prima2/timer-marco.c b/arch/arm/mach-prima2/timer-marco.c
deleted file mode 100644
index f4eea2e97eb0..000000000000
--- a/arch/arm/mach-prima2/timer-marco.c
+++ /dev/null
@@ -1,316 +0,0 @@
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-prima2.c b/arch/arm/mach-prima2/timer-prima2.c
deleted file mode 100644
index 6da584f8a949..000000000000
--- a/arch/arm/mach-prima2/timer-prima2.c
+++ /dev/null
@@ -1,241 +0,0 @@
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/err.h>
17#include <linux/slab.h>
18#include <linux/of.h>
19#include <linux/of_address.h>
20#include <mach/map.h>
21#include <asm/sched_clock.h>
22#include <asm/mach/time.h>
23
24#include "common.h"
25
26#define SIRFSOC_TIMER_COUNTER_LO 0x0000
27#define SIRFSOC_TIMER_COUNTER_HI 0x0004
28#define SIRFSOC_TIMER_MATCH_0 0x0008
29#define SIRFSOC_TIMER_MATCH_1 0x000C
30#define SIRFSOC_TIMER_MATCH_2 0x0010
31#define SIRFSOC_TIMER_MATCH_3 0x0014
32#define SIRFSOC_TIMER_MATCH_4 0x0018
33#define SIRFSOC_TIMER_MATCH_5 0x001C
34#define SIRFSOC_TIMER_STATUS 0x0020
35#define SIRFSOC_TIMER_INT_EN 0x0024
36#define SIRFSOC_TIMER_WATCHDOG_EN 0x0028
37#define SIRFSOC_TIMER_DIV 0x002C
38#define SIRFSOC_TIMER_LATCH 0x0030
39#define SIRFSOC_TIMER_LATCHED_LO 0x0034
40#define SIRFSOC_TIMER_LATCHED_HI 0x0038
41
42#define SIRFSOC_TIMER_WDT_INDEX 5
43
44#define SIRFSOC_TIMER_LATCH_BIT BIT(0)
45
46#define SIRFSOC_TIMER_REG_CNT 11
47
48static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
49 SIRFSOC_TIMER_MATCH_0, SIRFSOC_TIMER_MATCH_1, SIRFSOC_TIMER_MATCH_2,
50 SIRFSOC_TIMER_MATCH_3, SIRFSOC_TIMER_MATCH_4, SIRFSOC_TIMER_MATCH_5,
51 SIRFSOC_TIMER_INT_EN, SIRFSOC_TIMER_WATCHDOG_EN, SIRFSOC_TIMER_DIV,
52 SIRFSOC_TIMER_LATCHED_LO, SIRFSOC_TIMER_LATCHED_HI,
53};
54
55static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
56
57static void __iomem *sirfsoc_timer_base;
58static void __init sirfsoc_of_timer_map(void);
59
60/* timer0 interrupt handler */
61static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
62{
63 struct clock_event_device *ce = dev_id;
64
65 WARN_ON(!(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_STATUS) & BIT(0)));
66
67 /* clear timer0 interrupt */
68 writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
69
70 ce->event_handler(ce);
71
72 return IRQ_HANDLED;
73}
74
75/* read 64-bit timer counter */
76static cycle_t sirfsoc_timer_read(struct clocksource *cs)
77{
78 u64 cycles;
79
80 /* latch the 64-bit timer counter */
81 writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
82 cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_HI);
83 cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
84
85 return cycles;
86}
87
88static int sirfsoc_timer_set_next_event(unsigned long delta,
89 struct clock_event_device *ce)
90{
91 unsigned long now, next;
92
93 writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
94 now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
95 next = now + delta;
96 writel_relaxed(next, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0);
97 writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
98 now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
99
100 return next - now > delta ? -ETIME : 0;
101}
102
103static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
104 struct clock_event_device *ce)
105{
106 u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
107 switch (mode) {
108 case CLOCK_EVT_MODE_PERIODIC:
109 WARN_ON(1);
110 break;
111 case CLOCK_EVT_MODE_ONESHOT:
112 writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
113 break;
114 case CLOCK_EVT_MODE_SHUTDOWN:
115 writel_relaxed(val & ~BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
116 break;
117 case CLOCK_EVT_MODE_UNUSED:
118 case CLOCK_EVT_MODE_RESUME:
119 break;
120 }
121}
122
123static void sirfsoc_clocksource_suspend(struct clocksource *cs)
124{
125 int i;
126
127 writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
128
129 for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
130 sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
131}
132
133static void sirfsoc_clocksource_resume(struct clocksource *cs)
134{
135 int i;
136
137 for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
138 writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
139
140 writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
141 writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
142}
143
144static struct clock_event_device sirfsoc_clockevent = {
145 .name = "sirfsoc_clockevent",
146 .rating = 200,
147 .features = CLOCK_EVT_FEAT_ONESHOT,
148 .set_mode = sirfsoc_timer_set_mode,
149 .set_next_event = sirfsoc_timer_set_next_event,
150};
151
152static struct clocksource sirfsoc_clocksource = {
153 .name = "sirfsoc_clocksource",
154 .rating = 200,
155 .mask = CLOCKSOURCE_MASK(64),
156 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
157 .read = sirfsoc_timer_read,
158 .suspend = sirfsoc_clocksource_suspend,
159 .resume = sirfsoc_clocksource_resume,
160};
161
162static struct irqaction sirfsoc_timer_irq = {
163 .name = "sirfsoc_timer0",
164 .flags = IRQF_TIMER,
165 .irq = 0,
166 .handler = sirfsoc_timer_interrupt,
167 .dev_id = &sirfsoc_clockevent,
168};
169
170/* Overwrite weak default sched_clock with more precise one */
171static u32 notrace sirfsoc_read_sched_clock(void)
172{
173 return (u32)(sirfsoc_timer_read(NULL) & 0xffffffff);
174}
175
176static void __init sirfsoc_clockevent_init(void)
177{
178 sirfsoc_clockevent.cpumask = cpumask_of(0);
179 clockevents_config_and_register(&sirfsoc_clockevent, CLOCK_TICK_RATE,
180 2, -2);
181}
182
183/* initialize the kernel jiffy timer source */
184void __init sirfsoc_prima2_timer_init(void)
185{
186 unsigned long rate;
187 struct clk *clk;
188
189 /* initialize clocking early, we want to set the OS timer */
190 sirfsoc_of_clk_init();
191
192 /* timer's input clock is io clock */
193 clk = clk_get_sys("io", NULL);
194
195 BUG_ON(IS_ERR(clk));
196
197 rate = clk_get_rate(clk);
198
199 BUG_ON(rate < CLOCK_TICK_RATE);
200 BUG_ON(rate % CLOCK_TICK_RATE);
201
202 sirfsoc_of_timer_map();
203
204 writel_relaxed(rate / CLOCK_TICK_RATE / 2 - 1, sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
205 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
206 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
207 writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
208
209 BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
210
211 setup_sched_clock(sirfsoc_read_sched_clock, 32, CLOCK_TICK_RATE);
212
213 BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
214
215 sirfsoc_clockevent_init();
216}
217
218static struct of_device_id timer_ids[] = {
219 { .compatible = "sirf,prima2-tick" },
220 {},
221};
222
223static void __init sirfsoc_of_timer_map(void)
224{
225 struct device_node *np;
226 const unsigned int *intspec;
227
228 np = of_find_matching_node(NULL, timer_ids);
229 if (!np)
230 return;
231 sirfsoc_timer_base = of_iomap(np, 0);
232 if (!sirfsoc_timer_base)
233 panic("unable to map timer cpu registers\n");
234
235 /* Get the interrupts property */
236 intspec = of_get_property(np, "interrupts", NULL);
237 BUG_ON(!intspec);
238 sirfsoc_timer_irq.irq = be32_to_cpup(intspec);
239
240 of_node_put(np);
241}