mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
Arm SCMI updates for v6.4
The main and only new addition this time around is the support for unidirectional mailbox channels. SCMI communicates between the agent and the platform using one bidirectional 'a2p' channel used by the agent to send SCMI commands and synchronously receive the related replies, and an optional 'p2a' unidirectional channel used to asynchronously receive delayed responses and notifications emitted from the platform. In order to support platforms that support only unidirectional mailbox hardware channels, the existing bindings are extended to support the same. Both bidirectional and unidirectional channels support for the SCMI mailbox can coexist. The correct and effective combination of defined 'mboxes' and 'shmem' descriptors determines the type of the mailbox channel. This also contains a fix for the transfers allocation on Rx channel especially when the base protocol doesn't use Rx channel while some of the protocols can have dedicated Rx channels. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEunHlEgbzHrJD3ZPhAEG6vDF+4pgFAmQ9QqkACgkQAEG6vDF+ 4piUTxAAoScfTHbLJXvPIYiWwtDAn2huYZulwEgyP7IkllcF6s1DO2vFpUnYDg82 Ew+j+mAfylN5NvXIDI73kfltQJWL0+CKHEtIG3UTeqn9SDJOLDC2P6+HGAoRftdz n77ctYyKGL8vgL9gjPh/SVTs74hHbiMLOx7RJJ4udjptEpqT7DriGQneMN8J4F4u utgnJiV/21kqDLw1TUA/Z0pJCDXepMHeg6hBZfBw3bW59MN4rlkMk9bUqF2qk8Q3 vq4stuHZ/USv6Gpv3NLuN3By/+fSJtYrTSTP8jN4NUzjS+trko8CjyPZ19gvUXM8 dPuQyjyQ5eCWczDLy1mXZWG5ZVDbI1QLcGw70b5fro6/TBiky1zx63khrCTPSVIo oy1YajZE4HPmn53AtZ53Ef6fAvlJg35GAXMTd17dvfu0pGTI8qpLPDuEBNVZELbV YpMxm4Xk/yfM8p33Vyq7kYrzesHAfXbdkfFWAWchnpwsqW7YxFYiW9ysOM5zeFTa KiOyGFD1B6IeiLAMGfnShPkl1RsOY0yiD4KvUFUvoT0WVj0kNMNUK5jJv/g92SHG 6D4/25ko1Hb4y+W3lwLceY5G7dnxGxh+SXOnEna+vidwcnz10EcvO/u3/S/ufaBq xQs43loaN72vivzF4cMpJXpVfXWux3Wr6llosQ5ybJSMflEdq+0= =8/Bb -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmQ9aAIACgkQYKtH/8kJ UifrxA/9HZmzS1B5G0hR8JkENHNrCb6eNfygQo0Xbyrz0240k1cM5GK3APo/oDM8 RDTIcjh0o2nm4WJ9xvd0SmNQw9+EsrKi19weWVwoXKfYkniKPA+ULArJDXqy7rVT +m6s4tOJT2KaWVHZUDhSWRjeWIdv8olhXPxrcVvBpXEBRBrt4bO2UZLvJPXxkiSw r8Fih3Wo0QVCOBvxL6PMAQ1IKjqDdQCc1YqnQ+8kOSSfIeE0mVVtxhGAk21Ss8OU GCDJ4bSnReENi0KtKTBFTImfF6S2hxAHCTG8KZaR123I3csslRQHhVp+RnVqO61T buoFdqmN8Rf9/3pHdzw1rc7+LKX22YFn1n5kKGt1yRXgusJw4hw+EYadSSw0K7g+ kFplZqfb84Ps5+43xHZZ8jbc5Ifch/xQs2S3X0ysvqgBrZTZbwsEqn/yLOT6TL1/ g5ykA8lzApBMbk5y/6B7bXUcLtpt60HwXIzFHk0rxmhE9smcjntZ8MvrcbkZjPAY 136L42P2zn3eBd8kKDzUOU1Q/+YGuwpOQ51ZjEGCOcw8+XanDjUAxCec30L2qThx hGrkRY1d2at0pK+xOIQwL/mnyJ52nRzaGXlDBaANhPO/ITAVxgTAPp3MYc6k1hz1 WRG+t1JE2TChm5t881yUhex87w1pL4MgficgPq1BChExk3fJAPM= =maaU -----END PGP SIGNATURE----- Merge tag 'scmi-updates-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into soc/drivers Arm SCMI updates for v6.4 The main and only new addition this time around is the support for unidirectional mailbox channels. SCMI communicates between the agent and the platform using one bidirectional 'a2p' channel used by the agent to send SCMI commands and synchronously receive the related replies, and an optional 'p2a' unidirectional channel used to asynchronously receive delayed responses and notifications emitted from the platform. In order to support platforms that support only unidirectional mailbox hardware channels, the existing bindings are extended to support the same. Both bidirectional and unidirectional channels support for the SCMI mailbox can coexist. The correct and effective combination of defined 'mboxes' and 'shmem' descriptors determines the type of the mailbox channel. This also contains a fix for the transfers allocation on Rx channel especially when the base protocol doesn't use Rx channel while some of the protocols can have dedicated Rx channels. * tag 'scmi-updates-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: firmware: arm_scmi: Add support for unidirectional mailbox channels dt-bindings: firmware: arm,scmi: Support mailboxes unidirectional channels firmware: arm_scmi: Fix xfers allocation on Rx channel firmware: arm_scmi: Use the bitmap API to allocate bitmaps firmware: arm_scmi: Fix device node validation for mailbox transport firmware: arm_scmi: Fix raw coexistence mode behaviour on failure path firmware: arm_scmi: Remove duplicate include header inclusion firmware: arm_scmi: Return a literal instead of a variable firmware: arm_scmi: Clean up a return statement in scmi_probe Link: https://lore.kernel.org/r/20230417145743.1904318-1-sudeep.holla@arm.com Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
4c87f3ff78
@ -56,17 +56,38 @@ properties:
|
||||
description:
|
||||
Specifies the mailboxes used to communicate with SCMI compliant
|
||||
firmware.
|
||||
items:
|
||||
- const: tx
|
||||
- const: rx
|
||||
oneOf:
|
||||
- items:
|
||||
- const: tx
|
||||
- const: rx
|
||||
minItems: 1
|
||||
- items:
|
||||
- const: tx
|
||||
- const: tx_reply
|
||||
- const: rx
|
||||
minItems: 2
|
||||
|
||||
mboxes:
|
||||
description:
|
||||
List of phandle and mailbox channel specifiers. It should contain
|
||||
exactly one or two mailboxes, one for transmitting messages("tx")
|
||||
and another optional for receiving the notifications("rx") if supported.
|
||||
exactly one, two or three mailboxes; the first one or two for transmitting
|
||||
messages ("tx") and another optional ("rx") for receiving notifications
|
||||
and delayed responses, if supported by the platform.
|
||||
The number of mailboxes needed for transmitting messages depends on the
|
||||
type of channels exposed by the specific underlying mailbox controller;
|
||||
one single channel descriptor is enough if such channel is bidirectional,
|
||||
while two channel descriptors are needed to represent the SCMI ("tx")
|
||||
channel if the underlying mailbox channels are of unidirectional type.
|
||||
The effective combination in numbers of mboxes and shmem descriptors let
|
||||
the SCMI subsystem determine unambiguosly which type of SCMI channels are
|
||||
made available by the underlying mailbox controller and how to use them.
|
||||
1 mbox / 1 shmem => SCMI TX over 1 mailbox bidirectional channel
|
||||
2 mbox / 2 shmem => SCMI TX and RX over 2 mailbox bidirectional channels
|
||||
2 mbox / 1 shmem => SCMI TX over 2 mailbox unidirectional channels
|
||||
3 mbox / 2 shmem => SCMI TX and RX over 3 mailbox unidirectional channels
|
||||
Any other combination of mboxes and shmem is invalid.
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
maxItems: 3
|
||||
|
||||
shmem:
|
||||
description:
|
||||
@ -228,13 +249,20 @@ $defs:
|
||||
maxItems: 1
|
||||
|
||||
mbox-names:
|
||||
items:
|
||||
- const: tx
|
||||
- const: rx
|
||||
oneOf:
|
||||
- items:
|
||||
- const: tx
|
||||
- const: rx
|
||||
minItems: 1
|
||||
- items:
|
||||
- const: tx
|
||||
- const: tx_reply
|
||||
- const: rx
|
||||
minItems: 2
|
||||
|
||||
mboxes:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
maxItems: 3
|
||||
|
||||
shmem:
|
||||
minItems: 1
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@ -436,7 +435,7 @@ struct scmi_device *scmi_device_create(struct device_node *np,
|
||||
/* Nothing to do. */
|
||||
if (!phead) {
|
||||
mutex_unlock(&scmi_requested_devices_mtx);
|
||||
return scmi_dev;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Walk the list of requested devices for protocol and create them */
|
||||
|
@ -2221,8 +2221,8 @@ static int __scmi_xfer_info_init(struct scmi_info *sinfo,
|
||||
hash_init(info->pending_xfers);
|
||||
|
||||
/* Allocate a bitmask sized to hold MSG_TOKEN_MAX tokens */
|
||||
info->xfer_alloc_table = devm_kcalloc(dev, BITS_TO_LONGS(MSG_TOKEN_MAX),
|
||||
sizeof(long), GFP_KERNEL);
|
||||
info->xfer_alloc_table = devm_bitmap_zalloc(dev, MSG_TOKEN_MAX,
|
||||
GFP_KERNEL);
|
||||
if (!info->xfer_alloc_table)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -2289,7 +2289,7 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
|
||||
return ret;
|
||||
|
||||
ret = __scmi_xfer_info_init(sinfo, &sinfo->tx_minfo);
|
||||
if (!ret && idr_find(&sinfo->rx_idr, SCMI_PROTOCOL_BASE))
|
||||
if (!ret && !idr_is_empty(&sinfo->rx_idr))
|
||||
ret = __scmi_xfer_info_init(sinfo, &sinfo->rx_minfo);
|
||||
|
||||
return ret;
|
||||
@ -2657,6 +2657,7 @@ static int scmi_probe(struct platform_device *pdev)
|
||||
struct scmi_handle *handle;
|
||||
const struct scmi_desc *desc;
|
||||
struct scmi_info *info;
|
||||
bool coex = IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX);
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *child, *np = dev->of_node;
|
||||
|
||||
@ -2731,16 +2732,13 @@ static int scmi_probe(struct platform_device *pdev)
|
||||
dev_warn(dev, "Failed to setup SCMI debugfs.\n");
|
||||
|
||||
if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) {
|
||||
bool coex =
|
||||
IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX);
|
||||
|
||||
ret = scmi_debugfs_raw_mode_setup(info);
|
||||
if (!coex) {
|
||||
if (ret)
|
||||
goto clear_dev_req_notifier;
|
||||
|
||||
/* Bail out anyway when coex enabled */
|
||||
return ret;
|
||||
/* Bail out anyway when coex disabled. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Coex enabled, carry on in any case. */
|
||||
@ -2764,6 +2762,8 @@ static int scmi_probe(struct platform_device *pdev)
|
||||
ret = scmi_protocol_acquire(handle, SCMI_PROTOCOL_BASE);
|
||||
if (ret) {
|
||||
dev_err(dev, "unable to communicate with SCMI\n");
|
||||
if (coex)
|
||||
return 0;
|
||||
goto notification_exit;
|
||||
}
|
||||
|
||||
|
@ -19,13 +19,15 @@
|
||||
* struct scmi_mailbox - Structure representing a SCMI mailbox transport
|
||||
*
|
||||
* @cl: Mailbox Client
|
||||
* @chan: Transmit/Receive mailbox channel
|
||||
* @chan: Transmit/Receive mailbox uni/bi-directional channel
|
||||
* @chan_receiver: Optional Receiver mailbox unidirectional channel
|
||||
* @cinfo: SCMI channel info
|
||||
* @shmem: Transmit/Receive shared memory area
|
||||
*/
|
||||
struct scmi_mailbox {
|
||||
struct mbox_client cl;
|
||||
struct mbox_chan *chan;
|
||||
struct mbox_chan *chan_receiver;
|
||||
struct scmi_chan_info *cinfo;
|
||||
struct scmi_shared_mem __iomem *shmem;
|
||||
};
|
||||
@ -48,10 +50,98 @@ static void rx_callback(struct mbox_client *cl, void *m)
|
||||
|
||||
static bool mailbox_chan_available(struct device_node *of_node, int idx)
|
||||
{
|
||||
int num_mb;
|
||||
|
||||
/*
|
||||
* Just check if bidirrectional channels are involved, and check the
|
||||
* index accordingly; proper full validation will be made later
|
||||
* in mailbox_chan_setup().
|
||||
*/
|
||||
num_mb = of_count_phandle_with_args(of_node, "mboxes", "#mbox-cells");
|
||||
if (num_mb == 3 && idx == 1)
|
||||
idx = 2;
|
||||
|
||||
return !of_parse_phandle_with_args(of_node, "mboxes",
|
||||
"#mbox-cells", idx, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* mailbox_chan_validate - Validate transport configuration and map channels
|
||||
*
|
||||
* @cdev: Reference to the underlying transport device carrying the
|
||||
* of_node descriptor to analyze.
|
||||
* @a2p_rx_chan: A reference to an optional unidirectional channel to use
|
||||
* for replies on the a2p channel. Set as zero if not present.
|
||||
* @p2a_chan: A reference to the optional p2a channel.
|
||||
* Set as zero if not present.
|
||||
*
|
||||
* At first, validate the transport configuration as described in terms of
|
||||
* 'mboxes' and 'shmem', then determin which mailbox channel indexes are
|
||||
* appropriate to be use in the current configuration.
|
||||
*
|
||||
* Return: 0 on Success or error
|
||||
*/
|
||||
static int mailbox_chan_validate(struct device *cdev,
|
||||
int *a2p_rx_chan, int *p2a_chan)
|
||||
{
|
||||
int num_mb, num_sh, ret = 0;
|
||||
struct device_node *np = cdev->of_node;
|
||||
|
||||
num_mb = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
|
||||
num_sh = of_count_phandle_with_args(np, "shmem", NULL);
|
||||
dev_dbg(cdev, "Found %d mboxes and %d shmems !\n", num_mb, num_sh);
|
||||
|
||||
/* Bail out if mboxes and shmem descriptors are inconsistent */
|
||||
if (num_mb <= 0 || num_sh <= 0 || num_sh > 2 || num_mb > 3 ||
|
||||
(num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2)) {
|
||||
dev_warn(cdev,
|
||||
"Invalid channel descriptor for '%s' - mbs:%d shm:%d\n",
|
||||
of_node_full_name(np), num_mb, num_sh);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Bail out if provided shmem descriptors do not refer distinct areas */
|
||||
if (num_sh > 1) {
|
||||
struct device_node *np_tx, *np_rx;
|
||||
|
||||
np_tx = of_parse_phandle(np, "shmem", 0);
|
||||
np_rx = of_parse_phandle(np, "shmem", 1);
|
||||
if (!np_tx || !np_rx || np_tx == np_rx) {
|
||||
dev_warn(cdev, "Invalid shmem descriptor for '%s'\n",
|
||||
of_node_full_name(np));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
of_node_put(np_tx);
|
||||
of_node_put(np_rx);
|
||||
}
|
||||
|
||||
/* Calculate channels IDs to use depending on mboxes/shmem layout */
|
||||
if (!ret) {
|
||||
switch (num_mb) {
|
||||
case 1:
|
||||
*a2p_rx_chan = 0;
|
||||
*p2a_chan = 0;
|
||||
break;
|
||||
case 2:
|
||||
if (num_sh == 2) {
|
||||
*a2p_rx_chan = 0;
|
||||
*p2a_chan = 1;
|
||||
} else {
|
||||
*a2p_rx_chan = 1;
|
||||
*p2a_chan = 0;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
*a2p_rx_chan = 1;
|
||||
*p2a_chan = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
|
||||
bool tx)
|
||||
{
|
||||
@ -59,11 +149,18 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
|
||||
struct device *cdev = cinfo->dev;
|
||||
struct scmi_mailbox *smbox;
|
||||
struct device_node *shmem;
|
||||
int ret, idx = tx ? 0 : 1;
|
||||
int ret, a2p_rx_chan, p2a_chan, idx = tx ? 0 : 1;
|
||||
struct mbox_client *cl;
|
||||
resource_size_t size;
|
||||
struct resource res;
|
||||
|
||||
ret = mailbox_chan_validate(cdev, &a2p_rx_chan, &p2a_chan);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!tx && !p2a_chan)
|
||||
return -ENODEV;
|
||||
|
||||
smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL);
|
||||
if (!smbox)
|
||||
return -ENOMEM;
|
||||
@ -93,15 +190,26 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
|
||||
cl->tx_block = false;
|
||||
cl->knows_txdone = tx;
|
||||
|
||||
smbox->chan = mbox_request_channel(cl, tx ? 0 : 1);
|
||||
smbox->chan = mbox_request_channel(cl, tx ? 0 : p2a_chan);
|
||||
if (IS_ERR(smbox->chan)) {
|
||||
ret = PTR_ERR(smbox->chan);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(cdev, "failed to request SCMI %s mailbox\n",
|
||||
tx ? "Tx" : "Rx");
|
||||
dev_err(cdev,
|
||||
"failed to request SCMI %s mailbox\n", desc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Additional unidirectional channel for TX if needed */
|
||||
if (tx && a2p_rx_chan) {
|
||||
smbox->chan_receiver = mbox_request_channel(cl, a2p_rx_chan);
|
||||
if (IS_ERR(smbox->chan_receiver)) {
|
||||
ret = PTR_ERR(smbox->chan_receiver);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(cdev, "failed to request SCMI Tx Receiver mailbox\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
cinfo->transport_info = smbox;
|
||||
smbox->cinfo = cinfo;
|
||||
|
||||
@ -115,8 +223,10 @@ static int mailbox_chan_free(int id, void *p, void *data)
|
||||
|
||||
if (smbox && !IS_ERR(smbox->chan)) {
|
||||
mbox_free_channel(smbox->chan);
|
||||
mbox_free_channel(smbox->chan_receiver);
|
||||
cinfo->transport_info = NULL;
|
||||
smbox->chan = NULL;
|
||||
smbox->chan_receiver = NULL;
|
||||
smbox->cinfo = NULL;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user