linux/drivers/firmware/arm_scmi/driver.c

// SPDX-License-Identifier: GPL-2.0
/*
 * System Control and Management Interface (SCMI) Message Protocol driver
 *
 * SCMI Message Protocol is used between the System Control Processor(SCP)
 * and the Application Processors(AP). The Message Handling Unit(MHU)
 * provides a mechanism for inter-processor communication between SCP's
 * Cortex M3 and AP.
 *
 * SCP offers control and management of the core/cluster power states,
 * various power domain DVFS including the core/cluster, certain system
 * clocks configuration, thermal sensors and many others.
 *
 * Copyright (C) 2018-2024 ARM Ltd.
 */

#define pr_fmt(fmt)

#include <linux/bitmap.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/export.h>
#include <linux/idr.h>
#include <linux/io.h>
#include <linux/io-64-nonatomic-hi-lo.h>
#include <linux/kernel.h>
#include <linux/ktime.h>
#include <linux/hashtable.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/processor.h>
#include <linux/refcount.h>
#include <linux/slab.h>
#include <linux/xarray.h>

#include "common.h"
#include "notify.h"

#include "raw_mode.h"

#define CREATE_TRACE_POINTS
#include <trace/events/scmi.h>

static DEFINE_IDA(scmi_id);

static DEFINE_XARRAY(scmi_protocols);

/* List of all SCMI devices active in system */
static LIST_HEAD(scmi_list);
/* Protection for the entire list */
static DEFINE_MUTEX(scmi_list_mutex);
/* Track the unique id for the transfers for debug & profiling purpose */
static atomic_t transfer_last_id;

static struct dentry *scmi_top_dentry;

/**
 * struct scmi_xfers_info - Structure to manage transfer information
 *
 * @xfer_alloc_table: Bitmap table for allocated messages.
 *	Index of this bitmap table is also used for message
 *	sequence identifier.
 * @xfer_lock: Protection for message allocation
 * @max_msg: Maximum number of messages that can be pending
 * @free_xfers: A free list for available to use xfers. It is initialized with
 *		a number of xfers equal to the maximum allowed in-flight
 *		messages.
 * @pending_xfers: An hashtable, indexed by msg_hdr.seq, used to keep all the
 *		   currently in-flight messages.
 */
struct scmi_xfers_info {};

/**
 * struct scmi_protocol_instance  - Describe an initialized protocol instance.
 * @handle: Reference to the SCMI handle associated to this protocol instance.
 * @proto: A reference to the protocol descriptor.
 * @gid: A reference for per-protocol devres management.
 * @users: A refcount to track effective users of this protocol.
 * @priv: Reference for optional protocol private data.
 * @version: Protocol version supported by the platform as detected at runtime.
 * @negotiated_version: When the platform supports a newer protocol version,
 *			the agent will try to negotiate with the platform the
 *			usage of the newest version known to it, since
 *			backward compatibility is NOT automatically assured.
 *			This field is NON-zero when a successful negotiation
 *			has completed.
 * @ph: An embedded protocol handle that will be passed down to protocol
 *	initialization code to identify this instance.
 *
 * Each protocol is initialized independently once for each SCMI platform in
 * which is defined by DT and implemented by the SCMI server fw.
 */
struct scmi_protocol_instance {};

#define ph_to_pi(h)

/**
 * struct scmi_debug_info  - Debug common info
 * @top_dentry: A reference to the top debugfs dentry
 * @name: Name of this SCMI instance
 * @type: Type of this SCMI instance
 * @is_atomic: Flag to state if the transport of this instance is atomic
 * @counters: An array of atomic_c's used for tracking statistics (if enabled)
 */
struct scmi_debug_info {};

/**
 * struct scmi_info - Structure representing a SCMI instance
 *
 * @id: A sequence number starting from zero identifying this instance
 * @dev: Device pointer
 * @desc: SoC description for this instance
 * @version: SCMI revision information containing protocol version,
 *	implementation version and (sub-)vendor identification.
 * @handle: Instance of SCMI handle to send to clients
 * @tx_minfo: Universal Transmit Message management info
 * @rx_minfo: Universal Receive Message management info
 * @tx_idr: IDR object to map protocol id to Tx channel info pointer
 * @rx_idr: IDR object to map protocol id to Rx channel info pointer
 * @protocols: IDR for protocols' instance descriptors initialized for
 *	       this SCMI instance: populated on protocol's first attempted
 *	       usage.
 * @protocols_mtx: A mutex to protect protocols instances initialization.
 * @protocols_imp: List of protocols implemented, currently maximum of
 *		   scmi_revision_info.num_protocols elements allocated by the
 *		   base protocol
 * @active_protocols: IDR storing device_nodes for protocols actually defined
 *		      in the DT and confirmed as implemented by fw.
 * @atomic_threshold: Optional system wide DT-configured threshold, expressed
 *		      in microseconds, for atomic operations.
 *		      Only SCMI synchronous commands reported by the platform
 *		      to have an execution latency lesser-equal to the threshold
 *		      should be considered for atomic mode operation: such
 *		      decision is finally left up to the SCMI drivers.
 * @notify_priv: Pointer to private data structure specific to notifications.
 * @node: List head
 * @users: Number of users of this instance
 * @bus_nb: A notifier to listen for device bind/unbind on the scmi bus
 * @dev_req_nb: A notifier to listen for device request/unrequest on the scmi
 *		bus
 * @devreq_mtx: A mutex to serialize device creation for this SCMI instance
 * @dbg: A pointer to debugfs related data (if any)
 * @raw: An opaque reference handle used by SCMI Raw mode.
 */
