1 /* 2 * Copyright 2024 NXP 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef _ZEPHYR_DRIVERS_FIRMWARE_SCMI_MAILBOX_H_ 8 #define _ZEPHYR_DRIVERS_FIRMWARE_SCMI_MAILBOX_H_ 9 10 #include <zephyr/drivers/firmware/scmi/transport.h> 11 #include <zephyr/drivers/firmware/scmi/util.h> 12 #include <zephyr/drivers/firmware/scmi/shmem.h> 13 #include <zephyr/drivers/mbox.h> 14 #include <zephyr/kernel.h> 15 16 #define DT_DRV_COMPAT arm_scmi 17 18 /* get a `struct device` for a protocol's shared memory area */ 19 #define _SCMI_MBOX_SHMEM_BY_IDX(node_id, idx) \ 20 COND_CODE_1(DT_PROP_HAS_IDX(node_id, shmem, idx), \ 21 (DEVICE_DT_GET(DT_PROP_BY_IDX(node_id, shmem, idx))), \ 22 (NULL)) 23 24 /* get the name of mailbox channel's private data */ 25 #define _SCMI_MBOX_CHAN_NAME(proto, idx)\ 26 CONCAT(SCMI_TRANSPORT_CHAN_NAME(proto, idx), _, priv) 27 28 /* fetch a mailbox channel's doorbell */ 29 #define _SCMI_MBOX_CHAN_DBELL(node_id, name) \ 30 COND_CODE_1(DT_PROP_HAS_NAME(node_id, mboxes, name), \ 31 (MBOX_DT_SPEC_GET(node_id, name)), \ 32 ({ })) 33 34 /* define private data for a protocol TX channel */ 35 #define _SCMI_MBOX_CHAN_DEFINE_PRIV_TX(node_id, proto) \ 36 static struct scmi_mbox_channel _SCMI_MBOX_CHAN_NAME(proto, 0) =\ 37 { \ 38 .shmem = _SCMI_MBOX_SHMEM_BY_IDX(node_id, 0), \ 39 .tx = _SCMI_MBOX_CHAN_DBELL(node_id, tx), \ 40 .tx_reply = _SCMI_MBOX_CHAN_DBELL(node_id, tx_reply), \ 41 } 42 43 /* 44 * Define a mailbox channel. This does two things: 45 * 1) Define the mandatory `struct scmi_channel` structure 46 * 2) Define the mailbox-specific private data for said 47 * channel (i.e: a struct scmi_mbox_channel) 48 */ 49 #define _SCMI_MBOX_CHAN_DEFINE(node_id, proto, idx) \ 50 _SCMI_MBOX_CHAN_DEFINE_PRIV_TX(node_id, proto); \ 51 DT_SCMI_TRANSPORT_CHAN_DEFINE(node_id, idx, proto, \ 52 &(_SCMI_MBOX_CHAN_NAME(proto, idx))); \ 53 54 /* 55 * Optionally define a mailbox channel for a protocol. This is optional 56 * because a protocol might not have a dedicated channel. 57 */ 58 #define _SCMI_MBOX_CHAN_DEFINE_OPTIONAL(node_id, proto, idx) \ 59 COND_CODE_1(DT_PROP_HAS_IDX(node_id, shmem, idx), \ 60 (_SCMI_MBOX_CHAN_DEFINE(node_id, proto, idx)), \ 61 ()) 62 63 /* define a TX channel for a protocol node. This is preferred over 64 * _SCMI_MBOX_CHAN_DEFINE_OPTIONAL() since support for RX channels 65 * might be added later on. This macro is supposed to also define 66 * the RX channel 67 */ 68 #define SCMI_MBOX_PROTO_CHAN_DEFINE(node_id)\ 69 _SCMI_MBOX_CHAN_DEFINE_OPTIONAL(node_id, DT_REG_ADDR(node_id), 0) 70 71 /* define and validate base protocol TX channel */ 72 #define DT_INST_SCMI_MBOX_BASE_CHAN_DEFINE(inst) \ 73 BUILD_ASSERT(DT_INST_PROP_LEN(inst, mboxes) != 1 || \ 74 (DT_INST_PROP_HAS_IDX(inst, shmem, 0) && \ 75 DT_INST_PROP_HAS_NAME(inst, mboxes, tx)), \ 76 "bad bidirectional channel description"); \ 77 \ 78 BUILD_ASSERT(DT_INST_PROP_LEN(inst, mboxes) != 2 || \ 79 (DT_INST_PROP_HAS_NAME(inst, mboxes, tx) && \ 80 DT_INST_PROP_HAS_NAME(inst, mboxes, tx_reply)), \ 81 "bad unidirectional channel description"); \ 82 \ 83 BUILD_ASSERT(DT_INST_PROP_LEN(inst, shmem) == 1, \ 84 "bad SHMEM count"); \ 85 \ 86 BUILD_ASSERT(DT_INST_PROP_LEN(inst, mboxes) <= 2, \ 87 "bad mbox count"); \ 88 \ 89 _SCMI_MBOX_CHAN_DEFINE(DT_INST(inst, DT_DRV_COMPAT), SCMI_PROTOCOL_BASE, 0) 90 91 /* 92 * Define the mailbox-based transport layer. What this does is: 93 * 94 * 1) Goes through all protocol nodes (children of the `scmi` node) 95 * and creates a `struct scmi_channel` and its associated 96 * `struct scmi_mbox_channel` if the protocol has a dedicated channel. 97 * 98 * 2) Creates aforementioned structures for the base protocol 99 * (identified by the `scmi` node) 100 * 101 * 3) "registers" the driver via `DT_INST_SCMI_TRANSPORT_DEFINE()`. 102 */ 103 #define DT_INST_SCMI_MAILBOX_DEFINE(inst, level, prio, api) \ 104 DT_INST_FOREACH_CHILD_STATUS_OKAY(inst, SCMI_MBOX_PROTO_CHAN_DEFINE) \ 105 DT_INST_SCMI_MBOX_BASE_CHAN_DEFINE(inst) \ 106 DT_INST_SCMI_TRANSPORT_DEFINE(inst, NULL, NULL, NULL, level, prio, api) 107 108 struct scmi_mbox_channel { 109 /* SHMEM area bound to the channel */ 110 const struct device *shmem; 111 /* TX dbell */ 112 struct mbox_dt_spec tx; 113 /* TX reply dbell */ 114 struct mbox_dt_spec tx_reply; 115 }; 116 117 #endif /* _ZEPHYR_DRIVERS_FIRMWARE_SCMI_MAILBOX_H_ */ 118