diff options
author | Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> | 2009-11-28 02:17:18 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-11-28 05:22:52 -0500 |
commit | aa44ef4d43b200c0e318ade2a3c24d00a6fd942a (patch) | |
tree | 259b92c5ac721b0d5aa24186fcde9a22572c6a3c | |
parent | c6b503caef9abefb2e90ac83f672b75dc14bacd0 (diff) |
ARM: 5831/1: ARM: U8500 core machine support
Adds core support for the ST-Ericsson U8500
platform. It supports memory mappings, binds to
the existing modules like GIC, SCU, TWD and
local timers and sets up the infrastructure for
the secondary core.
Reviewed-by: Alessandro Rubini <rubini@unipv.it>
Reviewed-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: srinidhi kasagar <srinidhi.kasagar@stericsson.com>
Acked-by: Andrea Gallo <andrea.gallo@stericsson.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/mach-ux500/Kconfig | 15 | ||||
-rw-r--r-- | arch/arm/mach-ux500/Makefile | 8 | ||||
-rw-r--r-- | arch/arm/mach-ux500/board-mop500.c | 158 | ||||
-rw-r--r-- | arch/arm/mach-ux500/cpu-u8500.c | 64 | ||||
-rw-r--r-- | arch/arm/mach-ux500/headsmp.S | 38 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/debug-macro.S | 19 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/entry-macro.S | 89 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/memory.h | 18 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/setup.h | 23 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/smp.h | 32 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/system.h | 25 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/timex.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/uncompress.h | 58 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/vmalloc.h | 18 | ||||
-rw-r--r-- | arch/arm/mach-ux500/localtimer.c | 28 | ||||
-rw-r--r-- | arch/arm/mach-ux500/platsmp.c | 177 |
16 files changed, 776 insertions, 0 deletions
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig new file mode 100644 index 000000000000..03625d744857 --- /dev/null +++ b/arch/arm/mach-ux500/Kconfig | |||
@@ -0,0 +1,15 @@ | |||
1 | menu "ST-Ericsson platform type" | ||
2 | depends on ARCH_U8500 | ||
3 | |||
4 | comment "ST-Ericsson Multicore Mobile Platforms" | ||
5 | |||
6 | config MACH_U8500_MOP | ||
7 | bool "U8500 Early Development platform" | ||
8 | default y | ||
9 | select ARM_GIC | ||
10 | select HAS_MTU | ||
11 | help | ||
12 | Include support for mop500 development platform | ||
13 | based on U8500 architecture. The platform is based | ||
14 | on early drop silicon version of 8500. | ||
15 | endmenu | ||
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile new file mode 100644 index 000000000000..95e6e24c0042 --- /dev/null +++ b/arch/arm/mach-ux500/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel, U8500 machine. | ||
3 | # | ||
4 | |||
5 | obj-y := clock.o | ||
6 | obj-$(CONFIG_ARCH_U8500) += cpu-u8500.o | ||
7 | obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o | ||
8 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o | ||
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c new file mode 100644 index 000000000000..aa5afbcc90f9 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2009 ST-Ericsson | ||
3 | * | ||
4 | * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2, as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/amba/bus.h> | ||
17 | #include <linux/amba/pl022.h> | ||
18 | #include <linux/spi/spi.h> | ||
19 | |||
20 | #include <asm/localtimer.h> | ||
21 | #include <asm/mach-types.h> | ||
22 | #include <asm/mach/arch.h> | ||
23 | |||
24 | #include <plat/mtu.h> | ||
25 | |||
26 | #include <mach/hardware.h> | ||
27 | #include <mach/setup.h> | ||
28 | |||
29 | #define __MEM_4K_RESOURCE(x) \ | ||
30 | .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} | ||
31 | |||
32 | /* These are active devices on this board */ | ||
33 | static struct amba_device uart0_device = { | ||
34 | .dev = { .init_name = "uart0" }, | ||
35 | __MEM_4K_RESOURCE(U8500_UART0_BASE), | ||
36 | .irq = {IRQ_UART0, NO_IRQ}, | ||
37 | }; | ||
38 | |||
39 | static struct amba_device uart1_device = { | ||
40 | .dev = { .init_name = "uart1" }, | ||
41 | __MEM_4K_RESOURCE(U8500_UART1_BASE), | ||
42 | .irq = {IRQ_UART1, NO_IRQ}, | ||
43 | }; | ||
44 | |||
45 | static struct amba_device uart2_device = { | ||
46 | .dev = { .init_name = "uart2" }, | ||
47 | __MEM_4K_RESOURCE(U8500_UART2_BASE), | ||
48 | .irq = {IRQ_UART2, NO_IRQ}, | ||
49 | }; | ||
50 | |||
51 | static void ab4500_spi_cs_control(u32 command) | ||
52 | { | ||
53 | /* set the FRM signal, which is CS - TODO */ | ||
54 | } | ||
55 | |||
56 | struct pl022_config_chip ab4500_chip_info = { | ||
57 | .lbm = LOOPBACK_DISABLED, | ||
58 | .com_mode = INTERRUPT_TRANSFER, | ||
59 | .iface = SSP_INTERFACE_MOTOROLA_SPI, | ||
60 | /* we can act as master only */ | ||
61 | .hierarchy = SSP_MASTER, | ||
62 | .slave_tx_disable = 0, | ||
63 | .endian_rx = SSP_RX_MSB, | ||
64 | .endian_tx = SSP_TX_MSB, | ||
65 | .data_size = SSP_DATA_BITS_24, | ||
66 | .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM, | ||
67 | .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC, | ||
68 | .clk_phase = SSP_CLK_SECOND_EDGE, | ||
69 | .clk_pol = SSP_CLK_POL_IDLE_HIGH, | ||
70 | .cs_control = ab4500_spi_cs_control, | ||
71 | }; | ||
72 | |||
73 | static struct spi_board_info u8500_spi_devices[] = { | ||
74 | { | ||
75 | .modalias = "ab4500", | ||
76 | .controller_data = &ab4500_chip_info, | ||
77 | .max_speed_hz = 12000000, | ||
78 | .bus_num = 0, | ||
79 | .chip_select = 0, | ||
80 | .mode = SPI_MODE_0, | ||
81 | .irq = IRQ_AB4500, | ||
82 | }, | ||
83 | }; | ||
84 | |||
85 | static struct pl022_ssp_controller ssp0_platform_data = { | ||
86 | .bus_id = 0, | ||
87 | /* pl022 not yet supports dma */ | ||
88 | .enable_dma = 0, | ||
89 | /* on this platform, gpio 31,142,144,214 & | ||
90 | * 224 are connected as chip selects | ||
91 | */ | ||
92 | .num_chipselect = 5, | ||
93 | }; | ||
94 | |||
95 | static struct amba_device pl022_device = { | ||
96 | .dev = { | ||
97 | .coherent_dma_mask = ~0, | ||
98 | .init_name = "pl022", | ||
99 | .platform_data = &ssp0_platform_data, | ||
100 | }, | ||
101 | .res = { | ||
102 | .start = U8500_SSP0_BASE, | ||
103 | .end = U8500_SSP0_BASE + SZ_4K - 1, | ||
104 | .flags = IORESOURCE_MEM, | ||
105 | }, | ||
106 | .irq = {IRQ_SSP0, NO_IRQ }, | ||
107 | /* ST-Ericsson modified id */ | ||
108 | .periphid = SSP_PER_ID, | ||
109 | }; | ||
110 | |||
111 | static struct amba_device *amba_devs[] __initdata = { | ||
112 | &uart0_device, | ||
113 | &uart1_device, | ||
114 | &uart2_device, | ||
115 | &pl022_device, | ||
116 | }; | ||
117 | |||
118 | static void __init u8500_timer_init(void) | ||
119 | { | ||
120 | #ifdef CONFIG_LOCAL_TIMERS | ||
121 | /* Setup the local timer base */ | ||
122 | twd_base = __io_address(U8500_TWD_BASE); | ||
123 | #endif | ||
124 | /* Setup the MTU base */ | ||
125 | mtu_base = __io_address(U8500_MTU0_BASE); | ||
126 | |||
127 | nmdk_timer_init(); | ||
128 | } | ||
129 | |||
130 | static struct sys_timer u8500_timer = { | ||
131 | .init = u8500_timer_init, | ||
132 | }; | ||
133 | |||
134 | static void __init u8500_init_machine(void) | ||
135 | { | ||
136 | int i; | ||
137 | |||
138 | /* Register the active AMBA devices on this board */ | ||
139 | for (i = 0; i < ARRAY_SIZE(amba_devs); i++) | ||
140 | amba_device_register(amba_devs[i], &iomem_resource); | ||
141 | |||
142 | spi_register_board_info(u8500_spi_devices, | ||
143 | ARRAY_SIZE(u8500_spi_devices)); | ||
144 | |||
145 | u8500_init_devices(); | ||
146 | } | ||
147 | |||
148 | MACHINE_START(U8500, "ST-Ericsson MOP500 platform") | ||
149 | /* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */ | ||
150 | .phys_io = U8500_UART2_BASE, | ||
151 | .io_pg_offst = (IO_ADDRESS(U8500_UART2_BASE) >> 18) & 0xfffc, | ||
152 | .boot_params = 0x100, | ||
153 | .map_io = u8500_map_io, | ||
154 | .init_irq = u8500_init_irq, | ||
155 | /* we re-use nomadik timer here */ | ||
156 | .timer = &u8500_timer, | ||
157 | .init_machine = u8500_init_machine, | ||
158 | MACHINE_END | ||
diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c new file mode 100644 index 000000000000..5f05e5850f71 --- /dev/null +++ b/arch/arm/mach-ux500/cpu-u8500.c | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2009 ST-Ericsson | ||
3 | * | ||
4 | * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2, as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/amba/bus.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | #include <asm/hardware/gic.h> | ||
19 | #include <asm/mach/map.h> | ||
20 | #include <mach/hardware.h> | ||
21 | |||
22 | /* add any platform devices here - TODO */ | ||
23 | static struct platform_device *platform_devs[] __initdata = { | ||
24 | /* yet to be added, add i2c0, gpio.. */ | ||
25 | }; | ||
26 | |||
27 | #define __IO_DEV_DESC(x, sz) { \ | ||
28 | .virtual = IO_ADDRESS(x), \ | ||
29 | .pfn = __phys_to_pfn(x), \ | ||
30 | .length = sz, \ | ||
31 | .type = MT_DEVICE, \ | ||
32 | } | ||
33 | |||
34 | /* minimum static i/o mapping required to boot U8500 platforms */ | ||
35 | static struct map_desc u8500_io_desc[] __initdata = { | ||
36 | __IO_DEV_DESC(U8500_GIC_CPU_BASE, SZ_4K), | ||
37 | __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K), | ||
38 | __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), | ||
39 | __IO_DEV_DESC(U8500_TWD_BASE, SZ_4K), | ||
40 | __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), | ||
41 | __IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K), | ||
42 | }; | ||
43 | |||
44 | void __init u8500_map_io(void) | ||
45 | { | ||
46 | iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); | ||
47 | } | ||
48 | |||
49 | void __init u8500_init_irq(void) | ||
50 | { | ||
51 | gic_dist_init(0, __io_address(U8500_GIC_DIST_BASE), 29); | ||
52 | gic_cpu_init(0, __io_address(U8500_GIC_CPU_BASE)); | ||
53 | } | ||
54 | |||
55 | /* | ||
56 | * This function is called from the board init | ||
57 | */ | ||
58 | void __init u8500_init_devices(void) | ||
59 | { | ||
60 | /* Register the platform devices */ | ||
61 | platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); | ||
62 | |||
63 | return ; | ||
64 | } | ||
diff --git a/arch/arm/mach-ux500/headsmp.S b/arch/arm/mach-ux500/headsmp.S new file mode 100644 index 000000000000..a6be2cdf2b2f --- /dev/null +++ b/arch/arm/mach-ux500/headsmp.S | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2009 ST-Ericsson | ||
3 | * This file is based ARM Realview platform | ||
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 | * U8500 specific entry point for secondary CPUs. | ||
18 | */ | ||
19 | ENTRY(u8500_secondary_startup) | ||
20 | mrc p15, 0, r0, c0, c0, 5 | ||
21 | and r0, r0, #15 | ||
22 | adr r4, 1f | ||
23 | ldmia r4, {r5, r6} | ||
24 | sub r4, r4, r5 | ||
25 | add r6, r6, r4 | ||
26 | dsb | ||
27 | pen: ldr r7, [r6] | ||
28 | cmp r7, r0 | ||
29 | bne pen | ||
30 | |||
31 | /* | ||
32 | * we've been released from the holding pen: secondary_stack | ||
33 | * should now contain the SVC stack for this core | ||
34 | */ | ||
35 | b secondary_startup | ||
36 | |||
37 | 1: .long . | ||
38 | .long pen_release | ||
diff --git a/arch/arm/mach-ux500/include/mach/debug-macro.S b/arch/arm/mach-ux500/include/mach/debug-macro.S new file mode 100644 index 000000000000..8f21b6a95dce --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/debug-macro.S | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * Debugging macro include header | ||
3 | * | ||
4 | * Copyright (C) 2009 ST-Ericsson | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | .macro addruart,rx | ||
12 | mrc p15, 0, \rx, c1, c0 | ||
13 | tst \rx, #1 @MMU enabled? | ||
14 | moveq \rx, #0x80000000 @MMU off, Physical address | ||
15 | movne \rx, #0xF0000000 @MMU on, Virtual address | ||
16 | orr \rx, \rx, #0x7000 | ||
17 | .endm | ||
18 | |||
19 | #include <asm/hardware/debug-pl01x.S> | ||
diff --git a/arch/arm/mach-ux500/include/mach/entry-macro.S b/arch/arm/mach-ux500/include/mach/entry-macro.S new file mode 100644 index 000000000000..eece3301fef7 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/entry-macro.S | |||
@@ -0,0 +1,89 @@ | |||
1 | /* | ||
2 | * Low-level IRQ helper macros for U8500 platforms | ||
3 | * | ||
4 | * Copyright (C) 2009 ST-Ericsson. | ||
5 | * | ||
6 | * This file is a copy of ARM Realview platform. | ||
7 | * -just satisfied checkpatch script. | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public | ||
10 | * License version 2. This program is licensed "as is" without any | ||
11 | * warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | #include <mach/hardware.h> | ||
14 | #include <asm/hardware/gic.h> | ||
15 | |||
16 | .macro disable_fiq | ||
17 | .endm | ||
18 | |||
19 | .macro get_irqnr_preamble, base, tmp | ||
20 | ldr \base, =IO_ADDRESS(U8500_GIC_CPU_BASE) | ||
21 | .endm | ||
22 | |||
23 | .macro arch_ret_to_user, tmp1, tmp2 | ||
24 | .endm | ||
25 | |||
26 | /* | ||
27 | * The interrupt numbering scheme is defined in the | ||
28 | * interrupt controller spec. To wit: | ||
29 | * | ||
30 | * Interrupts 0-15 are IPI | ||
31 | * 16-28 are reserved | ||
32 | * 29-31 are local. We allow 30 to be used for the watchdog. | ||
33 | * 32-1020 are global | ||
34 | * 1021-1022 are reserved | ||
35 | * 1023 is "spurious" (no interrupt) | ||
36 | * | ||
37 | * For now, we ignore all local interrupts so only return an | ||
38 | * interrupt if it's between 30 and 1020. The test_for_ipi | ||
39 | * routine below will pick up on IPIs. | ||
40 | * | ||
41 | * A simple read from the controller will tell us the number | ||
42 | * of the highest priority enabled interrupt. We then just | ||
43 | * need to check whether it is in the valid range for an | ||
44 | * IRQ (30-1020 inclusive). | ||
45 | */ | ||
46 | |||
47 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
48 | |||
49 | /* bits 12-10 = src CPU, 9-0 = int # */ | ||
50 | ldr \irqstat, [\base, #GIC_CPU_INTACK] | ||
51 | |||
52 | ldr \tmp, =1021 | ||
53 | |||
54 | bic \irqnr, \irqstat, #0x1c00 | ||
55 | |||
56 | cmp \irqnr, #29 | ||
57 | cmpcc \irqnr, \irqnr | ||
58 | cmpne \irqnr, \tmp | ||
59 | cmpcs \irqnr, \irqnr | ||
60 | |||
61 | .endm | ||
62 | |||
63 | /* We assume that irqstat (the raw value of the IRQ | ||
64 | * acknowledge register) is preserved from the macro above. | ||
65 | * If there is an IPI, we immediately signal end of | ||
66 | * interrupt on the controller, since this requires the | ||
67 | * original irqstat value which we won't easily be able | ||
68 | * to recreate later. | ||
69 | */ | ||
70 | |||
71 | .macro test_for_ipi, irqnr, irqstat, base, tmp | ||
72 | bic \irqnr, \irqstat, #0x1c00 | ||
73 | cmp \irqnr, #16 | ||
74 | strcc \irqstat, [\base, #GIC_CPU_EOI] | ||
75 | cmpcs \irqnr, \irqnr | ||
76 | .endm | ||
77 | |||
78 | /* As above, this assumes that irqstat and base | ||
79 | * are preserved.. | ||
80 | */ | ||
81 | |||
82 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
83 | bic \irqnr, \irqstat, #0x1c00 | ||
84 | mov \tmp, #0 | ||
85 | cmp \irqnr, #29 | ||
86 | moveq \tmp, #1 | ||
87 | streq \irqstat, [\base, #GIC_CPU_EOI] | ||
88 | cmp \tmp, #0 | ||
89 | .endm | ||
diff --git a/arch/arm/mach-ux500/include/mach/memory.h b/arch/arm/mach-ux500/include/mach/memory.h new file mode 100644 index 000000000000..510571a59e25 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/memory.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 ST-Ericsson | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | */ | ||
9 | #ifndef __ASM_ARCH_MEMORY_H | ||
10 | #define __ASM_ARCH_MEMORY_H | ||
11 | |||
12 | /* | ||
13 | * Physical DRAM offset. | ||
14 | */ | ||
15 | #define PHYS_OFFSET UL(0x00000000) | ||
16 | #define BUS_OFFSET UL(0x00000000) | ||
17 | |||
18 | #endif | ||
diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h new file mode 100644 index 000000000000..cf0ce1687f24 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/setup.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 ST-Ericsson. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * These symbols are needed for board-specific files to call their | ||
9 | * own cpu-specific files | ||
10 | */ | ||
11 | #ifndef __ASM_ARCH_SETUP_H | ||
12 | #define __ASM_ARCH_SETUP_H | ||
13 | |||
14 | #include <asm/mach/time.h> | ||
15 | #include <linux/init.h> | ||
16 | |||
17 | extern void u8500_map_io(void); | ||
18 | extern void u8500_init_devices(void); | ||
19 | extern void u8500_init_irq(void); | ||
20 | /* We re-use nomadik_timer for this platform */ | ||
21 | extern void nmdk_timer_init(void); | ||
22 | |||
23 | #endif /* __ASM_ARCH_SETUP_H */ | ||
diff --git a/arch/arm/mach-ux500/include/mach/smp.h b/arch/arm/mach-ux500/include/mach/smp.h new file mode 100644 index 000000000000..b59f7bc9725d --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/smp.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * This file is based ARM realview platform. | ||
3 | * Copyright (C) ARM Limited. | ||
4 | * | ||
5 | * This file is licensed under the terms of the GNU General Public | ||
6 | * License version 2. This program is licensed "as is" without any | ||
7 | * warranty of any kind, whether express or implied. | ||
8 | */ | ||
9 | #ifndef ASMARM_ARCH_SMP_H | ||
10 | #define ASMARM_ARCH_SMP_H | ||
11 | |||
12 | #include <asm/hardware/gic.h> | ||
13 | |||
14 | /* This is required to wakeup the secondary core */ | ||
15 | extern void u8500_secondary_startup(void); | ||
16 | |||
17 | #define hard_smp_processor_id() \ | ||
18 | ({ \ | ||
19 | unsigned int cpunum; \ | ||
20 | __asm__("mrc p15, 0, %0, c0, c0, 5" \ | ||
21 | : "=r" (cpunum)); \ | ||
22 | cpunum &= 0x0F; \ | ||
23 | }) | ||
24 | |||
25 | /* | ||
26 | * We use IRQ1 as the IPI | ||
27 | */ | ||
28 | static inline void smp_cross_call(const struct cpumask *mask) | ||
29 | { | ||
30 | gic_raise_softirq(mask, 1); | ||
31 | } | ||
32 | #endif | ||
diff --git a/arch/arm/mach-ux500/include/mach/system.h b/arch/arm/mach-ux500/include/mach/system.h new file mode 100644 index 000000000000..c0cd8006f1a2 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/system.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 ST-Ericsson. | ||
3 | * | ||
4 | * This file is licensed under the terms of the GNU General Public | ||
5 | * License version 2. This program is licensed "as is" without any | ||
6 | * warranty of any kind, whether express or implied. | ||
7 | */ | ||
8 | #ifndef __ASM_ARCH_SYSTEM_H | ||
9 | #define __ASM_ARCH_SYSTEM_H | ||
10 | |||
11 | static inline void arch_idle(void) | ||
12 | { | ||
13 | /* | ||
14 | * This should do all the clock switching | ||
15 | * and wait for interrupt tricks | ||
16 | */ | ||
17 | cpu_do_idle(); | ||
18 | } | ||
19 | |||
20 | static inline void arch_reset(char mode, const char *cmd) | ||
21 | { | ||
22 | /* yet to be implemented - TODO */ | ||
23 | } | ||
24 | |||
25 | #endif | ||
diff --git a/arch/arm/mach-ux500/include/mach/timex.h b/arch/arm/mach-ux500/include/mach/timex.h new file mode 100644 index 000000000000..d0942c174018 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/timex.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_ARCH_TIMEX_H | ||
2 | #define __ASM_ARCH_TIMEX_H | ||
3 | |||
4 | #define CLOCK_TICK_RATE 110000000 | ||
5 | |||
6 | #endif | ||
diff --git a/arch/arm/mach-ux500/include/mach/uncompress.h b/arch/arm/mach-ux500/include/mach/uncompress.h new file mode 100644 index 000000000000..8552eb188b50 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/uncompress.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 ST-Ericsson | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | #ifndef __ASM_ARCH_UNCOMPRESS_H | ||
19 | #define __ASM_ARCH_UNCOMPRESS_H | ||
20 | |||
21 | #include <asm/setup.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <mach/hardware.h> | ||
24 | |||
25 | #define U8500_UART_DR 0x80007000 | ||
26 | #define U8500_UART_LCRH 0x8000702c | ||
27 | #define U8500_UART_CR 0x80007030 | ||
28 | #define U8500_UART_FR 0x80007018 | ||
29 | |||
30 | static void putc(const char c) | ||
31 | { | ||
32 | /* Do nothing if the UART is not enabled. */ | ||
33 | if (!(readb(U8500_UART_CR) & 0x1)) | ||
34 | return; | ||
35 | |||
36 | if (c == '\n') | ||
37 | putc('\r'); | ||
38 | |||
39 | while (readb(U8500_UART_FR) & (1 << 5)) | ||
40 | barrier(); | ||
41 | writeb(c, U8500_UART_DR); | ||
42 | } | ||
43 | |||
44 | static void flush(void) | ||
45 | { | ||
46 | if (!(readb(U8500_UART_CR) & 0x1)) | ||
47 | return; | ||
48 | while (readb(U8500_UART_FR) & (1 << 3)) | ||
49 | barrier(); | ||
50 | } | ||
51 | |||
52 | static inline void arch_decomp_setup(void) | ||
53 | { | ||
54 | } | ||
55 | |||
56 | #define arch_decomp_wdog() /* nothing to do here */ | ||
57 | |||
58 | #endif /* __ASM_ARCH_UNCOMPRESS_H */ | ||
diff --git a/arch/arm/mach-ux500/include/mach/vmalloc.h b/arch/arm/mach-ux500/include/mach/vmalloc.h new file mode 100644 index 000000000000..86cdbbce1842 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/vmalloc.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 ST-Ericsson | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | #define VMALLOC_END 0xf0000000 | ||
diff --git a/arch/arm/mach-ux500/localtimer.c b/arch/arm/mach-ux500/localtimer.c new file mode 100644 index 000000000000..2288f6a7c518 --- /dev/null +++ b/arch/arm/mach-ux500/localtimer.c | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2009 ST-Ericsson | ||
3 | * Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> | ||
4 | * | ||
5 | * This file is heavily based on relaview platform, almost a copy. | ||
6 | * | ||
7 | * Copyright (C) 2002 ARM Ltd. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/smp.h> | ||
15 | #include <linux/clockchips.h> | ||
16 | |||
17 | #include <asm/irq.h> | ||
18 | #include <asm/smp_twd.h> | ||
19 | #include <asm/localtimer.h> | ||
20 | |||
21 | /* | ||
22 | * Setup the local clock events for a CPU. | ||
23 | */ | ||
24 | void __cpuinit local_timer_setup(struct clock_event_device *evt) | ||
25 | { | ||
26 | evt->irq = IRQ_LOCALTIMER; | ||
27 | twd_timer_setup(evt); | ||
28 | } | ||
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c new file mode 100644 index 000000000000..8dfe7ca245d8 --- /dev/null +++ b/arch/arm/mach-ux500/platsmp.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 ARM Ltd. | ||
3 | * Copyright (C) 2008 STMicroelctronics. | ||
4 | * Copyright (C) 2009 ST-Ericsson. | ||
5 | * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> | ||
6 | * | ||
7 | * This file is based on arm realview platform | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/smp.h> | ||
18 | #include <linux/io.h> | ||
19 | |||
20 | #include <asm/cacheflush.h> | ||
21 | #include <asm/localtimer.h> | ||
22 | #include <asm/smp_scu.h> | ||
23 | #include <mach/hardware.h> | ||
24 | |||
25 | /* | ||
26 | * control for which core is the next to come out of the secondary | ||
27 | * boot "holding pen" | ||
28 | */ | ||
29 | volatile int __cpuinitdata pen_release = -1; | ||
30 | |||
31 | static unsigned int __init get_core_count(void) | ||
32 | { | ||
33 | return scu_get_core_count(__io_address(U8500_SCU_BASE)); | ||
34 | } | ||
35 | |||
36 | static DEFINE_SPINLOCK(boot_lock); | ||
37 | |||
38 | void __cpuinit platform_secondary_init(unsigned int cpu) | ||
39 | { | ||
40 | trace_hardirqs_off(); | ||
41 | |||
42 | /* | ||
43 | * if any interrupts are already enabled for the primary | ||
44 | * core (e.g. timer irq), then they will not have been enabled | ||
45 | * for us: do so | ||
46 | */ | ||
47 | gic_cpu_init(0, __io_address(U8500_GIC_CPU_BASE)); | ||
48 | |||
49 | /* | ||
50 | * let the primary processor know we're out of the | ||
51 | * pen, then head off into the C entry point | ||
52 | */ | ||
53 | pen_release = -1; | ||
54 | |||
55 | /* | ||
56 | * Synchronise with the boot thread. | ||
57 | */ | ||
58 | spin_lock(&boot_lock); | ||
59 | spin_unlock(&boot_lock); | ||
60 | } | ||
61 | |||
62 | int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | ||
63 | { | ||
64 | unsigned long timeout; | ||
65 | |||
66 | /* | ||
67 | * set synchronisation state between this boot processor | ||
68 | * and the secondary one | ||
69 | */ | ||
70 | spin_lock(&boot_lock); | ||
71 | |||
72 | /* | ||
73 | * The secondary processor is waiting to be released from | ||
74 | * the holding pen - release it, then wait for it to flag | ||
75 | * that it has been released by resetting pen_release. | ||
76 | */ | ||
77 | pen_release = cpu; | ||
78 | flush_cache_all(); | ||
79 | |||
80 | timeout = jiffies + (1 * HZ); | ||
81 | while (time_before(jiffies, timeout)) { | ||
82 | if (pen_release == -1) | ||
83 | break; | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * now the secondary core is starting up let it run its | ||
88 | * calibrations, then wait for it to finish | ||
89 | */ | ||
90 | spin_unlock(&boot_lock); | ||
91 | |||
92 | return pen_release != -1 ? -ENOSYS : 0; | ||
93 | } | ||
94 | |||
95 | static void __init wakeup_secondary(void) | ||
96 | { | ||
97 | /* nobody is to be released from the pen yet */ | ||
98 | pen_release = -1; | ||
99 | |||
100 | /* | ||
101 | * write the address of secondary startup into the backup ram register | ||
102 | * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the | ||
103 | * backup ram register at offset 0x1FF0, which is what boot rom code | ||
104 | * is waiting for. This would wake up the secondary core from WFE | ||
105 | */ | ||
106 | #define U8500_CPU1_JUMPADDR_OFFSET 0x1FF4 | ||
107 | __raw_writel(virt_to_phys(u8500_secondary_startup), | ||
108 | (void __iomem *)IO_ADDRESS(U8500_BACKUPRAM0_BASE) + | ||
109 | U8500_CPU1_JUMPADDR_OFFSET); | ||
110 | |||
111 | #define U8500_CPU1_WAKEMAGIC_OFFSET 0x1FF0 | ||
112 | __raw_writel(0xA1FEED01, | ||
113 | (void __iomem *)IO_ADDRESS(U8500_BACKUPRAM0_BASE) + | ||
114 | U8500_CPU1_WAKEMAGIC_OFFSET); | ||
115 | |||
116 | /* make sure write buffer is drained */ | ||
117 | mb(); | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * Initialise the CPU possible map early - this describes the CPUs | ||
122 | * which may be present or become present in the system. | ||
123 | */ | ||
124 | void __init smp_init_cpus(void) | ||
125 | { | ||
126 | unsigned int i, ncores = get_core_count(); | ||
127 | |||
128 | for (i = 0; i < ncores; i++) | ||
129 | set_cpu_possible(i, true); | ||
130 | } | ||
131 | |||
132 | void __init smp_prepare_cpus(unsigned int max_cpus) | ||
133 | { | ||
134 | unsigned int ncores = get_core_count(); | ||
135 | unsigned int cpu = smp_processor_id(); | ||
136 | int i; | ||
137 | |||
138 | /* sanity check */ | ||
139 | if (ncores == 0) { | ||
140 | printk(KERN_ERR | ||
141 | "U8500: strange CM count of 0? Default to 1\n"); | ||
142 | ncores = 1; | ||
143 | } | ||
144 | |||
145 | if (ncores > num_possible_cpus()) { | ||
146 | printk(KERN_WARNING | ||
147 | "U8500: no. of cores (%d) greater than configured " | ||
148 | "maximum of %d - clipping\n", | ||
149 | ncores, num_possible_cpus()); | ||
150 | ncores = num_possible_cpus(); | ||
151 | } | ||
152 | |||
153 | smp_store_cpu_info(cpu); | ||
154 | |||
155 | /* | ||
156 | * are we trying to boot more cores than exist? | ||
157 | */ | ||
158 | if (max_cpus > ncores) | ||
159 | max_cpus = ncores; | ||
160 | |||
161 | /* | ||
162 | * Initialise the present map, which describes the set of CPUs | ||
163 | * actually populated at the present time. | ||
164 | */ | ||
165 | for (i = 0; i < max_cpus; i++) | ||
166 | set_cpu_present(i, true); | ||
167 | |||
168 | if (max_cpus > 1) { | ||
169 | /* | ||
170 | * Enable the local timer or broadcast device for the | ||
171 | * boot CPU, but only if we have more than one CPU. | ||
172 | */ | ||
173 | percpu_timer_setup(); | ||
174 | scu_enable(__io_address(U8500_SCU_BASE)); | ||
175 | wakeup_secondary(); | ||
176 | } | ||
177 | } | ||