struct scmi_info {};

#define handle_to_scmi_info(h)
#define bus_nb_to_scmi_info(nb)
#define req_nb_to_scmi_info(nb)

static void scmi_rx_callback(struct scmi_chan_info *cinfo,
			     u32 msg_hdr, void *priv);
static void scmi_bad_message_trace(struct scmi_chan_info *cinfo,
				   u32 msg_hdr, enum scmi_bad_msg err);

static struct scmi_transport_core_operations scmi_trans_core_ops =;

static unsigned long
scmi_vendor_protocol_signature(unsigned int protocol_id, char *vendor_id,
			       char *sub_vendor_id, u32 impl_ver)
{}

static unsigned long
scmi_protocol_key_calculate(int protocol_id, char *vendor_id,
			    char *sub_vendor_id, u32 impl_ver)
{}

static const struct scmi_protocol *
__scmi_vendor_protocol_lookup(int protocol_id, char *vendor_id,
			      char *sub_vendor_id, u32 impl_ver)
{}

static const struct scmi_protocol *
scmi_vendor_protocol_lookup(int protocol_id, char *vendor_id,
			    char *sub_vendor_id, u32 impl_ver)
{}

static const struct scmi_protocol *
scmi_protocol_get(int protocol_id, struct scmi_revision_info *version)
{}

static void scmi_protocol_put(const struct scmi_protocol *proto)
{}

static int scmi_vendor_protocol_check(const struct scmi_protocol *proto)
{}

int scmi_protocol_register(const struct scmi_protocol *proto)
{}
EXPORT_SYMBOL_GPL();

void scmi_protocol_unregister(const struct scmi_protocol *proto)
{}
EXPORT_SYMBOL_GPL();

/**
 * scmi_create_protocol_devices  - Create devices for all pending requests for
 * this SCMI instance.
 *
 * @np: The device node describing the protocol
 * @info: The SCMI instance descriptor
 * @prot_id: The protocol ID
 * @name: The optional name of the device to be created: if not provided this
 *	  call will lead to the creation of all the devices currently requested
 *	  for the specified protocol.
 */
static void scmi_create_protocol_devices(struct device_node *np,
					 struct scmi_info *info,
					 int prot_id, const char *name)
{}

static void scmi_destroy_protocol_devices(struct scmi_info *info,
					  int prot_id, const char *name)
{}

void scmi_notification_instance_data_set(const struct scmi_handle *handle,
					 void *priv)
{}

void *scmi_notification_instance_data_get(const struct scmi_handle *handle)
{}

/**
 * scmi_xfer_token_set  - Reserve and set new token for the xfer at hand
 *
 * @minfo: Pointer to Tx/Rx Message management info based on channel type
 * @xfer: The xfer to act upon
 *
 * Pick the next unused monotonically increasing token and set it into
 * xfer->hdr.seq: picking a monotonically increasing value avoids immediate
 * reuse of freshly completed or timed-out xfers, thus mitigating the risk
 * of incorrect association of a late and expired xfer with a live in-flight
 * transaction, both happening to re-use the same token identifier.
 *
 * Since platform is NOT required to answer our request in-order we should
 * account for a few rare but possible scenarios:
 *
 *  - exactly 'next_token' may be NOT available so pick xfer_id >= next_token
 *    using find_next_zero_bit() starting from candidate next_token bit
 *
 *  - all tokens ahead upto (MSG_TOKEN_ID_MASK - 1) are used in-flight but we
 *    are plenty of free tokens at start, so try a second pass using
 *    find_next_zero_bit() and starting from 0.
 *
 *  X = used in-flight
 *
 * Normal
 * ------
 *
 *		|- xfer_id picked
 *   -----------+----------------------------------------------------------
 *   | | |X|X|X| | | | | | ... ... ... ... ... ... ... ... ... ... ...|X|X|
 *   ----------------------------------------------------------------------
 *		^
 *		|- next_token
 *
 * Out-of-order pending at start
 * -----------------------------
 *
 *	  |- xfer_id picked, last_token fixed
 *   -----+----------------------------------------------------------------
 *   |X|X| | | | |X|X| ... ... ... ... ... ... ... ... ... ... ... ...|X| |
 *   ----------------------------------------------------------------------
 *    ^
 *    |- next_token
 *
 *
 * Out-of-order pending at end
 * ---------------------------
 *
 *	  |- xfer_id picked, last_token fixed
 *   -----+----------------------------------------------------------------
 *   |X|X| | | | |X|X| ... ... ... ... ... ... ... ... ... ... |X|X|X||X|X|
 *   ----------------------------------------------------------------------
 *								^
 *								|- next_token
 *
 * Context: Assumes to be called with @xfer_lock already acquired.
 *
 * Return: 0 on Success or error
 */
