aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-04 15:33:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-04 15:33:36 -0400
commite3d98847ded1d183111ff7c4d1ef56b161c7f13e (patch)
tree8ec2b298eef4f1695ca612014b7f75b85badae45 /arch/arm
parent22b154365fbc096a46d936ec1f462ef8b9bd1f05 (diff)
parent721e0205b07589223343737a9c421d8118d87bba (diff)
Merge tag 'firmware-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM platform specific firmware interfaces from Olof Johansson: "Two platforms, bcm and exynos have their own firmware interfaces using the "secure monitor call", this adds support for those. We had originally planned to have a third set of patches in here, which would extend support for the existing generic "psci" call that is used on multiple platforms as well as Xen and KVM guests, but that ended up getting dropped because the patches were not ready in time." * tag 'firmware-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: ARM: bcm: mark bcm_kona_smc_init as __init ARM: bcm281xx: Add DT support for SMC handler ARM: bcm281xx: Add L2 cache enable code ARM: EXYNOS: Add secure firmware support to secondary CPU bring-up ARM: EXYNOS: Add IO mapping for non-secure SYSRAM. ARM: EXYNOS: Add support for Exynos secure firmware ARM: EXYNOS: Add support for secure monitor calls ARM: Add interface for registering and calling firmware-specific operations
Diffstat (limited to 'arch/arm')
-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)