aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-vexpress
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/arm/mach-vexpress
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'arch/arm/mach-vexpress')
-rw-r--r--arch/arm/mach-vexpress/Kconfig3
-rw-r--r--arch/arm/mach-vexpress/Makefile4
-rw-r--r--arch/arm/mach-vexpress/core.h7
-rw-r--r--arch/arm/mach-vexpress/ct-ca9x4.c142
-rw-r--r--arch/arm/mach-vexpress/headsmp.S39
-rw-r--r--arch/arm/mach-vexpress/hotplug.c128
-rw-r--r--arch/arm/mach-vexpress/include/mach/ct-ca9x4.h2
-rw-r--r--arch/arm/mach-vexpress/include/mach/debug-macro.S10
-rw-r--r--arch/arm/mach-vexpress/include/mach/entry-macro.S62
-rw-r--r--arch/arm/mach-vexpress/include/mach/memory.h2
-rw-r--r--arch/arm/mach-vexpress/include/mach/motherboard.h22
-rw-r--r--arch/arm/mach-vexpress/include/mach/smp.h21
-rw-r--r--arch/arm/mach-vexpress/localtimer.c26
-rw-r--r--arch/arm/mach-vexpress/platsmp.c161
-rw-r--r--arch/arm/mach-vexpress/v2m.c147
15 files changed, 354 insertions, 422 deletions
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index 3f19b660a165..931148487f0b 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -5,5 +5,8 @@ config ARCH_VEXPRESS_CA9X4
5 bool "Versatile Express Cortex-A9x4 tile" 5 bool "Versatile Express Cortex-A9x4 tile"
6 select CPU_V7 6 select CPU_V7
7 select ARM_GIC 7 select ARM_GIC
8 select ARM_ERRATA_720789
9 select ARM_ERRATA_751472
10 select ARM_ERRATA_753970
8 11
9endmenu 12endmenu
diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile
index 1b71b77ade22..90551b9780ab 100644
--- a/arch/arm/mach-vexpress/Makefile
+++ b/arch/arm/mach-vexpress/Makefile
@@ -4,5 +4,5 @@
4 4
5obj-y := v2m.o 5obj-y := v2m.o
6obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o 6obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o
7obj-$(CONFIG_SMP) += platsmp.o headsmp.o 7obj-$(CONFIG_SMP) += platsmp.o
8obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o 8obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h
index 57dd95ce41f9..f4397159c173 100644
--- a/arch/arm/mach-vexpress/core.h
+++ b/arch/arm/mach-vexpress/core.h
@@ -17,10 +17,3 @@ struct amba_device name##_device = { \
17 .irq = IRQ_##base, \ 17 .irq = IRQ_##base, \
18 /* .dma = DMA_##base,*/ \ 18 /* .dma = DMA_##base,*/ \
19} 19}
20
21struct map_desc;
22
23void v2m_map_io(struct map_desc *tile, size_t num);
24extern struct sys_timer v2m_timer;
25
26extern void __iomem *gic_cpu_base_addr;
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 71fb17349520..765a71ff7f3b 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -8,22 +8,19 @@
8#include <linux/platform_device.h> 8#include <linux/platform_device.h>
9#include <linux/amba/bus.h> 9#include <linux/amba/bus.h>
10#include <linux/amba/clcd.h> 10#include <linux/amba/clcd.h>
11#include <linux/clkdev.h>
11 12
12#include <asm/clkdev.h>
13#include <asm/pgtable.h>
14#include <asm/hardware/arm_timer.h> 13#include <asm/hardware/arm_timer.h>
15#include <asm/hardware/cache-l2x0.h> 14#include <asm/hardware/cache-l2x0.h>
16#include <asm/hardware/gic.h> 15#include <asm/hardware/gic.h>
17#include <asm/mach-types.h>
18#include <asm/pmu.h> 16#include <asm/pmu.h>
17#include <asm/smp_scu.h>
19#include <asm/smp_twd.h> 18#include <asm/smp_twd.h>
20 19
21#include <mach/clkdev.h>
22#include <mach/ct-ca9x4.h> 20#include <mach/ct-ca9x4.h>
23 21
24#include <plat/timer-sp.h> 22#include <asm/hardware/timer-sp.h>
25 23
26#include <asm/mach/arch.h>
27#include <asm/mach/map.h> 24#include <asm/mach/map.h>
28#include <asm/mach/time.h> 25#include <asm/mach/time.h>
29 26
@@ -31,6 +28,8 @@
31 28
32#include <mach/motherboard.h> 29#include <mach/motherboard.h>
33 30
31#include <plat/clcd.h>
32
34#define V2M_PA_CS7 0x10000000 33#define V2M_PA_CS7 0x10000000
35 34
36static struct map_desc ct_ca9x4_io_desc[] __initdata = { 35static struct map_desc ct_ca9x4_io_desc[] __initdata = {
@@ -54,17 +53,16 @@ static struct map_desc ct_ca9x4_io_desc[] __initdata = {
54 53
55static void __init ct_ca9x4_map_io(void) 54static void __init ct_ca9x4_map_io(void)
56{ 55{
56#ifdef CONFIG_LOCAL_TIMERS
57 twd_base = MMIO_P2V(A9_MPCORE_TWD); 57 twd_base = MMIO_P2V(A9_MPCORE_TWD);
58 v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); 58#endif
59 iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
59} 60}
60 61
61void __iomem *gic_cpu_base_addr;
62
63static void __init ct_ca9x4_init_irq(void) 62static void __init ct_ca9x4_init_irq(void)
64{ 63{
65 gic_cpu_base_addr = MMIO_P2V(A9_MPCORE_GIC_CPU); 64 gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST),
66 gic_dist_init(0, MMIO_P2V(A9_MPCORE_GIC_DIST), 29); 65 MMIO_P2V(A9_MPCORE_GIC_CPU));
67 gic_cpu_init(0, gic_cpu_base_addr);
68} 66}
69 67
70#if 0 68#if 0
@@ -73,8 +71,9 @@ static void __init ct_ca9x4_timer_init(void)
73 writel(0, MMIO_P2V(CT_CA9X4_TIMER0) + TIMER_CTRL); 71 writel(0, MMIO_P2V(CT_CA9X4_TIMER0) + TIMER_CTRL);
74 writel(0, MMIO_P2V(CT_CA9X4_TIMER1) + TIMER_CTRL); 72 writel(0, MMIO_P2V(CT_CA9X4_TIMER1) + TIMER_CTRL);
75 73
76 sp804_clocksource_init(MMIO_P2V(CT_CA9X4_TIMER1)); 74 sp804_clocksource_init(MMIO_P2V(CT_CA9X4_TIMER1), "ct-timer1");
77 sp804_clockevents_init(MMIO_P2V(CT_CA9X4_TIMER0), IRQ_CT_CA9X4_TIMER0); 75 sp804_clockevents_init(MMIO_P2V(CT_CA9X4_TIMER0), IRQ_CT_CA9X4_TIMER0,
76 "ct-timer0");
78} 77}
79 78
80static struct sys_timer ct_ca9x4_timer = { 79static struct sys_timer ct_ca9x4_timer = {
@@ -82,29 +81,6 @@ static struct sys_timer ct_ca9x4_timer = {
82}; 81};
83#endif 82#endif
84 83
85static struct clcd_panel xvga_panel = {
86 .mode = {
87 .name = "XVGA",
88 .refresh = 60,
89 .xres = 1024,
90 .yres = 768,
91 .pixclock = 15384,
92 .left_margin = 168,
93 .right_margin = 8,
94 .upper_margin = 29,
95 .lower_margin = 3,
96 .hsync_len = 144,
97 .vsync_len = 6,
98 .sync = 0,
99 .vmode = FB_VMODE_NONINTERLACED,
100 },
101 .width = -1,
102 .height = -1,
103 .tim2 = TIM2_BCD | TIM2_IPC,
104 .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
105 .bpp = 16,
106};
107
108static void ct_ca9x4_clcd_enable(struct clcd_fb *fb) 84static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
109{ 85{
110 v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0); 86 v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0);
@@ -114,42 +90,23 @@ static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
114static int ct_ca9x4_clcd_setup(struct clcd_fb *fb) 90static int ct_ca9x4_clcd_setup(struct clcd_fb *fb)
115{ 91{
116 unsigned long framesize = 1024 * 768 * 2; 92 unsigned long framesize = 1024 * 768 * 2;
117 dma_addr_t dma;
118
119 fb->panel = &xvga_panel;
120 93
121 fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize, 94 fb->panel = versatile_clcd_get_panel("XVGA");
122 &dma, GFP_KERNEL); 95 if (!fb->panel)
123 if (!fb->fb.screen_base) { 96 return -EINVAL;
124 printk(KERN_ERR "CLCD: unable to map frame buffer\n");
125 return -ENOMEM;
126 }
127 fb->fb.fix.smem_start = dma;
128 fb->fb.fix.smem_len = framesize;
129 97
130 return 0; 98 return versatile_clcd_setup_dma(fb, framesize);
131}
132
133static int ct_ca9x4_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
134{
135 return dma_mmap_writecombine(&fb->dev->dev, vma, fb->fb.screen_base,
136 fb->fb.fix.smem_start, fb->fb.fix.smem_len);
137}
138
139static void ct_ca9x4_clcd_remove(struct clcd_fb *fb)
140{
141 dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
142 fb->fb.screen_base, fb->fb.fix.smem_start);
143} 99}
144 100
145static struct clcd_board ct_ca9x4_clcd_data = { 101static struct clcd_board ct_ca9x4_clcd_data = {
146 .name = "CT-CA9X4", 102 .name = "CT-CA9X4",
103 .caps = CLCD_CAP_5551 | CLCD_CAP_565,
147 .check = clcdfb_check, 104 .check = clcdfb_check,
148 .decode = clcdfb_decode, 105 .decode = clcdfb_decode,
149 .enable = ct_ca9x4_clcd_enable, 106 .enable = ct_ca9x4_clcd_enable,
150 .setup = ct_ca9x4_clcd_setup, 107 .setup = ct_ca9x4_clcd_setup,
151 .mmap = ct_ca9x4_clcd_mmap, 108 .mmap = versatile_clcd_mmap_dma,
152 .remove = ct_ca9x4_clcd_remove, 109 .remove = versatile_clcd_remove_dma,
153}; 110};
154 111
155static AMBA_DEVICE(clcd, "ct:clcd", CT_CA9X4_CLCDC, &ct_ca9x4_clcd_data); 112static AMBA_DEVICE(clcd, "ct:clcd", CT_CA9X4_CLCDC, &ct_ca9x4_clcd_data);
@@ -185,10 +142,22 @@ static struct clk osc1_clk = {
185 .rate = 24000000, 142 .rate = 24000000,
186}; 143};
187 144
145static struct clk ct_sp804_clk = {
146 .rate = 1000000,
147};
148
188static struct clk_lookup lookups[] = { 149static struct clk_lookup lookups[] = {
189 { /* CLCD */ 150 { /* CLCD */
190 .dev_id = "ct:clcd", 151 .dev_id = "ct:clcd",
191 .clk = &osc1_clk, 152 .clk = &osc1_clk,
153 }, { /* SP804 timers */
154 .dev_id = "sp804",
155 .con_id = "ct-timer0",
156 .clk = &ct_sp804_clk,
157 }, { /* SP804 timers */
158 .dev_id = "sp804",
159 .con_id = "ct-timer1",
160 .clk = &ct_sp804_clk,
192 }, 161 },
193}; 162};
194 163
@@ -222,6 +191,11 @@ static struct platform_device pmu_device = {
222 .resource = pmu_resources, 191 .resource = pmu_resources,
223}; 192};
224 193
194static void __init ct_ca9x4_init_early(void)
195{
196 clkdev_add_table(lookups, ARRAY_SIZE(lookups));
197}
198
225static void __init ct_ca9x4_init(void) 199static void __init ct_ca9x4_init(void)
226{ 200{
227 int i; 201 int i;
@@ -236,24 +210,42 @@ static void __init ct_ca9x4_init(void)
236 l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff); 210 l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
237#endif 211#endif
238 212
239 clkdev_add_table(lookups, ARRAY_SIZE(lookups));
240
241 for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++) 213 for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++)
242 amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); 214 amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
243 215
244 platform_device_register(&pmu_device); 216 platform_device_register(&pmu_device);
245} 217}
246 218
247MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4") 219#ifdef CONFIG_SMP
248 .phys_io = V2M_UART0 & SECTION_MASK, 220static void ct_ca9x4_init_cpu_map(void)
249 .io_pg_offst = (__MMIO_P2V(V2M_UART0) >> 18) & 0xfffc, 221{
250 .boot_params = PHYS_OFFSET + 0x00000100, 222 int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU));
223
224 for (i = 0; i < ncores; ++i)
225 set_cpu_possible(i, true);
226
227 set_smp_cross_call(gic_raise_softirq);
228}
229
230static void ct_ca9x4_smp_enable(unsigned int max_cpus)
231{
232 int i;
233 for (i = 0; i < max_cpus; i++)
234 set_cpu_present(i, true);
235
236 scu_enable(MMIO_P2V(A9_MPCORE_SCU));
237}
238#endif
239
240struct ct_desc ct_ca9x4_desc __initdata = {
241 .id = V2M_CT_ID_CA9,
242 .name = "CA9x4",
251 .map_io = ct_ca9x4_map_io, 243 .map_io = ct_ca9x4_map_io,
244 .init_early = ct_ca9x4_init_early,
252 .init_irq = ct_ca9x4_init_irq, 245 .init_irq = ct_ca9x4_init_irq,
253#if 0 246 .init_tile = ct_ca9x4_init,
254 .timer = &ct_ca9x4_timer, 247#ifdef CONFIG_SMP
255#else 248 .init_cpu_map = ct_ca9x4_init_cpu_map,
256 .timer = &v2m_timer, 249 .smp_enable = ct_ca9x4_smp_enable,
257#endif 250#endif
258 .init_machine = ct_ca9x4_init, 251};
259MACHINE_END
diff --git a/arch/arm/mach-vexpress/headsmp.S b/arch/arm/mach-vexpress/headsmp.S
deleted file mode 100644
index 8a78ff68e1ee..000000000000
--- a/arch/arm/mach-vexpress/headsmp.S
+++ /dev/null
@@ -1,39 +0,0 @@
1/*
2 * linux/arch/arm/mach-vexpress/headsmp.S
3 *
4 * Copyright (c) 2003 ARM Limited
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/linkage.h>
12#include <linux/init.h>
13
14 __INIT
15
16/*
17 * Versatile Express specific entry point for secondary CPUs. This
18 * provides a "holding pen" into which all secondary cores are held
19 * until we're ready for them to initialise.
20 */
21ENTRY(vexpress_secondary_startup)
22 mrc p15, 0, r0, c0, c0, 5
23 and r0, r0, #15
24 adr r4, 1f
25 ldmia r4, {r5, r6}
26 sub r4, r4, r5
27 add r6, r6, r4
28pen: ldr r7, [r6]
29 cmp r7, r0
30 bne pen
31
32 /*
33 * we've been released from the holding pen: secondary_stack
34 * should now contain the SVC stack for this core
35 */
36 b secondary_startup
37
381: .long .
39 .long pen_release
diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c
new file mode 100644
index 000000000000..ea4cbfb90a66
--- /dev/null
+++ b/arch/arm/mach-vexpress/hotplug.c
@@ -0,0 +1,128 @@
1/*
2 * linux/arch/arm/mach-realview/hotplug.c
3 *
4 * Copyright (C) 2002 ARM Ltd.
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/kernel.h>
12#include <linux/errno.h>
13#include <linux/smp.h>
14
15#include <asm/cacheflush.h>
16
17extern volatile int pen_release;
18
19static inline void cpu_enter_lowpower(void)
20{
21 unsigned int v;
22
23 flush_cache_all();
24 asm volatile(
25 "mcr p15, 0, %1, c7, c5, 0\n"
26 " mcr p15, 0, %1, c7, c10, 4\n"
27 /*
28 * Turn off coherency
29 */
30 " mrc p15, 0, %0, c1, c0, 1\n"
31 " bic %0, %0, %3\n"
32 " mcr p15, 0, %0, c1, c0, 1\n"
33 " mrc p15, 0, %0, c1, c0, 0\n"
34 " bic %0, %0, %2\n"
35 " mcr p15, 0, %0, c1, c0, 0\n"
36 : "=&r" (v)
37 : "r" (0), "Ir" (CR_C), "Ir" (0x40)
38 : "cc");
39}
40
41static inline void cpu_leave_lowpower(void)
42{
43 unsigned int v;
44
45 asm volatile(
46 "mrc p15, 0, %0, c1, c0, 0\n"
47 " orr %0, %0, %1\n"
48 " mcr p15, 0, %0, c1, c0, 0\n"
49 " mrc p15, 0, %0, c1, c0, 1\n"
50 " orr %0, %0, %2\n"
51 " mcr p15, 0, %0, c1, c0, 1\n"
52 : "=&r" (v)
53 : "Ir" (CR_C), "Ir" (0x40)
54 : "cc");
55}
56
57static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
58{
59 /*
60 * there is no power-control hardware on this platform, so all
61 * we can do is put the core into WFI; this is safe as the calling
62 * code will have already disabled interrupts
63 */
64 for (;;) {
65 /*
66 * here's the WFI
67 */
68 asm(".word 0xe320f003\n"
69 :
70 :
71 : "memory", "cc");
72
73 if (pen_release == cpu) {
74 /*
75 * OK, proper wakeup, we're done
76 */
77 break;
78 }
79
80 /*
81 * Getting here, means that we have come out of WFI without
82 * having been woken up - this shouldn't happen
83 *
84 * Just note it happening - when we're woken, we can report
85 * its occurrence.
86 */
87 (*spurious)++;
88 }
89}
90
91int platform_cpu_kill(unsigned int cpu)
92{
93 return 1;
94}
95
96/*
97 * platform-specific code to shutdown a CPU
98 *
99 * Called with IRQs disabled
100 */
101void platform_cpu_die(unsigned int cpu)
102{
103 int spurious = 0;
104
105 /*
106 * we're ready for shutdown now, so do it
107 */
108 cpu_enter_lowpower();
109 platform_do_lowpower(cpu, &spurious);
110
111 /*
112 * bring this CPU back into the world of cache
113 * coherency, and then restore interrupts
114 */
115 cpu_leave_lowpower();
116
117 if (spurious)
118 pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
119}
120
121int platform_cpu_disable(unsigned int cpu)
122{
123 /*
124 * we don't allow CPU 0 to be shutdown (it is still too special
125 * e.g. clock tick interrupts)
126 */
127 return cpu == 0 ? -EPERM : 0;
128}
diff --git a/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h b/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h
index f9e2f8d22962..a34d3d4faae1 100644
--- a/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h
+++ b/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h
@@ -45,4 +45,6 @@
45#define IRQ_CT_CA9X4_PMU_CPU2 94 45#define IRQ_CT_CA9X4_PMU_CPU2 94
46#define IRQ_CT_CA9X4_PMU_CPU3 95 46#define IRQ_CT_CA9X4_PMU_CPU3 95
47 47
48extern struct ct_desc ct_ca9x4_desc;
49
48#endif 50#endif
diff --git a/arch/arm/mach-vexpress/include/mach/debug-macro.S b/arch/arm/mach-vexpress/include/mach/debug-macro.S
index 5167e2aceeba..050d65e02a42 100644
--- a/arch/arm/mach-vexpress/include/mach/debug-macro.S
+++ b/arch/arm/mach-vexpress/include/mach/debug-macro.S
@@ -12,12 +12,10 @@
12 12
13#define DEBUG_LL_UART_OFFSET 0x00009000 13#define DEBUG_LL_UART_OFFSET 0x00009000
14 14
15 .macro addruart,rx,tmp 15 .macro addruart,rp,rv
16 mrc p15, 0, \rx, c1, c0 16 mov \rp, #DEBUG_LL_UART_OFFSET
17 tst \rx, #1 @ MMU enabled? 17 orr \rv, \rp, #0xf8000000 @ virtual base
18 moveq \rx, #0x10000000 18 orr \rp, \rp, #0x10000000 @ physical base
19 movne \rx, #0xf8000000 @ virtual base
20 orr \rx, \rx, #DEBUG_LL_UART_OFFSET
21 .endm 19 .endm
22 20
23#include <asm/hardware/debug-pl01x.S> 21#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-vexpress/include/mach/entry-macro.S b/arch/arm/mach-vexpress/include/mach/entry-macro.S
index 20e9fb514f0a..73c11297509e 100644
--- a/arch/arm/mach-vexpress/include/mach/entry-macro.S
+++ b/arch/arm/mach-vexpress/include/mach/entry-macro.S
@@ -1,67 +1,7 @@
1#include <asm/hardware/gic.h> 1#include <asm/hardware/entry-macro-gic.S>
2 2
3 .macro disable_fiq 3 .macro disable_fiq
4 .endm 4 .endm
5 5
6 .macro get_irqnr_preamble, base, tmp
7 ldr \base, =gic_cpu_base_addr
8 ldr \base, [\base]
9 .endm
10
11 .macro arch_ret_to_user, tmp1, tmp2 6 .macro arch_ret_to_user, tmp1, tmp2
12 .endm 7 .endm
13
14 /*
15 * The interrupt numbering scheme is defined in the
16 * interrupt controller spec. To wit:
17 *
18 * Interrupts 0-15 are IPI
19 * 16-28 are reserved
20 * 29-31 are local. We allow 30 to be used for the watchdog.
21 * 32-1020 are global
22 * 1021-1022 are reserved
23 * 1023 is "spurious" (no interrupt)
24 *
25 * For now, we ignore all local interrupts so only return an interrupt if it's
26 * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
27 *
28 * A simple read from the controller will tell us the number of the highest
29 * priority enabled interrupt. We then just need to check whether it is in the
30 * valid range for an IRQ (30-1020 inclusive).
31 */
32
33 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
34 ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
35 ldr \tmp, =1021
36 bic \irqnr, \irqstat, #0x1c00
37 cmp \irqnr, #29
38 cmpcc \irqnr, \irqnr
39 cmpne \irqnr, \tmp
40 cmpcs \irqnr, \irqnr
41 .endm
42
43 /* We assume that irqstat (the raw value of the IRQ acknowledge
44 * register) is preserved from the macro above.
45 * If there is an IPI, we immediately signal end of interrupt on the
46 * controller, since this requires the original irqstat value which
47 * we won't easily be able to recreate later.
48 */
49
50 .macro test_for_ipi, irqnr, irqstat, base, tmp
51 bic \irqnr, \irqstat, #0x1c00
52 cmp \irqnr, #16
53 strcc \irqstat, [\base, #GIC_CPU_EOI]
54 cmpcs \irqnr, \irqnr
55 .endm
56
57 /* As above, this assumes that irqstat and base are preserved.. */
58
59 .macro test_for_ltirq, irqnr, irqstat, base, tmp
60 bic \irqnr, \irqstat, #0x1c00
61 mov \tmp, #0
62 cmp \irqnr, #29
63 moveq \tmp, #1
64 streq \irqstat, [\base, #GIC_CPU_EOI]
65 cmp \tmp, #0
66 .endm
67
diff --git a/arch/arm/mach-vexpress/include/mach/memory.h b/arch/arm/mach-vexpress/include/mach/memory.h
index be28232ae639..5b7fcd439d87 100644
--- a/arch/arm/mach-vexpress/include/mach/memory.h
+++ b/arch/arm/mach-vexpress/include/mach/memory.h
@@ -20,6 +20,6 @@
20#ifndef __ASM_ARCH_MEMORY_H 20#ifndef __ASM_ARCH_MEMORY_H
21#define __ASM_ARCH_MEMORY_H 21#define __ASM_ARCH_MEMORY_H
22 22
23#define PHYS_OFFSET UL(0x60000000) 23#define PLAT_PHYS_OFFSET UL(0x60000000)
24 24
25#endif 25#endif
diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h
index 98a8ded055bf..0a3a37518405 100644
--- a/arch/arm/mach-vexpress/include/mach/motherboard.h
+++ b/arch/arm/mach-vexpress/include/mach/motherboard.h
@@ -118,4 +118,26 @@
118int v2m_cfg_write(u32 devfn, u32 data); 118int v2m_cfg_write(u32 devfn, u32 data);
119int v2m_cfg_read(u32 devfn, u32 *data); 119int v2m_cfg_read(u32 devfn, u32 *data);
120 120
121/*
122 * Core tile IDs
123 */
124#define V2M_CT_ID_CA9 0x0c000191
125#define V2M_CT_ID_UNSUPPORTED 0xff000191
126#define V2M_CT_ID_MASK 0xff000fff
127
128struct ct_desc {
129 u32 id;
130 const char *name;
131 void (*map_io)(void);
132 void (*init_early)(void);
133 void (*init_irq)(void);
134 void (*init_tile)(void);
135#ifdef CONFIG_SMP
136 void (*init_cpu_map)(void);
137 void (*smp_enable)(unsigned int);
138#endif
139};
140
141extern struct ct_desc *ct_desc;
142
121#endif 143#endif
diff --git a/arch/arm/mach-vexpress/include/mach/smp.h b/arch/arm/mach-vexpress/include/mach/smp.h
deleted file mode 100644
index 72a9621ed087..000000000000
--- a/arch/arm/mach-vexpress/include/mach/smp.h
+++ /dev/null
@@ -1,21 +0,0 @@
1#ifndef __MACH_SMP_H
2#define __MACH_SMP_H
3
4#include <asm/hardware/gic.h>
5
6#define hard_smp_processor_id() \
7 ({ \
8 unsigned int cpunum; \
9 __asm__("mrc p15, 0, %0, c0, c0, 5" \
10 : "=r" (cpunum)); \
11 cpunum &= 0x0F; \
12 })
13
14/*
15 * We use IRQ1 as the IPI
16 */
17static inline void smp_cross_call(const struct cpumask *mask)
18{
19 gic_raise_softirq(mask, 1);
20}
21#endif
diff --git a/arch/arm/mach-vexpress/localtimer.c b/arch/arm/mach-vexpress/localtimer.c
deleted file mode 100644
index c0e3a59a0bfc..000000000000
--- a/arch/arm/mach-vexpress/localtimer.c
+++ /dev/null
@@ -1,26 +0,0 @@
1/*
2 * linux/arch/arm/mach-vexpress/localtimer.c
3 *
4 * Copyright (C) 2002 ARM Ltd.
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/init.h>
12#include <linux/smp.h>
13#include <linux/clockchips.h>
14
15#include <asm/smp_twd.h>
16#include <asm/localtimer.h>
17#include <mach/irqs.h>
18
19/*
20 * Setup the local clock events for a CPU.
21 */
22void __cpuinit local_timer_setup(struct clock_event_device *evt)
23{
24 evt->irq = IRQ_LOCALTIMER;
25 twd_timer_setup(evt);
26}
diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
index 670970699ba9..2b5f7ac001a3 100644
--- a/arch/arm/mach-vexpress/platsmp.c
+++ b/arch/arm/mach-vexpress/platsmp.c
@@ -10,107 +10,17 @@
10 */ 10 */
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/errno.h> 12#include <linux/errno.h>
13#include <linux/delay.h>
14#include <linux/device.h>
15#include <linux/jiffies.h>
16#include <linux/smp.h> 13#include <linux/smp.h>
17#include <linux/io.h> 14#include <linux/io.h>
18 15
19#include <asm/cacheflush.h>
20#include <asm/localtimer.h>
21#include <asm/smp_scu.h>
22#include <asm/unified.h> 16#include <asm/unified.h>
23 17
24#include <mach/ct-ca9x4.h>
25#include <mach/motherboard.h> 18#include <mach/motherboard.h>
26#define V2M_PA_CS7 0x10000000 19#define V2M_PA_CS7 0x10000000
27 20
28#include "core.h" 21#include "core.h"
29 22
30extern void vexpress_secondary_startup(void); 23extern void versatile_secondary_startup(void);
31
32/*
33 * control for which core is the next to come out of the secondary
34 * boot "holding pen"
35 */
36volatile int __cpuinitdata pen_release = -1;
37
38static void __iomem *scu_base_addr(void)
39{
40 return MMIO_P2V(A9_MPCORE_SCU);
41}
42
43static DEFINE_SPINLOCK(boot_lock);
44
45void __cpuinit platform_secondary_init(unsigned int cpu)
46{
47 trace_hardirqs_off();
48
49 /*
50 * if any interrupts are already enabled for the primary
51 * core (e.g. timer irq), then they will not have been enabled
52 * for us: do so
53 */
54 gic_cpu_init(0, gic_cpu_base_addr);
55
56 /*
57 * let the primary processor know we're out of the
58 * pen, then head off into the C entry point
59 */
60 pen_release = -1;
61 smp_wmb();
62
63 /*
64 * Synchronise with the boot thread.
65 */
66 spin_lock(&boot_lock);
67 spin_unlock(&boot_lock);
68}
69
70int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
71{
72 unsigned long timeout;
73
74 /*
75 * Set synchronisation state between this boot processor
76 * and the secondary one
77 */
78 spin_lock(&boot_lock);
79
80 /*
81 * This is really belt and braces; we hold unintended secondary
82 * CPUs in the holding pen until we're ready for them. However,
83 * since we haven't sent them a soft interrupt, they shouldn't
84 * be there.
85 */
86 pen_release = cpu;
87 __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
88 outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
89
90 /*
91 * Send the secondary CPU a soft interrupt, thereby causing
92 * the boot monitor to read the system wide flags register,
93 * and branch to the address found there.
94 */
95 smp_cross_call(cpumask_of(cpu));
96
97 timeout = jiffies + (1 * HZ);
98 while (time_before(jiffies, timeout)) {
99 smp_rmb();
100 if (pen_release == -1)
101 break;
102
103 udelay(10);
104 }
105
106 /*
107 * now the secondary core is starting up let it run its
108 * calibrations, then wait for it to finish
109 */
110 spin_unlock(&boot_lock);
111
112 return pen_release != -1 ? -ENOSYS : 0;
113}
114 24
115/* 25/*
116 * Initialise the CPU possible map early - this describes the CPUs 26 * Initialise the CPU possible map early - this describes the CPUs
@@ -118,73 +28,24 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
118 */ 28 */
119void __init smp_init_cpus(void) 29void __init smp_init_cpus(void)
120{ 30{
121 void __iomem *scu_base = scu_base_addr(); 31 ct_desc->init_cpu_map();
122 unsigned int i, ncores;
123
124 ncores = scu_base ? scu_get_core_count(scu_base) : 1;
125
126 /* sanity check */
127 if (ncores == 0) {
128 printk(KERN_ERR
129 "vexpress: strange CM count of 0? Default to 1\n");
130
131 ncores = 1;
132 }
133
134 if (ncores > NR_CPUS) {
135 printk(KERN_WARNING
136 "vexpress: no. of cores (%d) greater than configured "
137 "maximum of %d - clipping\n",
138 ncores, NR_CPUS);
139 ncores = NR_CPUS;
140 }
141
142 for (i = 0; i < ncores; i++)
143 set_cpu_possible(i, true);
144} 32}
145 33
146void __init smp_prepare_cpus(unsigned int max_cpus) 34void __init platform_smp_prepare_cpus(unsigned int max_cpus)
147{ 35{
148 unsigned int ncores = num_possible_cpus();
149 unsigned int cpu = smp_processor_id();
150 int i;
151
152 smp_store_cpu_info(cpu);
153
154 /*
155 * are we trying to boot more cores than exist?
156 */
157 if (max_cpus > ncores)
158 max_cpus = ncores;
159
160 /* 36 /*
161 * Initialise the present map, which describes the set of CPUs 37 * Initialise the present map, which describes the set of CPUs
162 * actually populated at the present time. 38 * actually populated at the present time.
163 */ 39 */
164 for (i = 0; i < max_cpus; i++) 40 ct_desc->smp_enable(max_cpus);
165 set_cpu_present(i, true);
166 41
167 /* 42 /*
168 * Initialise the SCU if there are more than one CPU and let 43 * Write the address of secondary startup into the
169 * them know where to start. 44 * system-wide flags register. The boot monitor waits
45 * until it receives a soft interrupt, and then the
46 * secondary CPU branches to this address.
170 */ 47 */
171 if (max_cpus > 1) { 48 writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR));
172 /* 49 writel(BSYM(virt_to_phys(versatile_secondary_startup)),
173 * Enable the local timer or broadcast device for the 50 MMIO_P2V(V2M_SYS_FLAGSSET));
174 * boot CPU, but only if we have more than one CPU.
175 */
176 percpu_timer_setup();
177
178 scu_enable(scu_base_addr());
179
180 /*
181 * Write the address of secondary startup into the
182 * system-wide flags register. The boot monitor waits
183 * until it receives a soft interrupt, and then the
184 * secondary CPU branches to this address.
185 */
186 writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR));
187 writel(BSYM(virt_to_phys(vexpress_secondary_startup)),
188 MMIO_P2V(V2M_SYS_FLAGSSET));
189 }
190} 51}
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 7eaa232180a5..9e6b93b1a043 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -7,22 +7,27 @@
7#include <linux/io.h> 7#include <linux/io.h>
8#include <linux/init.h> 8#include <linux/init.h>
9#include <linux/platform_device.h> 9#include <linux/platform_device.h>
10#include <linux/ata_platform.h>
10#include <linux/smsc911x.h> 11#include <linux/smsc911x.h>
11#include <linux/spinlock.h> 12#include <linux/spinlock.h>
12#include <linux/sysdev.h> 13#include <linux/sysdev.h>
13#include <linux/usb/isp1760.h> 14#include <linux/usb/isp1760.h>
15#include <linux/clkdev.h>
16#include <linux/mtd/physmap.h>
14 17
15#include <asm/clkdev.h> 18#include <asm/mach-types.h>
16#include <asm/sizes.h> 19#include <asm/sizes.h>
17#include <asm/mach/flash.h> 20#include <asm/mach/arch.h>
18#include <asm/mach/map.h> 21#include <asm/mach/map.h>
19#include <asm/mach/time.h> 22#include <asm/mach/time.h>
20#include <asm/hardware/arm_timer.h> 23#include <asm/hardware/arm_timer.h>
24#include <asm/hardware/timer-sp.h>
25#include <asm/hardware/sp810.h>
21 26
22#include <mach/clkdev.h> 27#include <mach/ct-ca9x4.h>
23#include <mach/motherboard.h> 28#include <mach/motherboard.h>
24 29
25#include <plat/timer-sp.h> 30#include <plat/sched_clock.h>
26 31
27#include "core.h" 32#include "core.h"
28 33
@@ -41,23 +46,25 @@ static struct map_desc v2m_io_desc[] __initdata = {
41 }, 46 },
42}; 47};
43 48
44void __init v2m_map_io(struct map_desc *tile, size_t num) 49static void __init v2m_timer_init(void)
45{ 50{
46 iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); 51 u32 scctrl;
47 iotable_init(tile, num);
48}
49 52
53 /* Select 1MHz TIMCLK as the reference clock for SP804 timers */
54 scctrl = readl(MMIO_P2V(V2M_SYSCTL + SCCTRL));
55 scctrl |= SCCTRL_TIMEREN0SEL_TIMCLK;
56 scctrl |= SCCTRL_TIMEREN1SEL_TIMCLK;
57 writel(scctrl, MMIO_P2V(V2M_SYSCTL + SCCTRL));
50 58
51static void __init v2m_timer_init(void)
52{
53 writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL); 59 writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL);
54 writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL); 60 writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL);
55 61
56 sp804_clocksource_init(MMIO_P2V(V2M_TIMER1)); 62 sp804_clocksource_init(MMIO_P2V(V2M_TIMER1), "v2m-timer1");
57 sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0); 63 sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0,
64 "v2m-timer0");
58} 65}
59 66
60struct sys_timer v2m_timer = { 67static struct sys_timer v2m_timer = {
61 .init = v2m_timer_init, 68 .init = v2m_timer_init,
62}; 69};
63 70
@@ -194,27 +201,13 @@ static struct platform_device v2m_usb_device = {
194 .dev.platform_data = &v2m_usb_config, 201 .dev.platform_data = &v2m_usb_config,
195}; 202};
196 203
197static int v2m_flash_init(void) 204static void v2m_flash_set_vpp(struct platform_device *pdev, int on)
198{
199 writel(0, MMIO_P2V(V2M_SYS_FLASH));
200 return 0;
201}
202
203static void v2m_flash_exit(void)
204{
205 writel(0, MMIO_P2V(V2M_SYS_FLASH));
206}
207
208static void v2m_flash_set_vpp(int on)
209{ 205{
210 writel(on != 0, MMIO_P2V(V2M_SYS_FLASH)); 206 writel(on != 0, MMIO_P2V(V2M_SYS_FLASH));
211} 207}
212 208
213static struct flash_platform_data v2m_flash_data = { 209static struct physmap_flash_data v2m_flash_data = {
214 .map_name = "cfi_probe",
215 .width = 4, 210 .width = 4,
216 .init = v2m_flash_init,
217 .exit = v2m_flash_exit,
218 .set_vpp = v2m_flash_set_vpp, 211 .set_vpp = v2m_flash_set_vpp,
219}; 212};
220 213
@@ -231,13 +224,36 @@ static struct resource v2m_flash_resources[] = {
231}; 224};
232 225
233static struct platform_device v2m_flash_device = { 226static struct platform_device v2m_flash_device = {
234 .name = "armflash", 227 .name = "physmap-flash",
235 .id = -1, 228 .id = -1,
236 .resource = v2m_flash_resources, 229 .resource = v2m_flash_resources,
237 .num_resources = ARRAY_SIZE(v2m_flash_resources), 230 .num_resources = ARRAY_SIZE(v2m_flash_resources),
238 .dev.platform_data = &v2m_flash_data, 231 .dev.platform_data = &v2m_flash_data,
239}; 232};
240 233
234static struct pata_platform_info v2m_pata_data = {
235 .ioport_shift = 2,
236};
237
238static struct resource v2m_pata_resources[] = {
239 {
240 .start = V2M_CF,
241 .end = V2M_CF + 0xff,
242 .flags = IORESOURCE_MEM,
243 }, {
244 .start = V2M_CF + 0x100,
245 .end = V2M_CF + SZ_4K - 1,
246 .flags = IORESOURCE_MEM,
247 },
248};
249
250static struct platform_device v2m_cf_device = {
251 .name = "pata_platform",
252 .id = -1,
253 .resource = v2m_pata_resources,
254 .num_resources = ARRAY_SIZE(v2m_pata_resources),
255 .dev.platform_data = &v2m_pata_data,
256};
241 257
242static unsigned int v2m_mmci_status(struct device *dev) 258static unsigned int v2m_mmci_status(struct device *dev)
243{ 259{
@@ -298,6 +314,10 @@ static struct clk osc2_clk = {
298 .rate = 24000000, 314 .rate = 24000000,
299}; 315};
300 316
317static struct clk v2m_sp804_clk = {
318 .rate = 1000000,
319};
320
301static struct clk dummy_apb_pclk; 321static struct clk dummy_apb_pclk;
302 322
303static struct clk_lookup v2m_lookups[] = { 323static struct clk_lookup v2m_lookups[] = {
@@ -328,9 +348,24 @@ static struct clk_lookup v2m_lookups[] = {
328 }, { /* CLCD */ 348 }, { /* CLCD */
329 .dev_id = "mb:clcd", 349 .dev_id = "mb:clcd",
330 .clk = &osc1_clk, 350 .clk = &osc1_clk,
351 }, { /* SP804 timers */
352 .dev_id = "sp804",
353 .con_id = "v2m-timer0",
354 .clk = &v2m_sp804_clk,
355 }, { /* SP804 timers */
356 .dev_id = "sp804",
357 .con_id = "v2m-timer1",
358 .clk = &v2m_sp804_clk,
331 }, 359 },
332}; 360};
333 361
362static void __init v2m_init_early(void)
363{
364 ct_desc->init_early();
365 clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups));
366 versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
367}
368
334static void v2m_power_off(void) 369static void v2m_power_off(void)
335{ 370{
336 if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0)) 371 if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0))
@@ -343,15 +378,51 @@ static void v2m_restart(char str, const char *cmd)
343 printk(KERN_EMERG "Unable to reboot\n"); 378 printk(KERN_EMERG "Unable to reboot\n");
344} 379}
345 380
346static int __init v2m_init(void) 381struct ct_desc *ct_desc;
382
383static struct ct_desc *ct_descs[] __initdata = {
384#ifdef CONFIG_ARCH_VEXPRESS_CA9X4
385 &ct_ca9x4_desc,
386#endif
387};
388
389static void __init v2m_populate_ct_desc(void)
347{ 390{
348 int i; 391 int i;
392 u32 current_tile_id;
349 393
350 clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups)); 394 ct_desc = NULL;
395 current_tile_id = readl(MMIO_P2V(V2M_SYS_PROCID0)) & V2M_CT_ID_MASK;
396
397 for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i)
398 if (ct_descs[i]->id == current_tile_id)
399 ct_desc = ct_descs[i];
400
401 if (!ct_desc)
402 panic("vexpress: failed to populate core tile description "
403 "for tile ID 0x%8x\n", current_tile_id);
404}
405
406static void __init v2m_map_io(void)
407{
408 iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
409 v2m_populate_ct_desc();
410 ct_desc->map_io();
411}
412
413static void __init v2m_init_irq(void)
414{
415 ct_desc->init_irq();
416}
417
418static void __init v2m_init(void)
419{
420 int i;
351 421
352 platform_device_register(&v2m_pcie_i2c_device); 422 platform_device_register(&v2m_pcie_i2c_device);
353 platform_device_register(&v2m_ddc_i2c_device); 423 platform_device_register(&v2m_ddc_i2c_device);
354 platform_device_register(&v2m_flash_device); 424 platform_device_register(&v2m_flash_device);
425 platform_device_register(&v2m_cf_device);
355 platform_device_register(&v2m_eth_device); 426 platform_device_register(&v2m_eth_device);
356 platform_device_register(&v2m_usb_device); 427 platform_device_register(&v2m_usb_device);
357 428
@@ -361,6 +432,14 @@ static int __init v2m_init(void)
361 pm_power_off = v2m_power_off; 432 pm_power_off = v2m_power_off;
362 arm_pm_restart = v2m_restart; 433 arm_pm_restart = v2m_restart;
363 434
364 return 0; 435 ct_desc->init_tile();
365} 436}
366arch_initcall(v2m_init); 437
438MACHINE_START(VEXPRESS, "ARM-Versatile Express")
439 .boot_params = PLAT_PHYS_OFFSET + 0x00000100,
440 .map_io = v2m_map_io,
441 .init_early = v2m_init_early,
442 .init_irq = v2m_init_irq,
443 .timer = &v2m_timer,
444 .init_machine = v2m_init,
445MACHINE_END