static int scmi_xfer_token_set(struct scmi_xfers_info *minfo,
			       struct scmi_xfer *xfer)
{}

/**
 * scmi_xfer_token_clear  - Release the token
 *
 * @minfo: Pointer to Tx/Rx Message management info based on channel type
 * @xfer: The xfer to act upon
 */
static inline void scmi_xfer_token_clear(struct scmi_xfers_info *minfo,
					 struct scmi_xfer *xfer)
{}

/**
 * scmi_xfer_inflight_register_unlocked  - Register the xfer as in-flight
 *
 * @xfer: The xfer to register
 * @minfo: Pointer to Tx/Rx Message management info based on channel type
 *
 * Note that this helper assumes that the xfer to be registered as in-flight
 * had been built using an xfer sequence number which still corresponds to a
 * free slot in the xfer_alloc_table.
 *
 * Context: Assumes to be called with @xfer_lock already acquired.
 */
static inline void
scmi_xfer_inflight_register_unlocked(struct scmi_xfer *xfer,
				     struct scmi_xfers_info *minfo)
{}

/**
 * scmi_xfer_inflight_register  - Try to register an xfer as in-flight
 *
 * @xfer: The xfer to register
 * @minfo: Pointer to Tx/Rx Message management info based on channel type
 *
 * Note that this helper does NOT assume anything about the sequence number
 * that was baked into the provided xfer, so it checks at first if it can
 * be mapped to a free slot and fails with an error if another xfer with the
 * same sequence number is currently still registered as in-flight.
 *
 * Return: 0 on Success or -EBUSY if sequence number embedded in the xfer
 *	   could not rbe mapped to a free slot in the xfer_alloc_table.
 */
static int scmi_xfer_inflight_register(struct scmi_xfer *xfer,
				       struct scmi_xfers_info *minfo)
{}

/**
 * scmi_xfer_raw_inflight_register  - An helper to register the given xfer as in
 * flight on the TX channel, if possible.
 *
 * @handle: Pointer to SCMI entity handle
 * @xfer: The xfer to register
 *
 * Return: 0 on Success, error otherwise
 */
int scmi_xfer_raw_inflight_register(const struct scmi_handle *handle,
				    struct scmi_xfer *xfer)
{}

/**
 * scmi_xfer_pending_set  - Pick a proper sequence number and mark the xfer
 * as pending in-flight
 *
 * @xfer: The xfer to act upon
 * @minfo: Pointer to Tx/Rx Message management info based on channel type
 *
 * Return: 0 on Success or error otherwise
 */
static inline int scmi_xfer_pending_set(struct scmi_xfer *xfer,
					struct scmi_xfers_info *minfo)
{}

/**
 * scmi_xfer_get() - Allocate one message
 *
 * @handle: Pointer to SCMI entity handle
 * @minfo: Pointer to Tx/Rx Message management info based on channel type
 *
 * Helper function which is used by various message functions that are
 * exposed to clients of this driver for allocating a message traffic event.
 *
 * Picks an xfer from the free list @free_xfers (if any available) and perform
 * a basic initialization.
 *
 * Note that, at this point, still no sequence number is assigned to the
 * allocated xfer, nor it is registered as a pending transaction.
 *
 * The successfully initialized xfer is refcounted.
 *
 * Context: Holds @xfer_lock while manipulating @free_xfers.
 *
 * Return: An initialized xfer if all went fine, else pointer error.
 */
static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle,
				       struct scmi_xfers_info *minfo)
{}

/**
 * scmi_xfer_raw_get  - Helper to get a bare free xfer from the TX channel
 *
 * @handle: Pointer to SCMI entity handle
 *
 * Note that xfer is taken from the TX channel structures.
 *
 * Return: A valid xfer on Success, or an error-pointer otherwise
 */
struct scmi_xfer *scmi_xfer_raw_get(const struct scmi_handle *handle)
{}

/**
 * scmi_xfer_raw_channel_get  - Helper to get a reference to the proper channel
 * to use for a specific protocol_id Raw transaction.
 *
 * @handle: Pointer to SCMI entity handle
 * @protocol_id: Identifier of the protocol
 *
 * Note that in a regular SCMI stack, usually, a protocol has to be defined in
 * the DT to have an associated channel and be usable; but in Raw mode any
 * protocol in range is allowed, re-using the Base channel, so as to enable
 * fuzzing on any protocol without the need of a fully compiled DT.
 *
 * Return: A reference to the channel to use, or an ERR_PTR
 */
