| @@ -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_POINTS | 30 | #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 | | | |
| 48 | enum scmi_error_codes { | 33 | enum 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 | */ | | |
| 93 | struct 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 | */ | | |
| 109 | struct 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 instance | 71 | * struct scmi_info - Structure representing a SCMI instance |
| 119 | * | 72 | * |
| 120 | * @dev: Device pointer | 73 | * @dev: Device pointer |
| 121 | * @desc: SoC description for this instance | 74 | * @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 info | 78 | * @tx_minfo: Universal Transmit Message management info |
| 126 | * @tx_idr: IDR object to map protocol id to Tx channel info pointer | 79 | * @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 pointer | 80 | * @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 | */ | | |
| 154 | struct 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 | | | |
| 167 | static const int scmi_linux_errmap[] = { | 101 | static 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 | |
| 202 | static 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 | */ | | |
| 221 | static 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 | */ | | |
| 234 | static 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 | */ | | |
| 249 | static 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 message | 137 | * 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 messages | 204 | * scmi_rx_callback() - callback for receiving messages |
| 342 | * | 205 | * |
| 343 | * @cl: client pointer | 206 | * @cinfo: SCMI channel info |
| 344 | * @m: mailbox message | 207 | * @msg_hdr: Message header |
| 345 | * | 208 | * |
| 346 | * Processes one received message to appropriate transfer information and | 209 | * 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 be | 212 | * NOTE: This function will be invoked in IRQ context, hence should be |
| 350 | * as optimal as possible. | 213 | * as optimal as possible. |
| 351 | */ | 214 | */ |
| 352 | static void scmi_rx_callback(struct mbox_client *cl, void *m) | 215 | void 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 | |
| 406 | static bool | | |
| 407 | scmi_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 | |
| 422 | static bool scmi_xfer_done_no_timeout(const struct scmi_chan_info *cinfo, | 264 | static 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 | else | 312 | 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 the | 328 | 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 | |
| 734 | static int scmi_mailbox_check(struct device_node *np, int idx) | 569 | static 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 | | | |
| 740 | static 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 | |
| 805 | idr_alloc: | 602 | idr_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 | |
| 816 | static inline int | 613 | static inline int |
| 817 | scmi_mbox_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id) | 614 | scmi_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 | |
| 958 | static int scmi_mbox_free_channel(int id, void *p, void *data) | 749 | void 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 | |
| 973 | static int scmi_remove(struct platform_device *pdev) | 754 | static 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 | }; |
| 1044 | ATTRIBUTE_GROUPS(versions); | 825 | ATTRIBUTE_GROUPS(versions); |
| 1045 | | 826 | |
| 1046 | static 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 */ |
| 1053 | static const struct of_device_id scmi_of_match[] = { | 828 | static 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 | |