1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * System Control and Management Interface (SCMI) Message Mailbox Transport 4 * driver. 5 * 6 * Copyright (C) 2019-2024 ARM Ltd. 7 */ 8 9 #include <linux/err.h> 10 #include <linux/device.h> 11 #include <linux/mailbox_client.h> 12 #include <linux/of.h> 13 #include <linux/of_address.h> 14 #include <linux/platform_device.h> 15 #include <linux/slab.h> 16 17 #include "../common.h" 18 19 /** 20 * struct scmi_mailbox - Structure representing a SCMI mailbox transport 21 * 22 * @cl: Mailbox Client 23 * @chan: Transmit/Receive mailbox uni/bi-directional channel 24 * @chan_receiver: Optional Receiver mailbox unidirectional channel 25 * @chan_platform_receiver: Optional Platform Receiver mailbox unidirectional channel 26 * @cinfo: SCMI channel info 27 * @shmem: Transmit/Receive shared memory area 28 */ 29 struct scmi_mailbox { 30 struct mbox_client cl; 31 struct mbox_chan *chan; 32 struct mbox_chan *chan_receiver; 33 struct mbox_chan *chan_platform_receiver; 34 struct scmi_chan_info *cinfo; 35 struct scmi_shared_mem __iomem *shmem; 36 }; 37 38 #define client_to_scmi_mailbox(c) container_of(c, struct scmi_mailbox, cl) 39 40 static struct scmi_transport_core_operations *core; 41 42 static void tx_prepare(struct mbox_client *cl, void *m) 43 { 44 struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl); 45 46 core->shmem->tx_prepare(smbox->shmem, m, smbox->cinfo); 47 } 48 49 static void rx_callback(struct mbox_client *cl, void *m) 50 { 51 struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl); 52 53 /* 54 * An A2P IRQ is NOT valid when received while the platform still has 55 * the ownership of the channel, because the platform at first releases 56 * the SMT channel and then sends the completion interrupt. 57 * 58 * This addresses a possible race condition in which a spurious IRQ from 59 * a previous timed-out reply which arrived late could be wrongly 60 * associated with the next pending transaction. 61 */ 62 if (cl->knows_txdone && 63 !core->shmem->channel_free(smbox->shmem)) { 64 dev_warn(smbox->cinfo->dev, "Ignoring spurious A2P IRQ !\n"); 65 core->bad_message_trace(smbox->cinfo, 66 core->shmem->read_header(smbox->shmem), 67 MSG_MBOX_SPURIOUS); 68 return; 69 } 70 71 core->rx_callback(smbox->cinfo, 72 core->shmem->read_header(smbox->shmem), NULL); 73 } 74 75 static bool mailbox_chan_available(struct device_node *of_node, int idx) 76 { 77 int num_mb; 78 79 /* 80 * Just check if bidirrectional channels are involved, and check the 81 * index accordingly; proper full validation will be made later 82 * in mailbox_chan_setup(). 83 */ 84 num_mb = of_count_phandle_with_args(of_node, "mboxes", "#mbox-cells"); 85 if (num_mb == 3 && idx == 1) 86 idx = 2; 87 88 return !of_parse_phandle_with_args(of_node, "mboxes", 89 "#mbox-cells", idx, NULL); 90 } 91 92 /** 93 * mailbox_chan_validate - Validate transport configuration and map channels 94 * 95 * @cdev: Reference to the underlying transport device carrying the 96 * of_node descriptor to analyze. 97 * @a2p_rx_chan: A reference to an optional unidirectional channel to use 98 * for replies on the a2p channel. Set as zero if not present. 99 * @p2a_chan: A reference to the optional p2a channel. 100 * Set as zero if not present. 101 * @p2a_rx_chan: A reference to the optional p2a completion channel. 102 * Set as zero if not present. 103 * 104 * At first, validate the transport configuration as described in terms of 105 * 'mboxes' and 'shmem', then determin which mailbox channel indexes are 106 * appropriate to be use in the current configuration. 107 * 108 * Return: 0 on Success or error 109 */ 110 static int mailbox_chan_validate(struct device *cdev, int *a2p_rx_chan, 111 int *p2a_chan, int *p2a_rx_chan) 112 { 113 int num_mb, num_sh, ret = 0; 114 struct device_node *np = cdev->of_node; 115 116 num_mb = of_count_phandle_with_args(np, "mboxes", "#mbox-cells"); 117 num_sh = of_count_phandle_with_args(np, "shmem", NULL); 118 dev_dbg(cdev, "Found %d mboxes and %d shmems !\n", num_mb, num_sh); 119 120 /* Bail out if mboxes and shmem descriptors are inconsistent */ 121 if (num_mb <= 0 || num_sh <= 0 || num_sh > 2 || num_mb > 4 || 122 (num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2) || 123 (num_mb == 4 && num_sh != 2)) { 124 dev_warn(cdev, 125 "Invalid channel descriptor for '%s' - mbs:%d shm:%d\n", 126 of_node_full_name(np), num_mb, num_sh); 127 return -EINVAL; 128 } 129 130 /* Bail out if provided shmem descriptors do not refer distinct areas */ 131 if (num_sh > 1) { 132 struct device_node *np_tx __free(device_node) = 133 of_parse_phandle(np, "shmem", 0); 134 struct device_node *np_rx __free(device_node) = 135 of_parse_phandle(np, "shmem", 1); 136 137 if (!np_tx || !np_rx || np_tx == np_rx) { 138 dev_warn(cdev, "Invalid shmem descriptor for '%s'\n", 139 of_node_full_name(np)); 140 ret = -EINVAL; 141 } 142 } 143 144 /* Calculate channels IDs to use depending on mboxes/shmem layout */ 145 if (!ret) { 146 switch (num_mb) { 147 case 1: 148 *a2p_rx_chan = 0; 149 *p2a_chan = 0; 150 *p2a_rx_chan = 0; 151 break; 152 case 2: 153 if (num_sh == 2) { 154 *a2p_rx_chan = 0; 155 *p2a_chan = 1; 156 } else { 157 *a2p_rx_chan = 1; 158 *p2a_chan = 0; 159 } 160 *p2a_rx_chan = 0; 161 break; 162 case 3: 163 *a2p_rx_chan = 1; 164 *p2a_chan = 2; 165 *p2a_rx_chan = 0; 166 break; 167 case 4: 168 *a2p_rx_chan = 1; 169 *p2a_chan = 2; 170 *p2a_rx_chan = 3; 171 break; 172 } 173 } 174 175 return ret; 176 } 177 178 static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, 179 bool tx) 180 { 181 const char *desc = tx ? "Tx" : "Rx"; 182 struct device *cdev = cinfo->dev; 183 struct scmi_mailbox *smbox; 184 int ret, a2p_rx_chan, p2a_chan, p2a_rx_chan; 185 struct mbox_client *cl; 186 187 ret = mailbox_chan_validate(cdev, &a2p_rx_chan, &p2a_chan, &p2a_rx_chan); 188 if (ret) 189 return ret; 190 191 if (!tx && !p2a_chan) 192 return -ENODEV; 193 194 smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL); 195 if (!smbox) 196 return -ENOMEM; 197 198 smbox->shmem = core->shmem->setup_iomap(cinfo, dev, tx, NULL); 199 if (IS_ERR(smbox->shmem)) 200 return PTR_ERR(smbox->shmem); 201 202 cl = &smbox->cl; 203 cl->dev = cdev; 204 cl->tx_prepare = tx ? tx_prepare : NULL; 205 cl->rx_callback = rx_callback; 206 cl->tx_block = false; 207 cl->knows_txdone = tx; 208 209 smbox->chan = mbox_request_channel(cl, tx ? 0 : p2a_chan); 210 if (IS_ERR(smbox->chan)) { 211 ret = PTR_ERR(smbox->chan); 212 if (ret != -EPROBE_DEFER) 213 dev_err(cdev, 214 "failed to request SCMI %s mailbox\n", desc); 215 return ret; 216 } 217 218 /* Additional unidirectional channel for TX if needed */ 219 if (tx && a2p_rx_chan) { 220 smbox->chan_receiver = mbox_request_channel(cl, a2p_rx_chan); 221 if (IS_ERR(smbox->chan_receiver)) { 222 ret = PTR_ERR(smbox->chan_receiver); 223 if (ret != -EPROBE_DEFER) 224 dev_err(cdev, "failed to request SCMI Tx Receiver mailbox\n"); 225 return ret; 226 } 227 } 228 229 if (!tx && p2a_rx_chan) { 230 smbox->chan_platform_receiver = mbox_request_channel(cl, p2a_rx_chan); 231 if (IS_ERR(smbox->chan_platform_receiver)) { 232 ret = PTR_ERR(smbox->chan_platform_receiver); 233 if (ret != -EPROBE_DEFER) 234 dev_err(cdev, "failed to request SCMI P2A Receiver mailbox\n"); 235 return ret; 236 } 237 } 238 239 cinfo->transport_info = smbox; 240 smbox->cinfo = cinfo; 241 242 return 0; 243 } 244 245 static int mailbox_chan_free(int id, void *p, void *data) 246 { 247 struct scmi_chan_info *cinfo = p; 248 struct scmi_mailbox *smbox = cinfo->transport_info; 249 250 if (smbox && !IS_ERR(smbox->chan)) { 251 mbox_free_channel(smbox->chan); 252 mbox_free_channel(smbox->chan_receiver); 253 mbox_free_channel(smbox->chan_platform_receiver); 254 cinfo->transport_info = NULL; 255 smbox->chan = NULL; 256 smbox->chan_receiver = NULL; 257 smbox->chan_platform_receiver = NULL; 258 smbox->cinfo = NULL; 259 } 260 261 return 0; 262 } 263 264 static int mailbox_send_message(struct scmi_chan_info *cinfo, 265 struct scmi_xfer *xfer) 266 { 267 struct scmi_mailbox *smbox = cinfo->transport_info; 268 int ret; 269 270 ret = mbox_send_message(smbox->chan, xfer); 271 272 /* mbox_send_message returns non-negative value on success, so reset */ 273 if (ret > 0) 274 ret = 0; 275 276 return ret; 277 } 278 279 static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret, 280 struct scmi_xfer *__unused) 281 { 282 struct scmi_mailbox *smbox = cinfo->transport_info; 283 284 /* 285 * NOTE: we might prefer not to need the mailbox ticker to manage the 286 * transfer queueing since the protocol layer queues things by itself. 287 * Unfortunately, we have to kick the mailbox framework after we have 288 * received our message. 289 */ 290 mbox_client_txdone(smbox->chan, ret); 291 } 292 293 static void mailbox_fetch_response(struct scmi_chan_info *cinfo, 294 struct scmi_xfer *xfer) 295 { 296 struct scmi_mailbox *smbox = cinfo->transport_info; 297 298 core->shmem->fetch_response(smbox->shmem, xfer); 299 } 300 301 static void mailbox_fetch_notification(struct scmi_chan_info *cinfo, 302 size_t max_len, struct scmi_xfer *xfer) 303 { 304 struct scmi_mailbox *smbox = cinfo->transport_info; 305 306 core->shmem->fetch_notification(smbox->shmem, max_len, xfer); 307 } 308 309 static void mailbox_clear_channel(struct scmi_chan_info *cinfo) 310 { 311 struct scmi_mailbox *smbox = cinfo->transport_info; 312 struct mbox_chan *intr_chan; 313 int ret; 314 315 core->shmem->clear_channel(smbox->shmem); 316 317 if (!core->shmem->channel_intr_enabled(smbox->shmem)) 318 return; 319 320 if (smbox->chan_platform_receiver) 321 intr_chan = smbox->chan_platform_receiver; 322 else if (smbox->chan) 323 intr_chan = smbox->chan; 324 else 325 return; 326 327 ret = mbox_send_message(intr_chan, NULL); 328 /* mbox_send_message returns non-negative value on success, so reset */ 329 if (ret > 0) 330 ret = 0; 331 332 mbox_client_txdone(intr_chan, ret); 333 } 334 335 static bool 336 mailbox_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer) 337 { 338 struct scmi_mailbox *smbox = cinfo->transport_info; 339 340 return core->shmem->poll_done(smbox->shmem, xfer); 341 } 342 343 static const struct scmi_transport_ops scmi_mailbox_ops = { 344 .chan_available = mailbox_chan_available, 345 .chan_setup = mailbox_chan_setup, 346 .chan_free = mailbox_chan_free, 347 .send_message = mailbox_send_message, 348 .mark_txdone = mailbox_mark_txdone, 349 .fetch_response = mailbox_fetch_response, 350 .fetch_notification = mailbox_fetch_notification, 351 .clear_channel = mailbox_clear_channel, 352 .poll_done = mailbox_poll_done, 353 }; 354 355 static struct scmi_desc scmi_mailbox_desc = { 356 .ops = &scmi_mailbox_ops, 357 .max_rx_timeout_ms = 30, /* We may increase this if required */ 358 .max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */ 359 .max_msg_size = 128, 360 }; 361 362 static const struct of_device_id scmi_of_match[] = { 363 { .compatible = "arm,scmi" }, 364 { /* Sentinel */ }, 365 }; 366 367 DEFINE_SCMI_TRANSPORT_DRIVER(scmi_mailbox, scmi_mailbox_driver, 368 scmi_mailbox_desc, scmi_of_match, core); 369 module_platform_driver(scmi_mailbox_driver); 370 371 MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>"); 372 MODULE_DESCRIPTION("SCMI Mailbox Transport driver"); 373 MODULE_LICENSE("GPL"); 374