struct scmi_chan_info *
scmi_xfer_raw_channel_get(const struct scmi_handle *handle, u8 protocol_id)
{}

/**
 * __scmi_xfer_put() - Release a message
 *
 * @minfo: Pointer to Tx/Rx Message management info based on channel type
 * @xfer: message that was reserved by scmi_xfer_get
 *
 * After refcount check, possibly release an xfer, clearing the token slot,
 * removing xfer from @pending_xfers and putting it back into free_xfers.
 *
 * This holds a spinlock to maintain integrity of internal data structures.
 */
static void
__scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer)
{}

/**
 * scmi_xfer_raw_put  - Release an xfer that was taken by @scmi_xfer_raw_get
 *
 * @handle: Pointer to SCMI entity handle
 * @xfer: A reference to the xfer to put
 *
 * Note that as with other xfer_put() handlers the xfer is really effectively
 * released only if there are no more users on the system.
 */
void scmi_xfer_raw_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
{}

/**
 * scmi_xfer_lookup_unlocked  -  Helper to lookup an xfer_id
 *
 * @minfo: Pointer to Tx/Rx Message management info based on channel type
 * @xfer_id: Token ID to lookup in @pending_xfers
 *
 * Refcounting is untouched.
 *
 * Context: Assumes to be called with @xfer_lock already acquired.
 *
 * Return: A valid xfer on Success or error otherwise
 */
static struct scmi_xfer *
scmi_xfer_lookup_unlocked(struct scmi_xfers_info *minfo, u16 xfer_id)
{}

/**
 * scmi_bad_message_trace  - A helper to trace weird messages
 *
 * @cinfo: A reference to the channel descriptor on which the message was
 *	   received
 * @msg_hdr: Message header to track
 * @err: A specific error code used as a status value in traces.
 *
 * This helper can be used to trace any kind of weird, incomplete, unexpected,
 * timed-out message that arrives and as such, can be traced only referring to
 * the header content, since the payload is missing/unreliable.
 */
static void scmi_bad_message_trace(struct scmi_chan_info *cinfo, u32 msg_hdr,
				   enum scmi_bad_msg err)
{}

/**
 * scmi_msg_response_validate  - Validate message type against state of related
 * xfer
 *
 * @cinfo: A reference to the channel descriptor.
 * @msg_type: Message type to check
 * @xfer: A reference to the xfer to validate against @msg_type
 *
 * This function checks if @msg_type is congruent with the current state of
 * a pending @xfer; if an asynchronous delayed response is received before the
 * related synchronous response (Out-of-Order Delayed Response) the missing
 * synchronous response is assumed to be OK and completed, carrying on with the
 * Delayed Response: this is done to address the case in which the underlying
 * SCMI transport can deliver such out-of-order responses.
 *
 * Context: Assumes to be called with xfer->lock already acquired.
 *
 * Return: 0 on Success, error otherwise
 */
static inline int scmi_msg_response_validate(struct scmi_chan_info *cinfo,
					     u8 msg_type,
					     struct scmi_xfer *xfer)
{}

/**
 * scmi_xfer_state_update  - Update xfer state
 *
 * @xfer: A reference to the xfer to update
 * @msg_type: Type of message being processed.
 *
 * Note that this message is assumed to have been already successfully validated
 * by @scmi_msg_response_validate(), so here we just update the state.
 *
 * Context: Assumes to be called on an xfer exclusively acquired using the
 *	    busy flag.
 */
static inline void scmi_xfer_state_update(struct scmi_xfer *xfer, u8 msg_type)
{}

static bool scmi_xfer_acquired(struct scmi_xfer *xfer)
{}

/**
 * scmi_xfer_command_acquire  -  Helper to lookup and acquire a command xfer
 *
 * @cinfo: A reference to the channel descriptor.
 * @msg_hdr: A message header to use as lookup key
 *
 * When a valid xfer is found for the sequence number embedded in the provided
 * msg_hdr, reference counting is properly updated and exclusive access to this
 * xfer is granted till released with @scmi_xfer_command_release.
 *
 * Return: A valid @xfer on Success or error otherwise.
 */
static inline struct scmi_xfer *
scmi_xfer_command_acquire(struct scmi_chan_info *cinfo, u32 msg_hdr)
{}

static inline void scmi_xfer_command_release(struct scmi_info *info,
					     struct scmi_xfer *xfer)
{}

static inline void scmi_clear_channel(struct scmi_info *info,
				      struct scmi_chan_info *cinfo)
{}

static void scmi_handle_notification(struct scmi_chan_info *cinfo,
				     u32 msg_hdr, void *priv)
{}

