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