Commit 41bcf301 authored by Ben Levinsky's avatar Ben Levinsky Committed by Jassi Brar
Browse files

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: default avatarBen Levinsky <ben.levinsky@amd.com>
Signed-off-by: default avatarJassi Brar <jassisinghbrar@gmail.com>
parent 6efb4958
Loading
Loading
Loading
Loading
+87 −35
Original line number Diff line number Diff line
@@ -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);