Skip to content

Commit 9f68ff7

Browse files
cris-masudeep-holla
authored andcommitted
firmware: arm_scmi: Add support for unidirectional mailbox channels
Extend the SCMI transport layer to support mailbox controllers that expose communication channels that are unidirectional by nature. Signed-off-by: Cristian Marussi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Sudeep Holla <[email protected]>
1 parent 92ac94f commit 9f68ff7

File tree

1 file changed

+84
-11
lines changed

1 file changed

+84
-11
lines changed

drivers/firmware/arm_scmi/mailbox.c

Lines changed: 84 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
* struct scmi_mailbox - Structure representing a SCMI mailbox transport
2020
*
2121
* @cl: Mailbox Client
22-
* @chan: Transmit/Receive mailbox channel
22+
* @chan: Transmit/Receive mailbox uni/bi-directional channel
23+
* @chan_receiver: Optional Receiver mailbox unidirectional channel
2324
* @cinfo: SCMI channel info
2425
* @shmem: Transmit/Receive shared memory area
2526
*/
2627
struct scmi_mailbox {
2728
struct mbox_client cl;
2829
struct mbox_chan *chan;
30+
struct mbox_chan *chan_receiver;
2931
struct scmi_chan_info *cinfo;
3032
struct scmi_shared_mem __iomem *shmem;
3133
};
@@ -48,30 +50,62 @@ static void rx_callback(struct mbox_client *cl, void *m)
4850

4951
static bool mailbox_chan_available(struct device_node *of_node, int idx)
5052
{
53+
int num_mb;
54+
55+
/*
56+
* Just check if bidirrectional channels are involved, and check the
57+
* index accordingly; proper full validation will be made later
58+
* in mailbox_chan_setup().
59+
*/
60+
num_mb = of_count_phandle_with_args(of_node, "mboxes", "#mbox-cells");
61+
if (num_mb == 3 && idx == 1)
62+
idx = 2;
63+
5164
return !of_parse_phandle_with_args(of_node, "mboxes",
5265
"#mbox-cells", idx, NULL);
5366
}
5467

