mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
mailbox: zynqmp: Move buffered IPI setup to of_match selected routine
Move routine that initializes the mailboxes for send and receive to a function pointer that is set based on compatible string. Signed-off-by: Ben Levinsky <ben.levinsky@amd.com> Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
This commit is contained in:
parent
6efb495826
commit
41bcf30100
@ -72,6 +72,10 @@ struct zynqmp_ipi_mchan {
|
||||
unsigned int chan_type;
|
||||
};
|
||||
|
||||
struct zynqmp_ipi_mbox;
|
||||
|
||||
typedef int (*setup_ipi_fn)(struct zynqmp_ipi_mbox *ipi_mbox, struct device_node *node);
|
||||
|
||||
/**
|
||||
* struct zynqmp_ipi_mbox - Description of a ZynqMP IPI mailbox
|
||||
* platform data.
|
||||
@ -81,6 +85,7 @@ struct zynqmp_ipi_mchan {
|
||||
* @remote_id: remote IPI agent ID
|
||||
* @mbox: mailbox Controller
|
||||
* @mchans: array for channels, tx channel and rx channel.
|
||||
* @setup_ipi_fn: Function Pointer to set up IPI Channels
|
||||
*/
|
||||
struct zynqmp_ipi_mbox {
|
||||
struct zynqmp_ipi_pdata *pdata;
|
||||
@ -88,6 +93,7 @@ struct zynqmp_ipi_mbox {
|
||||
u32 remote_id;
|
||||
struct mbox_controller mbox;
|
||||
struct zynqmp_ipi_mchan mchans[2];
|
||||
setup_ipi_fn setup_ipi_fn;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -464,12 +470,9 @@ static void zynqmp_ipi_mbox_dev_release(struct device *dev)
|
||||
static int zynqmp_ipi_mbox_probe(struct zynqmp_ipi_mbox *ipi_mbox,
|
||||
struct device_node *node)
|
||||
{
|
||||
struct zynqmp_ipi_mchan *mchan;
|
||||
struct mbox_chan *chans;
|
||||
struct mbox_controller *mbox;
|
||||
struct resource res;
|
||||
struct device *dev, *mdev;
|
||||
const char *name;
|
||||
int ret;
|
||||
|
||||
dev = ipi_mbox->pdata->dev;
|
||||
@ -489,6 +492,73 @@ static int zynqmp_ipi_mbox_probe(struct zynqmp_ipi_mbox *ipi_mbox,
|
||||
}
|
||||
mdev = &ipi_mbox->dev;
|
||||
|
||||
/* Get the IPI remote agent ID */
|
||||
ret = of_property_read_u32(node, "xlnx,ipi-id", &ipi_mbox->remote_id);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "No IPI remote ID is specified.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ipi_mbox->setup_ipi_fn(ipi_mbox, node);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to set up IPI Buffers.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
mbox = &ipi_mbox->mbox;
|
||||
mbox->dev = mdev;
|
||||
mbox->ops = &zynqmp_ipi_chan_ops;
|
||||
mbox->num_chans = 2;
|
||||
mbox->txdone_irq = false;
|
||||
mbox->txdone_poll = true;
|
||||
mbox->txpoll_period = 5;
|
||||
mbox->of_xlate = zynqmp_ipi_of_xlate;
|
||||
chans = devm_kzalloc(mdev, 2 * sizeof(*chans), GFP_KERNEL);
|
||||
if (!chans)
|
||||
return -ENOMEM;
|
||||
mbox->chans = chans;
|
||||
chans[IPI_MB_CHNL_TX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_TX];
|
||||
chans[IPI_MB_CHNL_RX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_RX];
|
||||
ipi_mbox->mchans[IPI_MB_CHNL_TX].chan_type = IPI_MB_CHNL_TX;
|
||||
ipi_mbox->mchans[IPI_MB_CHNL_RX].chan_type = IPI_MB_CHNL_RX;
|
||||
ret = devm_mbox_controller_register(mdev, mbox);
|
||||
if (ret)
|
||||
dev_err(mdev,
|
||||
"Failed to register mbox_controller(%d)\n", ret);
|
||||
else
|
||||
dev_info(mdev,
|
||||
"Registered ZynqMP IPI mbox with TX/RX channels.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* zynqmp_ipi_setup - set up IPI Buffers for classic flow
|
||||
*
|
||||
* @ipi_mbox: pointer to IPI mailbox private data structure
|
||||
* @node: IPI mailbox device node
|
||||
*
|
||||
* This will be used to set up IPI Buffers for ZynqMP SOC if user
|
||||
* wishes to use classic driver usage model on new SOC's with only
|
||||
* buffered IPIs.
|
||||
*
|
||||
* Note that bufferless IPIs and mixed usage of buffered and bufferless
|
||||
* IPIs are not supported with this flow.
|
||||
*
|
||||
* This will be invoked with compatible string "xlnx,zynqmp-ipi-mailbox".
|
||||
*
|
||||
* Return: 0 for success, negative value for failure
|
||||
*/
|
||||
static int zynqmp_ipi_setup(struct zynqmp_ipi_mbox *ipi_mbox,
|
||||
struct device_node *node)
|
||||
{
|
||||
struct zynqmp_ipi_mchan *mchan;
|
||||
struct device *mdev;
|
||||
struct resource res;
|
||||
const char *name;
|
||||
int ret;
|
||||
|
||||
mdev = &ipi_mbox->dev;
|
||||
|
||||
mchan = &ipi_mbox->mchans[IPI_MB_CHNL_TX];
|
||||
name = "local_request_region";
|
||||
ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);
|
||||
@ -563,37 +633,7 @@ static int zynqmp_ipi_mbox_probe(struct zynqmp_ipi_mbox *ipi_mbox,
|
||||
if (!mchan->rx_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Get the IPI remote agent ID */
|
||||
ret = of_property_read_u32(node, "xlnx,ipi-id", &ipi_mbox->remote_id);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "No IPI remote ID is specified.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
mbox = &ipi_mbox->mbox;
|
||||
mbox->dev = mdev;
|
||||
mbox->ops = &zynqmp_ipi_chan_ops;
|
||||
mbox->num_chans = 2;
|
||||
mbox->txdone_irq = false;
|
||||
mbox->txdone_poll = true;
|
||||
mbox->txpoll_period = 5;
|
||||
mbox->of_xlate = zynqmp_ipi_of_xlate;
|
||||
chans = devm_kzalloc(mdev, 2 * sizeof(*chans), GFP_KERNEL);
|
||||
if (!chans)
|
||||
return -ENOMEM;
|
||||
mbox->chans = chans;
|
||||
chans[IPI_MB_CHNL_TX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_TX];
|
||||
chans[IPI_MB_CHNL_RX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_RX];
|
||||
ipi_mbox->mchans[IPI_MB_CHNL_TX].chan_type = IPI_MB_CHNL_TX;
|
||||
ipi_mbox->mchans[IPI_MB_CHNL_RX].chan_type = IPI_MB_CHNL_RX;
|
||||
ret = devm_mbox_controller_register(mdev, mbox);
|
||||
if (ret)
|
||||
dev_err(mdev,
|
||||
"Failed to register mbox_controller(%d)\n", ret);
|
||||
else
|
||||
dev_info(mdev,
|
||||
"Registered ZynqMP IPI mbox with TX/RX channels.\n");
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -624,6 +664,7 @@ static int zynqmp_ipi_probe(struct platform_device *pdev)
|
||||
struct zynqmp_ipi_pdata *pdata;
|
||||
struct zynqmp_ipi_mbox *mbox;
|
||||
int num_mboxes, ret = -EINVAL;
|
||||
setup_ipi_fn ipi_fn;
|
||||
|
||||
num_mboxes = of_get_available_child_count(np);
|
||||
if (num_mboxes == 0) {
|
||||
@ -644,9 +685,18 @@ static int zynqmp_ipi_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ipi_fn = (setup_ipi_fn)device_get_match_data(&pdev->dev);
|
||||
if (!ipi_fn) {
|
||||
dev_err(dev,
|
||||
"Mbox Compatible String is missing IPI Setup fn.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pdata->num_mboxes = num_mboxes;
|
||||
|
||||
mbox = pdata->ipi_mboxes;
|
||||
mbox->setup_ipi_fn = ipi_fn;
|
||||
|
||||
for_each_available_child_of_node(np, nc) {
|
||||
mbox->pdata = pdata;
|
||||
ret = zynqmp_ipi_mbox_probe(mbox, nc);
|
||||
@ -690,7 +740,9 @@ static void zynqmp_ipi_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct of_device_id zynqmp_ipi_of_match[] = {
|
||||
{ .compatible = "xlnx,zynqmp-ipi-mailbox" },
|
||||
{ .compatible = "xlnx,zynqmp-ipi-mailbox",
|
||||
.data = &zynqmp_ipi_setup,
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, zynqmp_ipi_of_match);
|
||||
|
Loading…
Reference in New Issue
Block a user