• Home
  • Raw
  • Download

Lines Matching +full:scmi +full:- +full:smc

1 // SPDX-License-Identifier: GPL-2.0
3 * System Control and Management Interface (SCMI) Message Protocol driver
5 * SCMI Message Protocol is used between the System Control Processor(SCP)
7 * provides a mechanism for inter-processor communication between SCP's
32 #include <trace/events/scmi.h>
36 SCMI_ERR_SUPPORT = -1, /* Not supported */
37 SCMI_ERR_PARAMS = -2, /* Invalid Parameters */
38 SCMI_ERR_ACCESS = -3, /* Invalid access/permission denied */
39 SCMI_ERR_ENTRY = -4, /* Not found */
40 SCMI_ERR_RANGE = -5, /* Value out of range */
41 SCMI_ERR_BUSY = -6, /* Device busy */
42 SCMI_ERR_COMMS = -7, /* Communication Error */
43 SCMI_ERR_GENERIC = -8, /* Generic Error */
44 SCMI_ERR_HARDWARE = -9, /* Hardware Error */
45 SCMI_ERR_PROTOCOL = -10,/* Protocol Error */
48 /* List of all SCMI devices active in system */
56 * struct scmi_xfers_info - Structure to manage transfer information
71 * struct scmi_info - Structure representing a SCMI instance
75 * @version: SCMI revision information containing protocol version,
76 * implementation version and (sub-)vendor identification.
77 * @handle: Instance of SCMI handle to send to clients
106 -EOPNOTSUPP, /* SCMI_ERR_SUPPORT */
107 -EINVAL, /* SCMI_ERR_PARAM */
108 -EACCES, /* SCMI_ERR_ACCESS */
109 -ENOENT, /* SCMI_ERR_ENTRY */
110 -ERANGE, /* SCMI_ERR_RANGE */
111 -EBUSY, /* SCMI_ERR_BUSY */
112 -ECOMM, /* SCMI_ERR_COMMS */
113 -EIO, /* SCMI_ERR_GENERIC */
114 -EREMOTEIO, /* SCMI_ERR_HARDWARE */
115 -EPROTO, /* SCMI_ERR_PROTOCOL */
120 int err_idx = -errno; in scmi_to_linux_errno()
124 return -EIO; in scmi_to_linux_errno()
128 * scmi_dump_header_dbg() - Helper to dump a message header.
130 * @dev: Device pointer corresponding to the SCMI entity
137 hdr->id, hdr->seq, hdr->protocol_id); in scmi_dump_header_dbg()
141 * scmi_xfer_get() - Allocate one message
143 * @handle: Pointer to SCMI entity handle
150 * for the SCMI entity. Further, this also holds a spinlock to maintain
164 spin_lock_irqsave(&minfo->xfer_lock, flags); in scmi_xfer_get()
165 bit_pos = find_first_zero_bit(minfo->xfer_alloc_table, in scmi_xfer_get()
166 info->desc->max_msg); in scmi_xfer_get()
167 if (bit_pos == info->desc->max_msg) { in scmi_xfer_get()
168 spin_unlock_irqrestore(&minfo->xfer_lock, flags); in scmi_xfer_get()
169 return ERR_PTR(-ENOMEM); in scmi_xfer_get()
171 set_bit(bit_pos, minfo->xfer_alloc_table); in scmi_xfer_get()
172 spin_unlock_irqrestore(&minfo->xfer_lock, flags); in scmi_xfer_get()
176 xfer = &minfo->xfer_block[xfer_id]; in scmi_xfer_get()
177 xfer->hdr.seq = xfer_id; in scmi_xfer_get()
178 reinit_completion(&xfer->done); in scmi_xfer_get()
179 xfer->transfer_id = atomic_inc_return(&transfer_last_id); in scmi_xfer_get()
185 * __scmi_xfer_put() - Release a message
202 spin_lock_irqsave(&minfo->xfer_lock, flags); in __scmi_xfer_put()
203 clear_bit(xfer->hdr.seq, minfo->xfer_alloc_table); in __scmi_xfer_put()
204 spin_unlock_irqrestore(&minfo->xfer_lock, flags); in __scmi_xfer_put()
210 struct device *dev = cinfo->dev; in scmi_handle_notification()
211 struct scmi_info *info = handle_to_scmi_info(cinfo->handle); in scmi_handle_notification()
212 struct scmi_xfers_info *minfo = &info->rx_minfo; in scmi_handle_notification()
216 xfer = scmi_xfer_get(cinfo->handle, minfo); in scmi_handle_notification()
220 info->desc->ops->clear_channel(cinfo); in scmi_handle_notification()
224 unpack_scmi_header(msg_hdr, &xfer->hdr); in scmi_handle_notification()
225 scmi_dump_header_dbg(dev, &xfer->hdr); in scmi_handle_notification()
226 info->desc->ops->fetch_notification(cinfo, info->desc->max_msg_size, in scmi_handle_notification()
228 scmi_notify(cinfo->handle, xfer->hdr.protocol_id, in scmi_handle_notification()
229 xfer->hdr.id, xfer->rx.buf, xfer->rx.len, ts); in scmi_handle_notification()
231 trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id, in scmi_handle_notification()
232 xfer->hdr.protocol_id, xfer->hdr.seq, in scmi_handle_notification()
237 info->desc->ops->clear_channel(cinfo); in scmi_handle_notification()
244 struct device *dev = cinfo->dev; in scmi_handle_response()
245 struct scmi_info *info = handle_to_scmi_info(cinfo->handle); in scmi_handle_response()
246 struct scmi_xfers_info *minfo = &info->tx_minfo; in scmi_handle_response()
249 if (!test_bit(xfer_id, minfo->xfer_alloc_table)) { in scmi_handle_response()
251 info->desc->ops->clear_channel(cinfo); in scmi_handle_response()
255 xfer = &minfo->xfer_block[xfer_id]; in scmi_handle_response()
259 * delayed response we're not prepared to handle: bail-out safely in scmi_handle_response()
262 if (unlikely(msg_type == MSG_TYPE_DELAYED_RESP && !xfer->async_done)) { in scmi_handle_response()
266 info->desc->ops->clear_channel(cinfo); in scmi_handle_response()
274 xfer->rx.len = info->desc->max_msg_size; in scmi_handle_response()
276 scmi_dump_header_dbg(dev, &xfer->hdr); in scmi_handle_response()
278 info->desc->ops->fetch_response(cinfo, xfer); in scmi_handle_response()
280 trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id, in scmi_handle_response()
281 xfer->hdr.protocol_id, xfer->hdr.seq, in scmi_handle_response()
285 info->desc->ops->clear_channel(cinfo); in scmi_handle_response()
286 complete(xfer->async_done); in scmi_handle_response()
288 complete(&xfer->done); in scmi_handle_response()
293 * scmi_rx_callback() - callback for receiving messages
295 * @cinfo: SCMI channel info
324 * scmi_xfer_put() - Release a transmit message
326 * @handle: Pointer to SCMI entity handle
333 __scmi_xfer_put(&info->tx_minfo, xfer); in scmi_xfer_put()
341 struct scmi_info *info = handle_to_scmi_info(cinfo->handle); in scmi_xfer_done_no_timeout()
343 return info->desc->ops->poll_done(cinfo, xfer) || in scmi_xfer_done_no_timeout()
348 * scmi_do_xfer() - Do one transfer
350 * @handle: Pointer to SCMI entity handle
353 * Return: -ETIMEDOUT in case of no response, if transmit error,
362 struct device *dev = info->dev; in scmi_do_xfer()
365 cinfo = idr_find(&info->tx_idr, xfer->hdr.protocol_id); in scmi_do_xfer()
367 return -EINVAL; in scmi_do_xfer()
369 trace_scmi_xfer_begin(xfer->transfer_id, xfer->hdr.id, in scmi_do_xfer()
370 xfer->hdr.protocol_id, xfer->hdr.seq, in scmi_do_xfer()
371 xfer->hdr.poll_completion); in scmi_do_xfer()
373 ret = info->desc->ops->send_message(cinfo, xfer); in scmi_do_xfer()
379 if (xfer->hdr.poll_completion) { in scmi_do_xfer()
385 info->desc->ops->fetch_response(cinfo, xfer); in scmi_do_xfer()
387 ret = -ETIMEDOUT; in scmi_do_xfer()
390 timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms); in scmi_do_xfer()
391 if (!wait_for_completion_timeout(&xfer->done, timeout)) { in scmi_do_xfer()
394 ret = -ETIMEDOUT; in scmi_do_xfer()
398 if (!ret && xfer->hdr.status) in scmi_do_xfer()
399 ret = scmi_to_linux_errno(xfer->hdr.status); in scmi_do_xfer()
401 if (info->desc->ops->mark_txdone) in scmi_do_xfer()
402 info->desc->ops->mark_txdone(cinfo, ret); in scmi_do_xfer()
404 trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id, in scmi_do_xfer()
405 xfer->hdr.protocol_id, xfer->hdr.seq, ret); in scmi_do_xfer()
415 xfer->rx.len = info->desc->max_msg_size; in scmi_reset_rx_to_maxsz()
421 * scmi_do_xfer_with_response() - Do one transfer and wait until the delayed
424 * @handle: Pointer to SCMI entity handle
427 * Return: -ETIMEDOUT in case of no delayed response, if transmit error,
436 xfer->async_done = &async_response; in scmi_do_xfer_with_response()
440 if (!wait_for_completion_timeout(xfer->async_done, timeout)) in scmi_do_xfer_with_response()
441 ret = -ETIMEDOUT; in scmi_do_xfer_with_response()
442 else if (xfer->hdr.status) in scmi_do_xfer_with_response()
443 ret = scmi_to_linux_errno(xfer->hdr.status); in scmi_do_xfer_with_response()
446 xfer->async_done = NULL; in scmi_do_xfer_with_response()
451 * scmi_xfer_get_init() - Allocate and initialise one message for transmit
453 * @handle: Pointer to SCMI entity handle
472 struct scmi_xfers_info *minfo = &info->tx_minfo; in scmi_xfer_get_init()
473 struct device *dev = info->dev; in scmi_xfer_get_init()
476 if (rx_size > info->desc->max_msg_size || in scmi_xfer_get_init()
477 tx_size > info->desc->max_msg_size) in scmi_xfer_get_init()
478 return -ERANGE; in scmi_xfer_get_init()
487 xfer->tx.len = tx_size; in scmi_xfer_get_init()
488 xfer->rx.len = rx_size ? : info->desc->max_msg_size; in scmi_xfer_get_init()
489 xfer->hdr.id = msg_id; in scmi_xfer_get_init()
490 xfer->hdr.protocol_id = prot_id; in scmi_xfer_get_init()
491 xfer->hdr.poll_completion = false; in scmi_xfer_get_init()
499 * scmi_version_get() - command to get the revision of the SCMI entity
501 * @handle: Pointer to SCMI entity handle
505 * Updates the SCMI information in the internal data structure.
523 rev_info = t->rx.buf; in scmi_version_get()
536 info->protocols_imp = prot_imp; in scmi_setup_protocol_implemented()
545 if (!info->protocols_imp) in scmi_is_protocol_implemented()
549 if (info->protocols_imp[i] == prot_id) in scmi_is_protocol_implemented()
555 * scmi_handle_get() - Get the SCMI handle for a device
557 * @dev: pointer to device for which we want SCMI handle
560 * and is expected to be maintained by caller of SCMI protocol library.
574 if (dev->parent == info->dev) { in scmi_handle_get()
575 handle = &info->handle; in scmi_handle_get()
576 info->users++; in scmi_handle_get()
586 * scmi_handle_put() - Release the handle acquired by scmi_handle_get
591 * and is expected to be maintained by caller of SCMI protocol library.
595 * if null was passed, it returns -EINVAL;
602 return -EINVAL; in scmi_handle_put()
606 if (!WARN_ON(!info->users)) in scmi_handle_put()
607 info->users--; in scmi_handle_put()
618 struct device *dev = sinfo->dev; in __scmi_xfer_info_init()
619 const struct scmi_desc *desc = sinfo->desc; in __scmi_xfer_info_init()
621 /* Pre-allocated messages, no more than what hdr.seq can support */ in __scmi_xfer_info_init()
622 if (WARN_ON(!desc->max_msg || desc->max_msg > MSG_TOKEN_MAX)) { in __scmi_xfer_info_init()
624 "Invalid maximum messages %d, not in range [1 - %lu]\n", in __scmi_xfer_info_init()
625 desc->max_msg, MSG_TOKEN_MAX); in __scmi_xfer_info_init()
626 return -EINVAL; in __scmi_xfer_info_init()
629 info->xfer_block = devm_kcalloc(dev, desc->max_msg, in __scmi_xfer_info_init()
630 sizeof(*info->xfer_block), GFP_KERNEL); in __scmi_xfer_info_init()
631 if (!info->xfer_block) in __scmi_xfer_info_init()
632 return -ENOMEM; in __scmi_xfer_info_init()
634 info->xfer_alloc_table = devm_kcalloc(dev, BITS_TO_LONGS(desc->max_msg), in __scmi_xfer_info_init()
636 if (!info->xfer_alloc_table) in __scmi_xfer_info_init()
637 return -ENOMEM; in __scmi_xfer_info_init()
639 /* Pre-initialize the buffer pointer to pre-allocated buffers */ in __scmi_xfer_info_init()
640 for (i = 0, xfer = info->xfer_block; i < desc->max_msg; i++, xfer++) { in __scmi_xfer_info_init()
641 xfer->rx.buf = devm_kcalloc(dev, sizeof(u8), desc->max_msg_size, in __scmi_xfer_info_init()
643 if (!xfer->rx.buf) in __scmi_xfer_info_init()
644 return -ENOMEM; in __scmi_xfer_info_init()
646 xfer->tx.buf = xfer->rx.buf; in __scmi_xfer_info_init()
647 init_completion(&xfer->done); in __scmi_xfer_info_init()
650 spin_lock_init(&info->xfer_lock); in __scmi_xfer_info_init()
657 int ret = __scmi_xfer_info_init(sinfo, &sinfo->tx_minfo); in scmi_xfer_info_init()
659 if (!ret && idr_find(&sinfo->rx_idr, SCMI_PROTOCOL_BASE)) in scmi_xfer_info_init()
660 ret = __scmi_xfer_info_init(sinfo, &sinfo->rx_minfo); in scmi_xfer_info_init()
674 idr = tx ? &info->tx_idr : &info->rx_idr; in scmi_chan_setup()
681 if (!info->desc->ops->chan_available(dev, idx)) { in scmi_chan_setup()
684 return -EINVAL; in scmi_chan_setup()
688 cinfo = devm_kzalloc(info->dev, sizeof(*cinfo), GFP_KERNEL); in scmi_chan_setup()
690 return -ENOMEM; in scmi_chan_setup()
692 cinfo->dev = dev; in scmi_chan_setup()
694 ret = info->desc->ops->chan_setup(cinfo, info->dev, tx); in scmi_chan_setup()
701 dev_err(dev, "unable to allocate SCMI idr slot err %d\n", ret); in scmi_chan_setup()
705 cinfo->handle = &info->handle; in scmi_chan_setup()
717 if (ret && ret != -ENOMEM) in scmi_txrx_setup()
730 sdev = scmi_device_create(np, info->dev, prot_id, name); in scmi_create_protocol_device()
732 dev_err(info->dev, "failed to create %d protocol device\n", in scmi_create_protocol_device()
737 if (scmi_txrx_setup(info, &sdev->dev, prot_id)) { in scmi_create_protocol_device()
738 dev_err(&sdev->dev, "failed to setup transport\n"); in scmi_create_protocol_device()
788 struct device *dev = &pdev->dev; in scmi_probe()
789 struct device_node *child, *np = dev->of_node; in scmi_probe()
793 return -EINVAL; in scmi_probe()
797 return -ENOMEM; in scmi_probe()
799 info->dev = dev; in scmi_probe()
800 info->desc = desc; in scmi_probe()
801 INIT_LIST_HEAD(&info->node); in scmi_probe()
804 idr_init(&info->tx_idr); in scmi_probe()
805 idr_init(&info->rx_idr); in scmi_probe()
807 handle = &info->handle; in scmi_probe()
808 handle->dev = info->dev; in scmi_probe()
809 handle->version = &info->version; in scmi_probe()
820 dev_err(dev, "SCMI Notifications NOT available.\n"); in scmi_probe()
824 dev_err(dev, "unable to communicate with SCMI(%d)\n", ret); in scmi_probe()
829 list_add_tail(&info->node, &scmi_list); in scmi_probe()
842 dev_err(dev, "SCMI protocol %d not implemented\n", in scmi_probe()
862 struct idr *idr = &info->tx_idr; in scmi_remove()
865 if (info->users) in scmi_remove()
866 ret = -EBUSY; in scmi_remove()
868 list_del(&info->node); in scmi_remove()
874 scmi_notification_exit(&info->handle); in scmi_remove()
877 ret = idr_for_each(idr, info->desc->ops->chan_free, idr); in scmi_remove()
878 idr_destroy(&info->tx_idr); in scmi_remove()
880 idr = &info->rx_idr; in scmi_remove()
881 ret = idr_for_each(idr, info->desc->ops->chan_free, idr); in scmi_remove()
882 idr_destroy(&info->rx_idr); in scmi_remove()
892 return sprintf(buf, "%u.%u\n", info->version.major_ver, in protocol_version_show()
893 info->version.minor_ver); in protocol_version_show()
902 return sprintf(buf, "0x%x\n", info->version.impl_ver); in firmware_version_show()
911 return sprintf(buf, "%s\n", info->version.vendor_id); in vendor_id_show()
920 return sprintf(buf, "%s\n", info->version.sub_vendor_id); in sub_vendor_id_show()
936 { .compatible = "arm,scmi", .data = &scmi_mailbox_desc },
939 { .compatible = "arm,scmi-smc", .data = &scmi_smc_desc},
948 .name = "arm-scmi",
987 MODULE_ALIAS("platform:arm-scmi");
989 MODULE_DESCRIPTION("ARM SCMI protocol driver");