static void scmi_handle_response(struct scmi_chan_info *cinfo,
				 u32 msg_hdr, void *priv)
{}

/**
 * scmi_rx_callback() - callback for receiving messages
 *
 * @cinfo: SCMI channel info
 * @msg_hdr: Message header
 * @priv: Transport specific private data.
 *
 * Processes one received message to appropriate transfer information and
 * signals completion of the transfer.
 *
 * NOTE: This function will be invoked in IRQ context, hence should be
 * as optimal as possible.
 */
static void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr,
			     void *priv)
{}

/**
 * xfer_put() - Release a transmit message
 *
 * @ph: Pointer to SCMI protocol handle
 * @xfer: message that was reserved by xfer_get_init
 */
static void xfer_put(const struct scmi_protocol_handle *ph,
		     struct scmi_xfer *xfer)
{}

static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
				      struct scmi_xfer *xfer, ktime_t stop)
{}

static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc,
			       struct scmi_chan_info *cinfo,
			       struct scmi_xfer *xfer, unsigned int timeout_ms)
{}

/**
 * scmi_wait_for_message_response  - An helper to group all the possible ways of
 * waiting for a synchronous message response.
 *
 * @cinfo: SCMI channel info
 * @xfer: Reference to the transfer being waited for.
 *
 * Chooses waiting strategy (sleep-waiting vs busy-waiting) depending on
 * configuration flags like xfer->hdr.poll_completion.
 *
 * Return: 0 on Success, error otherwise.
 */
static int scmi_wait_for_message_response(struct scmi_chan_info *cinfo,
					  struct scmi_xfer *xfer)
{}

/**
 * scmi_xfer_raw_wait_for_message_response  - An helper to wait for a message
 * reply to an xfer raw request on a specific channel for the required timeout.
 *
 * @cinfo: SCMI channel info
 * @xfer: Reference to the transfer being waited for.
 * @timeout_ms: The maximum timeout in milliseconds
 *
 * Return: 0 on Success, error otherwise.
 */
int scmi_xfer_raw_wait_for_message_response(struct scmi_chan_info *cinfo,
					    struct scmi_xfer *xfer,
					    unsigned int timeout_ms)
{}

/**
 * do_xfer() - Do one transfer
 *
 * @ph: Pointer to SCMI protocol handle
 * @xfer: Transfer to initiate and wait for response
 *
 * Return: -ETIMEDOUT in case of no response, if transmit error,
 *	return corresponding error, else if all goes well,
 *	return 0.
 */
static int do_xfer(const struct scmi_protocol_handle *ph,
		   struct scmi_xfer *xfer)
{}

static void reset_rx_to_maxsz(const struct scmi_protocol_handle *ph,
			      struct scmi_xfer *xfer)
{}

/**
 * do_xfer_with_response() - Do one transfer and wait until the delayed
 *	response is received
 *
 * @ph: Pointer to SCMI protocol handle
 * @xfer: Transfer to initiate and wait for response
 *
 * Using asynchronous commands in atomic/polling mode should be avoided since
 * it could cause long busy-waiting here, so ignore polling for the delayed
 * response and WARN if it was requested for this command transaction since
 * upper layers should refrain from issuing such kind of requests.
 *
 * The only other option would have been to refrain from using any asynchronous
 * command even if made available, when an atomic transport is detected, and
 * instead forcibly use the synchronous version (thing that can be easily
 * attained at the protocol layer), but this would also have led to longer
 * stalls of the channel for synchronous commands and possibly timeouts.
 * (in other words there is usually a good reason if a platform provides an
 *  asynchronous version of a command and we should prefer to use it...just not
 *  when using atomic/polling mode)
 *
 * Return: -ETIMEDOUT in case of no delayed response, if transmit error,
 *	return corresponding error, else if all goes well, return 0.
 */
static int do_xfer_with_response(const struct scmi_protocol_handle *ph,
				 struct scmi_xfer *xfer)
{}

/**
 * xfer_get_init() - Allocate and initialise one message for transmit
 *
 * @ph: Pointer to SCMI protocol handle
 * @msg_id: Message identifier
 * @tx_size: transmit message size
 * @rx_size: receive message size
 * @p: pointer to the allocated and initialised message
 *
 * This function allocates the message using @scmi_xfer_get and
 * initialise the header.
 *
 * Return: 0 if all went fine with @p pointing to message, else
 *	corresponding error.
 */
static int xfer_get_init(const struct scmi_protocol_handle *ph,
			 u8 msg_id, size_t tx_size, size_t rx_size,
			 struct scmi_xfer **p)
{}

/**
 * version_get() - command to get the revision of the SCMI entity
 *
 * @ph: Pointer to SCMI protocol handle
 * @version: Holds returned version of protocol.
 *
 * Updates the SCMI information in the internal data structure.
 *
 * Return: 0 if all went fine, else return appropriate error.
 */
