Commit | Line | Data |
---|---|---|
d2527682 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
aa4f886f SH |
2 | /* |
3 | * System Control and Management Interface (SCMI) Message Protocol | |
4 | * driver common header file containing some definitions, structures | |
5 | * and function prototypes used in all the different SCMI protocols. | |
6 | * | |
23136bff | 7 | * Copyright (C) 2018-2022 ARM Ltd. |
aa4f886f | 8 | */ |
1fc2dd18 CM |
9 | #ifndef _SCMI_COMMON_H |
10 | #define _SCMI_COMMON_H | |
aa4f886f | 11 | |
354b2e36 | 12 | #include <linux/bitfield.h> |
aa4f886f | 13 | #include <linux/completion.h> |
b6f20ff8 SH |
14 | #include <linux/device.h> |
15 | #include <linux/errno.h> | |
16 | #include <linux/kernel.h> | |
9ca5a183 CM |
17 | #include <linux/hashtable.h> |
18 | #include <linux/list.h> | |
f5800e0b | 19 | #include <linux/module.h> |
ed7c04c1 | 20 | #include <linux/refcount.h> |
aa4f886f | 21 | #include <linux/scmi_protocol.h> |
ed7c04c1 | 22 | #include <linux/spinlock.h> |
aa4f886f SH |
23 | #include <linux/types.h> |
24 | ||
aa90ac45 SH |
25 | #include <asm/unaligned.h> |
26 | ||
23136bff | 27 | #include "protocols.h" |
a4a20b09 CM |
28 | #include "notify.h" |
29 | ||
c4eb8366 VK |
30 | #define MSG_ID_MASK GENMASK(7, 0) |
31 | #define MSG_XTRACT_ID(hdr) FIELD_GET(MSG_ID_MASK, (hdr)) | |
32 | #define MSG_TYPE_MASK GENMASK(9, 8) | |
33 | #define MSG_XTRACT_TYPE(hdr) FIELD_GET(MSG_TYPE_MASK, (hdr)) | |
34 | #define MSG_TYPE_COMMAND 0 | |
35 | #define MSG_TYPE_DELAYED_RESP 2 | |
36 | #define MSG_TYPE_NOTIFICATION 3 | |
37 | #define MSG_PROTOCOL_ID_MASK GENMASK(17, 10) | |
38 | #define MSG_XTRACT_PROT_ID(hdr) FIELD_GET(MSG_PROTOCOL_ID_MASK, (hdr)) | |
39 | #define MSG_TOKEN_ID_MASK GENMASK(27, 18) | |
40 | #define MSG_XTRACT_TOKEN(hdr) FIELD_GET(MSG_TOKEN_ID_MASK, (hdr)) | |
41 | #define MSG_TOKEN_MAX (MSG_XTRACT_TOKEN(MSG_TOKEN_ID_MASK) + 1) | |
42 | ||
9ca5a183 CM |
43 | /* |
44 | * Size of @pending_xfers hashtable included in @scmi_xfers_info; ideally, in | |
45 | * order to minimize space and collisions, this should equal max_msg, i.e. the | |
46 | * maximum number of in-flight messages on a specific platform, but such value | |
47 | * is only available at runtime while kernel hashtables are statically sized: | |
48 | * pick instead as a fixed static size the maximum number of entries that can | |
49 | * fit the whole table into one 4k page. | |
50 | */ | |
51 | #define SCMI_PENDING_XFERS_HT_ORDER_SZ 9 | |
52 | ||
c4eb8366 VK |
53 | /** |
54 | * pack_scmi_header() - packs and returns 32-bit header | |
55 | * | |
56 | * @hdr: pointer to header containing all the information on message id, | |
63b282f1 | 57 | * protocol id, sequence id and type. |
c4eb8366 VK |
58 | * |
59 | * Return: 32-bit packed message header to be sent to the platform. | |
60 | */ | |
61 | static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr) | |
62 | { | |
63 | return FIELD_PREP(MSG_ID_MASK, hdr->id) | | |
63b282f1 | 64 | FIELD_PREP(MSG_TYPE_MASK, hdr->type) | |
c4eb8366 VK |
65 | FIELD_PREP(MSG_TOKEN_ID_MASK, hdr->seq) | |
66 | FIELD_PREP(MSG_PROTOCOL_ID_MASK, hdr->protocol_id); | |
67 | } | |
68 | ||
69 | /** | |
70 | * unpack_scmi_header() - unpacks and records message and protocol id | |
71 | * | |
72 | * @msg_hdr: 32-bit packed message header sent from the platform | |
73 | * @hdr: pointer to header to fetch message and protocol id. | |
74 | */ | |
75 | static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr) | |
76 | { | |
77 | hdr->id = MSG_XTRACT_ID(msg_hdr); | |
78 | hdr->protocol_id = MSG_XTRACT_PROT_ID(msg_hdr); | |
63b282f1 | 79 | hdr->type = MSG_XTRACT_TYPE(msg_hdr); |
c4eb8366 VK |
80 | } |
81 | ||
9ca5a183 CM |
82 | /* |
83 | * An helper macro to lookup an xfer from the @pending_xfers hashtable | |
84 | * using the message sequence number token as a key. | |
85 | */ | |
86 | #define XFER_FIND(__ht, __k) \ | |
87 | ({ \ | |
88 | typeof(__k) k_ = __k; \ | |
89 | struct scmi_xfer *xfer_ = NULL; \ | |
90 | \ | |
91 | hash_for_each_possible((__ht), xfer_, node, k_) \ | |
92 | if (xfer_->hdr.seq == k_) \ | |
93 | break; \ | |
94 | xfer_; \ | |
95 | }) | |
96 | ||
3d5d6e84 CM |
97 | struct scmi_revision_info * |
98 | scmi_revision_area_get(const struct scmi_protocol_handle *ph); | |
aa4f886f SH |
99 | int scmi_handle_put(const struct scmi_handle *handle); |
100 | struct scmi_handle *scmi_handle_get(struct device *dev); | |
933c5044 | 101 | void scmi_set_handle(struct scmi_device *scmi_dev); |
8d3581c2 | 102 | void scmi_setup_protocol_implemented(const struct scmi_protocol_handle *ph, |
b6f20ff8 SH |
103 | u8 *prot_imp); |
104 | ||
5a2f0a0b SH |
105 | int __init scmi_bus_init(void); |
106 | void __exit scmi_bus_exit(void); | |
107 | ||
48dc16e2 | 108 | const struct scmi_protocol *scmi_protocol_get(int protocol_id); |
f5800e0b | 109 | void scmi_protocol_put(int protocol_id); |
48dc16e2 | 110 | |
f0e73cee CM |
111 | int scmi_protocol_acquire(const struct scmi_handle *handle, u8 protocol_id); |
112 | void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id); | |
48dc16e2 | 113 | |
5c8a47a5 VK |
114 | /* SCMI Transport */ |
115 | /** | |
116 | * struct scmi_chan_info - Structure representing a SCMI channel information | |
117 | * | |
118 | * @dev: Reference to device in the SCMI hierarchy corresponding to this | |
119 | * channel | |
120 | * @handle: Pointer to SCMI entity handle | |
a690b7e6 CM |
121 | * @no_completion_irq: Flag to indicate that this channel has no completion |
122 | * interrupt mechanism for synchronous commands. | |
123 | * This can be dynamically set by transports at run-time | |
124 | * inside their provided .chan_setup(). | |
5c8a47a5 VK |
125 | * @transport_info: Transport layer related information |
126 | */ | |
127 | struct scmi_chan_info { | |
128 | struct device *dev; | |
129 | struct scmi_handle *handle; | |
a690b7e6 | 130 | bool no_completion_irq; |
5c8a47a5 VK |
131 | void *transport_info; |
132 | }; | |
133 | ||
134 | /** | |
135 | * struct scmi_transport_ops - Structure representing a SCMI transport ops | |
136 | * | |
78852812 | 137 | * @link_supplier: Optional callback to add link to a supplier device |
5c8a47a5 VK |
138 | * @chan_available: Callback to check if channel is available or not |
139 | * @chan_setup: Callback to allocate and setup a channel | |
140 | * @chan_free: Callback to free a channel | |
c92c3e38 IS |
141 | * @get_max_msg: Optional callback to provide max_msg dynamically |
142 | * Returns the maximum number of messages for the channel type | |
143 | * (tx or rx) that can be pending simultaneously in the system | |
5c8a47a5 VK |
144 | * @send_message: Callback to send a message |
145 | * @mark_txdone: Callback to mark tx as done | |
146 | * @fetch_response: Callback to fetch response | |
d5141f37 | 147 | * @fetch_notification: Callback to fetch notification |
87dff4e6 | 148 | * @clear_channel: Callback to clear a channel |
5c8a47a5 VK |
149 | * @poll_done: Callback to poll transfer status |
150 | */ | |
151 | struct scmi_transport_ops { | |
78852812 | 152 | int (*link_supplier)(struct device *dev); |
5c8a47a5 VK |
153 | bool (*chan_available)(struct device *dev, int idx); |
154 | int (*chan_setup)(struct scmi_chan_info *cinfo, struct device *dev, | |
155 | bool tx); | |
156 | int (*chan_free)(int id, void *p, void *data); | |
c92c3e38 | 157 | unsigned int (*get_max_msg)(struct scmi_chan_info *base_cinfo); |
5c8a47a5 VK |
158 | int (*send_message)(struct scmi_chan_info *cinfo, |
159 | struct scmi_xfer *xfer); | |
94d0cd1d CM |
160 | void (*mark_txdone)(struct scmi_chan_info *cinfo, int ret, |
161 | struct scmi_xfer *xfer); | |
5c8a47a5 VK |
162 | void (*fetch_response)(struct scmi_chan_info *cinfo, |
163 | struct scmi_xfer *xfer); | |
d5141f37 CM |
164 | void (*fetch_notification)(struct scmi_chan_info *cinfo, |
165 | size_t max_len, struct scmi_xfer *xfer); | |
87dff4e6 | 166 | void (*clear_channel)(struct scmi_chan_info *cinfo); |
5c8a47a5 VK |
167 | bool (*poll_done)(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer); |
168 | }; | |
169 | ||
d4f9dddd CM |
170 | int scmi_protocol_device_request(const struct scmi_device_id *id_table); |
171 | void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table); | |
172 | struct scmi_device *scmi_child_dev_find(struct device *parent, | |
173 | int prot_id, const char *name); | |
174 | ||
5c8a47a5 VK |
175 | /** |
176 | * struct scmi_desc - Description of SoC integration | |
177 | * | |
ceac257d CM |
178 | * @transport_init: An optional function that a transport can provide to |
179 | * initialize some transport-specific setup during SCMI core | |
180 | * initialization, so ahead of SCMI core probing. | |
181 | * @transport_exit: An optional function that a transport can provide to | |
182 | * de-initialize some transport-specific setup during SCMI core | |
183 | * de-initialization, so after SCMI core removal. | |
5c8a47a5 VK |
184 | * @ops: Pointer to the transport specific ops structure |
185 | * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds) | |
c92c3e38 IS |
186 | * @max_msg: Maximum number of messages for a channel type (tx or rx) that can |
187 | * be pending simultaneously in the system. May be overridden by the | |
188 | * get_max_msg op. | |
5c8a47a5 | 189 | * @max_msg_size: Maximum size of data per message that can be handled. |
a690b7e6 CM |
190 | * @force_polling: Flag to force this whole transport to use SCMI core polling |
191 | * mechanism instead of completion interrupts even if available. | |
31d2f803 CM |
192 | * @sync_cmds_completed_on_ret: Flag to indicate that the transport assures |
193 | * synchronous-command messages are atomically | |
194 | * completed on .send_message: no need to poll | |
195 | * actively waiting for a response. | |
196 | * Used by core internally only when polling is | |
197 | * selected as a waiting for reply method: i.e. | |
198 | * if a completion irq was found use that anyway. | |
69255e74 CM |
199 | * @atomic_enabled: Flag to indicate that this transport, which is assured not |
200 | * to sleep anywhere on the TX path, can be used in atomic mode | |
201 | * when requested. | |
5c8a47a5 VK |
202 | */ |
203 | struct scmi_desc { | |
ceac257d CM |
204 | int (*transport_init)(void); |
205 | void (*transport_exit)(void); | |
3de7b830 | 206 | const struct scmi_transport_ops *ops; |
5c8a47a5 VK |
207 | int max_rx_timeout_ms; |
208 | int max_msg; | |
209 | int max_msg_size; | |
a690b7e6 | 210 | const bool force_polling; |
31d2f803 | 211 | const bool sync_cmds_completed_on_ret; |
69255e74 | 212 | const bool atomic_enabled; |
5c8a47a5 VK |
213 | }; |
214 | ||
e8419c24 | 215 | #ifdef CONFIG_ARM_SCMI_TRANSPORT_MAILBOX |
5c8a47a5 | 216 | extern const struct scmi_desc scmi_mailbox_desc; |
e8419c24 CM |
217 | #endif |
218 | #ifdef CONFIG_ARM_SCMI_TRANSPORT_SMC | |
1dc65580 PF |
219 | extern const struct scmi_desc scmi_smc_desc; |
220 | #endif | |
46abe13b IS |
221 | #ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO |
222 | extern const struct scmi_desc scmi_virtio_desc; | |
223 | #endif | |
5f90f189 EC |
224 | #ifdef CONFIG_ARM_SCMI_TRANSPORT_OPTEE |
225 | extern const struct scmi_desc scmi_optee_desc; | |
226 | #endif | |
5c8a47a5 | 227 | |
13fba878 | 228 | void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr, void *priv); |
5c8a47a5 VK |
229 | void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id); |
230 | ||
231 | /* shmem related declarations */ | |
232 | struct scmi_shared_mem; | |
233 | ||
234 | void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem, | |
235 | struct scmi_xfer *xfer); | |
236 | u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem); | |
237 | void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem, | |
238 | struct scmi_xfer *xfer); | |
d5141f37 CM |
239 | void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem, |
240 | size_t max_len, struct scmi_xfer *xfer); | |
87dff4e6 | 241 | void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem); |
5c8a47a5 VK |
242 | bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem, |
243 | struct scmi_xfer *xfer); | |
1fc2dd18 | 244 | |
f301bba0 PH |
245 | /* declarations for message passing transports */ |
246 | struct scmi_msg_payld; | |
247 | ||
248 | /* Maximum overhead of message w.r.t. struct scmi_desc.max_msg_size */ | |
249 | #define SCMI_MSG_MAX_PROT_OVERHEAD (2 * sizeof(__le32)) | |
250 | ||
251 | size_t msg_response_size(struct scmi_xfer *xfer); | |
252 | size_t msg_command_size(struct scmi_xfer *xfer); | |
253 | void msg_tx_prepare(struct scmi_msg_payld *msg, struct scmi_xfer *xfer); | |
254 | u32 msg_read_header(struct scmi_msg_payld *msg); | |
255 | void msg_fetch_response(struct scmi_msg_payld *msg, size_t len, | |
256 | struct scmi_xfer *xfer); | |
257 | void msg_fetch_notification(struct scmi_msg_payld *msg, size_t len, | |
258 | size_t max_len, struct scmi_xfer *xfer); | |
259 | ||
a02d7c93 CM |
260 | void scmi_notification_instance_data_set(const struct scmi_handle *handle, |
261 | void *priv); | |
262 | void *scmi_notification_instance_data_get(const struct scmi_handle *handle); | |
1fc2dd18 | 263 | #endif /* _SCMI_COMMON_H */ |