1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * System Control and Management Interface (SCMI) Message SMC/HVC 4 * Transport driver 5 * 6 * Copyright 2020 NXP 7 */ 8 9 #include <linux/arm-smccc.h> 10 #include <linux/atomic.h> 11 #include <linux/device.h> 12 #include <linux/err.h> 13 #include <linux/interrupt.h> 14 #include <linux/mutex.h> 15 #include <linux/of.h> 16 #include <linux/of_address.h> 17 #include <linux/of_irq.h> 18 #include <linux/limits.h> 19 #include <linux/platform_device.h> 20 #include <linux/processor.h> 21 #include <linux/slab.h> 22 23 #include "../common.h" 24 25 /* 26 * The shmem address is split into 4K page and offset. 27 * This is to make sure the parameters fit in 32bit arguments of the 28 * smc/hvc call to keep it uniform across smc32/smc64 conventions. 29 * This however limits the shmem address to 44 bit. 30 * 31 * These optional parameters can be used to distinguish among multiple 32 * scmi instances that are using the same smc-id. 33 * The page parameter is passed in r1/x1/w1 register and the offset parameter 34 * is passed in r2/x2/w2 register. 35 */ 36 37 #define SHMEM_SIZE (SZ_4K) 38 #define SHMEM_SHIFT 12 39 #define SHMEM_PAGE(x) (_UL((x) >> SHMEM_SHIFT)) 40 #define SHMEM_OFFSET(x) ((x) & (SHMEM_SIZE - 1)) 41 42 /** 43 * struct scmi_smc - Structure representing a SCMI smc transport 44 * 45 * @irq: An optional IRQ for completion 46 * @cinfo: SCMI channel info 47 * @shmem: Transmit/Receive shared memory area 48 * @shmem_lock: Lock to protect access to Tx/Rx shared memory area. 49 * Used when NOT operating in atomic mode. 50 * @inflight: Atomic flag to protect access to Tx/Rx shared memory area. 51 * Used when operating in atomic mode. 52 * @func_id: smc/hvc call function id 53 * @param_page: 4K page number of the shmem channel 54 * @param_offset: Offset within the 4K page of the shmem channel 55 * @cap_id: smc/hvc doorbell's capability id to be used on Qualcomm virtual 56 * platforms 57 */ 58 59 struct scmi_smc { 60 int irq; 61 struct scmi_chan_info *cinfo; 62 struct scmi_shared_mem __iomem *shmem; 63 /* Protect access to shmem area */ 64 struct mutex shmem_lock; 65 #define INFLIGHT_NONE MSG_TOKEN_MAX 66 atomic_t inflight; 67 unsigned long func_id; 68 unsigned long param_page; 69 unsigned long param_offset; 70 unsigned long cap_id; 71 }; 72 73 static struct scmi_transport_core_operations *core; 74 75 static irqreturn_t smc_msg_done_isr(int irq, void *data) 76 { 77 struct scmi_smc *scmi_info = data; 78 79 core->rx_callback(scmi_info->cinfo, 80 core->shmem->read_header(scmi_info->shmem), NULL); 81 82 return IRQ_HANDLED; 83 } 84 85 static bool smc_chan_available(struct device_node *of_node, int idx) 86 { 87 struct device_node *np __free(device_node) = 88 of_parse_phandle(of_node, "shmem", 0); 89 if (!np) 90 return false; 91 92 return true; 93 } 94 95 static inline void smc_channel_lock_init(struct scmi_smc *scmi_info) 96 { 97 if (IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE)) 98 atomic_set(&scmi_info->inflight, INFLIGHT_NONE); 99 else 100 mutex_init(&scmi_info->shmem_lock); 101 } 102 103 static bool smc_xfer_inflight(struct scmi_xfer *xfer, atomic_t *inflight) 104 { 105 int ret; 106 107 ret = atomic_cmpxchg(inflight, INFLIGHT_NONE, xfer->hdr.seq); 108 109 return ret == INFLIGHT_NONE; 110 } 111 112 static inline void 113 smc_channel_lock_acquire(struct scmi_smc *scmi_info, 114 struct scmi_xfer *xfer __maybe_unused) 115 { 116 if (IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE)) 117 spin_until_cond(smc_xfer_inflight(xfer, &scmi_info->inflight)); 118 else 119 mutex_lock(&scmi_info->shmem_lock); 120 } 121 122 static inline void smc_channel_lock_release(struct scmi_smc *scmi_info) 123 { 124 if (IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE)) 125 atomic_set(&scmi_info->inflight, INFLIGHT_NONE); 126 else 127 mutex_unlock(&scmi_info->shmem_lock); 128 } 129 130 static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, 131 bool tx) 132 { 133 struct device *cdev = cinfo->dev; 134 unsigned long cap_id = ULONG_MAX; 135 struct scmi_smc *scmi_info; 136 struct resource res = {}; 137 u32 func_id; 138 int ret; 139 140 if (!tx) 141 return -ENODEV; 142 143 scmi_info = devm_kzalloc(dev, sizeof(*scmi_info), GFP_KERNEL); 144 if (!scmi_info) 145 return -ENOMEM; 146 147 scmi_info->shmem = core->shmem->setup_iomap(cinfo, dev, tx, &res); 148 if (IS_ERR(scmi_info->shmem)) 149 return PTR_ERR(scmi_info->shmem); 150 151 ret = of_property_read_u32(dev->of_node, "arm,smc-id", &func_id); 152 if (ret < 0) 153 return ret; 154 155 if (of_device_is_compatible(dev->of_node, "qcom,scmi-smc")) { 156 resource_size_t size = resource_size(&res); 157 void __iomem *ptr = (void __iomem *)scmi_info->shmem + size - 8; 158 /* The capability-id is kept in last 8 bytes of shmem. 159 * +-------+ <-- 0 160 * | shmem | 161 * +-------+ <-- size - 8 162 * | capId | 163 * +-------+ <-- size 164 */ 165 memcpy_fromio(&cap_id, ptr, sizeof(cap_id)); 166 } 167 168 if (of_device_is_compatible(dev->of_node, "arm,scmi-smc-param")) { 169 scmi_info->param_page = SHMEM_PAGE(res.start); 170 scmi_info->param_offset = SHMEM_OFFSET(res.start); 171 } 172 /* 173 * If there is an interrupt named "a2p", then the service and 174 * completion of a message is signaled by an interrupt rather than by 175 * the return of the SMC call. 176 */ 177 scmi_info->irq = of_irq_get_byname(cdev->of_node, "a2p"); 178 if (scmi_info->irq > 0) { 179 ret = request_irq(scmi_info->irq, smc_msg_done_isr, 180 IRQF_NO_SUSPEND, dev_name(dev), scmi_info); 181 if (ret) { 182 dev_err(dev, "failed to setup SCMI smc irq\n"); 183 return ret; 184 } 185 } else { 186 cinfo->no_completion_irq = true; 187 } 188 189 scmi_info->func_id = func_id; 190 scmi_info->cap_id = cap_id; 191 scmi_info->cinfo = cinfo; 192 smc_channel_lock_init(scmi_info); 193 cinfo->transport_info = scmi_info; 194 195 return 0; 196 } 197 198 static int smc_chan_free(int id, void *p, void *data) 199 { 200 struct scmi_chan_info *cinfo = p; 201 struct scmi_smc *scmi_info = cinfo->transport_info; 202 203 /* 204 * Different protocols might share the same chan info, so a previous 205 * smc_chan_free call might have already freed the structure. 206 */ 207 if (!scmi_info) 208 return 0; 209 210 /* Ignore any possible further reception on the IRQ path */ 211 if (scmi_info->irq > 0) 212 free_irq(scmi_info->irq, scmi_info); 213 214 cinfo->transport_info = NULL; 215 scmi_info->cinfo = NULL; 216 217 return 0; 218 } 219 220 static int smc_send_message(struct scmi_chan_info *cinfo, 221 struct scmi_xfer *xfer) 222 { 223 struct scmi_smc *scmi_info = cinfo->transport_info; 224 struct arm_smccc_res res; 225 226 /* 227 * Channel will be released only once response has been 228 * surely fully retrieved, so after .mark_txdone() 229 */ 230 smc_channel_lock_acquire(scmi_info, xfer); 231 232 core->shmem->tx_prepare(scmi_info->shmem, xfer, cinfo); 233 234 if (scmi_info->cap_id != ULONG_MAX) 235 arm_smccc_1_1_invoke(scmi_info->func_id, scmi_info->cap_id, 0, 236 0, 0, 0, 0, 0, &res); 237 else 238 arm_smccc_1_1_invoke(scmi_info->func_id, scmi_info->param_page, 239 scmi_info->param_offset, 0, 0, 0, 0, 0, 240 &res); 241 242 /* Only SMCCC_RET_NOT_SUPPORTED is valid error code */ 243 if (res.a0) { 244 smc_channel_lock_release(scmi_info); 245 return -EOPNOTSUPP; 246 } 247 248 return 0; 249 } 250 251 static void smc_fetch_response(struct scmi_chan_info *cinfo, 252 struct scmi_xfer *xfer) 253 { 254 struct scmi_smc *scmi_info = cinfo->transport_info; 255 256 core->shmem->fetch_response(scmi_info->shmem, xfer); 257 } 258 259 static void smc_mark_txdone(struct scmi_chan_info *cinfo, int ret, 260 struct scmi_xfer *__unused) 261 { 262 struct scmi_smc *scmi_info = cinfo->transport_info; 263 264 smc_channel_lock_release(scmi_info); 265 } 266 267 static const struct scmi_transport_ops scmi_smc_ops = { 268 .chan_available = smc_chan_available, 269 .chan_setup = smc_chan_setup, 270 .chan_free = smc_chan_free, 271 .send_message = smc_send_message, 272 .mark_txdone = smc_mark_txdone, 273 .fetch_response = smc_fetch_response, 274 }; 275 276 static struct scmi_desc scmi_smc_desc = { 277 .ops = &scmi_smc_ops, 278 .max_rx_timeout_ms = 30, 279 .max_msg = 20, 280 .max_msg_size = 128, 281 /* 282 * Setting .sync_cmds_atomic_replies to true for SMC assumes that, 283 * once the SMC instruction has completed successfully, the issued 284 * SCMI command would have been already fully processed by the SCMI 285 * platform firmware and so any possible response value expected 286 * for the issued command will be immmediately ready to be fetched 287 * from the shared memory area. 288 */ 289 .sync_cmds_completed_on_ret = true, 290 .atomic_enabled = IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE), 291 }; 292 293 static const struct of_device_id scmi_of_match[] = { 294 { .compatible = "arm,scmi-smc" }, 295 { .compatible = "arm,scmi-smc-param" }, 296 { .compatible = "qcom,scmi-smc" }, 297 { /* Sentinel */ }, 298 }; 299 300 DEFINE_SCMI_TRANSPORT_DRIVER(scmi_smc, scmi_smc_driver, scmi_smc_desc, 301 scmi_of_match, core); 302 module_platform_driver(scmi_smc_driver); 303 304 MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>"); 305 MODULE_AUTHOR("Nikunj Kela <quic_nkela@quicinc.com>"); 306 MODULE_DESCRIPTION("SCMI SMC Transport driver"); 307 MODULE_LICENSE("GPL"); 308