static int version_get(const struct scmi_protocol_handle *ph, u32 *version)
{}

/**
 * scmi_set_protocol_priv  - Set protocol specific data at init time
 *
 * @ph: A reference to the protocol handle.
 * @priv: The private data to set.
 * @version: The detected protocol version for the core to register.
 *
 * Return: 0 on Success
 */
static int scmi_set_protocol_priv(const struct scmi_protocol_handle *ph,
				  void *priv, u32 version)
{}

/**
 * scmi_get_protocol_priv  - Set protocol specific data at init time
 *
 * @ph: A reference to the protocol handle.
 *
 * Return: Protocol private data if any was set.
 */
static void *scmi_get_protocol_priv(const struct scmi_protocol_handle *ph)
{}

static const struct scmi_xfer_ops xfer_ops =;

struct scmi_msg_resp_domain_name_get {};

/**
 * scmi_common_extended_name_get  - Common helper to get extended resources name
 * @ph: A protocol handle reference.
 * @cmd_id: The specific command ID to use.
 * @res_id: The specific resource ID to use.
 * @flags: A pointer to specific flags to use, if any.
 * @name: A pointer to the preallocated area where the retrieved name will be
 *	  stored as a NULL terminated string.
 * @len: The len in bytes of the @name char array.
 *
 * Return: 0 on Succcess
 */
static int scmi_common_extended_name_get(const struct scmi_protocol_handle *ph,
					 u8 cmd_id, u32 res_id, u32 *flags,
					 char *name, size_t len)
{}

/**
 * scmi_common_get_max_msg_size  - Get maximum message size
 * @ph: A protocol handle reference.
 *
 * Return: Maximum message size for the current protocol.
 */
static int scmi_common_get_max_msg_size(const struct scmi_protocol_handle *ph)
{}

/**
 * struct scmi_iterator  - Iterator descriptor
 * @msg: A reference to the message TX buffer; filled by @prepare_message with
 *	 a proper custom command payload for each multi-part command request.
 * @resp: A reference to the response RX buffer; used by @update_state and
 *	  @process_response to parse the multi-part replies.
 * @t: A reference to the underlying xfer initialized and used transparently by
 *     the iterator internal routines.
 * @ph: A reference to the associated protocol handle to be used.
 * @ops: A reference to the custom provided iterator operations.
 * @state: The current iterator state; used and updated in turn by the iterators
 *	   internal routines and by the caller-provided @scmi_iterator_ops.
 * @priv: A reference to optional private data as provided by the caller and
 *	  passed back to the @@scmi_iterator_ops.
 */
struct scmi_iterator {};

static void *scmi_iterator_init(const struct scmi_protocol_handle *ph,
				struct scmi_iterator_ops *ops,
				unsigned int max_resources, u8 msg_id,
				size_t tx_size, void *priv)
{}

static int scmi_iterator_run(void *iter)
{}

struct scmi_msg_get_fc_info {};

struct scmi_msg_resp_desc_fc {};

static void
scmi_common_fastchannel_init(const struct scmi_protocol_handle *ph,
			     u8 describe_id, u32 message_id, u32 valid_size,
			     u32 domain, void __iomem **p_addr,
			     struct scmi_fc_db_info **p_db, u32 *rate_limit)
{}

#define SCMI_PROTO_FC_RING_DB(w)

static void scmi_common_fastchannel_db_ring(struct scmi_fc_db_info *db)
{}

/**
 * scmi_protocol_msg_check  - Check protocol message attributes
 *
 * @ph: A reference to the protocol handle.
 * @message_id: The ID of the message to check.
 * @attributes: A parameter to optionally return the retrieved message
 *		attributes, in case of Success.
 *
 * An helper to check protocol message attributes for a specific protocol
 * and message pair.
 *
 * Return: 0 on SUCCESS
 */
static int scmi_protocol_msg_check(const struct scmi_protocol_handle *ph,
				   u32 message_id, u32 *attributes)
{}

static const struct scmi_proto_helpers_ops helpers_ops =;

/**
 * scmi_revision_area_get  - Retrieve version memory area.
 *
 * @ph: A reference to the protocol handle.
 *
 * A helper to grab the version memory area reference during SCMI Base protocol
 * initialization.
 *
 * Return: A reference to the version memory area associated to the SCMI
 *	   instance underlying this protocol handle.
 */
struct scmi_revision_info *
scmi_revision_area_get(const struct scmi_protocol_handle *ph)
{}

/**
 * scmi_protocol_version_negotiate  - Negotiate protocol version
 *
 * @ph: A reference to the protocol handle.
 *
 * An helper to negotiate a protocol version different from the latest
 * advertised as supported from the platform: on Success backward
 * compatibility is assured by the platform.
 *
 * Return: 0 on Success
 */
static int scmi_protocol_version_negotiate(struct scmi_protocol_handle *ph)
{}

