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/device.h> 11 #include <linux/err.h> 12 #include <linux/interrupt.h> 13 #include <linux/mutex.h> 14 #include <linux/of.h> 15 #include <linux/of_address.h> 16 #include <linux/of_irq.h> 17 #include <linux/slab.h> 18 19 #include "common.h" 20 21 /** 22 * struct scmi_smc - Structure representing a SCMI smc transport 23 * 24 * @cinfo: SCMI channel info 25 * @shmem: Transmit/Receive shared memory area 26 * @shmem_lock: Lock to protect access to Tx/Rx shared memory area 27 * @func_id: smc/hvc call function id 28 * @irq: Optional; employed when platforms indicates msg completion by intr. 29 * @tx_complete: Optional, employed only when irq is valid. 30 */ 31 32 struct scmi_smc { 33 struct scmi_chan_info *cinfo; 34 struct scmi_shared_mem __iomem *shmem; 35 struct mutex shmem_lock; 36 u32 func_id; 37 int irq; 38 struct completion tx_complete; 39 }; 40 41 static irqreturn_t smc_msg_done_isr(int irq, void *data) 42 { 43 struct scmi_smc *scmi_info = data; 44 45 complete(&scmi_info->tx_complete); 46 47 return IRQ_HANDLED; 48 } 49 50 static bool smc_chan_available(struct device *dev, int idx) 51 { 52 struct device_node *np = of_parse_phandle(dev->of_node, "shmem", 0); 53 if (!np) 54 return false; 55 56 of_node_put(np); 57 return true; 58 } 59 60 static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, 61 bool tx) 62 { 63 struct device *cdev = cinfo->dev; 64 struct scmi_smc *scmi_info; 65 resource_size_t size; 66 struct resource res; 67 struct device_node *np; 68 u32 func_id; 69 int ret, irq; 70 71 if (!tx) 72 return -ENODEV; 73 74 scmi_info = devm_kzalloc(dev, sizeof(*scmi_info), GFP_KERNEL); 75 if (!scmi_info) 76 return -ENOMEM; 77 78 np = of_parse_phandle(cdev->of_node, "shmem", 0); 79 ret = of_address_to_resource(np, 0, &res); 80 of_node_put(np); 81 if (ret) { 82 dev_err(cdev, "failed to get SCMI Tx shared memory\n"); 83 return ret; 84 } 85 86 size = resource_size(&res); 87 scmi_info->shmem = devm_ioremap(dev, res.start, size); 88 if (!scmi_info->shmem) { 89 dev_err(dev, "failed to ioremap SCMI Tx shared memory\n"); 90 return -EADDRNOTAVAIL; 91 } 92 93 ret = of_property_read_u32(dev->of_node, "arm,smc-id", &func_id); 94 if (ret < 0) 95 return ret; 96 97 /* 98 * If there is an interrupt named "a2p", then the service and 99 * completion of a message is signaled by an interrupt rather than by 100 * the return of the SMC call. 101 */ 102 irq = of_irq_get_byname(cdev->of_node, "a2p"); 103 if (irq > 0) { 104 ret = devm_request_irq(dev, irq, smc_msg_done_isr, 105 IRQF_NO_SUSPEND, 106 dev_name(dev), scmi_info); 107 if (ret) { 108 dev_err(dev, "failed to setup SCMI smc irq\n"); 109 return ret; 110 } 111 init_completion(&scmi_info->tx_complete); 112 scmi_info->irq = irq; 113 } 114 115 scmi_info->func_id = func_id; 116 scmi_info->cinfo = cinfo; 117 mutex_init(&scmi_info->shmem_lock); 118 cinfo->transport_info = scmi_info; 119 120 return 0; 121 } 122 123 static int smc_chan_free(int id, void *p, void *data) 124 { 125 struct scmi_chan_info *cinfo = p; 126 struct scmi_smc *scmi_info = cinfo->transport_info; 127 128 cinfo->transport_info = NULL; 129 scmi_info->cinfo = NULL; 130 131 scmi_free_channel(cinfo, data, id); 132 133 return 0; 134 } 135 136 static int smc_send_message(struct scmi_chan_info *cinfo, 137 struct scmi_xfer *xfer) 138 { 139 struct scmi_smc *scmi_info = cinfo->transport_info; 140 struct arm_smccc_res res; 141 142 mutex_lock(&scmi_info->shmem_lock); 143 144 shmem_tx_prepare(scmi_info->shmem, xfer); 145 146 if (scmi_info->irq) 147 reinit_completion(&scmi_info->tx_complete); 148 149 arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res); 150 151 if (scmi_info->irq) 152 wait_for_completion(&scmi_info->tx_complete); 153 154 scmi_rx_callback(scmi_info->cinfo, shmem_read_header(scmi_info->shmem)); 155 156 mutex_unlock(&scmi_info->shmem_lock); 157 158 /* Only SMCCC_RET_NOT_SUPPORTED is valid error code */ 159 if (res.a0) 160 return -EOPNOTSUPP; 161 return 0; 162 } 163 164 static void smc_fetch_response(struct scmi_chan_info *cinfo, 165 struct scmi_xfer *xfer) 166 { 167 struct scmi_smc *scmi_info = cinfo->transport_info; 168 169 shmem_fetch_response(scmi_info->shmem, xfer); 170 } 171 172 static bool 173 smc_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer) 174 { 175 struct scmi_smc *scmi_info = cinfo->transport_info; 176 177 return shmem_poll_done(scmi_info->shmem, xfer); 178 } 179 180 static const struct scmi_transport_ops scmi_smc_ops = { 181 .chan_available = smc_chan_available, 182 .chan_setup = smc_chan_setup, 183 .chan_free = smc_chan_free, 184 .send_message = smc_send_message, 185 .fetch_response = smc_fetch_response, 186 .poll_done = smc_poll_done, 187 }; 188 189 const struct scmi_desc scmi_smc_desc = { 190 .ops = &scmi_smc_ops, 191 .max_rx_timeout_ms = 30, 192 .max_msg = 20, 193 .max_msg_size = 128, 194 }; 195