55-
static int mailbox_chan_validate(struct device *cdev)
68+
/**
69+
* mailbox_chan_validate - Validate transport configuration and map channels
70+
*
71+
* @cdev: Reference to the underlying transport device carrying the
72+
* of_node descriptor to analyze.
73+
* @a2p_rx_chan: A reference to an optional unidirectional channel to use
74+
* for replies on the a2p channel. Set as zero if not present.
75+
* @p2a_chan: A reference to the optional p2a channel.
76+
* Set as zero if not present.
77+
*
78+
* At first, validate the transport configuration as described in terms of
79+
* 'mboxes' and 'shmem', then determin which mailbox channel indexes are
80+
* appropriate to be use in the current configuration.
81+
*
82+
* Return: 0 on Success or error
83+
*/
84+
static int mailbox_chan_validate(struct device *cdev,
85+
int *a2p_rx_chan, int *p2a_chan)
5686
{
5787
int num_mb, num_sh, ret = 0;
5888
struct device_node *np = cdev->of_node;
5989

6090
num_mb = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
6191
num_sh = of_count_phandle_with_args(np, "shmem", NULL);
92+
dev_dbg(cdev, "Found %d mboxes and %d shmems !\n", num_mb, num_sh);
93+
6294
/* Bail out if mboxes and shmem descriptors are inconsistent */
63-
if (num_mb <= 0 || num_sh > 2 || num_mb != num_sh) {
64-
dev_warn(cdev, "Invalid channel descriptor for '%s'\n",
65-
of_node_full_name(np));
95+
if (num_mb <= 0 || num_sh <= 0 || num_sh > 2 || num_mb > 3 ||
96+
(num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2)) {
97+
dev_warn(cdev,
98+
"Invalid channel descriptor for '%s' - mbs:%d shm:%d\n",
99+
of_node_full_name(np), num_mb, num_sh);
66100
return -EINVAL;
67101
}
68102

103+
/* Bail out if provided shmem descriptors do not refer distinct areas */
69104
if (num_sh > 1) {
70105
struct device_node *np_tx, *np_rx;
71106

72107
np_tx = of_parse_phandle(np, "shmem", 0);
73108
np_rx = of_parse_phandle(np, "shmem", 1);
74-
/* SCMI Tx and Rx shared mem areas have to be distinct */
75109
if (!np_tx || !np_rx || np_tx == np_rx) {
76110
dev_warn(cdev, "Invalid shmem descriptor for '%s'\n",
77111
of_node_full_name(np));
@@ -82,6 +116,29 @@ static int mailbox_chan_validate(struct device *cdev)
82116
of_node_put(np_rx);
83117
}
84118

119+
/* Calculate channels IDs to use depending on mboxes/shmem layout */
120+
if (!ret) {
121+
switch (num_mb) {
122+
case 1:
123+
*a2p_rx_chan = 0;
124+
*p2a_chan = 0;
125+
break;
126+
case 2:
127+
if (num_sh == 2) {
128+
*a2p_rx_chan = 0;
129+
*p2a_chan = 1;
130+
} else {
131+
*a2p_rx_chan = 1;
132+
*p2a_chan = 0;
133+
}
134+
break;
135+
case 3:
136+
*a2p_rx_chan = 1;
137+
*p2a_chan = 2;
138+
break;
139+
}
140+
}
141+
85142
return ret;
86143
}
87144

@@ -92,15 +149,18 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
92149
struct device *cdev = cinfo->dev;
93150
struct scmi_mailbox *smbox;
94151
struct device_node *shmem;
95-
int ret, idx = tx ? 0 : 1;
152+
int ret, a2p_rx_chan, p2a_chan, idx = tx ? 0 : 1;
96153
struct mbox_client *cl;
97154
resource_size_t size;
98155
struct resource res;
99156

100-
ret = mailbox_chan_validate(cdev);
157+
ret = mailbox_chan_validate(cdev, &a2p_rx_chan, &p2a_chan);
101158
if (ret)
102159
return ret;
103160

161+
if (!tx && !p2a_chan)
162+
return -ENODEV;
163+
104164
smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL);
105165
if (!smbox)
106166
return -ENOMEM;
@@ -130,15 +190,26 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
130190
cl->tx_block = false;
131191
cl->knows_txdone = tx;
132192

133-
smbox->chan = mbox_request_channel(cl, tx ? 0 : 1);
193+
smbox->chan = mbox_request_channel(cl, tx ? 0 : p2a_chan);
134194
if (IS_ERR(smbox->chan)) {
135195
ret = PTR_ERR(smbox->chan);
136196
if (ret != -EPROBE_DEFER)
137-
dev_err(cdev, "failed to request SCMI %s mailbox\n",
138-
tx ? "Tx" : "Rx");
197+
dev_err(cdev,
198+
"failed to request SCMI %s mailbox\n", desc);
139199
return ret;
140200
}
141201

202+
/* Additional unidirectional channel for TX if needed */
203+
if (tx && a2p_rx_chan) {
204+
smbox->chan_receiver = mbox_request_channel(cl, a2p_rx_chan);
205+
if (IS_ERR(smbox->chan_receiver)) {
206+
ret = PTR_ERR(smbox->chan_receiver);
207+
if (ret != -EPROBE_DEFER)
208+
dev_err(cdev, "failed to request SCMI Tx Receiver mailbox\n");
209+
return ret;
210+
}
211+
}
212+
142213
cinfo->transport_info = smbox;
143214
smbox->cinfo = cinfo;
144215

@@ -152,8 +223,10 @@ static int mailbox_chan_free(int id, void *p, void *data)
152223

153224
if (smbox && !IS_ERR(smbox->chan)) {
154225
mbox_free_channel(smbox->chan);
226+
mbox_free_channel(smbox->chan_receiver);
155227
cinfo->transport_info = NULL;
156228
smbox->chan = NULL;
229+
smbox->chan_receiver = NULL;
157230
smbox->cinfo = NULL;
158231
}
159232

0 commit comments

Comments
 (0)