/**
 * scmi_alloc_init_protocol_instance  - Allocate and initialize a protocol
 * instance descriptor.
 * @info: The reference to the related SCMI instance.
 * @proto: The protocol descriptor.
 *
 * Allocate a new protocol instance descriptor, using the provided @proto
 * description, against the specified SCMI instance @info, and initialize it;
 * all resources management is handled via a dedicated per-protocol devres
 * group.
 *
 * Context: Assumes to be called with @protocols_mtx already acquired.
 * Return: A reference to a freshly allocated and initialized protocol instance
 *	   or ERR_PTR on failure. On failure the @proto reference is at first
 *	   put using @scmi_protocol_put() before releasing all the devres group.
 */
static struct scmi_protocol_instance *
scmi_alloc_init_protocol_instance(struct scmi_info *info,
				  const struct scmi_protocol *proto)
{}

/**
 * scmi_get_protocol_instance  - Protocol initialization helper.
 * @handle: A reference to the SCMI platform instance.
 * @protocol_id: The protocol being requested.
 *
 * In case the required protocol has never been requested before for this
 * instance, allocate and initialize all the needed structures while handling
 * resource allocation with a dedicated per-protocol devres subgroup.
 *
 * Return: A reference to an initialized protocol instance or error on failure:
 *	   in particular returns -EPROBE_DEFER when the desired protocol could
 *	   NOT be found.
 */
static struct scmi_protocol_instance * __must_check
scmi_get_protocol_instance(const struct scmi_handle *handle, u8 protocol_id)
{}

/**
 * scmi_protocol_acquire  - Protocol acquire
 * @handle: A reference to the SCMI platform instance.
 * @protocol_id: The protocol being requested.
 *
 * Register a new user for the requested protocol on the specified SCMI
 * platform instance, possibly triggering its initialization on first user.
 *
 * Return: 0 if protocol was acquired successfully.
 */
int scmi_protocol_acquire(const struct scmi_handle *handle, u8 protocol_id)
{}

/**
 * scmi_protocol_release  - Protocol de-initialization helper.
 * @handle: A reference to the SCMI platform instance.
 * @protocol_id: The protocol being requested.
 *
 * Remove one user for the specified protocol and triggers de-initialization
 * and resources de-allocation once the last user has gone.
 */
void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id)
{}

void scmi_setup_protocol_implemented(const struct scmi_protocol_handle *ph,
				     u8 *prot_imp)
{}

static bool
scmi_is_protocol_implemented(const struct scmi_handle *handle, u8 prot_id)
{}

struct scmi_protocol_devres {};

static void scmi_devm_release_protocol(struct device *dev, void *res)
{}

static struct scmi_protocol_instance __must_check *
scmi_devres_protocol_instance_get(struct scmi_device *sdev, u8 protocol_id)
{}

/**
 * scmi_devm_protocol_get  - Devres managed get protocol operations and handle
 * @sdev: A reference to an scmi_device whose embedded struct device is to
 *	  be used for devres accounting.
 * @protocol_id: The protocol being requested.
 * @ph: A pointer reference used to pass back the associated protocol handle.
 *
 * Get hold of a protocol accounting for its usage, eventually triggering its
 * initialization, and returning the protocol specific operations and related
 * protocol handle which will be used as first argument in most of the
 * protocols operations methods.
 * Being a devres based managed method, protocol hold will be automatically
 * released, and possibly de-initialized on last user, once the SCMI driver
 * owning the scmi_device is unbound from it.
 *
 * Return: A reference to the requested protocol operations or error.
 *	   Must be checked for errors by caller.
 */
static const void __must_check *
scmi_devm_protocol_get(struct scmi_device *sdev, u8 protocol_id,
		       struct scmi_protocol_handle **ph)
{}

/**
 * scmi_devm_protocol_acquire  - Devres managed helper to get hold of a protocol
 * @sdev: A reference to an scmi_device whose embedded struct device is to
 *	  be used for devres accounting.
 * @protocol_id: The protocol being requested.
 *
 * Get hold of a protocol accounting for its usage, possibly triggering its
 * initialization but without getting access to its protocol specific operations
 * and handle.
 *
 * Being a devres based managed method, protocol hold will be automatically
 * released, and possibly de-initialized on last user, once the SCMI driver
 * owning the scmi_device is unbound from it.
 *
 * Return: 0 on SUCCESS
 */
static int __must_check scmi_devm_protocol_acquire(struct scmi_device *sdev,
						   u8 protocol_id)
{}

static int scmi_devm_protocol_match(struct device *dev, void *res, void *data)
{}

/**
 * scmi_devm_protocol_put  - Devres managed put protocol operations and handle
 * @sdev: A reference to an scmi_device whose embedded struct device is to
 *	  be used for devres accounting.
 * @protocol_id: The protocol being requested.
 *
 * Explicitly release a protocol hold previously obtained calling the above
 * @scmi_devm_protocol_get.
 */
