.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * OMAP Secure API infrastructure. |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2011 Texas Instruments, Inc. |
---|
5 | 6 | * Santosh Shilimkar <santosh.shilimkar@ti.com> |
---|
6 | 7 | * Copyright (C) 2012 Ivaylo Dimitrov <freemangordon@abv.bg> |
---|
7 | | - * Copyright (C) 2013 Pali Rohár <pali.rohar@gmail.com> |
---|
8 | | - * |
---|
9 | | - * |
---|
10 | | - * This program is free software,you can redistribute it and/or modify |
---|
11 | | - * it under the terms of the GNU General Public License version 2 as |
---|
12 | | - * published by the Free Software Foundation. |
---|
| 8 | + * Copyright (C) 2013 Pali Rohár <pali@kernel.org> |
---|
13 | 9 | */ |
---|
14 | 10 | |
---|
| 11 | +#include <linux/arm-smccc.h> |
---|
| 12 | +#include <linux/cpu_pm.h> |
---|
15 | 13 | #include <linux/kernel.h> |
---|
16 | 14 | #include <linux/init.h> |
---|
17 | 15 | #include <linux/io.h> |
---|
18 | 16 | #include <linux/memblock.h> |
---|
| 17 | +#include <linux/of.h> |
---|
19 | 18 | |
---|
20 | 19 | #include <asm/cacheflush.h> |
---|
21 | 20 | #include <asm/memblock.h> |
---|
22 | 21 | |
---|
| 22 | +#include "common.h" |
---|
23 | 23 | #include "omap-secure.h" |
---|
| 24 | +#include "soc.h" |
---|
24 | 25 | |
---|
25 | 26 | static phys_addr_t omap_secure_memblock_base; |
---|
| 27 | + |
---|
| 28 | +bool optee_available; |
---|
| 29 | + |
---|
| 30 | +#define OMAP_SIP_SMC_STD_CALL_VAL(func_num) \ |
---|
| 31 | + ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_32, \ |
---|
| 32 | + ARM_SMCCC_OWNER_SIP, (func_num)) |
---|
| 33 | + |
---|
| 34 | +static void __init omap_optee_init_check(void) |
---|
| 35 | +{ |
---|
| 36 | + struct device_node *np; |
---|
| 37 | + |
---|
| 38 | + /* |
---|
| 39 | + * We only check that the OP-TEE node is present and available. The |
---|
| 40 | + * OP-TEE kernel driver is not needed for the type of interaction made |
---|
| 41 | + * with OP-TEE here so the driver's status is not checked. |
---|
| 42 | + */ |
---|
| 43 | + np = of_find_node_by_path("/firmware/optee"); |
---|
| 44 | + if (np && of_device_is_available(np)) |
---|
| 45 | + optee_available = true; |
---|
| 46 | + of_node_put(np); |
---|
| 47 | +} |
---|
26 | 48 | |
---|
27 | 49 | /** |
---|
28 | 50 | * omap_sec_dispatcher: Routine to dispatch low power secure |
---|
.. | .. |
---|
55 | 77 | ret = omap_smc2(idx, flag, __pa(param)); |
---|
56 | 78 | |
---|
57 | 79 | return ret; |
---|
| 80 | +} |
---|
| 81 | + |
---|
| 82 | +void omap_smccc_smc(u32 fn, u32 arg) |
---|
| 83 | +{ |
---|
| 84 | + struct arm_smccc_res res; |
---|
| 85 | + |
---|
| 86 | + arm_smccc_smc(OMAP_SIP_SMC_STD_CALL_VAL(fn), arg, |
---|
| 87 | + 0, 0, 0, 0, 0, 0, &res); |
---|
| 88 | + WARN(res.a0, "Secure function call 0x%08x failed\n", fn); |
---|
| 89 | +} |
---|
| 90 | + |
---|
| 91 | +void omap_smc1(u32 fn, u32 arg) |
---|
| 92 | +{ |
---|
| 93 | + /* |
---|
| 94 | + * If this platform has OP-TEE installed we use ARM SMC calls |
---|
| 95 | + * otherwise fall back to the OMAP ROM style calls. |
---|
| 96 | + */ |
---|
| 97 | + if (optee_available) |
---|
| 98 | + omap_smccc_smc(fn, arg); |
---|
| 99 | + else |
---|
| 100 | + _omap_smc1(fn, arg); |
---|
58 | 101 | } |
---|
59 | 102 | |
---|
60 | 103 | /* Allocate the memory to save secure ram */ |
---|
.. | .. |
---|
167 | 210 | NO_FLAG, |
---|
168 | 211 | 3, ptr, count, flag, 0); |
---|
169 | 212 | } |
---|
| 213 | + |
---|
| 214 | +void __init omap_secure_init(void) |
---|
| 215 | +{ |
---|
| 216 | + omap_optee_init_check(); |
---|
| 217 | +} |
---|
| 218 | + |
---|
| 219 | +/* |
---|
| 220 | + * Dummy dispatcher call after core OSWR and MPU off. Updates the ROM return |
---|
| 221 | + * address after MMU has been re-enabled after CPU1 has been woken up again. |
---|
| 222 | + * Otherwise the ROM code will attempt to use the earlier physical return |
---|
| 223 | + * address that got set with MMU off when waking up CPU1. Only used on secure |
---|
| 224 | + * devices. |
---|
| 225 | + */ |
---|
| 226 | +static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v) |
---|
| 227 | +{ |
---|
| 228 | + switch (cmd) { |
---|
| 229 | + case CPU_CLUSTER_PM_EXIT: |
---|
| 230 | + omap_secure_dispatcher(OMAP4_PPA_SERVICE_0, |
---|
| 231 | + FLAG_START_CRITICAL, |
---|
| 232 | + 0, 0, 0, 0, 0); |
---|
| 233 | + break; |
---|
| 234 | + default: |
---|
| 235 | + break; |
---|
| 236 | + } |
---|
| 237 | + |
---|
| 238 | + return NOTIFY_OK; |
---|
| 239 | +} |
---|
| 240 | + |
---|
| 241 | +static struct notifier_block secure_notifier_block = { |
---|
| 242 | + .notifier_call = cpu_notifier, |
---|
| 243 | +}; |
---|
| 244 | + |
---|
| 245 | +static int __init secure_pm_init(void) |
---|
| 246 | +{ |
---|
| 247 | + if (omap_type() == OMAP2_DEVICE_TYPE_GP || !soc_is_omap44xx()) |
---|
| 248 | + return 0; |
---|
| 249 | + |
---|
| 250 | + cpu_pm_register_notifier(&secure_notifier_block); |
---|
| 251 | + |
---|
| 252 | + return 0; |
---|
| 253 | +} |
---|
| 254 | +omap_arch_initcall(secure_pm_init); |
---|