Commit | Line | Data |
---|---|---|
b8eb35fd CD |
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 */ | |
721e0205 | 44 | void __init bcm_kona_smc_init(void) |
b8eb35fd CD |
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 | } |