static void scmi_devm_protocol_put(struct scmi_device *sdev, u8 protocol_id)
{}

/**
 * scmi_is_transport_atomic  - Method to check if underlying transport for an
 * SCMI instance is configured as atomic.
 *
 * @handle: A reference to the SCMI platform instance.
 * @atomic_threshold: An optional return value for the system wide currently
 *		      configured threshold for atomic operations.
 *
 * Return: True if transport is configured as atomic
 */
static bool scmi_is_transport_atomic(const struct scmi_handle *handle,
				     unsigned int *atomic_threshold)
{}

/**
 * scmi_handle_get() - Get the SCMI handle for a device
 *
 * @dev: pointer to device for which we want SCMI handle
 *
 * NOTE: The function does not track individual clients of the framework
 * and is expected to be maintained by caller of SCMI protocol library.
 * scmi_handle_put must be balanced with successful scmi_handle_get
 *
 * Return: pointer to handle if successful, NULL on error
 */
static struct scmi_handle *scmi_handle_get(struct device *dev)
{}

/**
 * scmi_handle_put() - Release the handle acquired by scmi_handle_get
 *
 * @handle: handle acquired by scmi_handle_get
 *
 * NOTE: The function does not track individual clients of the framework
 * and is expected to be maintained by caller of SCMI protocol library.
 * scmi_handle_put must be balanced with successful scmi_handle_get
 *
 * Return: 0 is successfully released
 *	if null was passed, it returns -EINVAL;
 */
static int scmi_handle_put(const struct scmi_handle *handle)
{}

static void scmi_device_link_add(struct device *consumer,
				 struct device *supplier)
{}

static void scmi_set_handle(struct scmi_device *scmi_dev)
{}

static int __scmi_xfer_info_init(struct scmi_info *sinfo,
				 struct scmi_xfers_info *info)
{}

static int scmi_channels_max_msg_configure(struct scmi_info *sinfo)
{}

static int scmi_xfer_info_init(struct scmi_info *sinfo)
{}

static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node,
			   int prot_id, bool tx)
{}

static inline int
scmi_txrx_setup(struct scmi_info *info, struct device_node *of_node,
		int prot_id)
{}

/**
 * scmi_channels_setup  - Helper to initialize all required channels
 *
 * @info: The SCMI instance descriptor.
 *
 * Initialize all the channels found described in the DT against the underlying
 * configured transport using custom defined dedicated devices instead of
 * borrowing devices from the SCMI drivers; this way channels are initialized
 * upfront during core SCMI stack probing and are no more coupled with SCMI
 * devices used by SCMI drivers.
 *
 * Note that, even though a pair of TX/RX channels is associated to each
 * protocol defined in the DT, a distinct freshly initialized channel is
 * created only if the DT node for the protocol at hand describes a dedicated
 * channel: in all the other cases the common BASE protocol channel is reused.
 *
 * Return: 0 on Success
 */
static int scmi_channels_setup(struct scmi_info *info)
{}

static int scmi_chan_destroy(int id, void *p, void *idr)
{}

static void scmi_cleanup_channels(struct scmi_info *info, struct idr *idr)
{}

static void scmi_cleanup_txrx_channels(struct scmi_info *info)
{}

static int scmi_bus_notifier(struct notifier_block *nb,
			     unsigned long action, void *data)
{}

static int scmi_device_request_notifier(struct notifier_block *nb,
					unsigned long action, void *data)
{}

static const char * const dbg_counter_strs[] =;

static ssize_t reset_all_on_write(struct file *filp, const char __user *buf,
				  size_t count, loff_t *ppos)
{}

static const struct file_operations fops_reset_counts =;

static void scmi_debugfs_counters_setup(struct scmi_debug_info *dbg,
					struct dentry *trans)
{}

static void scmi_debugfs_common_cleanup(void *d)
{}

static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info)
{}

static int scmi_debugfs_raw_mode_setup(struct scmi_info *info)
{}

static const struct scmi_desc *scmi_transport_setup(struct device *dev)
{}

static int scmi_probe(struct platform_device *pdev)
{}

static void scmi_remove(struct platform_device *pdev)
{}

static ssize_t protocol_version_show(struct device *dev,
				     struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(protocol_version);

static ssize_t firmware_version_show(struct device *dev,
				     struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(firmware_version);

static ssize_t vendor_id_show(struct device *dev,
			      struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(vendor_id);

static ssize_t sub_vendor_id_show(struct device *dev,
				  struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(sub_vendor_id);

static struct attribute *versions_attrs[] =;
ATTRIBUTE_GROUPS();

static struct platform_driver scmi_driver =;

static struct dentry *scmi_debugfs_init(void)
{}

static int __init scmi_driver_init(void)
{}
module_init();

static void __exit scmi_driver_exit(void)
{}
module_exit(scmi_driver_exit);

MODULE_ALIAS();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();