History

Merge tag 'scmi-updates-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/drivers

ARM SCMI/SCPI updates for v5.7 1. Abstraction of the scmi transport type from the core protocol driver which enables addition of other transports like SMC/HVC, SPCI and virtio apart from the existing mailbox 2. Miscellaneous fix for minor formatting issues with the kernel-doc style comments 3. Replacement of zero-length array with flexible-array member which is part of tree-wide cleanup * tag 'scmi-updates-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: misc: vexpress: Replace zero-length array with flexible-array member firmware: arm_scpi: Replace zero-length array with flexible-array member firmware: arm_scmi/perf: Replace zero-length array with flexible-array member firmware: arm_scmi: Replace zero-length array with flexible-array member firmware: arm_scmi: Make scmi core independent of the transport type firmware: arm_scmi: Move macros and helpers to common.h firmware: arm_scmi: Update doc style comments

Arnd Bergmann committed 6 years ago

Commit cedb4142 parents 021249e 57c45d48 files · +420 −266Browse files

Unified · Split

8 files
  1. drivers/firmware/arm_scmi/Makefile +2 −1
  2. drivers/firmware/arm_scmi/common.h +113 −2
  3. drivers/firmware/arm_scmi/driver.c +34 −259
  4. drivers/firmware/arm_scmi/mailbox.c +184 −0
  5. drivers/firmware/arm_scmi/perf.c +1 −1
  6. drivers/firmware/arm_scmi/shmem.c +83 −0
  7. drivers/firmware/arm_scpi.c +2 −2
  8. drivers/misc/vexpress-syscfg.c +1 −1
