aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/boot/dts/bcm11351.dtsi5
-rw-r--r--arch/arm/common/Makefile2
-rw-r--r--arch/arm/common/firmware.c18
-rw-r--r--arch/arm/include/asm/firmware.h66
-rw-r--r--arch/arm/mach-bcm/Makefile4
-rw-r--r--arch/arm/mach-bcm/bcm_kona_smc.c118
-rw-r--r--arch/arm/mach-bcm/bcm_kona_smc.h80
-rw-r--r--arch/arm/mach-bcm/bcm_kona_smc_asm.S41
-rw-r--r--arch/arm/mach-bcm/board_bcm.c23
-rw-r--r--arch/arm/mach-exynos/Makefile6
-rw-r--r--arch/arm/mach-exynos/common.c35
-rw-r--r--arch/arm/mach-exynos/common.h2
-rw-r--r--arch/arm/mach-exynos/exynos-smc.S22
-rw-r--r--arch/arm/mach-exynos/firmware.c70
-rw-r--r--arch/arm/mach-exynos/include/mach/map.h3
-rw-r--r--arch/arm/mach-exynos/mach-exynos4-dt.c1
-rw-r--r--arch/arm/mach-exynos/platsmp.c32
-rw-r--r--arch/arm/mach-exynos/smc.h31
-rw-r--r--arch/arm/plat-samsung/include/plat/map-s5p.h1
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
5obj-y += firmware.o
6
5obj-$(CONFIG_ICST) += icst.o 7obj-$(CONFIG_ICST) += icst.o
6obj-$(CONFIG_SA1111) += sa1111.o 8obj-$(CONFIG_SA1111) += sa1111.o
7obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o 9obj-$(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
16static const struct firmware_ops default_firmware_ops;
17
18const 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 */
23struct 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. */
43extern 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 */
59static 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
13obj-$(CONFIG_ARCH_BCM) := board_bcm.o 13obj-$(CONFIG_ARCH_BCM) := board_bcm.o bcm_kona_smc.o bcm_kona_smc_asm.o
14plus_sec := $(call as-instr,.arch_extension sec,+sec)
15AFLAGS_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
24struct secure_bridge_data {
25 void __iomem *bounce; /* virtual address */
26 u32 __iomem buffer_addr; /* physical address */
27 int initialized;
28} bridge_data;
29
30struct bcm_kona_smc_data {
31 unsigned service_id;
32 unsigned arg0;
33 unsigned arg1;
34 unsigned arg2;
35 unsigned arg3;
36};
37
38static const struct of_device_id bcm_kona_smc_ids[] __initconst = {
39 {.compatible = "bcm,kona-smc"},
40 {},
41};
42
43/* Map in the bounce area */
44void __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 */
66static 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
95unsigned 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__
67extern void bcm_kona_smc_init(void);
68
69extern unsigned bcm_kona_smc(unsigned service_id,
70 unsigned arg0,
71 unsigned arg1,
72 unsigned arg2,
73 unsigned arg3);
74
75extern 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
21ENTRY(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}
41ENDPROC(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
28static 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
25static void __init board_init(void) 44static 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
31static const char * const bcm11351_dt_compat[] = { "bcm,bcm11351", NULL, }; 54static 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
25obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 25obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
26 26
27obj-$(CONFIG_ARCH_EXYNOS) += exynos-smc.o
28obj-$(CONFIG_ARCH_EXYNOS) += firmware.o
29
30plus_sec := $(call as-instr,.arch_extension sec,+sec)
31AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)
32
27# machine support 33# machine support
28 34
29obj-$(CONFIG_MACH_SMDKC210) += mach-smdkv310.o 35obj-$(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
236static 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
245static 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
254static 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
236static struct map_desc exynos5_iodesc[] __initdata = { 263static 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)
393static void __init exynos5_map_io(void) 425static 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
398static void __init exynos5440_map_io(void) 433static 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);
30void exynos4_clk_init(struct device_node *np); 30void exynos4_clk_init(struct device_node *np);
31void exynos4_clk_register_fixed_ext(unsigned long, unsigned long); 31void exynos4_clk_register_fixed_ext(unsigned long, unsigned long);
32 32
33void exynos_firmware_init(void);
34
33#ifdef CONFIG_PM_GENERIC_DOMAINS 35#ifdef CONFIG_PM_GENERIC_DOMAINS
34int exynos_pm_late_initcall(void); 36int 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
17ENTRY(exynos_smc)
18 stmfd sp!, {r4-r11, lr}
19 dsb
20 smc #0
21 ldmfd sp!, {r4-r11, pc}
22ENDPROC(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
23static int exynos_do_idle(void)
24{
25 exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
26 return 0;
27}
28
29static int exynos_cpu_boot(int cpu)
30{
31 exynos_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0);
32 return 0;
33}
34
35static 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
43static 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
49void __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
205struct smp_operations exynos_smp_ops __initdata = { 227struct 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
29extern 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)