|  | // SPDX-License-Identifier: GPL-2.0 | 
|  | /* | 
|  | * System Control and Management Interface (SCMI) Message Protocol | 
|  | * driver common header file containing some definitions, structures | 
|  | * and function prototypes used in all the different SCMI protocols. | 
|  | * | 
|  | * Copyright (C) 2018 ARM Ltd. | 
|  | */ | 
|  |  | 
|  | #include <linux/bitfield.h> | 
|  | #include <linux/completion.h> | 
|  | #include <linux/device.h> | 
|  | #include <linux/errno.h> | 
|  | #include <linux/kernel.h> | 
|  | #include <linux/scmi_protocol.h> | 
|  | #include <linux/types.h> | 
|  |  | 
|  | #define PROTOCOL_REV_MINOR_MASK	GENMASK(15, 0) | 
|  | #define PROTOCOL_REV_MAJOR_MASK	GENMASK(31, 16) | 
|  | #define PROTOCOL_REV_MAJOR(x)	(u16)(FIELD_GET(PROTOCOL_REV_MAJOR_MASK, (x))) | 
|  | #define PROTOCOL_REV_MINOR(x)	(u16)(FIELD_GET(PROTOCOL_REV_MINOR_MASK, (x))) | 
|  | #define MAX_PROTOCOLS_IMP	16 | 
|  | #define MAX_OPPS		16 | 
|  |  | 
|  | enum scmi_common_cmd { | 
|  | PROTOCOL_VERSION = 0x0, | 
|  | PROTOCOL_ATTRIBUTES = 0x1, | 
|  | PROTOCOL_MESSAGE_ATTRIBUTES = 0x2, | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct scmi_msg_resp_prot_version - Response for a message | 
|  | * | 
|  | * @major_version: Major version of the ABI that firmware supports | 
|  | * @minor_version: Minor version of the ABI that firmware supports | 
|  | * | 
|  | * In general, ABI version changes follow the rule that minor version increments | 
|  | * are backward compatible. Major revision changes in ABI may not be | 
|  | * backward compatible. | 
|  | * | 
|  | * Response to a generic message with message type SCMI_MSG_VERSION | 
|  | */ | 
|  | struct scmi_msg_resp_prot_version { | 
|  | __le16 minor_version; | 
|  | __le16 major_version; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct scmi_msg_hdr - Message(Tx/Rx) header | 
|  | * | 
|  | * @id: The identifier of the command being sent | 
|  | * @protocol_id: The identifier of the protocol used to send @id command | 
|  | * @seq: The token to identify the message. when a message/command returns, | 
|  | *	the platform returns the whole message header unmodified including | 
|  | *	the token | 
|  | * @status: Status of the transfer once it's complete | 
|  | * @poll_completion: Indicate if the transfer needs to be polled for | 
|  | *	completion or interrupt mode is used | 
|  | */ | 
|  | struct scmi_msg_hdr { | 
|  | u8 id; | 
|  | u8 protocol_id; | 
|  | u16 seq; | 
|  | u32 status; | 
|  | bool poll_completion; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct scmi_msg - Message(Tx/Rx) structure | 
|  | * | 
|  | * @buf: Buffer pointer | 
|  | * @len: Length of data in the Buffer | 
|  | */ | 
|  | struct scmi_msg { | 
|  | void *buf; | 
|  | size_t len; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct scmi_xfer - Structure representing a message flow | 
|  | * | 
|  | * @hdr: Transmit message header | 
|  | * @tx: Transmit message | 
|  | * @rx: Receive message, the buffer should be pre-allocated to store | 
|  | *	message. If request-ACK protocol is used, we can reuse the same | 
|  | *	buffer for the rx path as we use for the tx path. | 
|  | * @done: completion event | 
|  | */ | 
|  | struct scmi_xfer { | 
|  | struct scmi_msg_hdr hdr; | 
|  | struct scmi_msg tx; | 
|  | struct scmi_msg rx; | 
|  | struct completion done; | 
|  | }; | 
|  |  | 
|  | void scmi_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer); | 
|  | int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer); | 
|  | int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id, | 
|  | size_t tx_size, size_t rx_size, struct scmi_xfer **p); | 
|  | int scmi_handle_put(const struct scmi_handle *handle); | 
|  | struct scmi_handle *scmi_handle_get(struct device *dev); | 
|  | void scmi_set_handle(struct scmi_device *scmi_dev); | 
|  | int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version); | 
|  | void scmi_setup_protocol_implemented(const struct scmi_handle *handle, | 
|  | u8 *prot_imp); | 
|  |  | 
|  | int scmi_base_protocol_init(struct scmi_handle *h); |