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 = "brcm,kona-smc"}, 40 {.compatible = "bcm,kona-smc"}, /* deprecated name */ 41 {}, 42 }; 43 44 /* Map in the bounce area */ 45 int __init bcm_kona_smc_init(void) 46 { 47 struct device_node *node; 48 49 /* Read buffer addr and size from the device tree node */ 50 node = of_find_matching_node(NULL, bcm_kona_smc_ids); 51 if (!node) 52 return -ENODEV; 53 54 /* Don't care about size or flags of the DT node */ 55 bridge_data.buffer_addr = 56 be32_to_cpu(*of_get_address(node, 0, NULL, NULL)); 57 BUG_ON(!bridge_data.buffer_addr); 58 59 bridge_data.bounce = of_iomap(node, 0); 60 BUG_ON(!bridge_data.bounce); 61 62 bridge_data.initialized = 1; 63 64 pr_info("Kona Secure API initialized\n"); 65 66 return 0; 67 } 68 69 /* __bcm_kona_smc() should only run on CPU 0, with pre-emption disabled */ 70 static void __bcm_kona_smc(void *info) 71 { 72 struct bcm_kona_smc_data *data = info; 73 u32 *args = bridge_data.bounce; 74 int rc = 0; 75 76 /* Must run on CPU 0 */ 77 BUG_ON(smp_processor_id() != 0); 78 79 /* Check map in the bounce area */ 80 BUG_ON(!bridge_data.initialized); 81 82 /* Copy one 32 bit word into the bounce area */ 83 args[0] = data->arg0; 84 args[1] = data->arg1; 85 args[2] = data->arg2; 86 args[3] = data->arg3; 87 88 /* Flush caches for input data passed to Secure Monitor */ 89 if (data->service_id != SSAPI_BRCM_START_VC_CORE) 90 flush_cache_all(); 91 92 /* Trap into Secure Monitor */ 93 rc = bcm_kona_smc_asm(data->service_id, bridge_data.buffer_addr); 94 95 if (rc != SEC_ROM_RET_OK) 96 pr_err("Secure Monitor call failed (0x%x)!\n", rc); 97 } 98 99 unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, 100 unsigned arg2, unsigned arg3) 101 { 102 struct bcm_kona_smc_data data; 103 104 data.service_id = service_id; 105 data.arg0 = arg0; 106 data.arg1 = arg1; 107 data.arg2 = arg2; 108 data.arg3 = arg3; 109 110 /* 111 * Due to a limitation of the secure monitor, we must use the SMP 112 * infrastructure to forward all secure monitor calls to Core 0. 113 */ 114 if (get_cpu() != 0) 115 smp_call_function_single(0, __bcm_kona_smc, (void *)&data, 1); 116 else 117 __bcm_kona_smc(&data); 118 119 put_cpu(); 120 121 return 0; 122 } 123