drivers/firmware/arm_scmi/Makefile+2−1
@@ -1,6 +1,7 @@
1# SPDX-License-Identifier: GPL-2.0-only1# SPDX-License-Identifier: GPL-2.0-only
2obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o2obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o scmi-transport.o
3scmi-bus-y = bus.o3scmi-bus-y = bus.o
4scmi-driver-y = driver.o4scmi-driver-y = driver.o
5scmi-transport-y = mailbox.o shmem.o
5scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o6scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o
6obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o7obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
drivers/firmware/arm_scmi/common.h+113−2
@@ -33,8 +33,8 @@ enum scmi_common_cmd { · 32 unmodified lines
33/**33/**
34 * struct scmi_msg_resp_prot_version - Response for a message34 * struct scmi_msg_resp_prot_version - Response for a message
35 *35 *
36 * @major_version: Major version of the ABI that firmware supports
37 * @minor_version: Minor version of the ABI that firmware supports36 * @minor_version: Minor version of the ABI that firmware supports
37 * @major_version: Major version of the ABI that firmware supports
38 *38 *
39 * In general, ABI version changes follow the rule that minor version increments39 * In general, ABI version changes follow the rule that minor version increments
40 * are backward compatible. Major revision changes in ABI may not be40 * are backward compatible. Major revision changes in ABI may not be
@@ -47,6 +47,19 @@ struct scmi_msg_resp_prot_version { · 6 unmodified lines
47 __le16 major_version;47 __le16 major_version;
48};48};
49 49
50#define MSG_ID_MASK GENMASK(7, 0)
51#define MSG_XTRACT_ID(hdr) FIELD_GET(MSG_ID_MASK, (hdr))
52#define MSG_TYPE_MASK GENMASK(9, 8)
53#define MSG_XTRACT_TYPE(hdr) FIELD_GET(MSG_TYPE_MASK, (hdr))
54#define MSG_TYPE_COMMAND 0
55#define MSG_TYPE_DELAYED_RESP 2
56#define MSG_TYPE_NOTIFICATION 3
57#define MSG_PROTOCOL_ID_MASK GENMASK(17, 10)
58#define MSG_XTRACT_PROT_ID(hdr) FIELD_GET(MSG_PROTOCOL_ID_MASK, (hdr))
59#define MSG_TOKEN_ID_MASK GENMASK(27, 18)
60#define MSG_XTRACT_TOKEN(hdr) FIELD_GET(MSG_TOKEN_ID_MASK, (hdr))
61#define MSG_TOKEN_MAX (MSG_XTRACT_TOKEN(MSG_TOKEN_ID_MASK) + 1)
62
50/**63/**
51 * struct scmi_msg_hdr - Message(Tx/Rx) header64 * struct scmi_msg_hdr - Message(Tx/Rx) header
52 *65 *
@@ -67,6 +80,33 @@ struct scmi_msg_hdr { · 14 unmodified lines
67 bool poll_completion;80 bool poll_completion;
68};81};
69 82
83/**
84 * pack_scmi_header() - packs and returns 32-bit header
85 *
86 * @hdr: pointer to header containing all the information on message id,
87 * protocol id and sequence id.
88 *
89 * Return: 32-bit packed message header to be sent to the platform.
90 */
91static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
92{
93 return FIELD_PREP(MSG_ID_MASK, hdr->id) |
94 FIELD_PREP(MSG_TOKEN_ID_MASK, hdr->seq) |
95 FIELD_PREP(MSG_PROTOCOL_ID_MASK, hdr->protocol_id);
96}
97
98/**
99 * unpack_scmi_header() - unpacks and records message and protocol id
100 *
101 * @msg_hdr: 32-bit packed message header sent from the platform
102 * @hdr: pointer to header to fetch message and protocol id.
103 */
104static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr)
105{
106 hdr->id = MSG_XTRACT_ID(msg_hdr);
107 hdr->protocol_id = MSG_XTRACT_PROT_ID(msg_hdr);
108}
109
70/**110/**
71 * struct scmi_msg - Message(Tx/Rx) structure111 * struct scmi_msg - Message(Tx/Rx) structure
72 *112 *
@@ -88,7 +128,7 @@ struct scmi_msg { · 15 unmodified lines
88 * message. If request-ACK protocol is used, we can reuse the same128 * message. If request-ACK protocol is used, we can reuse the same
89 * buffer for the rx path as we use for the tx path.129 * buffer for the rx path as we use for the tx path.
90 * @done: command message transmit completion event130 * @done: command message transmit completion event
91 * @async: pointer to delayed response message received event completion131 * @async_done: pointer to delayed response message received event completion
92 */132 */
93struct scmi_xfer {133struct scmi_xfer {
94 int transfer_id;134 int transfer_id;
@@ -113,3 +153,74 @@ void scmi_setup_protocol_implemented(const struct scmi_handle *handle, · 18 unmodified lines
113 u8 *prot_imp);153 u8 *prot_imp);
114 154
115int scmi_base_protocol_init(struct scmi_handle *h);155int scmi_base_protocol_init(struct scmi_handle *h);
156
157/* SCMI Transport */
158/**
159 * struct scmi_chan_info - Structure representing a SCMI channel information
160 *
161 * @dev: Reference to device in the SCMI hierarchy corresponding to this
162 * channel
163 * @handle: Pointer to SCMI entity handle
164 * @transport_info: Transport layer related information
165 */
166struct scmi_chan_info {
167 struct device *dev;
168 struct scmi_handle *handle;
169 void *transport_info;
170};
171
172/**
173 * struct scmi_transport_ops - Structure representing a SCMI transport ops
174 *
175 * @chan_available: Callback to check if channel is available or not
176 * @chan_setup: Callback to allocate and setup a channel
177 * @chan_free: Callback to free a channel
178 * @send_message: Callback to send a message
179 * @mark_txdone: Callback to mark tx as done
180 * @fetch_response: Callback to fetch response
181 * @poll_done: Callback to poll transfer status
182 */
183struct scmi_transport_ops {
184 bool (*chan_available)(struct device *dev, int idx);
185 int (*chan_setup)(struct scmi_chan_info *cinfo, struct device *dev,
186 bool tx);
187 int (*chan_free)(int id, void *p, void *data);
188 int (*send_message)(struct scmi_chan_info *cinfo,
189 struct scmi_xfer *xfer);
190 void (*mark_txdone)(struct scmi_chan_info *cinfo, int ret);
191 void (*fetch_response)(struct scmi_chan_info *cinfo,
192 struct scmi_xfer *xfer);
193 bool (*poll_done)(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer);
194};
195
196/**
197 * struct scmi_desc - Description of SoC integration
198 *
199 * @ops: Pointer to the transport specific ops structure
200 * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
201 * @max_msg: Maximum number of messages that can be pending
202 * simultaneously in the system
203 * @max_msg_size: Maximum size of data per message that can be handled.
204 */
205struct scmi_desc {
206 struct scmi_transport_ops *ops;
207 int max_rx_timeout_ms;
208 int max_msg;
209 int max_msg_size;
210};
211
212extern const struct scmi_desc scmi_mailbox_desc;
213
214void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr);
215void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id);
216
217/* shmem related declarations */
218struct scmi_shared_mem;
219
220void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem,
221 struct scmi_xfer *xfer);
222u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem);
223void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem,
224 struct scmi_xfer *xfer);
225bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,
226 struct scmi_xfer *xfer);
drivers/firmware/arm_scmi/driver.c+34−259
@@ -19,12 +19,10 @@ · 18 unmodified lines
19#include <linux/io.h>19#include <linux/io.h>
20#include <linux/kernel.h>20#include <linux/kernel.h>
21#include <linux/ktime.h>21#include <linux/ktime.h>
22#include <linux/mailbox_client.h>
23#include <linux/module.h>22#include <linux/module.h>
24#include <linux/of_address.h>23#include <linux/of_address.h>
25#include <linux/of_device.h>24#include <linux/of_device.h>
26#include <linux/processor.h>25#include <linux/processor.h>
27#include <linux/semaphore.h>
28#include <linux/slab.h>26#include <linux/slab.h>
29 27
30#include "common.h"28#include "common.h"
@@ -32,19 +30,6 @@ · 1 unmodified line
32#define CREATE_TRACE_POINTS30#define CREATE_TRACE_POINTS
33#include <trace/events/scmi.h>31#include <trace/events/scmi.h>
34 32
35#define MSG_ID_MASK GENMASK(7, 0)
36#define MSG_XTRACT_ID(hdr) FIELD_GET(MSG_ID_MASK, (hdr))
37#define MSG_TYPE_MASK GENMASK(9, 8)
38#define MSG_XTRACT_TYPE(hdr) FIELD_GET(MSG_TYPE_MASK, (hdr))
39#define MSG_TYPE_COMMAND 0
40#define MSG_TYPE_DELAYED_RESP 2
41#define MSG_TYPE_NOTIFICATION 3
42#define MSG_PROTOCOL_ID_MASK GENMASK(17, 10)
43#define MSG_XTRACT_PROT_ID(hdr) FIELD_GET(MSG_PROTOCOL_ID_MASK, (hdr))
44#define MSG_TOKEN_ID_MASK GENMASK(27, 18)
45#define MSG_XTRACT_TOKEN(hdr) FIELD_GET(MSG_TOKEN_ID_MASK, (hdr))
46#define MSG_TOKEN_MAX (MSG_XTRACT_TOKEN(MSG_TOKEN_ID_MASK) + 1)
47
48enum scmi_error_codes {33enum scmi_error_codes {
49 SCMI_SUCCESS = 0, /* Success */34 SCMI_SUCCESS = 0, /* Success */
50 SCMI_ERR_SUPPORT = -1, /* Not supported */35 SCMI_ERR_SUPPORT = -1, /* Not supported */
@@ -82,46 +67,14 @@ struct scmi_xfers_info { · 31 unmodified lines
82 spinlock_t xfer_lock;67 spinlock_t xfer_lock;
83};68};
84 69
85/**
86 * struct scmi_desc - Description of SoC integration
87 *
88 * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
89 * @max_msg: Maximum number of messages that can be pending
90 * simultaneously in the system
91 * @max_msg_size: Maximum size of data per message that can be handled.
92 */
93struct scmi_desc {
94 int max_rx_timeout_ms;
95 int max_msg;
96 int max_msg_size;
97};
98
99/**
100 * struct scmi_chan_info - Structure representing a SCMI channel information
101 *
102 * @cl: Mailbox Client
103 * @chan: Transmit/Receive mailbox channel
104 * @payload: Transmit/Receive mailbox channel payload area
105 * @dev: Reference to device in the SCMI hierarchy corresponding to this
106 * channel
107 * @handle: Pointer to SCMI entity handle
108 */
109struct scmi_chan_info {
110 struct mbox_client cl;
111 struct mbox_chan *chan;
112 void __iomem *payload;
113 struct device *dev;
114 struct scmi_handle *handle;
115};
116
117/**70/**
118 * struct scmi_info - Structure representing a SCMI instance71 * struct scmi_info - Structure representing a SCMI instance
119 *72 *
120 * @dev: Device pointer73 * @dev: Device pointer
121 * @desc: SoC description for this instance74 * @desc: SoC description for this instance
122 * @handle: Instance of SCMI handle to send to clients
123 * @version: SCMI revision information containing protocol version,75 * @version: SCMI revision information containing protocol version,
124 * implementation version and (sub-)vendor identification.76 * implementation version and (sub-)vendor identification.
77 * @handle: Instance of SCMI handle to send to clients
125 * @tx_minfo: Universal Transmit Message management info78 * @tx_minfo: Universal Transmit Message management info
126 * @tx_idr: IDR object to map protocol id to Tx channel info pointer79 * @tx_idr: IDR object to map protocol id to Tx channel info pointer
127 * @rx_idr: IDR object to map protocol id to Rx channel info pointer80 * @rx_idr: IDR object to map protocol id to Rx channel info pointer
@@ -143,27 +96,8 @@ struct scmi_info { · 15 unmodified lines
143 int users;96 int users;
144};97};
145 98
146#define client_to_scmi_chan_info(c) container_of(c, struct scmi_chan_info, cl)
147#define handle_to_scmi_info(h) container_of(h, struct scmi_info, handle)99#define handle_to_scmi_info(h) container_of(h, struct scmi_info, handle)
148 100
149/*
150 * SCMI specification requires all parameters, message headers, return
151 * arguments or any protocol data to be expressed in little endian
152 * format only.
153 */
154struct scmi_shared_mem {
155 __le32 reserved;
156 __le32 channel_status;
157#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR BIT(1)
158#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE BIT(0)
159 __le32 reserved1[2];
160 __le32 flags;
161#define SCMI_SHMEM_FLAG_INTR_ENABLED BIT(0)
162 __le32 length;
163 __le32 msg_header;
164 u8 msg_payload[0];
165};
166
167static const int scmi_linux_errmap[] = {101static const int scmi_linux_errmap[] = {
168 /* better than switch case as long as return value is continuous */102 /* better than switch case as long as return value is continuous */
169 0, /* SCMI_SUCCESS */103 0, /* SCMI_SUCCESS */
@@ -199,77 +133,6 @@ static inline void scmi_dump_header_dbg(struct device *dev, · 29 unmodified lines
199 hdr->id, hdr->seq, hdr->protocol_id);133 hdr->id, hdr->seq, hdr->protocol_id);
200}134}
201 135
202static void scmi_fetch_response(struct scmi_xfer *xfer,
203 struct scmi_shared_mem __iomem *mem)
204{
205 xfer->hdr.status = ioread32(mem->msg_payload);
206 /* Skip the length of header and status in payload area i.e 8 bytes */
207 xfer->rx.len = min_t(size_t, xfer->rx.len, ioread32(&mem->length) - 8);
208
209 /* Take a copy to the rx buffer.. */
210 memcpy_fromio(xfer->rx.buf, mem->msg_payload + 4, xfer->rx.len);
211}
212
213/**
214 * pack_scmi_header() - packs and returns 32-bit header
215 *
216 * @hdr: pointer to header containing all the information on message id,
217 * protocol id and sequence id.
218 *
219 * Return: 32-bit packed message header to be sent to the platform.
220 */
221static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
222{
223 return FIELD_PREP(MSG_ID_MASK, hdr->id) |
224 FIELD_PREP(MSG_TOKEN_ID_MASK, hdr->seq) |
225 FIELD_PREP(MSG_PROTOCOL_ID_MASK, hdr->protocol_id);
226}
227
228/**
229 * unpack_scmi_header() - unpacks and records message and protocol id
230 *
231 * @msg_hdr: 32-bit packed message header sent from the platform
232 * @hdr: pointer to header to fetch message and protocol id.
233 */
234static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr)
235{
236 hdr->id = MSG_XTRACT_ID(msg_hdr);
237 hdr->protocol_id = MSG_XTRACT_PROT_ID(msg_hdr);
238}
239
240/**
241 * scmi_tx_prepare() - mailbox client callback to prepare for the transfer
242 *
243 * @cl: client pointer
244 * @m: mailbox message
245 *
246 * This function prepares the shared memory which contains the header and the
247 * payload.
248 */
249static void scmi_tx_prepare(struct mbox_client *cl, void *m)
250{
251 struct scmi_xfer *t = m;
252 struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
253 struct scmi_shared_mem __iomem *mem = cinfo->payload;
254
255 /*
256 * Ideally channel must be free by now unless OS timeout last
257 * request and platform continued to process the same, wait
258 * until it releases the shared memory, otherwise we may endup
259 * overwriting its response with new message payload or vice-versa
260 */
261 spin_until_cond(ioread32(&mem->channel_status) &
262 SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
263 /* Mark channel busy + clear error */
264 iowrite32(0x0, &mem->channel_status);
265 iowrite32(t->hdr.poll_completion ? 0 : SCMI_SHMEM_FLAG_INTR_ENABLED,
266 &mem->flags);
267 iowrite32(sizeof(mem->msg_header) + t->tx.len, &mem->length);
268 iowrite32(pack_scmi_header(&t->hdr), &mem->msg_header);
269 if (t->tx.buf)
270 memcpy_toio(mem->msg_payload, t->tx.buf, t->tx.len);
271}
272
273/**136/**
274 * scmi_xfer_get() - Allocate one message137 * scmi_xfer_get() - Allocate one message
275 *138 *
@@ -338,10 +201,10 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer) · 62 unmodified lines
338}201}
339 202
340/**203/**
341 * scmi_rx_callback() - mailbox client callback for receive messages204 * scmi_rx_callback() - callback for receiving messages
342 *205 *
343 * @cl: client pointer206 * @cinfo: SCMI channel info
344 * @m: mailbox message207 * @msg_hdr: Message header
345 *208 *
346 * Processes one received message to appropriate transfer information and209 * Processes one received message to appropriate transfer information and
347 * signals completion of the transfer.210 * signals completion of the transfer.
@@ -349,21 +212,14 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer) · 1 unmodified line
349 * NOTE: This function will be invoked in IRQ context, hence should be212 * NOTE: This function will be invoked in IRQ context, hence should be
350 * as optimal as possible.213 * as optimal as possible.
351 */214 */
352static void scmi_rx_callback(struct mbox_client *cl, void *m)215void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr)
353{216{
354 u8 msg_type;
355 u32 msg_hdr;
356 u16 xfer_id;
357 struct scmi_xfer *xfer;
358 struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
359 struct device *dev = cinfo->dev;
360 struct scmi_info *info = handle_to_scmi_info(cinfo->handle);217 struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
361 struct scmi_xfers_info *minfo = &info->tx_minfo;218 struct scmi_xfers_info *minfo = &info->tx_minfo;
362 struct scmi_shared_mem __iomem *mem = cinfo->payload;219 u16 xfer_id = MSG_XTRACT_TOKEN(msg_hdr);
363 220 u8 msg_type = MSG_XTRACT_TYPE(msg_hdr);
364 msg_hdr = ioread32(&mem->msg_header);221 struct device *dev = cinfo->dev;
365 msg_type = MSG_XTRACT_TYPE(msg_hdr);222 struct scmi_xfer *xfer;
366 xfer_id = MSG_XTRACT_TOKEN(msg_hdr);
367 223
368 if (msg_type == MSG_TYPE_NOTIFICATION)224 if (msg_type == MSG_TYPE_NOTIFICATION)
369 return; /* Notifications not yet supported */225 return; /* Notifications not yet supported */
@@ -378,7 +234,7 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m) · 8 unmodified lines
378 234
379 scmi_dump_header_dbg(dev, &xfer->hdr);235 scmi_dump_header_dbg(dev, &xfer->hdr);
380 236
381 scmi_fetch_response(xfer, mem);237 info->desc->ops->fetch_response(cinfo, xfer);
382 238
383 trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id,239 trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id,
384 xfer->hdr.protocol_id, xfer->hdr.seq,240 xfer->hdr.protocol_id, xfer->hdr.seq,
@@ -403,28 +259,15 @@ void scmi_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer) · 18 unmodified lines
403 __scmi_xfer_put(&info->tx_minfo, xfer);259 __scmi_xfer_put(&info->tx_minfo, xfer);
404}260}
405 261
406static bool
407scmi_xfer_poll_done(const struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
408{
409 struct scmi_shared_mem __iomem *mem = cinfo->payload;
410 u16 xfer_id = MSG_XTRACT_TOKEN(ioread32(&mem->msg_header));
411
412 if (xfer->hdr.seq != xfer_id)
413 return false;
414
415 return ioread32(&mem->channel_status) &
416 (SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR |
417 SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
418}
419
420#define SCMI_MAX_POLL_TO_NS (100 * NSEC_PER_USEC)262#define SCMI_MAX_POLL_TO_NS (100 * NSEC_PER_USEC)
421 263
422static bool scmi_xfer_done_no_timeout(const struct scmi_chan_info *cinfo,264static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
423 struct scmi_xfer *xfer, ktime_t stop)265 struct scmi_xfer *xfer, ktime_t stop)
424{266{
425 ktime_t __cur = ktime_get();267 struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
426 268
427 return scmi_xfer_poll_done(cinfo, xfer) || ktime_after(__cur, stop);269 return info->desc->ops->poll_done(cinfo, xfer) ||
270 ktime_after(ktime_get(), stop);
428}271}
429 272
430/**273/**
@@ -453,29 +296,26 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) · 22 unmodified lines
453 xfer->hdr.protocol_id, xfer->hdr.seq,296 xfer->hdr.protocol_id, xfer->hdr.seq,
454 xfer->hdr.poll_completion);297 xfer->hdr.poll_completion);
455 298
456 ret = mbox_send_message(cinfo->chan, xfer);299 ret = info->desc->ops->send_message(cinfo, xfer);
457 if (ret < 0) {300 if (ret < 0) {
458 dev_dbg(dev, "mbox send fail %d\n", ret);301 dev_dbg(dev, "Failed to send message %d\n", ret);
459 return ret;302 return ret;
460 }303 }
461 304
462 /* mbox_send_message returns non-negative value on success, so reset */
463 ret = 0;
464
465 if (xfer->hdr.poll_completion) {305 if (xfer->hdr.poll_completion) {
466 ktime_t stop = ktime_add_ns(ktime_get(), SCMI_MAX_POLL_TO_NS);306 ktime_t stop = ktime_add_ns(ktime_get(), SCMI_MAX_POLL_TO_NS);
467 307
468 spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer, stop));308 spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer, stop));
469 309
470 if (ktime_before(ktime_get(), stop))310 if (ktime_before(ktime_get(), stop))
471 scmi_fetch_response(xfer, cinfo->payload);311 info->desc->ops->fetch_response(cinfo, xfer);
472 else312 else
473 ret = -ETIMEDOUT;313 ret = -ETIMEDOUT;
474 } else {314 } else {
475 /* And we wait for the response. */315 /* And we wait for the response. */
476 timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);316 timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
477 if (!wait_for_completion_timeout(&xfer->done, timeout)) {317 if (!wait_for_completion_timeout(&xfer->done, timeout)) {
478 dev_err(dev, "mbox timed out in resp(caller: %pS)\n",318 dev_err(dev, "timed out in resp(caller: %pS)\n",
479 (void *)_RET_IP_);319 (void *)_RET_IP_);
480 ret = -ETIMEDOUT;320 ret = -ETIMEDOUT;
481 }321 }
@@ -484,13 +324,8 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) · 2 unmodified lines
484 if (!ret && xfer->hdr.status)324 if (!ret && xfer->hdr.status)
485 ret = scmi_to_linux_errno(xfer->hdr.status);325 ret = scmi_to_linux_errno(xfer->hdr.status);
486 326
487 /*327 if (info->desc->ops->mark_txdone)
488 * NOTE: we might prefer not to need the mailbox ticker to manage the328 info->desc->ops->mark_txdone(cinfo, ret);
489 * transfer queueing since the protocol layer queues things by itself.
490 * Unfortunately, we have to kick the mailbox framework after we have
491 * received our message.
492 */
493 mbox_client_txdone(cinfo->chan, ret);
494 329
495 trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id,330 trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id,
496 xfer->hdr.protocol_id, xfer->hdr.seq,331 xfer->hdr.protocol_id, xfer->hdr.seq,
@@ -731,23 +566,12 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo) · 234 unmodified lines
731 return 0;566 return 0;
732}567}
733 568
734static int scmi_mailbox_check(struct device_node *np, int idx)569static int scmi_chan_setup(struct scmi_info *info, struct device *dev,
735{570 int prot_id, bool tx)
736 return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells",
737 idx, NULL);
738}
739
740static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev,
741 int prot_id, bool tx)
742{571{
743 int ret, idx;572 int ret, idx;
744 struct resource res;
745 resource_size_t size;
746 struct device_node *shmem, *np = dev->of_node;
747 struct scmi_chan_info *cinfo;573 struct scmi_chan_info *cinfo;
748 struct mbox_client *cl;
749 struct idr *idr;574 struct idr *idr;
750 const char *desc = tx ? "Tx" : "Rx";
751 575
752 /* Transmit channel is first entry i.e. index 0 */576 /* Transmit channel is first entry i.e. index 0 */
753 idx = tx ? 0 : 1;577 idx = tx ? 0 : 1;
@@ -758,7 +582,7 @@ static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, · 4 unmodified lines
758 if (cinfo)582 if (cinfo)
759 return 0;583 return 0;
760 584
761 if (scmi_mailbox_check(np, idx)) {585 if (!info->desc->ops->chan_available(dev, idx)) {
762 cinfo = idr_find(idr, SCMI_PROTOCOL_BASE);586 cinfo = idr_find(idr, SCMI_PROTOCOL_BASE);
763 if (unlikely(!cinfo)) /* Possible only if platform has no Rx */587 if (unlikely(!cinfo)) /* Possible only if platform has no Rx */
764 return -EINVAL;588 return -EINVAL;
@@ -771,36 +595,9 @@ static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, · 6 unmodified lines
771 595
772 cinfo->dev = dev;596 cinfo->dev = dev;
773 597
774 cl = &cinfo->cl;598 ret = info->desc->ops->chan_setup(cinfo, info->dev, tx);
775 cl->dev = dev;599 if (ret)
776 cl->rx_callback = scmi_rx_callback;
777 cl->tx_prepare = tx ? scmi_tx_prepare : NULL;
778 cl->tx_block = false;
779 cl->knows_txdone = tx;
780
781 shmem = of_parse_phandle(np, "shmem", idx);
782 ret = of_address_to_resource(shmem, 0, &res);
783 of_node_put(shmem);
784 if (ret) {
785 dev_err(dev, "failed to get SCMI %s payload memory\n", desc);
786 return ret;
787 }
788
789 size = resource_size(&res);
790 cinfo->payload = devm_ioremap(info->dev, res.start, size);
791 if (!cinfo->payload) {
792 dev_err(dev, "failed to ioremap SCMI %s payload\n", desc);
793 return -EADDRNOTAVAIL;
794 }
795
796 cinfo->chan = mbox_request_channel(cl, idx);
797 if (IS_ERR(cinfo->chan)) {
798 ret = PTR_ERR(cinfo->chan);
799 if (ret != -EPROBE_DEFER)
800 dev_err(dev, "failed to request SCMI %s mailbox\n",
801 desc);
802 return ret;600 return ret;
803 }
804 601
805idr_alloc:602idr_alloc:
806 ret = idr_alloc(idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL);603 ret = idr_alloc(idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL);
@@ -814,12 +611,12 @@ idr_alloc: · 7 unmodified lines
814}611}
815 612
816static inline int613static inline int
817scmi_mbox_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id)614scmi_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id)
818{615{
819 int ret = scmi_mbox_chan_setup(info, dev, prot_id, true);616 int ret = scmi_chan_setup(info, dev, prot_id, true);
820 617
821 if (!ret) /* Rx is optional, hence no error check */618 if (!ret) /* Rx is optional, hence no error check */
822 scmi_mbox_chan_setup(info, dev, prot_id, false);619 scmi_chan_setup(info, dev, prot_id, false);
823 620
824 return ret;621 return ret;
825}622}
@@ -837,7 +634,7 @@ scmi_create_protocol_device(struct device_node *np, struct scmi_info *info, · 11 unmodified lines
837 return;634 return;
838 }635 }
839 636
840 if (scmi_mbox_txrx_setup(info, &sdev->dev, prot_id)) {637 if (scmi_txrx_setup(info, &sdev->dev, prot_id)) {
841 dev_err(&sdev->dev, "failed to setup transport\n");638 dev_err(&sdev->dev, "failed to setup transport\n");
842 scmi_device_destroy(sdev);639 scmi_device_destroy(sdev);
843 return;640 return;
@@ -890,12 +687,6 @@ static int scmi_probe(struct platform_device *pdev) · 46 unmodified lines
890 struct device *dev = &pdev->dev;687 struct device *dev = &pdev->dev;
891 struct device_node *child, *np = dev->of_node;688 struct device_node *child, *np = dev->of_node;
892 689
893 /* Only mailbox method supported, check for the presence of one */
894 if (scmi_mailbox_check(np, 0)) {
895 dev_err(dev, "no mailbox found in %pOF\n", np);
896 return -EINVAL;
897 }
898
899 desc = of_device_get_match_data(dev);690 desc = of_device_get_match_data(dev);
900 if (!desc)691 if (!desc)
901 return -EINVAL;692 return -EINVAL;
@@ -920,7 +711,7 @@ static int scmi_probe(struct platform_device *pdev) · 18 unmodified lines
920 handle->dev = info->dev;711 handle->dev = info->dev;
921 handle->version = &info->version;712 handle->version = &info->version;
922 713
923 ret = scmi_mbox_txrx_setup(info, dev, SCMI_PROTOCOL_BASE);714 ret = scmi_txrx_setup(info, dev, SCMI_PROTOCOL_BASE);
924 if (ret)715 if (ret)
925 return ret;716 return ret;
926 717
@@ -955,19 +746,9 @@ static int scmi_probe(struct platform_device *pdev) · 28 unmodified lines
955 return 0;746 return 0;
956}747}
957 748
958static int scmi_mbox_free_channel(int id, void *p, void *data)749void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id)
959{750{
960 struct scmi_chan_info *cinfo = p;
961 struct idr *idr = data;
962
963 if (!IS_ERR_OR_NULL(cinfo->chan)) {
964 mbox_free_channel(cinfo->chan);
965 cinfo->chan = NULL;
966 }
967
968 idr_remove(idr, id);751 idr_remove(idr, id);
969
970 return 0;
971}752}
972 753
973static int scmi_remove(struct platform_device *pdev)754static int scmi_remove(struct platform_device *pdev)
@@ -987,11 +768,11 @@ static int scmi_remove(struct platform_device *pdev) · 13 unmodified lines
987 return ret;768 return ret;
988 769
989 /* Safe to free channels since no more users */770 /* Safe to free channels since no more users */
990 ret = idr_for_each(idr, scmi_mbox_free_channel, idr);771 ret = idr_for_each(idr, info->desc->ops->chan_free, idr);
991 idr_destroy(&info->tx_idr);772 idr_destroy(&info->tx_idr);
992 773
993 idr = &info->rx_idr;774 idr = &info->rx_idr;
994 ret = idr_for_each(idr, scmi_mbox_free_channel, idr);775 ret = idr_for_each(idr, info->desc->ops->chan_free, idr);
995 idr_destroy(&info->rx_idr);776 idr_destroy(&info->rx_idr);
996 777
997 return ret;778 return ret;
@@ -1043,15 +824,9 @@ static struct attribute *versions_attrs[] = { · 45 unmodified lines
1043};824};
1044ATTRIBUTE_GROUPS(versions);825ATTRIBUTE_GROUPS(versions);
1045 826
1046static const struct scmi_desc scmi_generic_desc = {
1047 .max_rx_timeout_ms = 30, /* We may increase this if required */
1048 .max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */
1049 .max_msg_size = 128,
1050};
1051
1052/* Each compatible listed below must have descriptor associated with it */827/* Each compatible listed below must have descriptor associated with it */
1053static const struct of_device_id scmi_of_match[] = {828static const struct of_device_id scmi_of_match[] = {
1054 { .compatible = "arm,scmi", .data = &scmi_generic_desc },829 { .compatible = "arm,scmi", .data = &scmi_mailbox_desc },
1055 { /* Sentinel */ },830 { /* Sentinel */ },
1056};831};
1057 832
drivers/firmware/arm_scmi/mailbox.c+184−0
@@ -0,0 +1,184 @@
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 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/slab.h>
15
16#include "common.h"
17
18/**
19 * struct scmi_mailbox - Structure representing a SCMI mailbox transport
20 *
21 * @cl: Mailbox Client
22 * @chan: Transmit/Receive mailbox channel
23 * @cinfo: SCMI channel info
24 * @shmem: Transmit/Receive shared memory area
25 */
26struct scmi_mailbox {
27 struct mbox_client cl;
28 struct mbox_chan *chan;
29 struct scmi_chan_info *cinfo;
30 struct scmi_shared_mem __iomem *shmem;
31};
32
33#define client_to_scmi_mailbox(c) container_of(c, struct scmi_mailbox, cl)
34
35static void tx_prepare(struct mbox_client *cl, void *m)
36{
37 struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl);
38
39 shmem_tx_prepare(smbox->shmem, m);
40}
41
42static void rx_callback(struct mbox_client *cl, void *m)
43{
44 struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl);
45
46 scmi_rx_callback(smbox->cinfo, shmem_read_header(smbox->shmem));
47}
48
49static bool mailbox_chan_available(struct device *dev, int idx)
50{
51 return !of_parse_phandle_with_args(dev->of_node, "mboxes",
52 "#mbox-cells", idx, NULL);
53}
54
55static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
56 bool tx)
57{
58 const char *desc = tx ? "Tx" : "Rx";
59 struct device *cdev = cinfo->dev;
60 struct scmi_mailbox *smbox;
61 struct device_node *shmem;
62 int ret, idx = tx ? 0 : 1;
63 struct mbox_client *cl;
64 resource_size_t size;
65 struct resource res;
66
67 smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL);
68 if (!smbox)
69 return -ENOMEM;
70
71 shmem = of_parse_phandle(cdev->of_node, "shmem", idx);
72 ret = of_address_to_resource(shmem, 0, &res);
73 of_node_put(shmem);
74 if (ret) {
75 dev_err(cdev, "failed to get SCMI %s shared memory\n", desc);
76 return ret;
77 }
78
79 size = resource_size(&res);
80 smbox->shmem = devm_ioremap(dev, res.start, size);
81 if (!smbox->shmem) {
82 dev_err(dev, "failed to ioremap SCMI %s shared memory\n", desc);
83 return -EADDRNOTAVAIL;
84 }
85
86 cl = &smbox->cl;
87 cl->dev = cdev;
88 cl->tx_prepare = tx ? tx_prepare : NULL;
89 cl->rx_callback = rx_callback;
90 cl->tx_block = false;
91 cl->knows_txdone = tx;
92
93 smbox->chan = mbox_request_channel(cl, tx ? 0 : 1);
94 if (IS_ERR(smbox->chan)) {
95 ret = PTR_ERR(smbox->chan);
96 if (ret != -EPROBE_DEFER)
97 dev_err(cdev, "failed to request SCMI %s mailbox\n",
98 tx ? "Tx" : "Rx");
99 return ret;
100 }
101
102 cinfo->transport_info = smbox;
103 smbox->cinfo = cinfo;
104
105 return 0;
106}
107
108static int mailbox_chan_free(int id, void *p, void *data)
109{
110 struct scmi_chan_info *cinfo = p;
111 struct scmi_mailbox *smbox = cinfo->transport_info;
112
113 if (!IS_ERR(smbox->chan)) {
114 mbox_free_channel(smbox->chan);
115 cinfo->transport_info = NULL;
116 smbox->chan = NULL;
117 smbox->cinfo = NULL;
118 }
119
120 scmi_free_channel(cinfo, data, id);
121
122 return 0;
123}
124
125static int mailbox_send_message(struct scmi_chan_info *cinfo,
126 struct scmi_xfer *xfer)
127{
128 struct scmi_mailbox *smbox = cinfo->transport_info;
129 int ret;
130
131 ret = mbox_send_message(smbox->chan, xfer);
132
133 /* mbox_send_message returns non-negative value on success, so reset */
134 if (ret > 0)
135 ret = 0;
136
137 return ret;
138}
139
140static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret)
141{
142 struct scmi_mailbox *smbox = cinfo->transport_info;
143
144 /*
145 * NOTE: we might prefer not to need the mailbox ticker to manage the
146 * transfer queueing since the protocol layer queues things by itself.
147 * Unfortunately, we have to kick the mailbox framework after we have
148 * received our message.
149 */
150 mbox_client_txdone(smbox->chan, ret);
151}
152
153static void mailbox_fetch_response(struct scmi_chan_info *cinfo,
154 struct scmi_xfer *xfer)
155{
156 struct scmi_mailbox *smbox = cinfo->transport_info;
157
158 shmem_fetch_response(smbox->shmem, xfer);
159}
160
161static bool
162mailbox_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
163{
164 struct scmi_mailbox *smbox = cinfo->transport_info;
165
166 return shmem_poll_done(smbox->shmem, xfer);
167}
168
169static struct scmi_transport_ops scmi_mailbox_ops = {
170 .chan_available = mailbox_chan_available,
171 .chan_setup = mailbox_chan_setup,
172 .chan_free = mailbox_chan_free,
173 .send_message = mailbox_send_message,
174 .mark_txdone = mailbox_mark_txdone,
175 .fetch_response = mailbox_fetch_response,
176 .poll_done = mailbox_poll_done,
177};
178
179const struct scmi_desc scmi_mailbox_desc = {
180 .ops = &scmi_mailbox_ops,
181 .max_rx_timeout_ms = 30, /* We may increase this if required */
182 .max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */
183 .max_msg_size = 128,
184};
drivers/firmware/arm_scmi/perf.c+1−1
@@ -89,7 +89,7 @@ struct scmi_msg_resp_perf_describe_levels { · 88 unmodified lines
89 __le32 power;89 __le32 power;
90 __le16 transition_latency_us;90 __le16 transition_latency_us;
91 __le16 reserved;91 __le16 reserved;
92 } opp[0];92 } opp[];
93};93};
94 94
95struct scmi_perf_get_fc_info {95struct scmi_perf_get_fc_info {
drivers/firmware/arm_scmi/shmem.c+83−0
@@ -0,0 +1,83 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * For transport using shared mem structure.
4 *
5 * Copyright (C) 2019 ARM Ltd.
6 */
7
8#include <linux/io.h>
9#include <linux/processor.h>
10#include <linux/types.h>
11
12#include "common.h"
13
14/*
15 * SCMI specification requires all parameters, message headers, return
16 * arguments or any protocol data to be expressed in little endian
17 * format only.
18 */
19struct scmi_shared_mem {
20 __le32 reserved;
21 __le32 channel_status;
22#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR BIT(1)
23#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE BIT(0)
24 __le32 reserved1[2];
25 __le32 flags;
26#define SCMI_SHMEM_FLAG_INTR_ENABLED BIT(0)
27 __le32 length;
28 __le32 msg_header;
29 u8 msg_payload[];
30};
31
32void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem,
33 struct scmi_xfer *xfer)
34{
35 /*
36 * Ideally channel must be free by now unless OS timeout last
37 * request and platform continued to process the same, wait
38 * until it releases the shared memory, otherwise we may endup
39 * overwriting its response with new message payload or vice-versa
40 */
41 spin_until_cond(ioread32(&shmem->channel_status) &
42 SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
43 /* Mark channel busy + clear error */
44 iowrite32(0x0, &shmem->channel_status);
45 iowrite32(xfer->hdr.poll_completion ? 0 : SCMI_SHMEM_FLAG_INTR_ENABLED,
46 &shmem->flags);
47 iowrite32(sizeof(shmem->msg_header) + xfer->tx.len, &shmem->length);
48 iowrite32(pack_scmi_header(&xfer->hdr), &shmem->msg_header);
49 if (xfer->tx.buf)
50 memcpy_toio(shmem->msg_payload, xfer->tx.buf, xfer->tx.len);
51}
52
53u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem)
54{
55 return ioread32(&shmem->msg_header);
56}
57
58void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem,
59 struct scmi_xfer *xfer)
60{
61 xfer->hdr.status = ioread32(shmem->msg_payload);
62 /* Skip the length of header and status in shmem area i.e 8 bytes */
63 xfer->rx.len = min_t(size_t, xfer->rx.len,
64 ioread32(&shmem->length) - 8);
65
66 /* Take a copy to the rx buffer.. */
67 memcpy_fromio(xfer->rx.buf, shmem->msg_payload + 4, xfer->rx.len);
68}
69
70bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,
71 struct scmi_xfer *xfer)
72{
73 u16 xfer_id;
74
75 xfer_id = MSG_XTRACT_TOKEN(ioread32(&shmem->msg_header));
76
77 if (xfer->hdr.seq != xfer_id)
78 return false;
79
80 return ioread32(&shmem->channel_status) &
81 (SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR |
82 SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
83}
drivers/firmware/arm_scpi.c+2−2
@@ -262,12 +262,12 @@ struct scpi_drvinfo { · 261 unmodified lines
262struct scpi_shared_mem {262struct scpi_shared_mem {
263 __le32 command;263 __le32 command;
264 __le32 status;264 __le32 status;
265 u8 payload[0];265 u8 payload[];
266} __packed;266} __packed;
267 267
268struct legacy_scpi_shared_mem {268struct legacy_scpi_shared_mem {
269 __le32 status;269 __le32 status;
270 u8 payload[0];270 u8 payload[];
271} __packed;271} __packed;
272 272
273struct scp_capabilities {273struct scp_capabilities {
drivers/misc/vexpress-syscfg.c+1−1
@@ -42,7 +42,7 @@ struct vexpress_syscfg_func { · 41 unmodified lines
42 struct vexpress_syscfg *syscfg;42 struct vexpress_syscfg *syscfg;
43 struct regmap *regmap;43 struct regmap *regmap;
44 int num_templates;44 int num_templates;
45 u32 template[0]; /* Keep it last! */45 u32 template[]; /* Keep it last! */
46};46};
47 47
48 48