xref: /openbmc/linux/arch/arm/mach-bcm/bcm_kona_smc.c (revision aea237bfa0a8ce8fe364e3fa7de6850777044a60)
1b8eb35fdSChristian Daudt /*
2b8eb35fdSChristian Daudt  * Copyright (C) 2013 Broadcom Corporation
3b8eb35fdSChristian Daudt  *
4b8eb35fdSChristian Daudt  * This program is free software; you can redistribute it and/or
5b8eb35fdSChristian Daudt  * modify it under the terms of the GNU General Public License as
6b8eb35fdSChristian Daudt  * published by the Free Software Foundation version 2.
7b8eb35fdSChristian Daudt  *
8b8eb35fdSChristian Daudt  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9b8eb35fdSChristian Daudt  * kind, whether express or implied; without even the implied warranty
10b8eb35fdSChristian Daudt  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11b8eb35fdSChristian Daudt  * GNU General Public License for more details.
12b8eb35fdSChristian Daudt  */
13b8eb35fdSChristian Daudt 
14b8eb35fdSChristian Daudt #include <stdarg.h>
15b8eb35fdSChristian Daudt #include <linux/smp.h>
16b8eb35fdSChristian Daudt #include <linux/io.h>
17b8eb35fdSChristian Daudt #include <linux/ioport.h>
18b8eb35fdSChristian Daudt 
19b8eb35fdSChristian Daudt #include <asm/cacheflush.h>
20b8eb35fdSChristian Daudt #include <linux/of_address.h>
21b8eb35fdSChristian Daudt 
22b8eb35fdSChristian Daudt #include "bcm_kona_smc.h"
23b8eb35fdSChristian Daudt 
24b8eb35fdSChristian Daudt struct secure_bridge_data {
25b8eb35fdSChristian Daudt 	void __iomem *bounce;		/* virtual address */
26b8eb35fdSChristian Daudt 	u32 __iomem buffer_addr;	/* physical address */
27b8eb35fdSChristian Daudt 	int initialized;
28b8eb35fdSChristian Daudt } bridge_data;
29b8eb35fdSChristian Daudt 
30b8eb35fdSChristian Daudt struct bcm_kona_smc_data {
31b8eb35fdSChristian Daudt 	unsigned service_id;
32b8eb35fdSChristian Daudt 	unsigned arg0;
33b8eb35fdSChristian Daudt 	unsigned arg1;
34b8eb35fdSChristian Daudt 	unsigned arg2;
35b8eb35fdSChristian Daudt 	unsigned arg3;
36b8eb35fdSChristian Daudt };
37b8eb35fdSChristian Daudt 
38b8eb35fdSChristian Daudt static const struct of_device_id bcm_kona_smc_ids[] __initconst = {
39*aea237bfSChristian Daudt 	{.compatible = "brcm,kona-smc"},
40*aea237bfSChristian Daudt 	{.compatible = "bcm,kona-smc"}, /* deprecated name */
41b8eb35fdSChristian Daudt 	{},
42b8eb35fdSChristian Daudt };
43b8eb35fdSChristian Daudt 
44b8eb35fdSChristian Daudt /* Map in the bounce area */
45721e0205SArnd Bergmann void __init bcm_kona_smc_init(void)
46b8eb35fdSChristian Daudt {
47b8eb35fdSChristian Daudt 	struct device_node *node;
48b8eb35fdSChristian Daudt 
49b8eb35fdSChristian Daudt 	/* Read buffer addr and size from the device tree node */
50b8eb35fdSChristian Daudt 	node = of_find_matching_node(NULL, bcm_kona_smc_ids);
51b8eb35fdSChristian Daudt 	BUG_ON(!node);
52b8eb35fdSChristian Daudt 
53b8eb35fdSChristian Daudt 	/* Don't care about size or flags of the DT node */
54b8eb35fdSChristian Daudt 	bridge_data.buffer_addr =
55b8eb35fdSChristian Daudt 		be32_to_cpu(*of_get_address(node, 0, NULL, NULL));
56b8eb35fdSChristian Daudt 	BUG_ON(!bridge_data.buffer_addr);
57b8eb35fdSChristian Daudt 
58b8eb35fdSChristian Daudt 	bridge_data.bounce = of_iomap(node, 0);
59b8eb35fdSChristian Daudt 	BUG_ON(!bridge_data.bounce);
60b8eb35fdSChristian Daudt 
61b8eb35fdSChristian Daudt 	bridge_data.initialized = 1;
62b8eb35fdSChristian Daudt 
63b8eb35fdSChristian Daudt 	pr_info("Secure API initialized!\n");
64b8eb35fdSChristian Daudt }
65b8eb35fdSChristian Daudt 
66b8eb35fdSChristian Daudt /* __bcm_kona_smc() should only run on CPU 0, with pre-emption disabled */
67b8eb35fdSChristian Daudt static void __bcm_kona_smc(void *info)
68b8eb35fdSChristian Daudt {
69b8eb35fdSChristian Daudt 	struct bcm_kona_smc_data *data = info;
70b8eb35fdSChristian Daudt 	u32 *args = bridge_data.bounce;
71b8eb35fdSChristian Daudt 	int rc = 0;
72b8eb35fdSChristian Daudt 
73b8eb35fdSChristian Daudt 	/* Must run on CPU 0 */
74b8eb35fdSChristian Daudt 	BUG_ON(smp_processor_id() != 0);
75b8eb35fdSChristian Daudt 
76b8eb35fdSChristian Daudt 	/* Check map in the bounce area */
77b8eb35fdSChristian Daudt 	BUG_ON(!bridge_data.initialized);
78b8eb35fdSChristian Daudt 
79b8eb35fdSChristian Daudt 	/* Copy one 32 bit word into the bounce area */
80b8eb35fdSChristian Daudt 	args[0] = data->arg0;
81b8eb35fdSChristian Daudt 	args[1] = data->arg1;
82b8eb35fdSChristian Daudt 	args[2] = data->arg2;
83b8eb35fdSChristian Daudt 	args[3] = data->arg3;
84b8eb35fdSChristian Daudt 
85b8eb35fdSChristian Daudt 	/* Flush caches for input data passed to Secure Monitor */
86b8eb35fdSChristian Daudt 	if (data->service_id != SSAPI_BRCM_START_VC_CORE)
87b8eb35fdSChristian Daudt 		flush_cache_all();
88b8eb35fdSChristian Daudt 
89b8eb35fdSChristian Daudt 	/* Trap into Secure Monitor */
90b8eb35fdSChristian Daudt 	rc = bcm_kona_smc_asm(data->service_id, bridge_data.buffer_addr);
91b8eb35fdSChristian Daudt 
92b8eb35fdSChristian Daudt 	if (rc != SEC_ROM_RET_OK)
93b8eb35fdSChristian Daudt 		pr_err("Secure Monitor call failed (0x%x)!\n", rc);
94b8eb35fdSChristian Daudt }
95b8eb35fdSChristian Daudt 
96b8eb35fdSChristian Daudt unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1,
97b8eb35fdSChristian Daudt 		  unsigned arg2, unsigned arg3)
98b8eb35fdSChristian Daudt {
99b8eb35fdSChristian Daudt 	struct bcm_kona_smc_data data;
100b8eb35fdSChristian Daudt 
101b8eb35fdSChristian Daudt 	data.service_id = service_id;
102b8eb35fdSChristian Daudt 	data.arg0 = arg0;
103b8eb35fdSChristian Daudt 	data.arg1 = arg1;
104b8eb35fdSChristian Daudt 	data.arg2 = arg2;
105b8eb35fdSChristian Daudt 	data.arg3 = arg3;
106b8eb35fdSChristian Daudt 
107b8eb35fdSChristian Daudt 	/*
108b8eb35fdSChristian Daudt 	 * Due to a limitation of the secure monitor, we must use the SMP
109b8eb35fdSChristian Daudt 	 * infrastructure to forward all secure monitor calls to Core 0.
110b8eb35fdSChristian Daudt 	 */
111b8eb35fdSChristian Daudt 	if (get_cpu() != 0)
112b8eb35fdSChristian Daudt 		smp_call_function_single(0, __bcm_kona_smc, (void *)&data, 1);
113b8eb35fdSChristian Daudt 	else
114b8eb35fdSChristian Daudt 		__bcm_kona_smc(&data);
115b8eb35fdSChristian Daudt 
116b8eb35fdSChristian Daudt 	put_cpu();
117b8eb35fdSChristian Daudt 
118b8eb35fdSChristian Daudt 	return 0;
119b8eb35fdSChristian Daudt }
120