1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright (C) 2013 Broadcom Corporation 3 #include <linux/smp.h> 4 #include <linux/io.h> 5 #include <linux/ioport.h> 6 7 #include <asm/cacheflush.h> 8 #include <linux/of_address.h> 9 10 #include "bcm_kona_smc.h" 11 12 static u32 bcm_smc_buffer_phys; /* physical address */ 13 static void __iomem *bcm_smc_buffer; /* virtual address */ 14 15 struct bcm_kona_smc_data { 16 unsigned service_id; 17 unsigned arg0; 18 unsigned arg1; 19 unsigned arg2; 20 unsigned arg3; 21 unsigned result; 22 }; 23 24 static const struct of_device_id bcm_kona_smc_ids[] __initconst = { 25 {.compatible = "brcm,kona-smc"}, 26 {.compatible = "bcm,kona-smc"}, /* deprecated name */ 27 {}, 28 }; 29 30 /* Map in the args buffer area */ 31 int __init bcm_kona_smc_init(void) 32 { 33 struct device_node *node; 34 const __be32 *prop_val; 35 u64 prop_size = 0; 36 unsigned long buffer_size; 37 u32 buffer_phys; 38 39 /* Read buffer addr and size from the device tree node */ 40 node = of_find_matching_node(NULL, bcm_kona_smc_ids); 41 if (!node) 42 return -ENODEV; 43 44 prop_val = of_get_address(node, 0, &prop_size, NULL); 45 of_node_put(node); 46 if (!prop_val) 47 return -EINVAL; 48 49 /* We assume space for four 32-bit arguments */ 50 if (prop_size < 4 * sizeof(u32) || prop_size > (u64)ULONG_MAX) 51 return -EINVAL; 52 buffer_size = (unsigned long)prop_size; 53 54 buffer_phys = be32_to_cpup(prop_val); 55 if (!buffer_phys) 56 return -EINVAL; 57 58 bcm_smc_buffer = ioremap(buffer_phys, buffer_size); 59 if (!bcm_smc_buffer) 60 return -ENOMEM; 61 bcm_smc_buffer_phys = buffer_phys; 62 63 pr_info("Kona Secure API initialized\n"); 64 65 return 0; 66 } 67 68 /* 69 * int bcm_kona_do_smc(u32 service_id, u32 buffer_addr) 70 * 71 * Only core 0 can run the secure monitor code. If an "smc" request 72 * is initiated on a different core it must be redirected to core 0 73 * for execution. We rely on the caller to handle this. 74 * 75 * Each "smc" request supplies a service id and the address of a 76 * buffer containing parameters related to the service to be 77 * performed. A flags value defines the behavior of the level 2 78 * cache and interrupt handling while the secure monitor executes. 79 * 80 * Parameters to the "smc" request are passed in r4-r6 as follows: 81 * r4 service id 82 * r5 flags (SEC_ROM_*) 83 * r6 physical address of buffer with other parameters 84 * 85 * Execution of an "smc" request produces two distinct results. 86 * 87 * First, the secure monitor call itself (regardless of the specific 88 * service request) can succeed, or can produce an error. When an 89 * "smc" request completes this value is found in r12; it should 90 * always be SEC_EXIT_NORMAL. 91 * 92 * In addition, the particular service performed produces a result. 93 * The values that should be expected depend on the service. We 94 * therefore return this value to the caller, so it can handle the 95 * request result appropriately. This result value is found in r0 96 * when the "smc" request completes. 97 */ 98 static int bcm_kona_do_smc(u32 service_id, u32 buffer_phys) 99 { 100 register u32 ip asm("ip"); /* Also called r12 */ 101 register u32 r0 asm("r0"); 102 register u32 r4 asm("r4"); 103 register u32 r5 asm("r5"); 104 register u32 r6 asm("r6"); 105 106 r4 = service_id; 107 r5 = 0x3; /* Keep IRQ and FIQ off in SM */ 108 r6 = buffer_phys; 109 110 asm volatile ( 111 /* Make sure we got the registers we want */ 112 __asmeq("%0", "ip") 113 __asmeq("%1", "r0") 114 __asmeq("%2", "r4") 115 __asmeq("%3", "r5") 116 __asmeq("%4", "r6") 117 ".arch_extension sec\n" 118 " smc #0\n" 119 : "=r" (ip), "=r" (r0) 120 : "r" (r4), "r" (r5), "r" (r6) 121 : "r1", "r2", "r3", "r7", "lr"); 122 123 BUG_ON(ip != SEC_EXIT_NORMAL); 124 125 return r0; 126 } 127 128 /* __bcm_kona_smc() should only run on CPU 0, with pre-emption disabled */ 129 static void __bcm_kona_smc(void *info) 130 { 131 struct bcm_kona_smc_data *data = info; 132 u32 __iomem *args = bcm_smc_buffer; 133 134 BUG_ON(smp_processor_id() != 0); 135 BUG_ON(!args); 136 137 /* Copy the four 32 bit argument values into the bounce area */ 138 writel_relaxed(data->arg0, args++); 139 writel_relaxed(data->arg1, args++); 140 writel_relaxed(data->arg2, args++); 141 writel(data->arg3, args); 142 143 /* Flush caches for input data passed to Secure Monitor */ 144 flush_cache_all(); 145 146 /* Trap into Secure Monitor and record the request result */ 147 data->result = bcm_kona_do_smc(data->service_id, bcm_smc_buffer_phys); 148 } 149 150 unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, 151 unsigned arg2, unsigned arg3) 152 { 153 struct bcm_kona_smc_data data; 154 155 data.service_id = service_id; 156 data.arg0 = arg0; 157 data.arg1 = arg1; 158 data.arg2 = arg2; 159 data.arg3 = arg3; 160 data.result = 0; 161 162 /* 163 * Due to a limitation of the secure monitor, we must use the SMP 164 * infrastructure to forward all secure monitor calls to Core 0. 165 */ 166 smp_call_function_single(0, __bcm_kona_smc, &data, 1); 167 168 return data.result; 169 } 170