xref: /openbmc/linux/arch/arm/mach-omap2/omap-secure.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ba9456acSSantosh Shilimkar /*
3ba9456acSSantosh Shilimkar  * OMAP Secure API infrastructure.
4ba9456acSSantosh Shilimkar  *
5ba9456acSSantosh Shilimkar  * Copyright (C) 2011 Texas Instruments, Inc.
6ba9456acSSantosh Shilimkar  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
74748a724SPali Rohár  * Copyright (C) 2012 Ivaylo Dimitrov <freemangordon@abv.bg>
8149ed3d4SPali Rohár  * Copyright (C) 2013 Pali Rohár <pali@kernel.org>
9ba9456acSSantosh Shilimkar  */
10ba9456acSSantosh Shilimkar 
1148840e16SAndrew F. Davis #include <linux/arm-smccc.h>
12b3d09a06SCarlos Leija #include <linux/cpu_pm.h>
13ba9456acSSantosh Shilimkar #include <linux/kernel.h>
14ba9456acSSantosh Shilimkar #include <linux/init.h>
15ba9456acSSantosh Shilimkar #include <linux/io.h>
16259ee57aSSantosh Shilimkar #include <linux/memblock.h>
17dbebc8bfSAndrew F. Davis #include <linux/of.h>
18ba9456acSSantosh Shilimkar 
19ba9456acSSantosh Shilimkar #include <asm/cacheflush.h>
20716a3dc2SRussell King #include <asm/memblock.h>
21ba9456acSSantosh Shilimkar 
2248840e16SAndrew F. Davis #include "common.h"
23c1db9d73STony Lindgren #include "omap-secure.h"
24b3d09a06SCarlos Leija #include "soc.h"
25ba9456acSSantosh Shilimkar 
26259ee57aSSantosh Shilimkar static phys_addr_t omap_secure_memblock_base;
27259ee57aSSantosh Shilimkar 
28dbebc8bfSAndrew F. Davis bool optee_available;
29dbebc8bfSAndrew F. Davis 
3048840e16SAndrew F. Davis #define OMAP_SIP_SMC_STD_CALL_VAL(func_num) \
3148840e16SAndrew F. Davis 	ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_32, \
3248840e16SAndrew F. Davis 	ARM_SMCCC_OWNER_SIP, (func_num))
3348840e16SAndrew F. Davis 
omap_optee_init_check(void)34dbebc8bfSAndrew F. Davis static void __init omap_optee_init_check(void)
35dbebc8bfSAndrew F. Davis {
36dbebc8bfSAndrew F. Davis 	struct device_node *np;
37dbebc8bfSAndrew F. Davis 
38dbebc8bfSAndrew F. Davis 	/*
39dbebc8bfSAndrew F. Davis 	 * We only check that the OP-TEE node is present and available. The
40dbebc8bfSAndrew F. Davis 	 * OP-TEE kernel driver is not needed for the type of interaction made
41dbebc8bfSAndrew F. Davis 	 * with OP-TEE here so the driver's status is not checked.
42dbebc8bfSAndrew F. Davis 	 */
43dbebc8bfSAndrew F. Davis 	np = of_find_node_by_path("/firmware/optee");
44dbebc8bfSAndrew F. Davis 	if (np && of_device_is_available(np))
45dbebc8bfSAndrew F. Davis 		optee_available = true;
46dbebc8bfSAndrew F. Davis 	of_node_put(np);
47dbebc8bfSAndrew F. Davis }
48dbebc8bfSAndrew F. Davis 
49ba9456acSSantosh Shilimkar /**
50ba9456acSSantosh Shilimkar  * omap_sec_dispatcher: Routine to dispatch low power secure
51ba9456acSSantosh Shilimkar  * service routines
52ba9456acSSantosh Shilimkar  * @idx: The HAL API index
53ba9456acSSantosh Shilimkar  * @flag: The flag indicating criticality of operation
54ba9456acSSantosh Shilimkar  * @nargs: Number of valid arguments out of four.
55ba9456acSSantosh Shilimkar  * @arg1, arg2, arg3 args4: Parameters passed to secure API
56ba9456acSSantosh Shilimkar  *
57ba9456acSSantosh Shilimkar  * Return the non-zero error value on failure.
58ba9456acSSantosh Shilimkar  */
omap_secure_dispatcher(u32 idx,u32 flag,u32 nargs,u32 arg1,u32 arg2,u32 arg3,u32 arg4)59ba9456acSSantosh Shilimkar u32 omap_secure_dispatcher(u32 idx, u32 flag, u32 nargs, u32 arg1, u32 arg2,
60ba9456acSSantosh Shilimkar 							 u32 arg3, u32 arg4)
61ba9456acSSantosh Shilimkar {
628cf8df89STony Lindgren 	static u32 buf[NR_CPUS][5];
638cf8df89STony Lindgren 	u32 *param;
648cf8df89STony Lindgren 	int cpu;
65ba9456acSSantosh Shilimkar 	u32 ret;
668cf8df89STony Lindgren 
678cf8df89STony Lindgren 	cpu = get_cpu();
688cf8df89STony Lindgren 	param = buf[cpu];
69ba9456acSSantosh Shilimkar 
70ba9456acSSantosh Shilimkar 	param[0] = nargs;
71ba9456acSSantosh Shilimkar 	param[1] = arg1;
72ba9456acSSantosh Shilimkar 	param[2] = arg2;
73ba9456acSSantosh Shilimkar 	param[3] = arg3;
74ba9456acSSantosh Shilimkar 	param[4] = arg4;
75ba9456acSSantosh Shilimkar 
76ba9456acSSantosh Shilimkar 	/*
77ba9456acSSantosh Shilimkar 	 * Secure API needs physical address
78ba9456acSSantosh Shilimkar 	 * pointer for the parameters
79ba9456acSSantosh Shilimkar 	 */
80ba9456acSSantosh Shilimkar 	flush_cache_all();
81ba9456acSSantosh Shilimkar 	outer_clean_range(__pa(param), __pa(param + 5));
82ba9456acSSantosh Shilimkar 	ret = omap_smc2(idx, flag, __pa(param));
83ba9456acSSantosh Shilimkar 
848cf8df89STony Lindgren 	put_cpu();
858cf8df89STony Lindgren 
86ba9456acSSantosh Shilimkar 	return ret;
87ba9456acSSantosh Shilimkar }
88259ee57aSSantosh Shilimkar 
omap_smccc_smc(u32 fn,u32 arg)8948840e16SAndrew F. Davis void omap_smccc_smc(u32 fn, u32 arg)
9048840e16SAndrew F. Davis {
9148840e16SAndrew F. Davis 	struct arm_smccc_res res;
9248840e16SAndrew F. Davis 
9348840e16SAndrew F. Davis 	arm_smccc_smc(OMAP_SIP_SMC_STD_CALL_VAL(fn), arg,
9448840e16SAndrew F. Davis 		      0, 0, 0, 0, 0, 0, &res);
9548840e16SAndrew F. Davis 	WARN(res.a0, "Secure function call 0x%08x failed\n", fn);
9648840e16SAndrew F. Davis }
9748840e16SAndrew F. Davis 
omap_smc1(u32 fn,u32 arg)9848840e16SAndrew F. Davis void omap_smc1(u32 fn, u32 arg)
9948840e16SAndrew F. Davis {
10048840e16SAndrew F. Davis 	/*
10148840e16SAndrew F. Davis 	 * If this platform has OP-TEE installed we use ARM SMC calls
10248840e16SAndrew F. Davis 	 * otherwise fall back to the OMAP ROM style calls.
10348840e16SAndrew F. Davis 	 */
10448840e16SAndrew F. Davis 	if (optee_available)
10548840e16SAndrew F. Davis 		omap_smccc_smc(fn, arg);
10648840e16SAndrew F. Davis 	else
10748840e16SAndrew F. Davis 		_omap_smc1(fn, arg);
10848840e16SAndrew F. Davis }
10948840e16SAndrew F. Davis 
110259ee57aSSantosh Shilimkar /* Allocate the memory to save secure ram */
omap_secure_ram_reserve_memblock(void)111259ee57aSSantosh Shilimkar int __init omap_secure_ram_reserve_memblock(void)
112259ee57aSSantosh Shilimkar {
113259ee57aSSantosh Shilimkar 	u32 size = OMAP_SECURE_RAM_STORAGE;
114259ee57aSSantosh Shilimkar 
1157a285290SR Sricharan 	size = ALIGN(size, SECTION_SIZE);
1167a285290SR Sricharan 	omap_secure_memblock_base = arm_memblock_steal(size, SECTION_SIZE);
117259ee57aSSantosh Shilimkar 
118259ee57aSSantosh Shilimkar 	return 0;
119259ee57aSSantosh Shilimkar }
120259ee57aSSantosh Shilimkar 
121863204cfSArnd Bergmann #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
omap3_save_secure_ram(void * addr,int size)122deb44711SArnd Bergmann u32 omap3_save_secure_ram(void *addr, int size)
123d09220a8STony Lindgren {
1248cf8df89STony Lindgren 	static u32 param[5];
125d09220a8STony Lindgren 	u32 ret;
126d09220a8STony Lindgren 
127d09220a8STony Lindgren 	if (size != OMAP3_SAVE_SECURE_RAM_SZ)
128d09220a8STony Lindgren 		return OMAP3_SAVE_SECURE_RAM_SZ;
129d09220a8STony Lindgren 
130d09220a8STony Lindgren 	param[0] = 4;		/* Number of arguments */
131d09220a8STony Lindgren 	param[1] = __pa(addr);	/* Physical address for saving */
132d09220a8STony Lindgren 	param[2] = 0;
133d09220a8STony Lindgren 	param[3] = 1;
134d09220a8STony Lindgren 	param[4] = 1;
135d09220a8STony Lindgren 
136d09220a8STony Lindgren 	ret = save_secure_ram_context(__pa(param));
137d09220a8STony Lindgren 
138d09220a8STony Lindgren 	return ret;
139d09220a8STony Lindgren }
140863204cfSArnd Bergmann #endif
141d09220a8STony Lindgren 
1424748a724SPali Rohár /**
1434748a724SPali Rohár  * rx51_secure_dispatcher: Routine to dispatch secure PPA API calls
1444748a724SPali Rohár  * @idx: The PPA API index
1454748a724SPali Rohár  * @process: Process ID
1464748a724SPali Rohár  * @flag: The flag indicating criticality of operation
1474748a724SPali Rohár  * @nargs: Number of valid arguments out of four.
1484748a724SPali Rohár  * @arg1, arg2, arg3 args4: Parameters passed to secure API
1494748a724SPali Rohár  *
1504748a724SPali Rohár  * Return the non-zero error value on failure.
1514748a724SPali Rohár  *
1524748a724SPali Rohár  * NOTE: rx51_secure_dispatcher differs from omap_secure_dispatcher because
1534748a724SPali Rohár  *       it calling omap_smc3() instead omap_smc2() and param[0] is nargs+1
1544748a724SPali Rohár  */
rx51_secure_dispatcher(u32 idx,u32 process,u32 flag,u32 nargs,u32 arg1,u32 arg2,u32 arg3,u32 arg4)155*6aeb51c1SArnd Bergmann static u32 rx51_secure_dispatcher(u32 idx, u32 process, u32 flag, u32 nargs,
1564748a724SPali Rohár 			   u32 arg1, u32 arg2, u32 arg3, u32 arg4)
1574748a724SPali Rohár {
1588cf8df89STony Lindgren 	static u32 param[5];
1594748a724SPali Rohár 	u32 ret;
1604748a724SPali Rohár 
1614748a724SPali Rohár 	param[0] = nargs+1; /* RX-51 needs number of arguments + 1 */
1624748a724SPali Rohár 	param[1] = arg1;
1634748a724SPali Rohár 	param[2] = arg2;
1644748a724SPali Rohár 	param[3] = arg3;
1654748a724SPali Rohár 	param[4] = arg4;
1664748a724SPali Rohár 
1674748a724SPali Rohár 	/*
1684748a724SPali Rohár 	 * Secure API needs physical address
1694748a724SPali Rohár 	 * pointer for the parameters
1704748a724SPali Rohár 	 */
1714748a724SPali Rohár 	local_irq_disable();
1724748a724SPali Rohár 	local_fiq_disable();
1734748a724SPali Rohár 	flush_cache_all();
1744748a724SPali Rohár 	outer_clean_range(__pa(param), __pa(param + 5));
1754748a724SPali Rohár 	ret = omap_smc3(idx, process, flag, __pa(param));
1764748a724SPali Rohár 	flush_cache_all();
1774748a724SPali Rohár 	local_fiq_enable();
1784748a724SPali Rohár 	local_irq_enable();
1794748a724SPali Rohár 
1804748a724SPali Rohár 	return ret;
1814748a724SPali Rohár }
1824748a724SPali Rohár 
1834748a724SPali Rohár /**
1844748a724SPali Rohár  * rx51_secure_update_aux_cr: Routine to modify the contents of Auxiliary Control Register
1854748a724SPali Rohár  *  @set_bits: bits to set in ACR
1864748a724SPali Rohár  *  @clr_bits: bits to clear in ACR
1874748a724SPali Rohár  *
1884748a724SPali Rohár  * Return the non-zero error value on failure.
1894748a724SPali Rohár */
rx51_secure_update_aux_cr(u32 set_bits,u32 clear_bits)1904748a724SPali Rohár u32 rx51_secure_update_aux_cr(u32 set_bits, u32 clear_bits)
1914748a724SPali Rohár {
1924748a724SPali Rohár 	u32 acr;
1934748a724SPali Rohár 
1944748a724SPali Rohár 	/* Read ACR */
1954748a724SPali Rohár 	asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
1964748a724SPali Rohár 	acr &= ~clear_bits;
1974748a724SPali Rohár 	acr |= set_bits;
1984748a724SPali Rohár 
1994748a724SPali Rohár 	return rx51_secure_dispatcher(RX51_PPA_WRITE_ACR,
2004748a724SPali Rohár 				      0,
2014748a724SPali Rohár 				      FLAG_START_CRITICAL,
2024748a724SPali Rohár 				      1, acr, 0, 0, 0);
2034748a724SPali Rohár }
204d2065e2bSPali Rohár 
205d2065e2bSPali Rohár /**
206d2065e2bSPali Rohár  * rx51_secure_rng_call: Routine for HW random generator
207d2065e2bSPali Rohár  */
rx51_secure_rng_call(u32 ptr,u32 count,u32 flag)208d2065e2bSPali Rohár u32 rx51_secure_rng_call(u32 ptr, u32 count, u32 flag)
209d2065e2bSPali Rohár {
210d2065e2bSPali Rohár 	return rx51_secure_dispatcher(RX51_PPA_HWRNG,
211d2065e2bSPali Rohár 				      0,
212d2065e2bSPali Rohár 				      NO_FLAG,
213d2065e2bSPali Rohár 				      3, ptr, count, flag, 0);
214d2065e2bSPali Rohár }
215db711893SAndrew F. Davis 
omap_secure_init(void)216db711893SAndrew F. Davis void __init omap_secure_init(void)
217db711893SAndrew F. Davis {
218dbebc8bfSAndrew F. Davis 	omap_optee_init_check();
219db711893SAndrew F. Davis }
220b3d09a06SCarlos Leija 
221b3d09a06SCarlos Leija /*
222b3d09a06SCarlos Leija  * Dummy dispatcher call after core OSWR and MPU off. Updates the ROM return
223b3d09a06SCarlos Leija  * address after MMU has been re-enabled after CPU1 has been woken up again.
224b3d09a06SCarlos Leija  * Otherwise the ROM code will attempt to use the earlier physical return
225b3d09a06SCarlos Leija  * address that got set with MMU off when waking up CPU1. Only used on secure
226b3d09a06SCarlos Leija  * devices.
227b3d09a06SCarlos Leija  */
cpu_notifier(struct notifier_block * nb,unsigned long cmd,void * v)228b3d09a06SCarlos Leija static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v)
229b3d09a06SCarlos Leija {
230b3d09a06SCarlos Leija 	switch (cmd) {
231b3d09a06SCarlos Leija 	case CPU_CLUSTER_PM_EXIT:
232b3d09a06SCarlos Leija 		omap_secure_dispatcher(OMAP4_PPA_SERVICE_0,
233b3d09a06SCarlos Leija 				       FLAG_START_CRITICAL,
234b3d09a06SCarlos Leija 				       0, 0, 0, 0, 0);
235b3d09a06SCarlos Leija 		break;
236b3d09a06SCarlos Leija 	default:
237b3d09a06SCarlos Leija 		break;
238b3d09a06SCarlos Leija 	}
239b3d09a06SCarlos Leija 
240b3d09a06SCarlos Leija 	return NOTIFY_OK;
241b3d09a06SCarlos Leija }
242b3d09a06SCarlos Leija 
243b3d09a06SCarlos Leija static struct notifier_block secure_notifier_block = {
244b3d09a06SCarlos Leija 	.notifier_call = cpu_notifier,
245b3d09a06SCarlos Leija };
246b3d09a06SCarlos Leija 
secure_pm_init(void)247b3d09a06SCarlos Leija static int __init secure_pm_init(void)
248b3d09a06SCarlos Leija {
249b3d09a06SCarlos Leija 	if (omap_type() == OMAP2_DEVICE_TYPE_GP || !soc_is_omap44xx())
250b3d09a06SCarlos Leija 		return 0;
251b3d09a06SCarlos Leija 
252b3d09a06SCarlos Leija 	cpu_pm_register_notifier(&secure_notifier_block);
253b3d09a06SCarlos Leija 
254b3d09a06SCarlos Leija 	return 0;
255b3d09a06SCarlos Leija }
256b3d09a06SCarlos Leija omap_arch_initcall(secure_pm_init);
257