diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/boot/dts/bcm11351.dtsi | 5 | ||||
-rw-r--r-- | arch/arm/common/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/common/firmware.c | 18 | ||||
-rw-r--r-- | arch/arm/include/asm/firmware.h | 66 | ||||
-rw-r--r-- | arch/arm/mach-bcm/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/mach-bcm/bcm_kona_smc.c | 118 | ||||
-rw-r--r-- | arch/arm/mach-bcm/bcm_kona_smc.h | 80 | ||||
-rw-r--r-- | arch/arm/mach-bcm/bcm_kona_smc_asm.S | 41 | ||||
-rw-r--r-- | arch/arm/mach-bcm/board_bcm.c | 23 | ||||
-rw-r--r-- | arch/arm/mach-exynos/Makefile | 6 | ||||
-rw-r--r-- | arch/arm/mach-exynos/common.c | 35 | ||||
-rw-r--r-- | arch/arm/mach-exynos/common.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-exynos/exynos-smc.S | 22 | ||||
-rw-r--r-- | arch/arm/mach-exynos/firmware.c | 70 | ||||
-rw-r--r-- | arch/arm/mach-exynos/include/mach/map.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-exynos/mach-exynos4-dt.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-exynos/platsmp.c | 32 | ||||
-rw-r--r-- | arch/arm/mach-exynos/smc.h | 31 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/map-s5p.h | 1 |
19 files changed, 554 insertions, 6 deletions
diff --git a/arch/arm/boot/dts/bcm11351.dtsi b/arch/arm/boot/dts/bcm11351.dtsi index 8f71f40722b9..41b2c6c33f09 100644 --- a/arch/arm/boot/dts/bcm11351.dtsi +++ b/arch/arm/boot/dts/bcm11351.dtsi | |||
@@ -31,6 +31,11 @@ | |||
31 | <0x3ff00100 0x100>; | 31 | <0x3ff00100 0x100>; |
32 | }; | 32 | }; |
33 | 33 | ||
34 | smc@0x3404c000 { | ||
35 | compatible = "bcm,bcm11351-smc", "bcm,kona-smc"; | ||
36 | reg = <0x3404c000 0x400>; //1 KiB in SRAM | ||
37 | }; | ||
38 | |||
34 | uart@3e000000 { | 39 | uart@3e000000 { |
35 | compatible = "bcm,bcm11351-dw-apb-uart", "snps,dw-apb-uart"; | 40 | compatible = "bcm,bcm11351-dw-apb-uart", "snps,dw-apb-uart"; |
36 | status = "disabled"; | 41 | status = "disabled"; |
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 53e68b163196..48434cbe3e89 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile | |||
@@ -2,6 +2,8 @@ | |||
2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += firmware.o | ||
6 | |||
5 | obj-$(CONFIG_ICST) += icst.o | 7 | obj-$(CONFIG_ICST) += icst.o |
6 | obj-$(CONFIG_SA1111) += sa1111.o | 8 | obj-$(CONFIG_SA1111) += sa1111.o |
7 | obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o | 9 | obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o |
diff --git a/arch/arm/common/firmware.c b/arch/arm/common/firmware.c new file mode 100644 index 000000000000..27ddccb1131f --- /dev/null +++ b/arch/arm/common/firmware.c | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Samsung Electronics. | ||
3 | * Kyungmin Park <kyungmin.park@samsung.com> | ||
4 | * Tomasz Figa <t.figa@samsung.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/suspend.h> | ||
13 | |||
14 | #include <asm/firmware.h> | ||
15 | |||
16 | static const struct firmware_ops default_firmware_ops; | ||
17 | |||
18 | const struct firmware_ops *firmware_ops = &default_firmware_ops; | ||
diff --git a/arch/arm/include/asm/firmware.h b/arch/arm/include/asm/firmware.h new file mode 100644 index 000000000000..15631300c238 --- /dev/null +++ b/arch/arm/include/asm/firmware.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Samsung Electronics. | ||
3 | * Kyungmin Park <kyungmin.park@samsung.com> | ||
4 | * Tomasz Figa <t.figa@samsung.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __ASM_ARM_FIRMWARE_H | ||
12 | #define __ASM_ARM_FIRMWARE_H | ||
13 | |||
14 | #include <linux/bug.h> | ||
15 | |||
16 | /* | ||
17 | * struct firmware_ops | ||
18 | * | ||
19 | * A structure to specify available firmware operations. | ||
20 | * | ||
21 | * A filled up structure can be registered with register_firmware_ops(). | ||
22 | */ | ||
23 | struct firmware_ops { | ||
24 | /* | ||
25 | * Enters CPU idle mode | ||
26 | */ | ||
27 | int (*do_idle)(void); | ||
28 | /* | ||
29 | * Sets boot address of specified physical CPU | ||
30 | */ | ||
31 | int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr); | ||
32 | /* | ||
33 | * Boots specified physical CPU | ||
34 | */ | ||
35 | int (*cpu_boot)(int cpu); | ||
36 | /* | ||
37 | * Initializes L2 cache | ||
38 | */ | ||
39 | int (*l2x0_init)(void); | ||
40 | }; | ||
41 | |||
42 | /* Global pointer for current firmware_ops structure, can't be NULL. */ | ||
43 | extern const struct firmware_ops *firmware_ops; | ||
44 | |||
45 | /* | ||
46 | * call_firmware_op(op, ...) | ||
47 | * | ||
48 | * Checks if firmware operation is present and calls it, | ||
49 | * otherwise returns -ENOSYS | ||
50 | */ | ||
51 | #define call_firmware_op(op, ...) \ | ||
52 | ((firmware_ops->op) ? firmware_ops->op(__VA_ARGS__) : (-ENOSYS)) | ||
53 | |||
54 | /* | ||
55 | * register_firmware_ops(ops) | ||
56 | * | ||
57 | * A function to register platform firmware_ops struct. | ||
58 | */ | ||
59 | static inline void register_firmware_ops(const struct firmware_ops *ops) | ||
60 | { | ||
61 | BUG_ON(!ops); | ||
62 | |||
63 | firmware_ops = ops; | ||
64 | } | ||
65 | |||
66 | #endif | ||
diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile index bbf412261e5e..6adb6aecf48f 100644 --- a/arch/arm/mach-bcm/Makefile +++ b/arch/arm/mach-bcm/Makefile | |||
@@ -10,4 +10,6 @@ | |||
10 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 10 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | # GNU General Public License for more details. | 11 | # GNU General Public License for more details. |
12 | 12 | ||
13 | obj-$(CONFIG_ARCH_BCM) := board_bcm.o | 13 | obj-$(CONFIG_ARCH_BCM) := board_bcm.o bcm_kona_smc.o bcm_kona_smc_asm.o |
14 | plus_sec := $(call as-instr,.arch_extension sec,+sec) | ||
15 | AFLAGS_bcm_kona_smc_asm.o :=-Wa,-march=armv7-a$(plus_sec) | ||
diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c new file mode 100644 index 000000000000..56d9d19b2470 --- /dev/null +++ b/arch/arm/mach-bcm/bcm_kona_smc.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation version 2. | ||
7 | * | ||
8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
9 | * kind, whether express or implied; without even the implied warranty | ||
10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #include <stdarg.h> | ||
15 | #include <linux/smp.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/ioport.h> | ||
18 | |||
19 | #include <asm/cacheflush.h> | ||
20 | #include <linux/of_address.h> | ||
21 | |||
22 | #include "bcm_kona_smc.h" | ||
23 | |||
24 | struct secure_bridge_data { | ||
25 | void __iomem *bounce; /* virtual address */ | ||
26 | u32 __iomem buffer_addr; /* physical address */ | ||
27 | int initialized; | ||
28 | } bridge_data; | ||
29 | |||
30 | struct bcm_kona_smc_data { | ||
31 | unsigned service_id; | ||
32 | unsigned arg0; | ||
33 | unsigned arg1; | ||
34 | unsigned arg2; | ||
35 | unsigned arg3; | ||
36 | }; | ||
37 | |||
38 | static const struct of_device_id bcm_kona_smc_ids[] __initconst = { | ||
39 | {.compatible = "bcm,kona-smc"}, | ||
40 | {}, | ||
41 | }; | ||
42 | |||
43 | /* Map in the bounce area */ | ||
44 | void __init bcm_kona_smc_init(void) | ||
45 | { | ||
46 | struct device_node *node; | ||
47 | |||
48 | /* Read buffer addr and size from the device tree node */ | ||
49 | node = of_find_matching_node(NULL, bcm_kona_smc_ids); | ||
50 | BUG_ON(!node); | ||
51 | |||
52 | /* Don't care about size or flags of the DT node */ | ||
53 | bridge_data.buffer_addr = | ||
54 | be32_to_cpu(*of_get_address(node, 0, NULL, NULL)); | ||
55 | BUG_ON(!bridge_data.buffer_addr); | ||
56 | |||
57 | bridge_data.bounce = of_iomap(node, 0); | ||
58 | BUG_ON(!bridge_data.bounce); | ||
59 | |||
60 | bridge_data.initialized = 1; | ||
61 | |||
62 | pr_info("Secure API initialized!\n"); | ||
63 | } | ||
64 | |||
65 | /* __bcm_kona_smc() should only run on CPU 0, with pre-emption disabled */ | ||
66 | static void __bcm_kona_smc(void *info) | ||
67 | { | ||
68 | struct bcm_kona_smc_data *data = info; | ||
69 | u32 *args = bridge_data.bounce; | ||
70 | int rc = 0; | ||
71 | |||
72 | /* Must run on CPU 0 */ | ||
73 | BUG_ON(smp_processor_id() != 0); | ||
74 | |||
75 | /* Check map in the bounce area */ | ||
76 | BUG_ON(!bridge_data.initialized); | ||
77 | |||
78 | /* Copy one 32 bit word into the bounce area */ | ||
79 | args[0] = data->arg0; | ||
80 | args[1] = data->arg1; | ||
81 | args[2] = data->arg2; | ||
82 | args[3] = data->arg3; | ||
83 | |||
84 | /* Flush caches for input data passed to Secure Monitor */ | ||
85 | if (data->service_id != SSAPI_BRCM_START_VC_CORE) | ||
86 | flush_cache_all(); | ||
87 | |||
88 | /* Trap into Secure Monitor */ | ||
89 | rc = bcm_kona_smc_asm(data->service_id, bridge_data.buffer_addr); | ||
90 | |||
91 | if (rc != SEC_ROM_RET_OK) | ||
92 | pr_err("Secure Monitor call failed (0x%x)!\n", rc); | ||
93 | } | ||
94 | |||
95 | unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, | ||
96 | unsigned arg2, unsigned arg3) | ||
97 | { | ||
98 | struct bcm_kona_smc_data data; | ||
99 | |||
100 | data.service_id = service_id; | ||
101 | data.arg0 = arg0; | ||
102 | data.arg1 = arg1; | ||
103 | data.arg2 = arg2; | ||
104 | data.arg3 = arg3; | ||
105 | |||
106 | /* | ||
107 | * Due to a limitation of the secure monitor, we must use the SMP | ||
108 | * infrastructure to forward all secure monitor calls to Core 0. | ||
109 | */ | ||
110 | if (get_cpu() != 0) | ||
111 | smp_call_function_single(0, __bcm_kona_smc, (void *)&data, 1); | ||
112 | else | ||
113 | __bcm_kona_smc(&data); | ||
114 | |||
115 | put_cpu(); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
diff --git a/arch/arm/mach-bcm/bcm_kona_smc.h b/arch/arm/mach-bcm/bcm_kona_smc.h new file mode 100644 index 000000000000..3bedbed1c21b --- /dev/null +++ b/arch/arm/mach-bcm/bcm_kona_smc.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation version 2. | ||
7 | * | ||
8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
9 | * kind, whether express or implied; without even the implied warranty | ||
10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #ifndef BCM_KONA_SMC_H | ||
15 | #define BCM_KONA_SMC_H | ||
16 | |||
17 | #include <linux/types.h> | ||
18 | #define FLAGS (SEC_ROM_ICACHE_ENABLE_MASK | SEC_ROM_DCACHE_ENABLE_MASK | \ | ||
19 | SEC_ROM_IRQ_ENABLE_MASK | SEC_ROM_FIQ_ENABLE_MASK) | ||
20 | |||
21 | /*! | ||
22 | * Definitions for IRQ & FIQ Mask for ARM | ||
23 | */ | ||
24 | |||
25 | #define FIQ_IRQ_MASK 0xC0 | ||
26 | #define FIQ_MASK 0x40 | ||
27 | #define IRQ_MASK 0x80 | ||
28 | |||
29 | /*! | ||
30 | * Secure Mode FLAGs | ||
31 | */ | ||
32 | |||
33 | /* When set, enables ICache within the secure mode */ | ||
34 | #define SEC_ROM_ICACHE_ENABLE_MASK 0x00000001 | ||
35 | |||
36 | /* When set, enables DCache within the secure mode */ | ||
37 | #define SEC_ROM_DCACHE_ENABLE_MASK 0x00000002 | ||
38 | |||
39 | /* When set, enables IRQ within the secure mode */ | ||
40 | #define SEC_ROM_IRQ_ENABLE_MASK 0x00000004 | ||
41 | |||
42 | /* When set, enables FIQ within the secure mode */ | ||
43 | #define SEC_ROM_FIQ_ENABLE_MASK 0x00000008 | ||
44 | |||
45 | /* When set, enables Unified L2 cache within the secure mode */ | ||
46 | #define SEC_ROM_UL2_CACHE_ENABLE_MASK 0x00000010 | ||
47 | |||
48 | /* Broadcom Secure Service API Service IDs */ | ||
49 | #define SSAPI_DORMANT_ENTRY_SERV 0x01000000 | ||
50 | #define SSAPI_PUBLIC_OTP_SERV 0x01000001 | ||
51 | #define SSAPI_ENABLE_L2_CACHE 0x01000002 | ||
52 | #define SSAPI_DISABLE_L2_CACHE 0x01000003 | ||
53 | #define SSAPI_WRITE_SCU_STATUS 0x01000004 | ||
54 | #define SSAPI_WRITE_PWR_GATE 0x01000005 | ||
55 | |||
56 | /* Broadcom Secure Service API Return Codes */ | ||
57 | #define SEC_ROM_RET_OK 0x00000001 | ||
58 | #define SEC_ROM_RET_FAIL 0x00000009 | ||
59 | |||
60 | #define SSAPI_RET_FROM_INT_SERV 0x4 | ||
61 | #define SEC_EXIT_NORMAL 0x1 | ||
62 | |||
63 | #define SSAPI_ROW_AES 0x0E000006 | ||
64 | #define SSAPI_BRCM_START_VC_CORE 0x0E000008 | ||
65 | |||
66 | #ifndef __ASSEMBLY__ | ||
67 | extern void bcm_kona_smc_init(void); | ||
68 | |||
69 | extern unsigned bcm_kona_smc(unsigned service_id, | ||
70 | unsigned arg0, | ||
71 | unsigned arg1, | ||
72 | unsigned arg2, | ||
73 | unsigned arg3); | ||
74 | |||
75 | extern int bcm_kona_smc_asm(u32 service_id, | ||
76 | u32 buffer_addr); | ||
77 | |||
78 | #endif /* __ASSEMBLY__ */ | ||
79 | |||
80 | #endif /* BCM_KONA_SMC_H */ | ||
diff --git a/arch/arm/mach-bcm/bcm_kona_smc_asm.S b/arch/arm/mach-bcm/bcm_kona_smc_asm.S new file mode 100644 index 000000000000..a1608480d60d --- /dev/null +++ b/arch/arm/mach-bcm/bcm_kona_smc_asm.S | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation version 2. | ||
7 | * | ||
8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
9 | * kind, whether express or implied; without even the implied warranty | ||
10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/linkage.h> | ||
15 | #include "bcm_kona_smc.h" | ||
16 | |||
17 | /* | ||
18 | * int bcm_kona_smc_asm(u32 service_id, u32 buffer_addr) | ||
19 | */ | ||
20 | |||
21 | ENTRY(bcm_kona_smc_asm) | ||
22 | stmfd sp!, {r4-r12, lr} | ||
23 | mov r4, r0 @ service_id | ||
24 | mov r5, #3 @ Keep IRQ and FIQ off in SM | ||
25 | /* | ||
26 | * Since interrupts are disabled in the open mode, we must keep | ||
27 | * interrupts disabled in secure mode by setting R5=0x3. If interrupts | ||
28 | * are enabled in open mode, we can set R5=0x0 to allow interrupts in | ||
29 | * secure mode. If we did this, the secure monitor would return back | ||
30 | * control to the open mode to handle the interrupt prior to completing | ||
31 | * the secure service. If this happened, R12 would not be | ||
32 | * SEC_EXIT_NORMAL and we would need to call SMC again after resetting | ||
33 | * R5 (it gets clobbered by the secure monitor) and setting R4 to | ||
34 | * SSAPI_RET_FROM_INT_SERV to indicate that we want the secure monitor | ||
35 | * to finish up the previous uncompleted secure service. | ||
36 | */ | ||
37 | mov r6, r1 @ buffer_addr | ||
38 | smc #0 | ||
39 | /* Check r12 for SEC_EXIT_NORMAL here if interrupts are enabled */ | ||
40 | ldmfd sp!, {r4-r12, pc} | ||
41 | ENDPROC(bcm_kona_smc_asm) | ||
diff --git a/arch/arm/mach-bcm/board_bcm.c b/arch/arm/mach-bcm/board_bcm.c index 259593540477..22e8421b1df3 100644 --- a/arch/arm/mach-bcm/board_bcm.c +++ b/arch/arm/mach-bcm/board_bcm.c | |||
@@ -20,12 +20,35 @@ | |||
20 | 20 | ||
21 | #include <asm/mach/arch.h> | 21 | #include <asm/mach/arch.h> |
22 | #include <asm/mach/time.h> | 22 | #include <asm/mach/time.h> |
23 | #include <asm/hardware/cache-l2x0.h> | ||
23 | 24 | ||
24 | 25 | ||
26 | #include "bcm_kona_smc.h" | ||
27 | |||
28 | static int __init kona_l2_cache_init(void) | ||
29 | { | ||
30 | if (!IS_ENABLED(CONFIG_CACHE_L2X0)) | ||
31 | return 0; | ||
32 | |||
33 | bcm_kona_smc(SSAPI_ENABLE_L2_CACHE, 0, 0, 0, 0); | ||
34 | |||
35 | /* | ||
36 | * The aux_val and aux_mask have no effect since L2 cache is already | ||
37 | * enabled. Pass 0s for aux_val and 1s for aux_mask for default value. | ||
38 | */ | ||
39 | l2x0_of_init(0, ~0); | ||
40 | |||
41 | return 0; | ||
42 | } | ||
43 | |||
25 | static void __init board_init(void) | 44 | static void __init board_init(void) |
26 | { | 45 | { |
27 | of_platform_populate(NULL, of_default_bus_match_table, NULL, | 46 | of_platform_populate(NULL, of_default_bus_match_table, NULL, |
28 | &platform_bus); | 47 | &platform_bus); |
48 | |||
49 | bcm_kona_smc_init(); | ||
50 | |||
51 | kona_l2_cache_init(); | ||
29 | } | 52 | } |
30 | 53 | ||
31 | static const char * const bcm11351_dt_compat[] = { "bcm,bcm11351", NULL, }; | 54 | static const char * const bcm11351_dt_compat[] = { "bcm,bcm11351", NULL, }; |
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index d2f6b362b6dd..b09b027178f3 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile | |||
@@ -24,6 +24,12 @@ obj-$(CONFIG_SMP) += platsmp.o headsmp.o | |||
24 | 24 | ||
25 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 25 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
26 | 26 | ||
27 | obj-$(CONFIG_ARCH_EXYNOS) += exynos-smc.o | ||
28 | obj-$(CONFIG_ARCH_EXYNOS) += firmware.o | ||
29 | |||
30 | plus_sec := $(call as-instr,.arch_extension sec,+sec) | ||
31 | AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec) | ||
32 | |||
27 | # machine support | 33 | # machine support |
28 | 34 | ||
29 | obj-$(CONFIG_MACH_SMDKC210) += mach-smdkv310.o | 35 | obj-$(CONFIG_MACH_SMDKC210) += mach-smdkv310.o |
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index b35c60059bb8..46089fe24705 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c | |||
@@ -233,6 +233,33 @@ static struct map_desc exynos4_iodesc1[] __initdata = { | |||
233 | }, | 233 | }, |
234 | }; | 234 | }; |
235 | 235 | ||
236 | static struct map_desc exynos4210_iodesc[] __initdata = { | ||
237 | { | ||
238 | .virtual = (unsigned long)S5P_VA_SYSRAM_NS, | ||
239 | .pfn = __phys_to_pfn(EXYNOS4210_PA_SYSRAM_NS), | ||
240 | .length = SZ_4K, | ||
241 | .type = MT_DEVICE, | ||
242 | }, | ||
243 | }; | ||
244 | |||
245 | static struct map_desc exynos4x12_iodesc[] __initdata = { | ||
246 | { | ||
247 | .virtual = (unsigned long)S5P_VA_SYSRAM_NS, | ||
248 | .pfn = __phys_to_pfn(EXYNOS4x12_PA_SYSRAM_NS), | ||
249 | .length = SZ_4K, | ||
250 | .type = MT_DEVICE, | ||
251 | }, | ||
252 | }; | ||
253 | |||
254 | static struct map_desc exynos5250_iodesc[] __initdata = { | ||
255 | { | ||
256 | .virtual = (unsigned long)S5P_VA_SYSRAM_NS, | ||
257 | .pfn = __phys_to_pfn(EXYNOS5250_PA_SYSRAM_NS), | ||
258 | .length = SZ_4K, | ||
259 | .type = MT_DEVICE, | ||
260 | }, | ||
261 | }; | ||
262 | |||
236 | static struct map_desc exynos5_iodesc[] __initdata = { | 263 | static struct map_desc exynos5_iodesc[] __initdata = { |
237 | { | 264 | { |
238 | .virtual = (unsigned long)S3C_VA_SYS, | 265 | .virtual = (unsigned long)S3C_VA_SYS, |
@@ -361,6 +388,11 @@ static void __init exynos4_map_io(void) | |||
361 | else | 388 | else |
362 | iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1)); | 389 | iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1)); |
363 | 390 | ||
391 | if (soc_is_exynos4210()) | ||
392 | iotable_init(exynos4210_iodesc, ARRAY_SIZE(exynos4210_iodesc)); | ||
393 | if (soc_is_exynos4212() || soc_is_exynos4412()) | ||
394 | iotable_init(exynos4x12_iodesc, ARRAY_SIZE(exynos4x12_iodesc)); | ||
395 | |||
364 | /* initialize device information early */ | 396 | /* initialize device information early */ |
365 | exynos4_default_sdhci0(); | 397 | exynos4_default_sdhci0(); |
366 | exynos4_default_sdhci1(); | 398 | exynos4_default_sdhci1(); |
@@ -393,6 +425,9 @@ static void __init exynos4_map_io(void) | |||
393 | static void __init exynos5_map_io(void) | 425 | static void __init exynos5_map_io(void) |
394 | { | 426 | { |
395 | iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc)); | 427 | iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc)); |
428 | |||
429 | if (soc_is_exynos5250()) | ||
430 | iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc)); | ||
396 | } | 431 | } |
397 | 432 | ||
398 | static void __init exynos5440_map_io(void) | 433 | static void __init exynos5440_map_io(void) |
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index cb89ab886950..b17448c1a164 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h | |||
@@ -30,6 +30,8 @@ void exynos_init_late(void); | |||
30 | void exynos4_clk_init(struct device_node *np); | 30 | void exynos4_clk_init(struct device_node *np); |
31 | void exynos4_clk_register_fixed_ext(unsigned long, unsigned long); | 31 | void exynos4_clk_register_fixed_ext(unsigned long, unsigned long); |
32 | 32 | ||
33 | void exynos_firmware_init(void); | ||
34 | |||
33 | #ifdef CONFIG_PM_GENERIC_DOMAINS | 35 | #ifdef CONFIG_PM_GENERIC_DOMAINS |
34 | int exynos_pm_late_initcall(void); | 36 | int exynos_pm_late_initcall(void); |
35 | #else | 37 | #else |
diff --git a/arch/arm/mach-exynos/exynos-smc.S b/arch/arm/mach-exynos/exynos-smc.S new file mode 100644 index 000000000000..2e27aa3813fd --- /dev/null +++ b/arch/arm/mach-exynos/exynos-smc.S | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Samsung Electronics. | ||
3 | * | ||
4 | * Copied from omap-smc.S Copyright (C) 2010 Texas Instruments, Inc. | ||
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/linkage.h> | ||
12 | |||
13 | /* | ||
14 | * Function signature: void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3) | ||
15 | */ | ||
16 | |||
17 | ENTRY(exynos_smc) | ||
18 | stmfd sp!, {r4-r11, lr} | ||
19 | dsb | ||
20 | smc #0 | ||
21 | ldmfd sp!, {r4-r11, pc} | ||
22 | ENDPROC(exynos_smc) | ||
diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c new file mode 100644 index 000000000000..ed11f100d479 --- /dev/null +++ b/arch/arm/mach-exynos/firmware.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Samsung Electronics. | ||
3 | * Kyungmin Park <kyungmin.park@samsung.com> | ||
4 | * Tomasz Figa <t.figa@samsung.com> | ||
5 | * | ||
6 | * This program is free software,you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/of_address.h> | ||
16 | |||
17 | #include <asm/firmware.h> | ||
18 | |||
19 | #include <mach/map.h> | ||
20 | |||
21 | #include "smc.h" | ||
22 | |||
23 | static int exynos_do_idle(void) | ||
24 | { | ||
25 | exynos_smc(SMC_CMD_SLEEP, 0, 0, 0); | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | static int exynos_cpu_boot(int cpu) | ||
30 | { | ||
31 | exynos_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0); | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr) | ||
36 | { | ||
37 | void __iomem *boot_reg = S5P_VA_SYSRAM_NS + 0x1c + 4*cpu; | ||
38 | |||
39 | __raw_writel(boot_addr, boot_reg); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static const struct firmware_ops exynos_firmware_ops = { | ||
44 | .do_idle = exynos_do_idle, | ||
45 | .set_cpu_boot_addr = exynos_set_cpu_boot_addr, | ||
46 | .cpu_boot = exynos_cpu_boot, | ||
47 | }; | ||
48 | |||
49 | void __init exynos_firmware_init(void) | ||
50 | { | ||
51 | if (of_have_populated_dt()) { | ||
52 | struct device_node *nd; | ||
53 | const __be32 *addr; | ||
54 | |||
55 | nd = of_find_compatible_node(NULL, NULL, | ||
56 | "samsung,secure-firmware"); | ||
57 | if (!nd) | ||
58 | return; | ||
59 | |||
60 | addr = of_get_address(nd, 0, NULL, NULL); | ||
61 | if (!addr) { | ||
62 | pr_err("%s: No address specified.\n", __func__); | ||
63 | return; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | pr_info("Running under secure firmware.\n"); | ||
68 | |||
69 | register_firmware_ops(&exynos_firmware_ops); | ||
70 | } | ||
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 7f99b7b187d6..99e0a79f3b1f 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h | |||
@@ -26,6 +26,9 @@ | |||
26 | #define EXYNOS4_PA_SYSRAM0 0x02025000 | 26 | #define EXYNOS4_PA_SYSRAM0 0x02025000 |
27 | #define EXYNOS4_PA_SYSRAM1 0x02020000 | 27 | #define EXYNOS4_PA_SYSRAM1 0x02020000 |
28 | #define EXYNOS5_PA_SYSRAM 0x02020000 | 28 | #define EXYNOS5_PA_SYSRAM 0x02020000 |
29 | #define EXYNOS4210_PA_SYSRAM_NS 0x0203F000 | ||
30 | #define EXYNOS4x12_PA_SYSRAM_NS 0x0204F000 | ||
31 | #define EXYNOS5250_PA_SYSRAM_NS 0x0204F000 | ||
29 | 32 | ||
30 | #define EXYNOS4_PA_FIMC0 0x11800000 | 33 | #define EXYNOS4_PA_FIMC0 0x11800000 |
31 | #define EXYNOS4_PA_FIMC1 0x11810000 | 34 | #define EXYNOS4_PA_FIMC1 0x11810000 |
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c index ac27f3cd121f..b9ed834a7eee 100644 --- a/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c | |||
@@ -57,6 +57,7 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)") | |||
57 | .smp = smp_ops(exynos_smp_ops), | 57 | .smp = smp_ops(exynos_smp_ops), |
58 | .init_irq = exynos4_init_irq, | 58 | .init_irq = exynos4_init_irq, |
59 | .map_io = exynos4_dt_map_io, | 59 | .map_io = exynos4_dt_map_io, |
60 | .init_early = exynos_firmware_init, | ||
60 | .init_machine = exynos4_dt_machine_init, | 61 | .init_machine = exynos4_dt_machine_init, |
61 | .init_late = exynos_init_late, | 62 | .init_late = exynos_init_late, |
62 | .init_time = exynos_init_time, | 63 | .init_time = exynos_init_time, |
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 95e04bd5813f..a0e8ff7758a4 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/cacheflush.h> | 24 | #include <asm/cacheflush.h> |
25 | #include <asm/smp_plat.h> | 25 | #include <asm/smp_plat.h> |
26 | #include <asm/smp_scu.h> | 26 | #include <asm/smp_scu.h> |
27 | #include <asm/firmware.h> | ||
27 | 28 | ||
28 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
29 | #include <mach/regs-clock.h> | 30 | #include <mach/regs-clock.h> |
@@ -137,10 +138,21 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct | |||
137 | 138 | ||
138 | timeout = jiffies + (1 * HZ); | 139 | timeout = jiffies + (1 * HZ); |
139 | while (time_before(jiffies, timeout)) { | 140 | while (time_before(jiffies, timeout)) { |
141 | unsigned long boot_addr; | ||
142 | |||
140 | smp_rmb(); | 143 | smp_rmb(); |
141 | 144 | ||
142 | __raw_writel(virt_to_phys(exynos4_secondary_startup), | 145 | boot_addr = virt_to_phys(exynos4_secondary_startup); |
143 | cpu_boot_reg(phys_cpu)); | 146 | |
147 | /* | ||
148 | * Try to set boot address using firmware first | ||
149 | * and fall back to boot register if it fails. | ||
150 | */ | ||
151 | if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr)) | ||
152 | __raw_writel(boot_addr, cpu_boot_reg(phys_cpu)); | ||
153 | |||
154 | call_firmware_op(cpu_boot, phys_cpu); | ||
155 | |||
144 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); | 156 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); |
145 | 157 | ||
146 | if (pen_release == -1) | 158 | if (pen_release == -1) |
@@ -196,10 +208,20 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) | |||
196 | * system-wide flags register. The boot monitor waits | 208 | * system-wide flags register. The boot monitor waits |
197 | * until it receives a soft interrupt, and then the | 209 | * until it receives a soft interrupt, and then the |
198 | * secondary CPU branches to this address. | 210 | * secondary CPU branches to this address. |
211 | * | ||
212 | * Try using firmware operation first and fall back to | ||
213 | * boot register if it fails. | ||
199 | */ | 214 | */ |
200 | for (i = 1; i < max_cpus; ++i) | 215 | for (i = 1; i < max_cpus; ++i) { |
201 | __raw_writel(virt_to_phys(exynos4_secondary_startup), | 216 | unsigned long phys_cpu; |
202 | cpu_boot_reg(cpu_logical_map(i))); | 217 | unsigned long boot_addr; |
218 | |||
219 | phys_cpu = cpu_logical_map(i); | ||
220 | boot_addr = virt_to_phys(exynos4_secondary_startup); | ||
221 | |||
222 | if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr)) | ||
223 | __raw_writel(boot_addr, cpu_boot_reg(phys_cpu)); | ||
224 | } | ||
203 | } | 225 | } |
204 | 226 | ||
205 | struct smp_operations exynos_smp_ops __initdata = { | 227 | struct smp_operations exynos_smp_ops __initdata = { |
diff --git a/arch/arm/mach-exynos/smc.h b/arch/arm/mach-exynos/smc.h new file mode 100644 index 000000000000..13a1dc8ecbf2 --- /dev/null +++ b/arch/arm/mach-exynos/smc.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Samsung Electronics. | ||
3 | * | ||
4 | * EXYNOS - SMC Call | ||
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 | #ifndef __ASM_ARCH_EXYNOS_SMC_H | ||
12 | #define __ASM_ARCH_EXYNOS_SMC_H | ||
13 | |||
14 | #define SMC_CMD_INIT (-1) | ||
15 | #define SMC_CMD_INFO (-2) | ||
16 | /* For Power Management */ | ||
17 | #define SMC_CMD_SLEEP (-3) | ||
18 | #define SMC_CMD_CPU1BOOT (-4) | ||
19 | #define SMC_CMD_CPU0AFTR (-5) | ||
20 | /* For CP15 Access */ | ||
21 | #define SMC_CMD_C15RESUME (-11) | ||
22 | /* For L2 Cache Access */ | ||
23 | #define SMC_CMD_L2X0CTRL (-21) | ||
24 | #define SMC_CMD_L2X0SETUP1 (-22) | ||
25 | #define SMC_CMD_L2X0SETUP2 (-23) | ||
26 | #define SMC_CMD_L2X0INVALL (-24) | ||
27 | #define SMC_CMD_L2X0DEBUG (-25) | ||
28 | |||
29 | extern void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3); | ||
30 | |||
31 | #endif | ||
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h index c2d7bdae5891..c18678610bc0 100644 --- a/arch/arm/plat-samsung/include/plat/map-s5p.h +++ b/arch/arm/plat-samsung/include/plat/map-s5p.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #define S5P_VA_GPIO3 S3C_ADDR(0x02280000) | 22 | #define S5P_VA_GPIO3 S3C_ADDR(0x02280000) |
23 | 23 | ||
24 | #define S5P_VA_SYSRAM S3C_ADDR(0x02400000) | 24 | #define S5P_VA_SYSRAM S3C_ADDR(0x02400000) |
25 | #define S5P_VA_SYSRAM_NS S3C_ADDR(0x02410000) | ||
25 | #define S5P_VA_DMC0 S3C_ADDR(0x02440000) | 26 | #define S5P_VA_DMC0 S3C_ADDR(0x02440000) |
26 | #define S5P_VA_DMC1 S3C_ADDR(0x02480000) | 27 | #define S5P_VA_DMC1 S3C_ADDR(0x02480000) |
27 | #define S5P_VA_SROMC S3C_ADDR(0x024C0000) | 28 | #define S5P_VA_SROMC S3C_ADDR(0x024C0000) |